diff --git a/OshimaModules/Items/GiftBox/礼包.cs b/OshimaModules/Items/GiftBox/礼包.cs index 6aa7641..ad34254 100644 --- a/OshimaModules/Items/GiftBox/礼包.cs +++ b/OshimaModules/Items/GiftBox/礼包.cs @@ -143,15 +143,18 @@ namespace Oshima.FunGame.OshimaModules.Items User = user; 礼包.Init(this, new() { - { General.GameplayEquilibriumConstant.InGameCurrency, 294000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 2660 }, - { new 升华之印().Name, 49 }, - { new 流光之印().Name, 21 }, - { new 永恒之印().Name, 6 }, - { new 技能卷轴().Name, 78 }, - { new 智慧之果().Name, 35 }, - { new 奥术符文().Name, 10 }, - { new 混沌之核().Name, 2 }, + { General.GameplayEquilibriumConstant.InGameCurrency, 667000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 6450 }, + { new 升华之印().Name, 126 }, + { new 流光之印().Name, 62 }, + { new 永恒之印().Name, 45 }, + { new 原初之印().Name, 35 }, + { new 创生之印().Name, 15 }, + { new 技能卷轴().Name, 190 }, + { new 智慧之果().Name, 94 }, + { new 奥术符文().Name, 68 }, + { new 混沌之核().Name, 42 }, + { new 法则精粹().Name, 22 }, { new 大经验书().Name, 164 } }, remainUseTimes); } diff --git a/OshimaModules/Items/ItemID.cs b/OshimaModules/Items/ItemID.cs index 6c6674c..57351c3 100644 --- a/OshimaModules/Items/ItemID.cs +++ b/OshimaModules/Items/ItemID.cs @@ -42,7 +42,11 @@ 混沌之核 = 18007, 奖券 = 18008, 十连奖券 = 18009, - 改名卡 = 18010 + 改名卡 = 18010, + 原初之印 = 18011, + 创生之印 = 18012, + 法则精粹 = 18013, + 探索许可 = 18999 } public enum GiftBoxID : long diff --git a/OshimaModules/Items/SpecialItem/创生之印.cs b/OshimaModules/Items/SpecialItem/创生之印.cs new file mode 100644 index 0000000..38f0de6 --- /dev/null +++ b/OshimaModules/Items/SpecialItem/创生之印.cs @@ -0,0 +1,13 @@ +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Oshima.FunGame.OshimaModules.Items +{ + public class 创生之印() : Item(ItemType.SpecialItem) + { + public override long Id => (long)SpecialItemID.创生之印; + public override string Name => "创生之印"; + public override string Description => "角色突破等阶必备的终级材料。"; + public override QualityType QualityType => QualityType.Orange; + } +} diff --git a/OshimaModules/Items/SpecialItem/原初之印.cs b/OshimaModules/Items/SpecialItem/原初之印.cs new file mode 100644 index 0000000..80c643c --- /dev/null +++ b/OshimaModules/Items/SpecialItem/原初之印.cs @@ -0,0 +1,13 @@ +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Oshima.FunGame.OshimaModules.Items +{ + public class 原初之印() : Item(ItemType.SpecialItem) + { + public override long Id => (long)SpecialItemID.原初之印; + public override string Name => "原初之印"; + public override string Description => "角色突破等阶必备的特级材料。"; + public override QualityType QualityType => QualityType.Purple; + } +} diff --git a/OshimaModules/Items/SpecialItem/探索许可.cs b/OshimaModules/Items/SpecialItem/探索许可.cs new file mode 100644 index 0000000..cb8fe0e --- /dev/null +++ b/OshimaModules/Items/SpecialItem/探索许可.cs @@ -0,0 +1,13 @@ +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Oshima.FunGame.OshimaModules.Items +{ + public class 探索许可() : Item(ItemType.SpecialItem) + { + public override long Id => (long)SpecialItemID.探索许可; + public override string Name => "探索许可"; + public override string Description => "铎京探索者协会为每位探索者发放的地区准入证明,拥有此证明可以接取各种各样的探索任务,并且享受铎京探索者协会的救援和协助服务。"; + public override QualityType QualityType => QualityType.White; + } +} diff --git a/OshimaModules/Items/SpecialItem/法则精粹.cs b/OshimaModules/Items/SpecialItem/法则精粹.cs new file mode 100644 index 0000000..32f55c9 --- /dev/null +++ b/OshimaModules/Items/SpecialItem/法则精粹.cs @@ -0,0 +1,13 @@ +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Constant; + +namespace Oshima.FunGame.OshimaModules.Items +{ + public class 法则精粹() : Item(ItemType.SpecialItem) + { + public override long Id => (long)SpecialItemID.法则精粹; + public override string Name => "法则精粹"; + public override string Description => "升级技能必备的终级材料。"; + public override QualityType QualityType => QualityType.Orange; + } +} diff --git a/OshimaModules/Items/SpecialItem/混沌之核.cs b/OshimaModules/Items/SpecialItem/混沌之核.cs index 7a64651..22cd8e8 100644 --- a/OshimaModules/Items/SpecialItem/混沌之核.cs +++ b/OshimaModules/Items/SpecialItem/混沌之核.cs @@ -7,7 +7,7 @@ namespace Oshima.FunGame.OshimaModules.Items { public override long Id => (long)SpecialItemID.混沌之核; public override string Name => "混沌之核"; - public override string Description => "升级技能必备的终级材料。"; + public override string Description => "升级技能必备的特级材料。"; public override QualityType QualityType => QualityType.Purple; } } diff --git a/OshimaModules/Modules/ItemModule.cs b/OshimaModules/Modules/ItemModule.cs index 0733b2b..bbdee5b 100644 --- a/OshimaModules/Modules/ItemModule.cs +++ b/OshimaModules/Modules/ItemModule.cs @@ -52,6 +52,10 @@ namespace Oshima.FunGame.OshimaModules (long)SpecialItemID.奖券 => new 奖券(), (long)SpecialItemID.十连奖券 => new 十连奖券(), (long)SpecialItemID.改名卡 => new 改名卡(), + (long)SpecialItemID.原初之印 => new 原初之印(), + (long)SpecialItemID.创生之印 => new 创生之印(), + (long)SpecialItemID.法则精粹 => new 法则精粹(), + (long)SpecialItemID.探索许可 => new 探索许可(), (long)ConsumableID.小回复药 => new 小回复药(), (long)ConsumableID.中回复药 => new 中回复药(), (long)ConsumableID.大回复药 => new 大回复药(), diff --git a/OshimaModules/Regions/OshimaRegion.cs b/OshimaModules/Regions/OshimaRegion.cs index 58bb08a..b4a7912 100644 --- a/OshimaModules/Regions/OshimaRegion.cs +++ b/OshimaModules/Regions/OshimaRegion.cs @@ -1,4 +1,5 @@ using System.Text; +using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; @@ -21,6 +22,11 @@ namespace Oshima.FunGame.OshimaModules.Regions return other is OshimaRegion && other.GetIdName() == GetIdName(); } + public virtual string VisitStore(EntityModuleConfig stores, User user, string storeName) + { + return ""; + } + public override string ToString() { StringBuilder builder = new(); diff --git a/OshimaModules/Regions/Players.cs b/OshimaModules/Regions/Players.cs index 1662337..4f370b1 100644 --- a/OshimaModules/Regions/Players.cs +++ b/OshimaModules/Regions/Players.cs @@ -1,4 +1,9 @@ -namespace Oshima.FunGame.OshimaModules.Regions +using Milimoe.FunGame.Core.Api.Utility; +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Constant; +using Oshima.FunGame.OshimaModules.Items; + +namespace Oshima.FunGame.OshimaModules.Regions { public class 铎京城 : OshimaRegion { @@ -18,5 +23,38 @@ Weathers.Add("霜冻", -18); ChangeRandomWeather(); } + + public override string VisitStore(EntityModuleConfig stores, User user, string storeName) + { + Store? store = stores.Get(storeName); + + if (store is null) + { + EntityModuleConfig storeTemplate = new("stores", "dokyo"); + storeTemplate.LoadConfig(); + Store? template = storeTemplate.Get(storeName); + if (template != null) + { + if (template.NextRefreshDate < DateTime.Now) + { + template.NextRefreshDate = DateTime.Today.AddHours(4); + template.UpdateRefreshTime(template.NextRefreshDate); + storeTemplate.Add(storeName, template); + storeTemplate.SaveConfig(); + } + stores.Add(storeName, template); + stores.SaveConfig(); + stores.LoadConfig(); + store = stores.Get(storeName); + } + } + + if (store != null) + { + return store.ToString(); + } + + return ""; + } } } diff --git a/OshimaServers/AnonymousServer.cs b/OshimaServers/AnonymousServer.cs index 82dea00..88ab438 100644 --- a/OshimaServers/AnonymousServer.cs +++ b/OshimaServers/AnonymousServer.cs @@ -166,6 +166,10 @@ namespace Oshima.FunGame.OshimaServers pc.Add("user", user); pc.SaveConfig(); } + if (FunGameConstant.UserLastVisitStore.TryGetValue(user.Id, out LastStoreModel? value) && value != null && (DateTime.Now - value.LastTime).TotalMinutes > 2) + { + FunGameConstant.UserLastVisitStore.Remove(user.Id); + } } } Controller.WriteLine("读取 FunGame 存档缓存", LogLevel.Debug); @@ -223,10 +227,23 @@ namespace Oshima.FunGame.OshimaServers foreach (string filePath in filePaths) { string fileName = Path.GetFileNameWithoutExtension(filePath); - EntityModuleConfig store = new("stores", fileName); - store.Clear(); - FunGameService.CheckDailyStore(store); - store.SaveConfig(); + if (long.TryParse(fileName, out long userId) && FunGameConstant.UserIdAndUsername.TryGetValue(userId, out User? user) && user != null) + { + EntityModuleConfig store = new("stores", fileName); + store.LoadConfig(); + store.Remove("daily"); + string[] stores = [.. store.Keys]; + foreach (string key in stores) + { + Store? s = store.Get(key); + if (s != null && s.AutoRefresh && s.NextRefreshDate.Date == DateTime.Today) + { + store.Remove(key); + } + } + FunGameService.CheckDailyStore(store, user); + store.SaveConfig(); + } } Controller.WriteLine("刷新商店"); } diff --git a/OshimaServers/Model/LastStoreModel.cs b/OshimaServers/Model/LastStoreModel.cs new file mode 100644 index 0000000..e5db5ec --- /dev/null +++ b/OshimaServers/Model/LastStoreModel.cs @@ -0,0 +1,10 @@ +namespace Oshima.FunGame.OshimaServers.Model +{ + public class LastStoreModel + { + public DateTime LastTime { get; set; } = DateTime.MinValue; + public bool IsDaily { get; set; } = false; + public string StoreRegion { get; set; } = ""; + public string StoreName { get; set; } = ""; + } +} diff --git a/OshimaServers/Service/FunGameConstant.cs b/OshimaServers/Service/FunGameConstant.cs index 1305175..d90f787 100644 --- a/OshimaServers/Service/FunGameConstant.cs +++ b/OshimaServers/Service/FunGameConstant.cs @@ -4,6 +4,7 @@ using Oshima.Core.Constant; using Oshima.FunGame.OshimaModules.Effects.OpenEffects; using Oshima.FunGame.OshimaModules.Items; using Oshima.FunGame.OshimaModules.Regions; +using Oshima.FunGame.OshimaServers.Model; namespace Oshima.FunGame.OshimaServers.Service { @@ -32,6 +33,7 @@ namespace Oshima.FunGame.OshimaServers.Service public static List AllSkills { get; } = []; public static Dictionary UserIdAndUsername { get; } = []; public static Dictionary MarketItemIdAndItem { get; } = []; + public static Dictionary UserLastVisitStore { get; } = []; public static ItemType[] ItemCanUsed => [ItemType.Consumable, ItemType.MagicCard, ItemType.SpecialItem, ItemType.GiftBox, ItemType.Others]; public static ItemType[] ItemCanNotDrawCard => [ItemType.Collectible, ItemType.QuestItem, ItemType.GiftBox, ItemType.Others]; @@ -40,49 +42,57 @@ namespace Oshima.FunGame.OshimaServers.Service { 0, new() { - { General.GameplayEquilibriumConstant.InGameMaterial, 20 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 40 }, { nameof(升华之印), 2 } } }, { 1, new() { - { General.GameplayEquilibriumConstant.InGameMaterial, 40 }, - { nameof(升华之印), 4 } + { General.GameplayEquilibriumConstant.InGameMaterial, 80 }, + { nameof(升华之印), 4 }, + { nameof(流光之印), 2 } } }, { 2, new() { - { General.GameplayEquilibriumConstant.InGameMaterial, 80 }, - { nameof(升华之印), 6 }, - { nameof(流光之印), 2 } + { General.GameplayEquilibriumConstant.InGameMaterial, 160 }, + { nameof(升华之印), 8 }, + { nameof(流光之印), 4 }, + { nameof(永恒之印), 3 } } }, { 3, new() { - { General.GameplayEquilibriumConstant.InGameMaterial, 160 }, - { nameof(升华之印), 9 }, - { nameof(流光之印), 4 } + { General.GameplayEquilibriumConstant.InGameMaterial, 320 }, + { nameof(升华之印), 16 }, + { nameof(流光之印), 8 }, + { nameof(永恒之印), 6 }, + { nameof(原初之印), 5 } } }, { 4, new() { - { General.GameplayEquilibriumConstant.InGameMaterial, 320 }, - { nameof(升华之印), 12 }, - { nameof(流光之印), 6 }, - { nameof(永恒之印), 2 } + { General.GameplayEquilibriumConstant.InGameMaterial, 640 }, + { nameof(升华之印), 32 }, + { nameof(流光之印), 16 }, + { nameof(永恒之印), 12 }, + { nameof(原初之印), 10 }, + { nameof(创生之印), 5 } } }, { 5, new() { - { General.GameplayEquilibriumConstant.InGameMaterial, 640 }, - { nameof(升华之印), 16 }, - { nameof(流光之印), 9 }, - { nameof(永恒之印), 4 } + { General.GameplayEquilibriumConstant.InGameMaterial, 1280 }, + { nameof(升华之印), 64 }, + { nameof(流光之印), 32 }, + { nameof(永恒之印), 24 }, + { nameof(原初之印), 20 }, + { nameof(创生之印), 10 } } }, }; @@ -93,61 +103,68 @@ namespace Oshima.FunGame.OshimaServers.Service 1, new() { { "角色等级", 1 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 2000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 10 }, - { nameof(技能卷轴), 1 }, + { General.GameplayEquilibriumConstant.InGameCurrency, 5000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 50 }, + { nameof(技能卷轴), 1 } } }, { 2, new() { { "角色等级", 12 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 5000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 30 }, + { General.GameplayEquilibriumConstant.InGameCurrency, 10000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 100 }, { nameof(技能卷轴), 2 }, + { nameof(智慧之果), 1 } } }, { 3, new() { { "角色等级", 24 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 10000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 60 }, + { General.GameplayEquilibriumConstant.InGameCurrency, 20000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 150 }, { nameof(技能卷轴), 4 }, - { nameof(智慧之果), 1 }, + { nameof(智慧之果), 2 }, + { nameof(奥术符文), 1 } } }, { 4, new() { { "角色等级", 36 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 18000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 100 }, - { nameof(技能卷轴), 6 }, - { nameof(智慧之果), 2 }, + { General.GameplayEquilibriumConstant.InGameCurrency, 40000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 250 }, + { nameof(技能卷轴), 8 }, + { nameof(智慧之果), 4 }, + { nameof(奥术符文), 3 }, + { nameof(混沌之核), 1 } } }, { 5, new() { { "角色等级", 48 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 30000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 150 }, - { nameof(技能卷轴), 9 }, - { nameof(智慧之果), 4 }, - { nameof(奥术符文), 1 } + { General.GameplayEquilibriumConstant.InGameCurrency, 70000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 400 }, + { nameof(技能卷轴), 16 }, + { nameof(智慧之果), 8 }, + { nameof(奥术符文), 6 }, + { nameof(混沌之核), 4 }, + { nameof(法则精粹), 1 } } }, { 6, new() { { "角色等级", 60 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 47000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 210 }, - { nameof(技能卷轴), 6 }, - { nameof(智慧之果), 6 }, - { nameof(奥术符文), 2 }, - { nameof(混沌之核), 1 } + { General.GameplayEquilibriumConstant.InGameCurrency, 110000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 600 }, + { nameof(技能卷轴), 32 }, + { nameof(智慧之果), 16 }, + { nameof(奥术符文), 12 }, + { nameof(混沌之核), 8 }, + { nameof(法则精粹), 5 } } } }; @@ -159,37 +176,41 @@ namespace Oshima.FunGame.OshimaServers.Service { { "角色等级", 8 }, { General.GameplayEquilibriumConstant.InGameCurrency, 2000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 10 }, - { nameof(技能卷轴), 1 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 30 }, + { nameof(技能卷轴), 1 } } }, { 3, new() { { "角色等级", 16 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 5000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 30 }, + { General.GameplayEquilibriumConstant.InGameCurrency, 10000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 100 }, { nameof(技能卷轴), 2 }, + { nameof(智慧之果), 1 } } }, { 4, new() { { "角色等级", 24 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 10000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 60 }, + { General.GameplayEquilibriumConstant.InGameCurrency, 20000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 150 }, { nameof(技能卷轴), 4 }, - { nameof(智慧之果), 1 }, + { nameof(智慧之果), 2 }, + { nameof(奥术符文), 1 } } }, { 5, new() { { "角色等级", 32 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 18000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 100 }, - { nameof(技能卷轴), 6 }, - { nameof(智慧之果), 2 }, + { General.GameplayEquilibriumConstant.InGameCurrency, 40000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 250 }, + { nameof(技能卷轴), 8 }, + { nameof(智慧之果), 4 }, + { nameof(奥术符文), 3 }, + { nameof(混沌之核), 1 } } }, { @@ -197,34 +218,39 @@ namespace Oshima.FunGame.OshimaServers.Service { { "角色等级", 40 }, { "角色突破进度", 4 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 30000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 150 }, - { nameof(技能卷轴), 9 }, - { nameof(智慧之果), 4 }, - { nameof(奥术符文), 1 } + { General.GameplayEquilibriumConstant.InGameCurrency, 70000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 400 }, + { nameof(技能卷轴), 16 }, + { nameof(智慧之果), 8 }, + { nameof(奥术符文), 6 }, + { nameof(混沌之核), 4 }, + { nameof(法则精粹), 1 } } }, { 7, new() { { "角色等级", 48 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 47000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 210 }, - { nameof(技能卷轴), 12 }, - { nameof(智慧之果), 6 }, - { nameof(奥术符文), 2 } + { General.GameplayEquilibriumConstant.InGameCurrency, 110000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 600 }, + { nameof(技能卷轴), 32 }, + { nameof(智慧之果), 16 }, + { nameof(奥术符文), 12 }, + { nameof(混沌之核), 8 }, + { nameof(法则精粹), 5 } } }, { 8, new() { { "角色等级", 56 }, - { General.GameplayEquilibriumConstant.InGameCurrency, 70000 }, - { General.GameplayEquilibriumConstant.InGameMaterial, 280 }, - { nameof(技能卷轴), 16 }, - { nameof(智慧之果), 9 }, - { nameof(奥术符文), 4 }, - { nameof(混沌之核), 1 } + { General.GameplayEquilibriumConstant.InGameCurrency, 160000 }, + { General.GameplayEquilibriumConstant.InGameMaterial, 850 }, + { nameof(技能卷轴), 64 }, + { nameof(智慧之果), 32 }, + { nameof(奥术符文), 24 }, + { nameof(混沌之核), 16 }, + { nameof(法则精粹), 10 } } } }; @@ -313,7 +339,7 @@ namespace Oshima.FunGame.OshimaServers.Service if (_precomputeTotalExperience.Count == 0) { double sum = 0; - _precomputeTotalExperience[0] = 0; + _precomputeTotalExperience[1] = 0; for (int i = 2; i <= General.GameplayEquilibriumConstant.MaxLevel; i++) { sum += General.GameplayEquilibriumConstant.EXPUpperLimit[i - 1]; @@ -390,12 +416,12 @@ namespace Oshima.FunGame.OshimaServers.Service public static Dictionary PriceRanges { get; } = new() { { QualityType.White, (200, 800) }, - { QualityType.Green, (800, 3500) }, - { QualityType.Blue, (3500, 8800) }, - { QualityType.Purple, (8800, 15600) }, - { QualityType.Orange, (15600, 32200) }, - { QualityType.Red, (32200, 67000) }, - { QualityType.Gold, (67000, 130000) } + { QualityType.Green, (800, 4200) }, + { QualityType.Blue, (4200, 11000) }, + { QualityType.Purple, (11000, 32200) }, + { QualityType.Orange, (32200, 67000) }, + { QualityType.Red, (67000, 130000) }, + { QualityType.Gold, (130000, 240000) } }; public static string[] GreekAlphabet { get; } = ["α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "σ", "τ", "υ", "φ", "χ", "ψ", "ω"]; diff --git a/OshimaServers/Service/FunGameOrderList.cs b/OshimaServers/Service/FunGameOrderList.cs index a93ba21..fa689dc 100644 --- a/OshimaServers/Service/FunGameOrderList.cs +++ b/OshimaServers/Service/FunGameOrderList.cs @@ -35,6 +35,7 @@ {"小队状态", "查看小队所有角色状态"}, {"清空小队", "清空所有小队成员"}, {"生命之泉", "使用金币回复角色状态"}, + {"酒馆", "使用材料使角色获得满能量"}, }; public static Dictionary ItemHelp { get; } = new() { @@ -67,6 +68,7 @@ {"练级结算", "收取练级奖励,并且回血和复活"}, {"练级信息", "查看练级进度"}, {"生命之泉", "使用金币回复角色状态"}, + {"酒馆", "使用材料使角色获得满能量"}, }; public static Dictionary PlayHelp { get; } = new() { @@ -125,8 +127,11 @@ public static Dictionary StoreHelp { get; } = new() { {"每日商店", "查看每日商店商品"}, - {"商店查看 <商品序号>", "查看指定商品详情"}, - {"商店购买 <商品序号>", "购买指定商品"}, + {"商店1", "查看后勤部商品"}, + {"商店2", "查看武器商会商品"}, + {"商店3", "查看杂货铺商品"}, + {"商店查看 <商品序号>", "查看指定商品详情,访问任意商店后2分钟内可用"}, + {"商店购买 <商品序号>", "购买指定商品,访问任意商店后2分钟内可用"}, {"商店出售 <物品序号>", "向商店出售具有回收价的指定物品"}, {"市场上架 <物品序号> <定价>", "将物品寄售到市场上,手续费15%"}, {"市场下架 <市场物品序号>", "下架指定物品"}, diff --git a/OshimaServers/Service/FunGameService.cs b/OshimaServers/Service/FunGameService.cs index c082040..a4c792c 100644 --- a/OshimaServers/Service/FunGameService.cs +++ b/OshimaServers/Service/FunGameService.cs @@ -1,4 +1,3 @@ -using System.Reflection; using System.Text; using Milimoe.FunGame.Core.Api.Transmittal; using Milimoe.FunGame.Core.Api.Utility; @@ -64,7 +63,7 @@ namespace Oshima.FunGame.OshimaServers.Service FunGameConstant.Items.AddRange(exItems.Values.Where(i => (int)i.ItemType > 4)); FunGameConstant.Items.AddRange([new 小经验书(), new 中经验书(), new 大经验书(), new 升华之印(), new 流光之印(), new 永恒之印(), new 技能卷轴(), new 智慧之果(), new 奥术符文(), new 混沌之核(), new 小回复药(), new 中回复药(), new 大回复药(), new 魔力填充剂1(), new 魔力填充剂2(), new 魔力填充剂3(), new 能量饮料1(), new 能量饮料2(), new 能量饮料3(), new 年夜饭(), new 蛇年大吉(), new 新春快乐(), new 毕业礼包(), - new 复苏药1(), new 复苏药2(), new 复苏药3(), new 全回复药(), new 魔法卡礼包(), new 奖券(), new 十连奖券(), new 改名卡() + new 复苏药1(), new 复苏药2(), new 复苏药3(), new 全回复药(), new 魔法卡礼包(), new 奖券(), new 十连奖券(), new 改名卡(), new 原初之印(), new 创生之印(), new 法则精粹() ]); FunGameConstant.AllItems.AddRange(FunGameConstant.Equipment); @@ -77,8 +76,8 @@ namespace Oshima.FunGame.OshimaServers.Service } FunGameConstant.DrawCardItems.AddRange(FunGameConstant.AllItems.Where(i => !FunGameConstant.ItemCanNotDrawCard.Contains(i.ItemType))); - FunGameConstant.CharacterLevelBreakItems.AddRange([new 升华之印(), new 流光之印(), new 永恒之印()]); - FunGameConstant.SkillLevelUpItems.AddRange([new 技能卷轴(), new 智慧之果(), new 奥术符文(), new 混沌之核()]); + FunGameConstant.CharacterLevelBreakItems.AddRange([new 升华之印(), new 流光之印(), new 永恒之印(), new 原初之印(), new 创生之印()]); + FunGameConstant.SkillLevelUpItems.AddRange([new 技能卷轴(), new 智慧之果(), new 奥术符文(), new 混沌之核(), new 法则精粹()]); FunGameConstant.AllItems.AddRange(FunGameConstant.ExploreItems.Values.SelectMany(list => list)); @@ -704,9 +703,9 @@ namespace Oshima.FunGame.OshimaServers.Service msgs.Add(GetDrawCardResult(reduce, reduceUnit, user, is10, count)); } } - if (msgs.Count <= 1) + if (msgs.Count == 0) { - msgs[0] = $"消耗 {reduce} {reduceUnit},你什么也没抽中……"; + msgs.Add($"消耗 {reduce} {reduceUnit},你什么也没抽中……"); } else { @@ -1282,10 +1281,7 @@ namespace Oshima.FunGame.OshimaServers.Service for (int i = 0; i < cardBox.Count; i++) { Item newItem = GenerateMagicCard(item.QualityType); - if (newItem.QualityType >= QualityType.Orange) newItem.IsLock = true; - SetSellAndTradeTime(newItem); - newItem.User = user; - user.Inventory.Items.Add(newItem); + AddItemToUserInventory(user, newItem, false); cards.Add($"[{ItemSet.GetQualityTypeName(item.QualityType)}|魔法卡] {newItem.Name}\r\n{newItem.ToStringInventory(false)}"); } msg = "打开礼包成功!获得了以下物品:\r\n" + string.Join("\r\n", cards); @@ -1313,11 +1309,7 @@ namespace Oshima.FunGame.OshimaServers.Service { for (int i = 0; i < box.Gifts[name]; i++) { - Item newItem = currentItem.Copy(); - if (newItem.QualityType >= QualityType.Orange) newItem.IsLock = true; - SetSellAndTradeTime(newItem); - newItem.User = user; - user.Inventory.Items.Add(newItem); + AddItemToUserInventory(user, currentItem, toExploreCache: false, toActivitiesCache: false); } } } @@ -1355,10 +1347,29 @@ namespace Oshima.FunGame.OshimaServers.Service return false; } - public static string GetLevelBreakNeedy(int levelBreak) + public static string GetLevelBreakNeedy(int levelBreak, User user) { if (FunGameConstant.LevelBreakNeedyList.TryGetValue(levelBreak, out Dictionary? needy) && needy != null && needy.Count > 0) { + List strings = []; + foreach (string key in needy.Keys) + { + int value = needy[key]; + int count = 0; + if (key == General.GameplayEquilibriumConstant.InGameCurrency) + { + count = (int)user.Inventory.Credits; + } + else if (key == General.GameplayEquilibriumConstant.InGameMaterial) + { + count = (int)user.Inventory.Materials; + } + else + { + count = user.Inventory.Items.Count(i => i.Name == key); + } + strings.Add($"{key} * {value}({count} / {value})"); + } return string.Join(",", needy.Select(kv => kv.Key + " * " + kv.Value)); } return ""; @@ -1458,25 +1469,25 @@ namespace Oshima.FunGame.OshimaServers.Service $"{(isPre ? "练级时间上限 2880 分钟(48小时),超时将不会再产生收益,请按时领取奖励!" : "")}"; } - public static string GetSkillLevelUpNeedy(int level) + public static string GetSkillLevelUpNeedy(int level, User user, Character character) { if (FunGameConstant.SkillLevelUpList.TryGetValue(level, out Dictionary? needy) && needy != null && needy.Count > 0) { - return GetNeedyInfo(needy); + return GetNeedyInfo(needy, user, character); } return ""; } - public static string GetNormalAttackLevelUpNeedy(int level) + public static string GetNormalAttackLevelUpNeedy(int level, User user, Character character) { if (FunGameConstant.NormalAttackLevelUpList.TryGetValue(level, out Dictionary? needy) && needy != null && needy.Count > 0) { - return GetNeedyInfo(needy); + return GetNeedyInfo(needy, user, character); } return ""; } - public static string GetNeedyInfo(Dictionary needy) + public static string GetNeedyInfo(Dictionary needy, User user, Character character) { string str = ""; foreach (string key in needy.Keys) @@ -1488,15 +1499,24 @@ namespace Oshima.FunGame.OshimaServers.Service } if (key == "角色等级") { - str += $"角色等级 {needCount} 级"; + str += $"角色等级 {needCount} 级({character.Level} / {needCount})"; } else if (key == "角色突破进度") { - str += $"角色突破进度 {needCount} 等阶"; + str += $"角色突破进度 {needCount} 等阶({character.LevelBreak + 1} / {needCount})"; + } + else if (key == General.GameplayEquilibriumConstant.InGameCurrency) + { + str += $"{key} * {needCount}({(int)user.Inventory.Credits} / {needCount})"; + } + else if (key == General.GameplayEquilibriumConstant.InGameMaterial) + { + str += $"{key} * {needCount}({(int)user.Inventory.Materials} / {needCount})"; } else { - str += $"{key} * {needCount}"; + int count = user.Inventory.Items.Count(i => i.Name == key); + str += $"{key} * {needCount}({count} / {needCount})"; } } return str; @@ -1708,7 +1728,7 @@ namespace Oshima.FunGame.OshimaServers.Service } // 伤害贡献 - double logDamageContribution = Math.Log(1 + (stats.TotalDamage / (stats.TotalTakenDamage + 1.75))); + double damageContribution = Math.Log(1 + stats.DamagePerSecond / 40); if (team != null && teammateStats != null) { // 考虑团队伤害排名,优先高伤害的 @@ -1717,12 +1737,12 @@ namespace Oshima.FunGame.OshimaServers.Service { double d = 1 - (0.1 * (damageRank - 1)); if (d < 0.1) d = 0.1; - logDamageContribution *= d; + damageContribution *= d; } } // 存活时间贡献 - double liveTimeContribution = Math.Log(1 + (stats.LiveTime / (stats.TotalTakenDamage + 0.01) * 100)); + double liveTimeContribution = Math.Log(1 + stats.LiveTime / ((stats.TotalTakenDamage == 0 ? stats.TotalTakenDamage : 500) + stats.Deaths + 1) * 60); // 团队模式参团率加成 double teamContribution = 0; @@ -1737,12 +1757,12 @@ namespace Oshima.FunGame.OshimaServers.Service } // 权重设置 - double k = stats.Deaths > 0 ? 0.2 : 0.075; // 伤害贡献权重 + double k = stats.Deaths > 0 ? 0.2 : 0.06; // 伤害贡献权重 double l = stats.Deaths > 0 ? 0.2 : 0.05; // 存活时间权重 double t = stats.Deaths > 0 ? 0.2 : 0.075; // 参团率权重 // 计算最终评分 - double rating = baseScore + k * logDamageContribution + l * liveTimeContribution + t * teamContribution; + double rating = baseScore + k * damageContribution + l * liveTimeContribution + t * teamContribution; // 确保评分在合理范围内 return Math.Max(0.01, rating); @@ -1988,12 +2008,12 @@ namespace Oshima.FunGame.OshimaServers.Service } } - public static string CheckDailyStore(EntityModuleConfig store, User? user = null) + public static string CheckDailyStore(EntityModuleConfig stores, User user) { - if (store.Count == 0) + if (stores.Count == 0) { // 生成每日商店 - Store daily = new($"{(user != null ? user.Username + "的" : "")}每日商店"); + Store daily = new($"{user.Username}的每日商店"); for (int i = 0; i < 4; i++) { Item item; @@ -2035,14 +2055,16 @@ namespace Oshima.FunGame.OshimaServers.Service item.Price = (int)price; daily.AddItem(item, stock); } - store.Add("daily", daily); - return daily.ToString() + "\r\n温馨提示:使用【商店查看+序号】查看物品详细信息,使用【商店购买+序号】购买物品!每天 4:00 刷新每日商店。"; + stores.Add("daily", daily); + SetLastStore(user, true, "", ""); + return daily.ToString(); } else { - if (store.Count > 0 && store.Where(kv => kv.Key == "daily").Select(kv => kv.Value).FirstOrDefault() is Store daily) + if (stores.Count > 0 && stores.Where(kv => kv.Key == "daily").Select(kv => kv.Value).FirstOrDefault() is Store daily) { - return daily.ToString() + "\r\n温馨提示:使用【商店查看+序号】查看物品详细信息,使用【商店购买+序号】购买物品!每天 4:00 刷新每日商店。"; + SetLastStore(user, true, "", ""); + return daily.ToString(); } else { @@ -2051,10 +2073,38 @@ namespace Oshima.FunGame.OshimaServers.Service } } - public static string StoreBuyItem(Store store, Goods goods, User user, int count) + public static void SetLastStore(User? user, bool isDaily, string storeRegion, string storeName) + { + if (user != null && FunGameConstant.UserLastVisitStore.TryGetValue(user.Id, out LastStoreModel? value) && value != null) + { + value.LastTime = DateTime.Now; + value.IsDaily = isDaily; + value.StoreRegion = storeRegion; + value.StoreName = storeName; + } + else if (user != null) + { + FunGameConstant.UserLastVisitStore[user.Id] = new() + { + LastTime = DateTime.Now, + IsDaily = isDaily, + StoreRegion = storeRegion, + StoreName = storeName + }; + } + } + + public static string StoreBuyItem(Store store, Goods goods, PluginConfig pc, User user, int count) { string msg = ""; - if (goods.Stock - count < 0) + + DateTime now = DateTime.Now; + if (store.StartTime > now || store.EndTime < now) + { + return "商店未处于营业时间内。"; + } + + if (goods.Stock != -1 && goods.Stock - count < 0) { return msg = $"此商品【{goods.Name}】库存不足,无法购买!\r\n你想要购买 {count} 件,但库存只有 {goods.Stock} 件。"; } @@ -2089,29 +2139,38 @@ namespace Oshima.FunGame.OshimaServers.Service foreach (Item item in goods.Items) { - for (int i = 0; i < count; i++) + if (item is 探索许可) { - Item newItem = item.Copy(true); - if (newItem.QualityType >= QualityType.Orange) newItem.IsLock = true; - SetSellAndTradeTime(newItem); - if (goods.GetPrice(General.GameplayEquilibriumConstant.InGameCurrency, out double price) && price > 0) + int exploreTimes = FunGameConstant.MaxExploreTimes + count; + if (pc.TryGetValue("exploreTimes", out object? value) && int.TryParse(value.ToString(), out exploreTimes)) { - newItem.Price = Calculation.Round2Digits(price * 0.35); + exploreTimes += count; + } + pc.Add("exploreTimes", exploreTimes); + } + else + { + for (int i = 0; i < count; i++) + { + if (goods.GetPrice(General.GameplayEquilibriumConstant.InGameCurrency, out double price)) + { + price = Calculation.Round2Digits(price * 0.35); + } + AddItemToUserInventory(user, item, copyLevel: true, price: price); } - newItem.User = user; - user.Inventory.Items.Add(newItem); - // 连接到任务系统 - AddExploreItemCache(user.Id, item.Name); - // 连接到活动系统 - ActivitiesItemCache.Add(item.Name); } } - goods.Stock -= count; + if (goods.Stock != -1) + { + goods.Stock -= count; + if (goods.Stock < 0) goods.Stock = 0; + } msg += $"恭喜你成功购买 {count} 件【{goods.Name}】!\r\n" + $"总计消费:{(goods.Prices.Count > 0 ? string.Join("、", goods.Prices.Select(kv => $"{kv.Value * count:0.##} {kv.Key}")) : "免单")}\r\n" + - $"包含物品:{string.Join("、", goods.Items.Select(i => $"[{ItemSet.GetQualityTypeName(i.QualityType)}|{ItemSet.GetItemTypeName(i.ItemType)}] {i.Name} * {count}"))}"; + $"包含物品:{string.Join("、", goods.Items.Select(i => $"[{ItemSet.GetQualityTypeName(i.QualityType)}|{ItemSet.GetItemTypeName(i.ItemType)}] {i.Name} * {count}"))}\r\n" + + $"{store.Name}期待你的下次光临。"; return msg; } @@ -3329,9 +3388,10 @@ namespace Oshima.FunGame.OshimaServers.Service return "服务器繁忙,请稍后再试。"; } - public static void AddItemToUserInventory(User user, Item item, bool hasLock = true, bool hasSellAndTradeTime = true, bool hasPrice = true, double price = 0, bool toExploreCache = true, bool toActivitiesCache = true) + public static void AddItemToUserInventory(User user, Item item, bool copyNew = true, bool copyLevel = false, bool hasLock = true, bool hasSellAndTradeTime = true, bool hasPrice = true, bool useOriginalPrice = false, double price = 0, bool toExploreCache = true, bool toActivitiesCache = true) { - Item newItem = item.Copy(); + Item newItem = item; + if (copyNew) newItem = item.Copy(copyLevel); newItem.User = user; if (hasLock && newItem.QualityType >= QualityType.Orange) newItem.IsLock = true; if (hasSellAndTradeTime) SetSellAndTradeTime(newItem); @@ -3339,12 +3399,19 @@ namespace Oshima.FunGame.OshimaServers.Service { if (price == 0) { - int min = 0, max = 0; - if (FunGameConstant.PriceRanges.TryGetValue(item.QualityType, out (int Min, int Max) range)) + if (useOriginalPrice) { - (min, max) = (range.Min, range.Max); + price = item.Price * 0.35; + } + else + { + int min = 0, max = 0; + if (FunGameConstant.PriceRanges.TryGetValue(item.QualityType, out (int Min, int Max) range)) + { + (min, max) = (range.Min, range.Max); + } + price = Random.Shared.Next(min, max) * 0.35; } - price = Random.Shared.Next(min, max) * 0.35; } newItem.Price = price; } @@ -3385,6 +3452,81 @@ namespace Oshima.FunGame.OshimaServers.Service } } + // 定义奖励 + Dictionary pCharacterLevelBreak = []; + Dictionary pSkillLevelUp = []; + Dictionary pRegionItem = []; + Dictionary rW = new() + { + { (int)RarityType.OneStar, 60 }, + { (int)RarityType.TwoStar, 30 }, + { (int)RarityType.ThreeStar, 10 }, + { (int)RarityType.FourStar, 0 }, + { (int)RarityType.FiveStar, 0 } + }; + switch (difficulty) + { + case 5: + rW[4] = 30; + rW[3] = 30; + rW[2] = 15; + rW[1] = 15; + rW[0] = 10; + break; + case 4: + rW[4] = 10; + rW[3] = 30; + rW[2] = 30; + rW[1] = 15; + rW[0] = 10; + break; + case 3: + rW[4] = 0; + rW[3] = 15; + rW[2] = 30; + rW[1] = 30; + rW[0] = 25; + break; + case 2: + rW[4] = 0; + rW[3] = 5; + rW[2] = 25; + rW[1] = 25; + rW[0] = 45; + break; + case 1: + default: + break; + } + double totalWeight; + totalWeight = FunGameConstant.CharacterLevelBreakItems.Sum(i => rW[(int)i.QualityType]); + foreach (Item item in FunGameConstant.CharacterLevelBreakItems) + { + if (rW.TryGetValue((int)item.QualityType, out double weight)) + { + pCharacterLevelBreak[item] = weight / totalWeight; + } + } + totalWeight = FunGameConstant.SkillLevelUpItems.Sum(i => rW[(int)i.QualityType]); + foreach (Item item in FunGameConstant.SkillLevelUpItems) + { + if (rW.TryGetValue((int)item.QualityType, out double weight)) + { + pSkillLevelUp[item] = weight / totalWeight; + } + } + totalWeight = FunGameConstant.Regions.Sum(r => rW[(int)r.Difficulty]); + foreach (OshimaRegion region in FunGameConstant.Regions) + { + if (rW.TryGetValue((int)region.Difficulty, out double weight)) + { + foreach (Item item in region.Crops) + { + pRegionItem[item] = weight / totalWeight; + } + } + } + Item[] weapons = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("11") && (int)i.QualityType == 5)]; Item[] armors = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("12") && (int)i.QualityType == 5)]; Item[] shoes = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("13") && (int)i.QualityType == 5)]; @@ -3424,7 +3566,7 @@ namespace Oshima.FunGame.OshimaServers.Service builder.AppendLine(string.Join("\r\n", msgs)); if (enemys.All(c => c.HP <= 0)) { - builder.Append($"探索小队战胜了敌人!获得了:"); + builder.Append($"小队战胜了敌人!获得了:"); switch (type) { case InstanceType.Currency: @@ -3524,11 +3666,29 @@ namespace Oshima.FunGame.OshimaServers.Service List regionItems = []; for (int i = 0; i < characterCount; i++) { - OshimaRegion region = FunGameConstant.Regions[Random.Shared.Next(FunGameConstant.Regions.Count)]; - Item item = FunGameConstant.ExploreItems[region][Random.Shared.Next(FunGameConstant.ExploreItems[region].Count)]; - award = Math.Max(2, Random.Shared.Next(2, 5) * difficulty / 2); - regionItems.Add($"{award} 个 {item.Name}(来自{region.Name})"); - AddItemToUserInventory(user, item); + double roll = Random.Shared.NextDouble(); + double cumulativeProbability = 0.0; + Item? item = null; + OshimaRegion? region = null; + foreach (Item loop in pRegionItem.Keys) + { + cumulativeProbability += pRegionItem[loop]; + // 如果随机数落在当前物品的累积概率范围内,则选中该物品 + if (roll < cumulativeProbability) + { + item = loop; + region = FunGameConstant.Regions.FirstOrDefault(r => r.Crops.Any(i => i.Id == item.Id)); + break; + } + } + region ??= FunGameConstant.Regions[Random.Shared.Next(FunGameConstant.Regions.Count)]; + item ??= region.Crops.ToList()[Random.Shared.Next(region.Crops.Count)]; + award = Math.Max(1, Random.Shared.Next(1, 4) * difficulty / 2); + regionItems.Add($"{award} 个{item.Name}(来自{region.Name})"); + for (int j = 0; j < award; j++) + { + AddItemToUserInventory(user, item); + } } builder.AppendLine($"{string.Join("、", regionItems)}!"); break; @@ -3536,10 +3696,26 @@ namespace Oshima.FunGame.OshimaServers.Service List characterLevelBreakItems = []; for (int i = 0; i < characterCount; i++) { - Item item = FunGameConstant.CharacterLevelBreakItems[Random.Shared.Next(FunGameConstant.CharacterLevelBreakItems.Count)]; - award = Math.Max(1, Random.Shared.Next(1, 4) * difficulty / 2); - characterLevelBreakItems.Add($"{award} 个 {item.Name}"); - AddItemToUserInventory(user, item); + double roll = Random.Shared.NextDouble(); + double cumulativeProbability = 0.0; + Item? item = null; + foreach (Item loop in pCharacterLevelBreak.Keys) + { + cumulativeProbability += pCharacterLevelBreak[loop]; + // 如果随机数落在当前物品的累积概率范围内,则选中该物品 + if (roll < cumulativeProbability) + { + item = loop; + break; + } + } + item ??= FunGameConstant.CharacterLevelBreakItems[Random.Shared.Next(FunGameConstant.CharacterLevelBreakItems.Count)]; + award = Math.Max(1, Random.Shared.Next(1, 4) * difficulty / Math.Max(2, (int)item.QualityType + 1)); + characterLevelBreakItems.Add($"{award} 个{item.Name}"); + for (int j = 0; j < award; j++) + { + AddItemToUserInventory(user, item); + } } builder.AppendLine($"{string.Join("、", characterLevelBreakItems)}!"); break; @@ -3547,10 +3723,26 @@ namespace Oshima.FunGame.OshimaServers.Service List skillLevelUpItems = []; for (int i = 0; i < characterCount; i++) { - Item item = FunGameConstant.SkillLevelUpItems[Random.Shared.Next(FunGameConstant.SkillLevelUpItems.Count)]; - award = Math.Max(1, Random.Shared.Next(1, 4) * difficulty / 2); - skillLevelUpItems.Add($"{award} 个 {item.Name}"); - AddItemToUserInventory(user, item); + double roll = Random.Shared.NextDouble(); + double cumulativeProbability = 0.0; + Item? item = null; + foreach (Item loop in pSkillLevelUp.Keys) + { + cumulativeProbability += pSkillLevelUp[loop]; + // 如果随机数落在当前物品的累积概率范围内,则选中该物品 + if (roll < cumulativeProbability) + { + item = loop; + break; + } + } + item ??= FunGameConstant.SkillLevelUpItems[Random.Shared.Next(FunGameConstant.SkillLevelUpItems.Count)]; + award = Math.Max(1, Random.Shared.Next(1, 4) * difficulty / Math.Max(2, (int)item.QualityType + 1)); + skillLevelUpItems.Add($"{award} 个{item.Name}"); + for (int j = 0; j < award; j++) + { + AddItemToUserInventory(user, item); + } } builder.AppendLine($"{string.Join("、", skillLevelUpItems)}!"); break; @@ -3662,14 +3854,86 @@ namespace Oshima.FunGame.OshimaServers.Service List regionItems = []; for (int i = 0; i < count; i++) { - OshimaRegion region = FunGameConstant.Regions[Random.Shared.Next(FunGameConstant.Regions.Count)]; - Item item = FunGameConstant.ExploreItems[region][Random.Shared.Next(FunGameConstant.ExploreItems[region].Count)]; + double roll = Random.Shared.NextDouble(); + double cumulativeProbability = 0.0; + Item? item = null; + OshimaRegion? region = null; + foreach (Item loop in pRegionItem.Keys) + { + cumulativeProbability += pRegionItem[loop]; + // 如果随机数落在当前物品的累积概率范围内,则选中该物品 + if (roll < cumulativeProbability) + { + item = loop; + region = FunGameConstant.Regions.FirstOrDefault(r => r.Crops.Any(i => i.Id == item.Id)); + break; + } + } + region ??= FunGameConstant.Regions[Random.Shared.Next(FunGameConstant.Regions.Count)]; + item ??= region.Crops.ToList()[Random.Shared.Next(region.Crops.Count)]; award = 1; - regionItems.Add($"{award} 个 {item.Name}(来自{region.Name})"); - AddItemToUserInventory(user, item); + regionItems.Add($"{award} 个{item.Name}(来自{region.Name})"); + for (int j = 0; j < award; j++) + { + AddItemToUserInventory(user, item); + } } builder.AppendLine($"{string.Join("、", regionItems)}!"); break; + case InstanceType.CharacterLevelBreak: + List characterLevelBreakItems = []; + for (int i = 0; i < count; i++) + { + double roll = Random.Shared.NextDouble(); + double cumulativeProbability = 0.0; + Item? item = null; + foreach (Item loop in pCharacterLevelBreak.Keys) + { + cumulativeProbability += pCharacterLevelBreak[loop]; + // 如果随机数落在当前物品的累积概率范围内,则选中该物品 + if (roll < cumulativeProbability) + { + item = loop; + break; + } + } + item ??= FunGameConstant.CharacterLevelBreakItems[Random.Shared.Next(FunGameConstant.CharacterLevelBreakItems.Count)]; + award = 1; + characterLevelBreakItems.Add($"{award} 个{item.Name}"); + for (int j = 0; j < award; j++) + { + AddItemToUserInventory(user, item); + } + } + builder.AppendLine($"{string.Join("、", characterLevelBreakItems)}!"); + break; + case InstanceType.SkillLevelUp: + List skillLevelUpItems = []; + for (int i = 0; i < count; i++) + { + double roll = Random.Shared.NextDouble(); + double cumulativeProbability = 0.0; + Item? item = null; + foreach (Item loop in pSkillLevelUp.Keys) + { + cumulativeProbability += pSkillLevelUp[loop]; + // 如果随机数落在当前物品的累积概率范围内,则选中该物品 + if (roll < cumulativeProbability) + { + item = loop; + break; + } + } + item ??= FunGameConstant.SkillLevelUpItems[Random.Shared.Next(FunGameConstant.SkillLevelUpItems.Count)]; + award = 1; + skillLevelUpItems.Add($"{award} 个{item.Name}"); + for (int j = 0; j < award; j++) + { + AddItemToUserInventory(user, item); + } + } + builder.AppendLine($"{string.Join("、", skillLevelUpItems)}!"); + break; default: break; } @@ -3678,5 +3942,29 @@ namespace Oshima.FunGame.OshimaServers.Service return builder.ToString().Trim(); } + + public static string CheckRegionStore(EntityModuleConfig stores, User user, string storeRegion, string storeName, out bool exist) + { + string msg = ""; + exist = false; + + Dictionary regionStores = FunGameConstant.PlayerRegions.ToDictionary(r => r.Name, r => r); + if (regionStores.TryGetValue(storeRegion, out OshimaRegion? value) && value != null) + { + msg = value.VisitStore(stores, user, storeName); + exist = msg != ""; + } + + if (!exist) + { + msg = "探索者协会专员为你跑遍了全大陆,也没有找到这个商店。"; + } + else + { + SetLastStore(user, false, storeRegion, storeName); + } + + return msg; + } } } diff --git a/OshimaWebAPI/Controllers/FunGameController.cs b/OshimaWebAPI/Controllers/FunGameController.cs index 354e8bd..e9cd4fa 100644 --- a/OshimaWebAPI/Controllers/FunGameController.cs +++ b/OshimaWebAPI/Controllers/FunGameController.cs @@ -1813,7 +1813,7 @@ namespace Oshima.FunGame.WebAPI.Controllers user.LastTime = DateTime.Now; pc.Add("user", user); pc.SaveConfig(); - return $"装备{ItemSet.GetQualityTypeName(item.QualityType)}{ItemSet.GetItemTypeName(item.ItemType)}【{item.Name}】成功!" + + return $"角色:{character.ToStringWithLevelWithOutUser()}\r\n装备{ItemSet.GetQualityTypeName(item.QualityType)}{ItemSet.GetItemTypeName(item.ItemType)}【{item.Name}】成功!" + $"({ItemSet.GetEquipSlotTypeName(item.EquipSlotType)}栏位)\r\n物品描述:{item.Description}"; } else @@ -1860,7 +1860,7 @@ namespace Oshima.FunGame.WebAPI.Controllers user.LastTime = DateTime.Now; pc.Add("user", user); pc.SaveConfig(); - return $"取消装备{ItemSet.GetQualityTypeName(item.QualityType)}{ItemSet.GetItemTypeName(item.ItemType)}【{item.Name}】成功!({ItemSet.GetEquipSlotTypeName(type)}栏位)"; + return $"角色:{character.ToStringWithLevelWithOutUser()}\r\n取消装备{ItemSet.GetQualityTypeName(item.QualityType)}{ItemSet.GetItemTypeName(item.ItemType)}【{item.Name}】成功!({ItemSet.GetEquipSlotTypeName(type)}栏位)"; } else return $"取消装备失败!角色并没有装备{ItemSet.GetEquipSlotTypeName(type)},或者库存中不存在此物品!"; } @@ -2636,7 +2636,7 @@ namespace Oshima.FunGame.WebAPI.Controllers } return $"角色 [ {character} ] 目前突破进度:{character.LevelBreak + 1}/{General.GameplayEquilibriumConstant.LevelBreakList.Count}" + - $"\r\n该角色下一个等级突破阶段在 {General.GameplayEquilibriumConstant.LevelBreakList.ToArray()[character.LevelBreak + 1]} 级,所需材料:\r\n" + FunGameService.GetLevelBreakNeedy(character.LevelBreak + 1); + $"\r\n该角色下一个等级突破阶段在 {General.GameplayEquilibriumConstant.LevelBreakList.ToArray()[character.LevelBreak + 1]} 级,所需材料:\r\n" + FunGameService.GetLevelBreakNeedy(character.LevelBreak + 1, user); } else { @@ -2719,7 +2719,7 @@ namespace Oshima.FunGame.WebAPI.Controllers if (originalBreak == character.LevelBreak) { return $"突破失败!角色 [ {character} ] 目前突破进度:{character.LevelBreak + 1}/{General.GameplayEquilibriumConstant.LevelBreakList.Count}。" + - $"\r\n该角色下一个等级突破阶段在 {General.GameplayEquilibriumConstant.LevelBreakList.ToArray()[character.LevelBreak + 1]} 级,所需材料:\r\n" + FunGameService.GetLevelBreakNeedy(character.LevelBreak + 1); + $"\r\n该角色下一个等级突破阶段在 {General.GameplayEquilibriumConstant.LevelBreakList.ToArray()[character.LevelBreak + 1]} 级,所需材料:\r\n" + FunGameService.GetLevelBreakNeedy(character.LevelBreak + 1, user); } else { @@ -2729,7 +2729,7 @@ namespace Oshima.FunGame.WebAPI.Controllers return $"突破成功!角色 [ {character} ] 目前突破进度:{character.LevelBreak + 1}/{General.GameplayEquilibriumConstant.LevelBreakList.Count}。" + $"{(character.LevelBreak + 1 == General.GameplayEquilibriumConstant.LevelBreakList.Count ? "\r\n该角色已完成全部的突破阶段,恭喜!" : - $"\r\n该角色下一个等级突破阶段在 {General.GameplayEquilibriumConstant.LevelBreakList.ToArray()[character.LevelBreak + 1]} 级,所需材料:\r\n" + FunGameService.GetLevelBreakNeedy(character.LevelBreak + 1))}"; + $"\r\n该角色下一个等级突破阶段在 {General.GameplayEquilibriumConstant.LevelBreakList.ToArray()[character.LevelBreak + 1]} 级,所需材料:\r\n" + FunGameService.GetLevelBreakNeedy(character.LevelBreak + 1, user))}"; } } else @@ -3510,7 +3510,7 @@ namespace Oshima.FunGame.WebAPI.Controllers } return $"角色 [ {character} ] 的【{skill.Name}】技能等级:{skill.Level} / {General.GameplayEquilibriumConstant.MaxSkillLevel}" + - $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetSkillLevelUpNeedy(skill.Level + 1); + $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetSkillLevelUpNeedy(skill.Level + 1, user, character); } return $"此技能无法升级!"; } @@ -3639,14 +3639,14 @@ namespace Oshima.FunGame.WebAPI.Controllers } else { - msg += $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetSkillLevelUpNeedy(skill.Level + 1); + msg += $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetSkillLevelUpNeedy(skill.Level + 1, user, character); } return msg; } return $"{isStudy}技能失败!角色 [ {character} ] 的【{skill.Name}】技能当前等级:{skill.Level}/{General.GameplayEquilibriumConstant.MaxSkillLevel}" + - $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetSkillLevelUpNeedy(skill.Level + 1); + $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetSkillLevelUpNeedy(skill.Level + 1, user, character); } return $"此技能无法{isStudy}!"; } @@ -3696,7 +3696,7 @@ namespace Oshima.FunGame.WebAPI.Controllers return $"角色 [ {character} ] 的【{na.Name}】已经升至满级!"; } return $"角色 [ {character} ] 的【{na.Name}】等级:{na.Level} / {General.GameplayEquilibriumConstant.MaxNormalAttackLevel}" + - $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetNormalAttackLevelUpNeedy(na.Level + 1); + $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetNormalAttackLevelUpNeedy(na.Level + 1, user, character); } else { @@ -3812,14 +3812,14 @@ namespace Oshima.FunGame.WebAPI.Controllers } else { - msg += $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetNormalAttackLevelUpNeedy(na.Level + 1); + msg += $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetNormalAttackLevelUpNeedy(na.Level + 1, user, character); } return msg; } return $"升级{na.Name}失败!角色 [ {character} ] 的【{na.Name}】当前等级:{na.Level}/{General.GameplayEquilibriumConstant.MaxNormalAttackLevel}" + - $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetSkillLevelUpNeedy(na.Level + 1); + $"\r\n下一级所需升级材料:\r\n" + FunGameService.GetSkillLevelUpNeedy(na.Level + 1, user, character); } else { @@ -5317,10 +5317,10 @@ namespace Oshima.FunGame.WebAPI.Controllers return refused + (e.EventMsg != "" ? $"原因:{e.EventMsg}" : ""); } - EntityModuleConfig store = new("stores", userid.ToString()); - store.LoadConfig(); - string msg = FunGameService.CheckDailyStore(store, user); - store.SaveConfig(); + EntityModuleConfig stores = new("stores", userid.ToString()); + stores.LoadConfig(); + string msg = FunGameService.CheckDailyStore(stores, user); + stores.SaveConfig(); user.LastTime = DateTime.Now; pc.Add("user", user); @@ -5355,30 +5355,29 @@ namespace Oshima.FunGame.WebAPI.Controllers { User user = FunGameService.GetUser(pc); - EntityModuleConfig store = new("stores", userid.ToString()); - store.LoadConfig(); + EntityModuleConfig stores = new("stores", userid.ToString()); + stores.LoadConfig(); string msg = ""; - Store? daily = store.Get("daily"); + Store? daily = stores.Get("daily"); if (daily != null) { if (daily.Goods.Values.FirstOrDefault(g => g.Id == goodid) is Goods good) { - msg = FunGameService.StoreBuyItem(daily, good, user, buycount); + msg = FunGameService.StoreBuyItem(daily, good, pc, user, buycount); } else { return $"没有对应编号的商品!"; } - } else { return $"商品列表为空,请使用【每日商店】指令来获取商品列表!"; } - store.Add("daily", daily); - store.SaveConfig(); + stores.Add("daily", daily); + stores.SaveConfig(); user.LastTime = DateTime.Now; pc.Add("user", user); pc.SaveConfig(); @@ -5403,11 +5402,11 @@ namespace Oshima.FunGame.WebAPI.Controllers { User user = FunGameService.GetUser(pc); - EntityModuleConfig store = new("stores", userid.ToString()); - store.LoadConfig(); + EntityModuleConfig stores = new("stores", userid.ToString()); + stores.LoadConfig(); string msg = ""; - Store? daily = store.Get("daily"); + Store? daily = stores.Get("daily"); if (daily != null) { if (daily.Goods.Values.FirstOrDefault(g => g.Id == goodid) is Goods good) @@ -5424,13 +5423,12 @@ namespace Oshima.FunGame.WebAPI.Controllers } msg = good.ToString().Split("包含物品:")[0].Trim(); msg += $"\r\n包含物品:\r\n" + itemMsg + - $"\r\n剩余库存:{good.Stock}"; + $"\r\n剩余库存:{(good.Stock == - 1 ? "不限量提供" : good.Stock)}"; } else { return $"没有对应编号的物品!"; } - } else { @@ -7012,6 +7010,136 @@ namespace Oshima.FunGame.WebAPI.Controllers } } + [HttpPost("showsystemstore")] + public string ShowSystemStore([FromQuery] long? uid = null, [FromQuery] string storeRegion = "", [FromQuery] string storeName = "") + { + long userid = uid ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11)); + + PluginConfig pc = new("saved", userid.ToString()); + pc.LoadConfig(); + + if (pc.Count > 0) + { + User user = FunGameService.GetUser(pc); + + EntityModuleConfig stores = new("stores", userid.ToString()); + stores.LoadConfig(); + string msg = FunGameService.CheckRegionStore(stores, user, storeRegion, storeName, out bool exist); + + user.LastTime = DateTime.Now; + pc.Add("user", user); + pc.SaveConfig(); + + return msg; + } + else + { + return noSaved; + } + } + + [HttpPost("systemstorebuy")] + public string SystemStoreBuy([FromQuery] long? uid = null, [FromQuery] string storeRegion = "", [FromQuery] string storeName = "", [FromQuery] long id = 0, [FromQuery] int count = 0) + { + long userid = uid ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11)); + + PluginConfig pc = new("saved", userid.ToString()); + pc.LoadConfig(); + + if (pc.Count > 0) + { + User user = FunGameService.GetUser(pc); + + EntityModuleConfig stores = new("stores", userid.ToString()); + stores.LoadConfig(); + string msg = ""; + Store? store = stores.Get(storeName); + if (store != null) + { + if (store.Goods.Values.FirstOrDefault(g => g.Id == id) is Goods good) + { + msg = FunGameService.StoreBuyItem(store, good, pc, user, count); + stores.Add(storeName, store); + stores.SaveConfig(); + } + else + { + msg = $"没有对应编号的商品!"; + } + } + else + { + string msg2 = FunGameService.CheckRegionStore(stores, user, storeRegion, storeName, out bool exist); + msg = exist ? $"正在获取最新商店数据,请稍后查看。" : msg2; + } + + user.LastTime = DateTime.Now; + pc.Add("user", user); + pc.SaveConfig(); + + return msg; + } + else + { + return noSaved; + } + } + + [HttpPost("systemstoreshowinfo")] + public string SystemStoreShowInfo([FromQuery] long? uid = null, [FromQuery] string storeRegion = "", [FromQuery] string storeName = "", [FromQuery] long? id = null) + { + long userid = uid ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11)); + long goodid = id ?? 0; + + PluginConfig pc = new("saved", userid.ToString()); + pc.LoadConfig(); + + if (pc.Count > 0) + { + User user = FunGameService.GetUser(pc); + + EntityModuleConfig stores = new("stores", userid.ToString()); + stores.LoadConfig(); + + string msg = ""; + Store? store = stores.Get(storeName); + if (store != null) + { + if (store.Goods.Values.FirstOrDefault(g => g.Id == goodid) is Goods good) + { + int count = 0; + string itemMsg = ""; + foreach (Item item in good.Items) + { + count++; + Item newItem = item.Copy(true); + newItem.Character = user.Inventory.MainCharacter; + if (newItem.ItemType != ItemType.MagicCard) newItem.SetLevel(1); + itemMsg += $"[ {count} ] {newItem.ToString(false, true)}".Trim(); + } + msg = good.ToString().Split("包含物品:")[0].Trim(); + msg += $"\r\n包含物品:\r\n" + itemMsg + + $"\r\n剩余库存:{(good.Stock == -1 ? "不限量提供" : good.Stock)}"; + } + else + { + return $"没有对应编号的物品!"; + } + } + else + { + string msg2 = FunGameService.CheckRegionStore(stores, user, storeRegion, storeName, out bool exist); + msg = exist ? $"正在获取最新商店数据,请稍后查看。" : msg2; + } + + return msg; + } + else + { + return noSaved; + } + } + [HttpPost("template")] public string Template([FromQuery] long? uid = null) { diff --git a/OshimaWebAPI/Services/RainBOTService.cs b/OshimaWebAPI/Services/RainBOTService.cs index 5009b70..9e91d29 100644 --- a/OshimaWebAPI/Services/RainBOTService.cs +++ b/OshimaWebAPI/Services/RainBOTService.cs @@ -8,6 +8,7 @@ using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Library.Constant; using Oshima.Core.Configs; using Oshima.Core.Constant; +using Oshima.FunGame.OshimaServers.Model; using Oshima.FunGame.OshimaServers.Service; using Oshima.FunGame.WebAPI.Constant; using Oshima.FunGame.WebAPI.Controllers; @@ -2141,6 +2142,11 @@ namespace Oshima.FunGame.WebAPI.Services if (e.Detail.StartsWith("商店购买", StringComparison.CurrentCultureIgnoreCase)) { + if (!FunGameConstant.UserLastVisitStore.TryGetValue(uid, out LastStoreModel? model) || model is null || (DateTime.Now - model.LastTime).TotalMinutes > 2) + { + await SendAsync(e, "商店购买", "为防止错误购买,请先打开一个商店,随后在 2 分钟内进行购买操作。"); + return result; + } string detail = e.Detail.Replace("商店购买", "").Trim(); string[] strings = detail.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries); if (strings.Length > 0 && int.TryParse(strings[0].Trim(), out int id)) @@ -2150,7 +2156,15 @@ namespace Oshima.FunGame.WebAPI.Services { count = temp; } - string msg = Controller.DailyStoreBuy(uid, id, count); + string msg = ""; + if (model.IsDaily) + { + msg = Controller.DailyStoreBuy(uid, id, count); + } + else + { + msg = Controller.SystemStoreBuy(uid, model.StoreRegion, model.StoreName, id, count); + } if (msg != "") { await SendAsync(e, "商店购买", msg); @@ -2161,10 +2175,23 @@ namespace Oshima.FunGame.WebAPI.Services if (e.Detail.StartsWith("商店查看", StringComparison.CurrentCultureIgnoreCase)) { + if (!FunGameConstant.UserLastVisitStore.TryGetValue(uid, out LastStoreModel? model) || model is null || (DateTime.Now - model.LastTime).TotalMinutes > 2) + { + await SendAsync(e, "商店购买", "请先打开一个商店,随后在 2 分钟内进行查看操作。"); + return result; + } string detail = e.Detail.Replace("商店查看", "").Trim(); if (int.TryParse(detail, out int id)) { - string msg = Controller.DailyStoreShowInfo(uid, id); + string msg = ""; + if (model.IsDaily) + { + msg = Controller.DailyStoreShowInfo(uid, id); + } + else + { + msg = Controller.SystemStoreShowInfo(uid, model.StoreRegion, model.StoreName, id); + } if (msg != "") { await SendAsync(e, "商店", msg); @@ -2721,6 +2748,34 @@ namespace Oshima.FunGame.WebAPI.Services } return result; } + + if (e.Detail.StartsWith("商店")) + { + string detail = e.Detail.Replace("商店", "").Trim(); + string msg = ""; + if (int.TryParse(detail, out int storeId)) + { + switch (storeId) + { + case 1: + msg = Controller.ShowSystemStore(uid, "铎京城", "dokyo_logistics"); + break; + case 2: + msg = Controller.ShowSystemStore(uid, "铎京城", "dokyo_weapons"); + break; + case 3: + msg = Controller.ShowSystemStore(uid, "铎京城", "dokyo_yuki"); + break; + default: + break; + } + if (msg.Trim() != "") + { + await SendAsync(e, "商店", msg); + } + } + return result; + } if (uid == GeneralSettings.Master && e.Detail.StartsWith("重载FunGame", StringComparison.CurrentCultureIgnoreCase)) {