添加更多实体;活动系统升级

This commit is contained in:
milimoe 2025-12-24 00:41:08 +08:00
parent c3af1fbbde
commit 73deee13cb
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
21 changed files with 763 additions and 121 deletions

View File

@ -0,0 +1,95 @@
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant;
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
using Oshima.FunGame.OshimaModules.Skills;
namespace Oshima.FunGame.OshimaModules.Items
{
public class 1: Item
{
public override long Id => (long)AccessoryID.1;
public override string Name => "回忆糖纸";
public override string Description => Skills.Passives.Count > 0 ? Skills.Passives.First().Description : "";
public override string BackgroundStory => "在魔法视觉下,可见其由无数层半透明糖纸压缩而成,每层糖纸都印着微缩画面。";
public override string Category => "糖糖一周年限定纪念物品";
public override QualityType QualityType => QualityType.Gold;
public 1(Character? character = null) : base(ItemType.Accessory)
{
Price = 0;
IsSellable = false;
IsTradable = false;
IsLock = true;
Skills.Passives.Add(new 1(character, this));
}
}
public class 1 : Skill
{
public override long Id => (long)ItemPassiveID.1;
public override string Name => "回忆糖纸";
public override string Description => string.Join("", Effects.Select(e => e.Description));
public 1(Character? character = null, Item? item = null) : base(SkillType.Passive, character)
{
Level = 1;
Item = item;
Dictionary<string, object> values = new()
{
{ "exls", 0.25 },
{ "shtr", 0.25 }
};
Effects.Add(new ExLifesteal(this, values, character));
Effects.Add(new SkillHardTimeReduce2(this, values, character));
}
public override IEnumerable<Effect> AddPassiveEffectToCharacter()
{
return Effects;
}
}
public class 2: Item
{
public override long Id => (long)AccessoryID.2;
public override string Name => "蜂糖蜜酿";
public override string Description => Skills.Passives.Count > 0 ? Skills.Passives.First().Description : "";
public override string BackgroundStory => "一对以秘银细链连接,随着光线折射散发极微弱糖霜光泽的耳坠。左耳为蜂糖,右耳为蜜酿。";
public override string Category => "糖糖一周年限定纪念物品";
public override QualityType QualityType => QualityType.Gold;
public 2(Character? character = null) : base(ItemType.Accessory)
{
Price = 0;
IsSellable = false;
IsTradable = false;
IsLock = true;
Skills.Passives.Add(new 2(character, this));
}
}
public class 2 : Skill
{
public override long Id => (long)ItemPassiveID.2;
public override string Name => "蜂糖蜜酿";
public override string Description => string.Join("", Effects.Select(e => e.Description));
public 2(Character? character = null, Item? item = null) : base(SkillType.Passive, character)
{
Level = 1;
Item = item;
Dictionary<string, object> values = new()
{
{ "exhp", 1550 },
{ "exmp", 800 }
};
Effects.Add(new ExMaxHP(this, values, character));
Effects.Add(new ExMaxMP(this, values, character));
}
public override IEnumerable<Effect> AddPassiveEffectToCharacter()
{
return Effects;
}
}
}

View File

@ -0,0 +1,55 @@
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant;
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
using Oshima.FunGame.OshimaModules.Skills;
namespace Oshima.FunGame.OshimaModules.Items
{
public class : Item
{
public override long Id => (long)ArmorID.;
public override string Name => "糖之誓约";
public override string Description => $"{Skills.Passives.FirstOrDefault()?.Description}{(Skills.Active != null ? $"{Skills.Active.Name}{Skills.Active.Description}" : "")}";
public override string BackgroundStory => "及膝的米白色复古风衣,在光线下会泛起珍珠母贝般柔和的七彩光泽,如同撒上了一层极细的糖霜。";
public override string Category => "糖糖一周年限定纪念物品";
public override QualityType QualityType => QualityType.Gold;
public (Character? character = null) : base(ItemType.Armor)
{
Price = 0;
IsSellable = false;
IsTradable = false;
IsLock = true;
Skills.Active = new (character)
{
Level = 6
};
Skills.Passives.Add(new (character, this));
}
}
public class : Skill
{
public override long Id => (long)ItemPassiveID.;
public override string Name => "糖之誓约";
public override string Description => string.Join("", Effects.Select(e => e.Description));
private readonly double = 180;
public (Character? character = null, Item? item = null) : base(SkillType.Passive, character)
{
Level = 1;
Item = item;
Dictionary<string, object> values = new()
{
{ "exdef", }
};
Effects.Add(new ExDEF(this, values, character));
}
public override IEnumerable<Effect> AddPassiveEffectToCharacter()
{
return Effects;
}
}
}

View File

@ -228,6 +228,10 @@ namespace Oshima.FunGame.OshimaModules.Items
public (User? user = null, int remainUseTimes = 1) : base(ItemType.GiftBox)
{
Price = 0;
IsSellable = false;
IsTradable = false;
IsLock = true;
User = user;
.Init(this, new()
{
@ -243,15 +247,23 @@ namespace Oshima.FunGame.OshimaModules.Items
public override long Id => (long)GiftBoxID.;
public override string Name => "一周年纪念套装";
public override string Description => Skills.Active?.Description ?? "";
public override QualityType QualityType => QualityType.White;
public override QualityType QualityType => QualityType.Gold;
public Dictionary<string, int> Gifts { get; set; } = [];
public (User? user = null, int remainUseTimes = 1) : base(ItemType.GiftBox)
{
Price = 0;
IsSellable = false;
IsTradable = false;
IsLock = true;
User = user;
.Init(this, new()
{
{ General.GameplayEquilibriumConstant.InGameCurrency, 50000 }
{ new ().Name, 1 },
{ new ().Name, 1 },
{ new ().Name, 1 },
{ new 1().Name, 1 },
{ new 2().Name, 1 }
}, remainUseTimes);
}
}

View File

@ -1,5 +1,21 @@
namespace Oshima.FunGame.OshimaModules.Items
{
public enum WeaponID : long
{
= 11001,
= 11002
}
public enum ArmorID : long
{
= 12001
}
public enum ShoesID : long
{
= 13001
}
public enum AccessoryID : long
{
10 = 14001,
@ -9,6 +25,8 @@
70 = 14005,
85 = 14006,
100 = 14007,
1 = 14008,
2 = 14009
}
public enum ConsumableID : long

View File

@ -0,0 +1,58 @@
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant;
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
using Oshima.FunGame.OshimaModules.Skills;
namespace Oshima.FunGame.OshimaModules.Items
{
public class : Item
{
public override long Id => (long)ShoesID.;
public override string Name => "蜜步流心";
public override string Description => $"{Skills.Passives.FirstOrDefault()?.Description}{(Skills.Active != null ? $"{Skills.Active.Name}{Skills.Active.Description}" : "")}";
public override string BackgroundStory => "一双棕色及踝短靴,靴面有蜂窝状暗纹,靴底内嵌彩色糖豆,每走一步糖豆轻轻碰撞,发出微不可闻的清脆声响。";
public override string Category => "糖糖一周年限定纪念物品";
public override QualityType QualityType => QualityType.Gold;
public (Character? character = null) : base(ItemType.Shoes)
{
Price = 0;
IsSellable = false;
IsTradable = false;
IsLock = true;
Skills.Active = new (character)
{
Level = 5
};
Skills.Passives.Add(new (character, this));
}
}
public class : Skill
{
public override long Id => (long)ItemPassiveID.;
public override string Name => "蜜步流心";
public override string Description => string.Join("", Effects.Select(e => e.Description));
private readonly double = 180;
private readonly double = 0.2;
public (Character? character = null, Item? item = null) : base(SkillType.Passive, character)
{
Level = 1;
Item = item;
Dictionary<string, object> values = new()
{
{ "exspd", },
{ "exacc", }
};
Effects.Add(new ExSPD(this, values, character));
Effects.Add(new AccelerationCoefficient(this, values, character));
}
public override IEnumerable<Effect> AddPassiveEffectToCharacter()
{
return Effects;
}
}
}

View File

@ -7,7 +7,7 @@ namespace Oshima.FunGame.OshimaModules.Items
[Obsolete("测试物品请勿使用")]
public class : Item
{
public override long Id => 11999;
public override long Id => (long)WeaponID.;
public override string Name => "独奏弓";
public override string Description => Skills.Passives.Count > 0 ? Skills.Passives.First().Description : "";
@ -20,9 +20,9 @@ namespace Oshima.FunGame.OshimaModules.Items
public class : Skill
{
public override long Id => 5999;
public override long Id => (long)WeaponID.;
public override string Name => "独奏弓";
public override string Description => $"增加角色 {攻击力加成:0.##} 点攻击力,减少普通攻击 {硬直时间减少:0.##} {GameplayEquilibriumConstant.InGameTime}硬直时间。";
public override string Description => string.Join("\r\n", Effects.Select(e => e.Description));
private readonly double = 80;
private readonly double = 2;

View File

@ -0,0 +1,56 @@
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant;
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
using Oshima.FunGame.OshimaModules.Skills;
namespace Oshima.FunGame.OshimaModules.Items
{
public class : Item
{
public override long Id => (long)WeaponID.;
public override string Name => "粉糖雾蝶";
public override string Description => $"{Skills.Passives.First().Description}{Skills.Passives.Last().Name}{Skills.Passives.Last().Description}";
public override string BackgroundStory => "可长达1.5米的权杖,通体呈半透明的琥珀金色,内部可见如星河般缓缓流动的魔法糖浆。";
public override string Category => "糖糖一周年限定纪念物品";
public override QualityType QualityType => QualityType.Gold;
public (Character? character = null) : base(ItemType.Weapon)
{
Price = 0;
IsSellable = false;
IsTradable = false;
IsLock = true;
WeaponType = WeaponType.Staff;
Skills.Passives.Add(new (character, this));
Skills.Passives.Add(new (character)
{
Level = 1
});
}
}
public class : Skill
{
public override long Id => (long)ItemPassiveID.;
public override string Name => "粉糖雾蝶";
public override string Description => string.Join("", Effects.Select(e => e.Description));
private readonly double = 0.46;
public (Character? character = null, Item? item = null) : base(SkillType.Passive, character)
{
Level = 1;
Item = item;
Dictionary<string, object> values = new()
{
{ "exatk", }
};
Effects.Add(new ExATK2(this, values, character));
}
public override IEnumerable<Effect> AddPassiveEffectToCharacter()
{
return Effects;
}
}
}

View File

@ -35,6 +35,9 @@ namespace Oshima.FunGame.OshimaModules
{
return id switch
{
(long)WeaponID. => new (),
(long)ArmorID. => new (),
(long)ShoesID. => new (),
(long)AccessoryID.10 => new 10(),
(long)AccessoryID.25 => new 25(),
(long)AccessoryID.40 => new 40(),
@ -42,6 +45,8 @@ namespace Oshima.FunGame.OshimaModules
(long)AccessoryID.70 => new 70(),
(long)AccessoryID.85 => new 85(),
(long)AccessoryID.100 => new 100(),
(long)AccessoryID.1 => new 1(),
(long)AccessoryID.2 => new 2(),
(long)ConsumableID. => new (),
(long)ConsumableID. => new (),
(long)ConsumableID. => new (),

View File

@ -130,6 +130,11 @@ namespace Oshima.FunGame.OshimaModules
(long)PassiveID. => new (),
(long)PassiveID. => new (),
(long)ItemPassiveID. => new (),
(long)ItemPassiveID. => new (),
(long)ItemPassiveID. => new (),
(long)ItemPassiveID. => new (),
(long)ItemPassiveID.1 => new 1(),
(long)ItemPassiveID.2 => new 2(),
(long)ItemActiveID. => new (),
(long)ItemActiveID. => new (),
_ => null

View File

@ -25,7 +25,7 @@ namespace Oshima.FunGame.OshimaModules.Skills
{
public override long Id => Skill.Id;
public override string Name => Skill.Name;
public override string Description => $"{Duration} {GameplayEquilibriumConstant.InGameTime}内,攻击拥有标记的角色将不会回收标记,增强 [ 累积之压 ] 的最大生命值伤害 {最大生命值伤害 * 100:0.##}%,并获得 {吸血 * 100:0.##}% 吸血。";
public override string Description => $"{Duration} {GameplayEquilibriumConstant.InGameTime}内,增强 [ 累积之压 ] 的最大生命值伤害 {最大生命值伤害 * 100:0.##}%,并获得 {吸血 * 100:0.##}% 吸血。";
public override bool Durative => true;
public override double Duration => 25;
public override DispelledType DispelledType => DispelledType.CannotBeDispelled;

View File

@ -47,10 +47,6 @@ namespace Oshima.FunGame.OshimaModules.Skills
{
IEnumerable<Effect> effects2 = character.Effects.Where(e => e is );
if (effects2.FirstOrDefault() is e2)
{
// 嗜血本能生效状态下,不会移除标记
}
else
{
// 移除标记
enemy.Effects.Remove(e);

View File

@ -419,6 +419,11 @@ namespace Oshima.FunGame.OshimaModules.Skills
public enum ItemPassiveID : long
{
= 5001,
= 5002,
= 5003,
= 5004,
1 = 5005,
2 = 5006,
}
public enum ItemActiveID : long

View File

@ -27,7 +27,7 @@ namespace Oshima.FunGame.OshimaModules.Skills
public override long Id => Skill.Id;
public override string Name => Skill.Name;
public override string Description => $"造成伤害时,标记目标 25 {GameplayEquilibriumConstant.InGameTime}并叠加 1 层数,当目标身上的电刑标记达到 3 层时,此次伤害提升 {伤害百分比 * 100:0.##}%。";
private double => Skill.Character != null ? 0.4 + Skill.Character.Level * 0.01 : 0;
private double => Skill.Character != null ? 0.3 + Skill.Character.Level * 0.005 : 0;
public override double AlterActualDamageAfterCalculation(Character character, Character enemy, double damage, bool isNormalAttack, DamageType damageType, MagicType magicType, DamageResult damageResult, ref bool isEvaded, Dictionary<Effect, double> totalDamageBonus)
{

View File

@ -116,7 +116,7 @@ namespace Oshima.FunGame.OshimaServers
Controller.WriteLine("已重置所有人的今日运势");
Daily.ClearDaily();
// 刷新活动缓存
FunGameService.GetEventCenter();
FunGameService.GetEventCenter(null);
FunGameService.RefreshNotice();
FunGameService.PreRefreshStore();
});
@ -164,7 +164,7 @@ namespace Oshima.FunGame.OshimaServers
Controller.WriteLine("刷新市场");
});
// 刷新活动缓存
FunGameService.GetEventCenter();
FunGameService.GetEventCenter(null);
FunGameService.RefreshNotice();
});
TaskScheduler.Shared.AddRecurringTask("刷新boss", TimeSpan.FromHours(1), () =>
@ -174,7 +174,7 @@ namespace Oshima.FunGame.OshimaServers
}, true);
TaskScheduler.Shared.AddRecurringTask("刷新活动缓存", TimeSpan.FromHours(4), () =>
{
FunGameService.GetEventCenter();
FunGameService.GetEventCenter(null);
Controller.WriteLine("刷新活动缓存");
}, true);
}

View File

@ -1,9 +1,7 @@
using System.Text;
using System.Xml.Linq;
using Milimoe.FunGame.Core.Api.Transmittal;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Interface.Entity;
using Milimoe.FunGame.Core.Library.Constant;
using Oshima.Core.Constant;
using Oshima.FunGame.OshimaModules.Characters;
@ -64,7 +62,8 @@ namespace Oshima.FunGame.OshimaServers.Service
Dictionary<string, Item> exItems = Factory.GetGameModuleInstances<Item>(OshimaGameModuleConstant.General, OshimaGameModuleConstant.Item);
FunGameConstant.Equipment.AddRange(exItems.Values.Where(i => (int)i.ItemType >= 0 && (int)i.ItemType < 5));
FunGameConstant.Equipment.AddRange([new 10(), new 25(), new 40(), new 55(), new 70(), new 85()]);
FunGameConstant.Equipment.AddRange([new 10(), new 25(), new 40(), new 55(), new 70(), new 85(), new (),
new (), new (), new 1(), new 2()]);
FunGameConstant.Items.AddRange(exItems.Values.Where(i => (int)i.ItemType > 4));
FunGameConstant.Items.AddRange([new (), new (), new (), new (), new (), new (), new (), new (), new (), new (),
@ -77,7 +76,8 @@ namespace Oshima.FunGame.OshimaServers.Service
new (), new (), new (), new (), new (), new (), new (), new 绿(), new (), new (), new (), new (), new (), new (), new (), new (), new (),
new (), new (), new (), new (), new (), new (), new (), new (), new (), new (), new (), new (), new (), new ()]);
FunGameConstant.NotForSaleItems.AddRange([new (), new (), new ()]);
FunGameConstant.NotForSaleItems.AddRange([new (), new (), new (), new (), new (), new (),
new 1(), new 2()]);
FunGameConstant.AllItems.AddRange(FunGameConstant.Equipment);
FunGameConstant.AllItems.AddRange(FunGameConstant.Items);
@ -981,13 +981,19 @@ namespace Oshima.FunGame.OshimaServers.Service
{
if (sell)
{
item.IsSellable = false;
item.NextSellableTime = DateTimeUtility.GetTradableTime(nextSell);
if (item.IsSellable || (!item.IsSellable && item.NextSellableTime != DateTime.MinValue))
{
item.IsSellable = false;
item.NextSellableTime = DateTimeUtility.GetTradableTime(nextSell);
}
}
if (trade)
{
item.IsTradable = false;
item.NextTradableTime = DateTimeUtility.GetTradableTime(nextTrade);
if (item.IsTradable || (!item.IsTradable && item.NextTradableTime != DateTime.MinValue))
{
item.IsTradable = false;
item.NextTradableTime = DateTimeUtility.GetTradableTime(nextTrade);
}
}
}
@ -1988,10 +1994,10 @@ namespace Oshima.FunGame.OshimaServers.Service
}
}
public static bool SettleQuest(User user, EntityModuleConfig<Quest> quests)
public static bool SettleQuest(User user, IEnumerable<Quest> quests, Activity? activity = null)
{
bool result = false;
IEnumerable<Quest> workingQuests = quests.Values.Where(q => q.QuestType == QuestType.Continuous && q.Status == QuestState.InProgress);
IEnumerable<Quest> workingQuests = quests.Where(q => q.QuestType == QuestType.Continuous && q.Status == QuestState.InProgress);
foreach (Quest quest in workingQuests)
{
if (quest.StartTime.HasValue && quest.StartTime.Value.AddMinutes(quest.EstimatedMinutes) <= DateTime.Now)
@ -2008,7 +2014,7 @@ namespace Oshima.FunGame.OshimaServers.Service
foreach (string item in itemsLoop)
{
IEnumerable<string> items = value.Where(str => str == item);
IEnumerable<Quest> progressiveQuests = quests.Values.Where(q => q.QuestType == QuestType.Progressive && q.Status == QuestState.InProgress);
IEnumerable<Quest> progressiveQuests = quests.Where(q => q.QuestType == QuestType.Progressive && q.Status == QuestState.InProgress);
foreach (Quest quest in progressiveQuests)
{
if (quest.NeedyExploreItemName == item)
@ -2026,7 +2032,7 @@ namespace Oshima.FunGame.OshimaServers.Service
}
value.RemoveAll(willRemove.Contains);
}
IEnumerable<Quest> finishQuests = quests.Values.Where(q => q.Status == QuestState.Completed);
IEnumerable<Quest> finishQuests = quests.Where(q => q.Status == QuestState.Completed && !q.Global);
foreach (Quest quest in finishQuests)
{
quest.Status = QuestState.Settled;
@ -2052,8 +2058,10 @@ namespace Oshima.FunGame.OshimaServers.Service
}
}
}
TaskUtility.NewTask(async () => await AnonymousServer.PushMessageToClients(user.AutoKey, $"FunGame Web API 推送:你的任务【{quest.Name}】已结算," +
$"获得奖励:【{quest.AwardsString}】!"));
string notice = $"FunGame Web API 推送:你的任务【{quest.Name}】已结算,获得奖励:【{quest.AwardsString}】!";
TaskUtility.NewTask(async () => await AnonymousServer.PushMessageToClients(user.AutoKey, notice));
AddNotice(user.Id, notice);
activity?.RegisterAwardedUser(user.Id, quest.Id);
result = true;
}
return result;
@ -2432,7 +2440,7 @@ namespace Oshima.FunGame.OshimaServers.Service
await Task.CompletedTask;
}
public static string GetEventCenter()
public static string GetEventCenter(User? user)
{
EntityModuleConfig<Activity> activities = new("activities", "activities");
activities.LoadConfig();
@ -2440,12 +2448,19 @@ namespace Oshima.FunGame.OshimaServers.Service
{
return "当前没有任何活动,敬请期待。";
}
EntityModuleConfig<Activity> userActivities = new("activities", user?.Id.ToString() ?? "");
if (user != null)
{
userActivities.LoadConfig();
}
lock (Activities)
{
Activities.Clear();
foreach (Activity activity in activities.Values)
{
activity.UpdateState();
Activities.Add(activity);
if (user != null) AddEventActivity(user.Id, activity, userActivities);
}
bool update = false;
if (ActivitiesCharacterCache.Count > 0)
@ -2457,6 +2472,8 @@ namespace Oshima.FunGame.OshimaServers.Service
{
IEnumerable<string> items = ActivitiesCharacterCache.Where(str => str == item);
IEnumerable<Quest> quests = activityList.SelectMany(a => a.Quests).Where(q => q.Status == QuestState.InProgress);
IEnumerable<Quest> userQuests = userActivities.Values.Where(a => a.Status == ActivityState.InProgress).SelectMany(a => a.Quests).Where(q => q.Status == QuestState.InProgress);
quests = [.. quests, .. userQuests];
foreach (Quest quest in quests)
{
if (quest.NeedyExploreCharacterName == item)
@ -2483,6 +2500,8 @@ namespace Oshima.FunGame.OshimaServers.Service
{
IEnumerable<string> items = ActivitiesItemCache.Where(str => str == item);
IEnumerable<Quest> quests = activityList.SelectMany(a => a.Quests).Where(q => q.Status == QuestState.InProgress);
IEnumerable<Quest> userQuests = userActivities.Values.Where(a => a.Status == ActivityState.InProgress).SelectMany(a => a.Quests).Where(q => q.Status == QuestState.InProgress);
quests = [.. quests, .. userQuests];
foreach (Quest quest in quests)
{
if (quest.NeedyExploreItemName == item)
@ -2509,6 +2528,8 @@ namespace Oshima.FunGame.OshimaServers.Service
{
IEnumerable<string> items = ActivitiesEventCache.Where(str => str == item);
IEnumerable<Quest> quests = activityList.SelectMany(a => a.Quests).Where(q => q.Status == QuestState.InProgress);
IEnumerable<Quest> userQuests = userActivities.Values.Where(a => a.Status == ActivityState.InProgress).SelectMany(a => a.Quests).Where(q => q.Status == QuestState.InProgress);
quests = [.. quests, .. userQuests];
foreach (Quest quest in quests)
{
if (quest.NeedyExploreEventName == item)
@ -2530,9 +2551,14 @@ namespace Oshima.FunGame.OshimaServers.Service
{
foreach (Activity activity in Activities)
{
if (user != null && (activity.Status == ActivityState.InProgress || activity.Status == ActivityState.Ended))
{
SettleQuest(user, activity.Quests, activity);
}
activities.Add(activity.Id.ToString(), activity);
}
activities.SaveConfig();
userActivities.SaveConfig();
}
}
StringBuilder builder = new();
@ -2554,9 +2580,9 @@ namespace Oshima.FunGame.OshimaServers.Service
return builder.ToString().Trim();
}
public static string GetEvents(ActivityState status = ActivityState.InProgress)
public static string GetEvents(User? user, ActivityState status = ActivityState.InProgress)
{
GetEventCenter();
GetEventCenter(user);
IEnumerable<Activity> filteredActivities = Activities.Where(a => a.Status == status);
if (!filteredActivities.Any())
{
@ -2567,12 +2593,23 @@ namespace Oshima.FunGame.OshimaServers.Service
$"请使用【查活动+活动序号】指令查询活动详细信息。";
}
public static string GetEvent(long id)
public static string GetEvent(User? user, long id)
{
GetEventCenter();
GetEventCenter(user);
if (Activities.FirstOrDefault(a => a.Id == id) is Activity activity)
{
return $"{activity}";
string result = activity.ToString();
if (user != null)
{
EntityModuleConfig<Activity> userActivities = new("activities", user.Id.ToString());
userActivities.LoadConfig();
if (userActivities.Values.FirstOrDefault(a => a.Id == id) is Activity userActivity)
{
if (result != "") result += "\r\n";
result += userActivity.ToString(true, true);
}
}
return result;
}
return "该活动不存在。";
}
@ -4892,6 +4929,47 @@ namespace Oshima.FunGame.OshimaServers.Service
return builder.ToString().Trim();
}
public static void AddEventActivity(long uid, Activity activity, EntityModuleConfig<Activity> userActivities)
{
if (activity.Id == 7 && activity.Status == ActivityState.InProgress)
{
// 为用户生成或更新活动专属任务
Activity newActivity;
if (userActivities.Values.FirstOrDefault(a => a.Id == activity.Id) is Activity userActivity)
{
newActivity = userActivity;
}
else
{
newActivity = new(activity.Id, "糖糖一周年纪念活动", new DateTime(2025, 12, 25, 4, 0, 0), new DateTime(2026, 1, 4, 3, 59, 59))
{
Description = "在活动期间,累计消耗 360 个探索许可即可领取【一周年纪念礼包】,打开后获得金币、钻石奖励以及【一周年纪念套装】(包含武器粉糖雾蝶 * 1防具糖之誓约 * 1鞋子蜜步流心 * 1饰品回忆糖纸 * 1饰品蜂糖蜜酿 * 1自2024年12月进入上线前的测试阶段起糖糖已经陪我们走过了第一个年头放眼未来糖糖将为我们带来更多快乐。"
};
}
if (!newActivity.Quests.Any(q => q.Id == 1))
{
Quest newQuest = new()
{
Id = 1,
Name = "糖糖一周年纪念",
Description = "消耗 360 个探索许可(即参与探索玩法、秘境挑战)。",
NeedyExploreEventName = "消耗探索许可",
CreditsAward = 10000,
Awards = [
new ()
],
AwardsCount = new() {
{ "一周年纪念礼包", 1 }
},
QuestType = QuestType.Progressive,
MaxProgress = 360
};
newActivity.Quests.Add(newQuest);
userActivities.Add(newActivity.Id.ToString(), newActivity);
}
}
}
public static void RefreshNotice()
{
Notices.LoadConfig();
@ -4956,7 +5034,7 @@ namespace Oshima.FunGame.OshimaServers.Service
// 任务结算
EntityModuleConfig<Quest> quests = new("quests", user.Id.ToString());
quests.LoadConfig();
if (quests.Count > 0 && SettleQuest(user, quests))
if (quests.Count > 0 && SettleQuest(user, quests.Values))
{
quests.SaveConfig();
updateQuest = true;
@ -5185,7 +5263,7 @@ namespace Oshima.FunGame.OshimaServers.Service
{
pc.Add("logon", true);
AddNotice(user.Id, "欢迎回到筽祀牻大陆!请发送【帮助】获取更多玩法指令哦~");
AddNotice(user.Id, GetEvents());
AddNotice(user.Id, GetEvents(user));
foreach (NoticeModel notice in Notices.Values)
{
if (now >= notice.StartTime && now <= notice.EndTime)

View File

@ -391,24 +391,24 @@ namespace Oshima.FunGame.OshimaServers.Service
DropItems(actionQueue, mQuality, wQuality, aQuality, sQuality, acQuality);
WriteLine("");
if (isWeb) result.Add("=== 空投 ===\r\n" + Msg);
nextDropTime = isTeam ? 100 : 40;
if (mQuality < 5)
nextDropTime = 40;
if (mQuality <= 5)
{
mQuality++;
}
if (wQuality < 5)
if (wQuality <= 5)
{
wQuality++;
}
if (aQuality < 5)
if (aQuality <= 5)
{
aQuality++;
}
if (sQuality < 5)
if (sQuality <= 5)
{
sQuality++;
}
if (acQuality < 5)
if (acQuality <= 5)
{
acQuality++;
}
@ -439,7 +439,8 @@ namespace Oshima.FunGame.OshimaServers.Service
mvpBuilder.AppendLine($"总计伤害:{stats.TotalDamage:0.##} / 总计物理伤害:{stats.TotalPhysicalDamage:0.##} / 总计魔法伤害:{stats.TotalMagicDamage:0.##}");
mvpBuilder.AppendLine($"总承受伤害:{stats.TotalTakenDamage:0.##} / 总承受物理伤害:{stats.TotalTakenPhysicalDamage:0.##} / 总承受魔法伤害:{stats.TotalTakenMagicDamage:0.##}");
if (stats.TotalTrueDamage > 0 || stats.TotalTakenTrueDamage > 0) mvpBuilder.AppendLine($"总计真实伤害:{stats.TotalTrueDamage:0.##} / 总承受真实伤害:{stats.TotalTakenTrueDamage:0.##}");
mvpBuilder.Append($"每秒伤害:{stats.DamagePerSecond:0.##} / 每回合伤害:{stats.DamagePerTurn:0.##}");
mvpBuilder.AppendLine($"每秒伤害:{stats.DamagePerSecond:0.##} / 每回合伤害:{stats.DamagePerTurn:0.##}");
mvpBuilder.Append($"{mvp.GetInfo()}");
}
int top = isWeb ? actionQueue.CharacterStatistics.Count : 0; // 回执多少个角色的统计信息
@ -1010,10 +1011,10 @@ namespace Oshima.FunGame.OshimaServers.Service
public static void DropItems(GamingQueue queue, int mQuality, int wQuality, int aQuality, int sQuality, int acQuality, bool addLevel = true)
{
Item[] weapons = [.. FunGameConstant.Equipment.Where(i => i.ItemType == ItemType.Weapon && (int)i.QualityType == wQuality)];
Item[] armors = [.. FunGameConstant.Equipment.Where(i => i.ItemType == ItemType.Armor && (int)i.QualityType == aQuality)];
Item[] shoes = [.. FunGameConstant.Equipment.Where(i => i.ItemType == ItemType.Shoes && (int)i.QualityType == sQuality)];
Item[] accessories = [.. FunGameConstant.Equipment.Where(i => i.ItemType == ItemType.Accessory && (int)i.QualityType == acQuality)];
Item[] weapons = [.. FunGameConstant.Equipment.Where(i => i.ItemType == ItemType.Weapon && (wQuality >= 5 && (int)i.QualityType >= 5 || wQuality < 5 && (int)i.QualityType == wQuality))];
Item[] armors = [.. FunGameConstant.Equipment.Where(i => i.ItemType == ItemType.Armor && (aQuality >= 5 && (int)i.QualityType == 5 || aQuality < 5 && (int)i.QualityType == aQuality))];
Item[] shoes = [.. FunGameConstant.Equipment.Where(i => i.ItemType == ItemType.Shoes && (sQuality >= 5 && (int)i.QualityType == 5 || sQuality < 5 && (int)i.QualityType == sQuality))];
Item[] accessories = [.. FunGameConstant.Equipment.Where(i => i.ItemType == ItemType.Accessory && (acQuality >= 5 && (int)i.QualityType == 5 || acQuality < 5 && (int)i.QualityType == acQuality))];
Item[] consumables = [.. FunGameConstant.AllItems.Where(i => i.ItemType == ItemType.Consumable && i.IsInGameItem)];
foreach (Character character in queue.AllCharacters)
{

View File

@ -1,7 +1,12 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant;
using Oshima.FunGame.OshimaModules.Items;
using Oshima.FunGame.OshimaModules.Models;
using Oshima.FunGame.OshimaServers.Service;
namespace Oshima.FunGame.WebAPI.Controllers
{
@ -75,6 +80,7 @@ namespace Oshima.FunGame.WebAPI.Controllers
// }
//}
[Authorize(AuthenticationSchemes = "CustomBearer")]
[HttpDelete("{id}")]
public IActionResult RemoveActivity(long id)
{
@ -159,6 +165,7 @@ namespace Oshima.FunGame.WebAPI.Controllers
// }
//}
[Authorize(AuthenticationSchemes = "CustomBearer")]
[HttpDelete("{id}/{questId}")]
public IActionResult RemoveQuest(long id, long questId)
{
@ -190,5 +197,61 @@ namespace Oshima.FunGame.WebAPI.Controllers
return StatusCode(500, "删除任务时发生错误,请检查日志。");
}
}
[Authorize(AuthenticationSchemes = "CustomBearer")]
[HttpPut("{id}/user_{uid}")]
public IActionResult AddToUser(long id, long uid)
{
try
{
if (uid <= 0)
{
return BadRequest("无效的用户编号。");
}
EntityModuleConfig<Activity> activities = new("activities", "activities");
activities.LoadConfig();
if (activities.Get(id.ToString()) is Activity activity)
{
EntityModuleConfig<Activity> userActivities = new("activities", uid.ToString());
userActivities.LoadConfig();
FunGameService.AddEventActivity(uid, activity, userActivities);
userActivities.SaveConfig();
return Ok($"{activity}");
}
return NotFound($"活动编号 {id} 不存在。");
}
catch (Exception e)
{
_logger.LogError(e, "Error: ");
return StatusCode(500, "获取活动信息时发生错误,请检查日志。");
}
}
[Authorize(AuthenticationSchemes = "CustomBearer")]
[HttpPost("{id}/addusers")]
public IActionResult AddToUsers(long id)
{
try
{
EntityModuleConfig<Activity> activities = new("activities", "activities");
activities.LoadConfig();
foreach (long uid in FunGameConstant.UserIdAndUsername.Keys)
{
if (activities.Get(id.ToString()) is Activity activity)
{
EntityModuleConfig<Activity> userActivities = new("activities", uid.ToString());
userActivities.LoadConfig();
FunGameService.AddEventActivity(uid, activity, userActivities);
userActivities.SaveConfig();
}
}
return Ok();
}
catch (Exception e)
{
_logger.LogError(e, "Error: ");
return StatusCode(500, "获取活动信息时发生错误,请检查日志。");
}
}
}
}

View File

@ -4505,7 +4505,7 @@ namespace Oshima.FunGame.WebAPI.Controllers
EntityModuleConfig<Quest> quests = new("quests", userid.ToString());
quests.LoadConfig();
if (quests.Count > 0 && FunGameService.SettleQuest(user, quests))
if (quests.Count > 0 && FunGameService.SettleQuest(user, quests.Values))
{
quests.SaveConfig();
}
@ -6160,6 +6160,10 @@ namespace Oshima.FunGame.WebAPI.Controllers
}
pc.Add("exploreTimes", exploreTimes);
for (int useCount = 0; useCount < reduce; useCount++)
{
FunGameService.ActivitiesEventCache.Add("消耗探索许可");
}
FunGameService.SetUserConfigAndReleaseSemaphoreSlim(userid, pc, user);
return (msg, exploreId);
@ -6426,15 +6430,46 @@ namespace Oshima.FunGame.WebAPI.Controllers
}
[HttpGet("getevents")]
public string GetEvents([FromQuery] long? id = null)
public string GetEvents([FromQuery] long uid, [FromQuery] long? id = null)
{
if (id != null)
try
{
return FunGameService.GetEvent(id.Value);
PluginConfig pc = FunGameService.GetUserConfig(uid, out bool isTimeout);
if (isTimeout)
{
return busy;
}
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
string msg = "";
if (id != null)
{
msg = FunGameService.GetEvent(user, id.Value);
}
else
{
msg = FunGameService.GetEventCenter(user);
}
FunGameService.SetUserConfigButNotRelease(uid, pc, user);
return msg;
}
else
{
return noSaved;
}
}
else
catch (Exception e)
{
return FunGameService.GetEventCenter();
if (Logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Error)) Logger.LogError(e, "Error: {e}", e);
return busy;
}
finally
{
FunGameService.ReleaseUserSemaphoreSlim(uid);
}
}
@ -7913,6 +7948,10 @@ namespace Oshima.FunGame.WebAPI.Controllers
}
pc.Add("exploreTimes", exploreTimes);
for (int useCount = 0; useCount < reduce; useCount++)
{
FunGameService.ActivitiesEventCache.Add("消耗探索许可");
}
}
}
@ -9182,71 +9221,6 @@ namespace Oshima.FunGame.WebAPI.Controllers
}
}
[HttpPost("receiveactivityawards")]
public string ReceiveActivityAwards([FromQuery] long uid = -1, [FromQuery] long aid = -1, [FromQuery] long qid = -1)
{
try
{
PluginConfig pc = FunGameService.GetUserConfig(uid, out bool isTimeout);
if (isTimeout)
{
return busy;
}
string msg = "";
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
if (FunGameService.Activities.FirstOrDefault(a => a.Id == aid) is Activity activity)
{
if (activity.Status == ActivityState.InProgress || activity.Status == ActivityState.Ended)
{
if (activity.Quests.FirstOrDefault(q => q.Id == qid) is Quest quest)
{
if (quest.Status == QuestState.Completed)
{
msg = "该任务未完成!";
}
else
{
}
}
else
{
msg = "没有指定的任务。";
}
}
else
{
msg = "该活动不在可领取奖励的时间内。";
}
}
else
{
msg = "没有指定的活动。";
}
FunGameService.SetUserConfigButNotRelease(uid, pc, user);
return msg;
}
else
{
return noSaved;
}
}
catch (Exception e)
{
if (Logger.IsEnabled(Microsoft.Extensions.Logging.LogLevel.Error)) Logger.LogError(e, "Error: {e}", e);
return busy;
}
finally
{
FunGameService.ReleaseUserSemaphoreSlim(uid);
}
}
[HttpPost("template")]
public string Template([FromQuery] long uid = -1)
{

View File

@ -0,0 +1,206 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant;
using Oshima.FunGame.WebAPI.Models;
namespace Oshima.FunGame.WebAPI.Controllers
{
[ApiController]
[Route("[controller]")]
public class StoreController(ILogger<StoreController> logger) : ControllerBase
{
private readonly ILogger<StoreController> _logger = logger;
[HttpGet("{region}/{id}")]
public IActionResult GetStore(string region, long id)
{
try
{
EntityModuleConfig<Store> stores = new("stores", region);
stores.LoadConfig();
if (stores.Get(id.ToString()) is Store Store)
{
return Ok($"{Store}");
}
return NotFound($"商店编号 {id} 不存在。");
}
catch (Exception e)
{
_logger.LogError(e, "Error: ");
return StatusCode(500, "获取商店信息时发生错误,请检查日志。");
}
}
[HttpGet("{region}/{id}/{goodsId}")]
public IActionResult GetGoods(string region, long id, long goodsId)
{
try
{
EntityModuleConfig<Store> stores = new("stores", region);
stores.LoadConfig();
Store? store = stores.Values.FirstOrDefault(s => s.Id == id);
if (store != null)
{
if (store.Goods.Values.FirstOrDefault(g => g.Id == goodsId) is Goods goods)
{
return Ok($"该商品属于商店【{store.Name}】,详情:\r\n{goods}");
}
else
{
return NotFound($"商品编号 {goodsId} 不存在。");
}
}
return NotFound($"商店编号 {id} 不存在。");
}
catch (Exception e)
{
_logger.LogError(e, "Error: ");
return StatusCode(500, "获取商品信息时发生错误,请检查日志。");
}
}
[Authorize(AuthenticationSchemes = "CustomBearer")]
[HttpPut("{region}/{id}")]
public IActionResult AddGoodsToStore(string region, long id, [FromBody] GoodsDTO dto)
{
try
{
EntityModuleConfig<Store> stores = new("stores", region);
stores.LoadConfig();
Store? store = stores.Values.FirstOrDefault(s => s.Id == id);
if (store != null)
{
if (!store.Goods.Values.Any(g => g.Name == dto.Name))
{
if (Factory.OpenFactory.GetInstance<Item>(dto.Id, dto.Name, dto.Values) is Item item)
{
store.AddItem(item, dto.Stock, dto.Name, dto.Description);
Goods newGoods = store.Goods.Values.Last();
if (dto.CurrencyPrice > 0)
{
newGoods.SetPrice(General.GameplayEquilibriumConstant.InGameCurrency, dto.CurrencyPrice);
}
if (dto.MaterialPrice > 0)
{
newGoods.SetPrice(General.GameplayEquilibriumConstant.InGameMaterial, dto.MaterialPrice);
}
newGoods.ExpireTime = dto.ExpireTime;
newGoods.Quota = dto.Quota;
store.CopyGoodsToNextRefreshGoods();
stores.Add(store.Id.ToString(), store);
stores.SaveConfig();
return Ok($"商品:\r\n{newGoods}\r\n已成功添加至商店 {id}{store.Name})。");
}
else
{
return NotFound($"系统中不存在此物品:{dto.Id}.{dto.Name}。");
}
}
else
{
return NotFound($"同名商品 {dto.Name} 已存在于该商店 {id}{store.Name})。");
}
}
return NotFound($"商店编号 {id} 不存在。");
}
catch (Exception e)
{
_logger.LogError(e, "Error: ");
return StatusCode(500, "添加商品时发生错误,请检查日志。");
}
}
[Authorize(AuthenticationSchemes = "CustomBearer")]
[HttpDelete("{region}/{id}")]
public IActionResult RemoveStore(string region, long id)
{
try
{
EntityModuleConfig<Store> stores = new("stores", region);
stores.LoadConfig();
if (stores.Count > 0)
{
stores.Remove(id.ToString());
stores.SaveConfig();
return Ok($"商店编号 {id} 已删除。");
}
return NotFound($"商店编号 {id} 不存在。");
}
catch (Exception e)
{
_logger.LogError(e, "Error: ");
return StatusCode(500, "删除商店时发生错误,请检查日志。");
}
}
[Authorize(AuthenticationSchemes = "CustomBearer")]
[HttpPatch("{region}/{id}/{goodsId}")]
public IActionResult PatchGoodsTime(string region, long id, long goodsId, [FromBody] DateTime? dt)
{
try
{
EntityModuleConfig<Store> stores = new("stores", region);
stores.LoadConfig();
Store? store = stores.Values.FirstOrDefault(s => s.Id == id);
if (store != null)
{
if (store.Goods.Values.FirstOrDefault(g => g.Id == goodsId) is Goods goods)
{
goods.ExpireTime = dt;
stores.Add(store.Id.ToString(), store);
stores.SaveConfig();
return Ok($"商品 {goods} 更新成功。");
}
else
{
return NotFound($"商品编号 {goodsId} 不存在。");
}
}
return NotFound($"商店编号 {id} 不存在。");
}
catch (Exception e)
{
_logger.LogError(e, "Error: ");
return StatusCode(500, "更新商品时发生错误,请检查日志。");
}
}
[Authorize(AuthenticationSchemes = "CustomBearer")]
[HttpDelete("{region}/{id}/{goodsId}")]
public IActionResult RemoveGoods(string region, long id, long goodsId)
{
try
{
EntityModuleConfig<Store> stores = new("stores", region);
stores.LoadConfig();
Store? store = stores.Values.FirstOrDefault(s => s.Id == id);
if (store != null)
{
if (store.Goods.Values.FirstOrDefault(g => g.Id == goodsId) is Goods goods)
{
store.Goods.Remove(goods.Id);
stores.Add(store.Id.ToString(), store);
stores.SaveConfig();
return Ok($"商品 {goods} 删除成功。");
}
else
{
return NotFound($"商品编号 {goodsId} 不存在。");
}
}
return NotFound($"商店编号 {id} 不存在。");
}
catch (Exception e)
{
_logger.LogError(e, "Error: ");
return StatusCode(500, "删除商品时发生错误,请检查日志。");
}
}
}
}

View File

@ -0,0 +1,15 @@
namespace Oshima.FunGame.WebAPI.Models
{
public class GoodsDTO
{
public long Id { get; set; } = 0;
public string Name { get; set; } = "";
public string Description { get; set; } = "";
public DateTime? ExpireTime { get; set; } = null;
public int Stock { get; set; } = 0;
public int Quota { get; set; } = 0;
public double CurrencyPrice { get; set; } = 0;
public double MaterialPrice { get; set; } = 0;
public Dictionary<string, object> Values { get; set; } = [];
}
}

View File

@ -2469,7 +2469,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail == "活动" || e.Detail == "活动中心")
{
string msg = Controller.GetEvents();
string msg = Controller.GetEvents(uid);
if (msg != "")
{
await SendAsync(e, "活动中心", string.Join("\r\n", msg));
@ -2483,7 +2483,7 @@ namespace Oshima.FunGame.WebAPI.Services
string msg = "";
if (int.TryParse(detail, out int eid))
{
msg = Controller.GetEvents(eid);
msg = Controller.GetEvents(uid, eid);
if (msg.Trim() != "")
{
await SendAsync(e, "查活动", msg);