稳定性改进

This commit is contained in:
milimoe 2025-06-30 22:46:30 +08:00
parent 2ed15a6419
commit 5447c6fe97
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
5 changed files with 328 additions and 160 deletions

View File

@ -13,7 +13,7 @@ namespace Oshima.FunGame.OshimaServers.Service
public const int ItemsPerPage1 = 6; public const int ItemsPerPage1 = 6;
public const int ItemsPerPage2 = 10; public const int ItemsPerPage2 = 10;
public const int ExploreTime = 2; public const int ExploreTime = 2;
public const int MaxExploreTimes = 12; public const int MaxExploreTimes = 60;
public static List<Character> Characters { get; } = []; public static List<Character> Characters { get; } = [];
public static List<Skill> Skills { get; } = []; public static List<Skill> Skills { get; } = [];
public static List<Skill> PassiveSkills { get; } = []; public static List<Skill> PassiveSkills { get; } = [];
@ -300,38 +300,56 @@ namespace Oshima.FunGame.OshimaServers.Service
new () new ()
]; ];
public static Dictionary<ExploreResult, double> ExploreResultProbabilities { get; } = new()
{
{ ExploreResult.General, 40 },
{ ExploreResult.Nothing, 20 },
{ ExploreResult.Fight, 20 },
{ ExploreResult.Earned, 20 },
{ ExploreResult.Event, 0 }
};
/// <summary> /// <summary>
/// 参数说明:{0} 奖励内容字符串,{1} 敌人名称,{2} NPC名称{3} 物品名称1{4} 地点名称1{5} 物品名称1{6} 地点名称2 /// 参数说明:{0} 奖励内容字符串,{1} 敌人名称,{2} NPC名称{3} 物品名称1{4} 地点名称1{5} 物品名称1{6} 地点名称2
/// </summary> /// </summary>
public static Dictionary<string, ExploreResult> ExploreString { get; } = new() public static Dictionary<ExploreResult, List<string>> ExploreString { get; } = new()
{ {
// General - 带奖励的普通结果 {
{ "当{3}的光芒洒满{4}时,{6}显露出了被封印的{0},你快马加鞭冲了上去夺走!", ExploreResult.General }, ExploreResult.General, [
{ "{2}的低语在风中消散,但留在你手中的是闪耀的{0}", ExploreResult.General }, "当{3}的光芒洒满{4}时,{6}显露出了被封印的{0},你快马加鞭冲了上去夺走!",
{ "恭喜你!成功在荒野中迷路!奖励…等等,好像是:{0}?至少不是空手而归…", ExploreResult.General }, "{2}的低语在风中消散,但留在你手中的是闪耀的{0}",
{ "你凝视着远方,远方也凝视着你…然后,你获得了:{0}!这大概就是命运吧。", ExploreResult.General }, "恭喜你!成功在荒野中迷路!奖励…等等,好像是:{0}?至少不是空手而归…",
{ "探索结果:空气,阳光,还有…奖励:{0}!看来今天运气还不错?", ExploreResult.General }, "你凝视着远方,远方也凝视着你…然后,你获得了:{0}!这大概就是命运吧。",
"探索结果:空气,阳光,还有…奖励:{0}!看来今天运气还不错?"
// Nothing - 无收获 ]
{ "风沙抹去了所有痕迹,只有{3}见证过你的到来。(什么也没有获得)", ExploreResult.Nothing }, },
{ "{4}地牢里的封印纹丝未动,仿佛在嘲笑着你的徒劳……(什么也没有获得)", ExploreResult.Nothing }, {
{ "在你的注视下,{4}的宝藏已被{2}掠夺一空。(什么也没有获得)", ExploreResult.Nothing }, ExploreResult.Nothing, [
{ "你对着空地发呆了半天,只剩冰冷的{4}和你的失望。(什么也没有获得)", ExploreResult.Nothing }, "风沙抹去了所有痕迹,只有{3}见证过你的到来。(什么也没有获得)",
{ "在空荡的回响中传来讥笑,原来{4}的秘宝不过是个传说。(什么也没有获得)", ExploreResult.Nothing }, "{4}地牢里的封印纹丝未动,仿佛在嘲笑着你的徒劳……(什么也没有获得)",
"在你的注视下,{4}的宝藏已被{2}掠夺一空。(什么也没有获得)",
// Fight - 遭遇敌人 "你对着空地发呆了半天,只剩冰冷的{4}和你的失望。(什么也没有获得)",
{ "{4}的地面突然裂开,{1}扑向了你!迎接战斗吧!", ExploreResult.Fight }, "在空荡的回响中传来讥笑,原来{4}的秘宝不过是个传说。(什么也没有获得)"
{ "当你触碰{3}时,{1}的咆哮震撼着{4}", ExploreResult.Fight }, ]
{ "原来这里真的有危险……是{1}守卫着{4},不得不战了!", ExploreResult.Fight }, },
{ "在探索{4}的某处时,身旁的墙突然破裂,{1}从阴影中降临!", ExploreResult.Fight }, {
{ "你惊动了{1}{4}瞬间化作战场!", ExploreResult.Fight }, ExploreResult.Fight, [
"{4}的地面突然裂开,{1}扑向了你!迎接战斗吧!",
// Earned - 珍贵收获 "当你触碰{3}时,{1}的咆哮震撼着{4}",
{ "当{3}发出诡异的光芒照亮{4}时,藏在其中的{0}突然落入你手中!", ExploreResult.Earned }, "原来这里真的有危险……是{1}守卫着{4},不得不战了!",
{ "祝福应验!{4}深处的{0}为你所有!", ExploreResult.Earned }, "在探索{4}的某处时,身旁的墙突然破裂,{1}从阴影中降临!",
{ "解开{4}地牢中的谜题后,{0}终于显现!", ExploreResult.Earned }, "你惊动了{1}{4}瞬间化作战场!"
{ "屏障消散,至宝{0}光芒万丈,自觉地飞进了你的口袋!", ExploreResult.Earned }, ]
{ "在偶遇{1}和{2}的遭遇战时,你渔翁得利抢到了:{0}", ExploreResult.Earned } },
{
ExploreResult.Earned, [
"当{3}发出诡异的光芒照亮{4}时,藏在其中的{0}突然落入你手中!",
"祝福应验!{4}深处的{0}为你所有!",
"解开{4}地牢中的谜题后,{0}终于显现!",
"屏障消散,至宝{0}光芒万丈,自觉地飞进了你的口袋!",
"在偶遇{1}和{2}的遭遇战时,你渔翁得利抢到了:{0}"
]
}
}; };
public static Dictionary<QualityType, double> DrawCardProbabilities { get; } = new() public static Dictionary<QualityType, double> DrawCardProbabilities { get; } = new()

View File

@ -16,9 +16,13 @@ namespace Oshima.FunGame.OshimaServers.Service
{ {
public class FunGameService public class FunGameService
{ {
public static Dictionary<long, List<string>> UserExploreCharacterCache { get; } = [];
public static Dictionary<long, List<string>> UserExploreItemCache { get; } = []; public static Dictionary<long, List<string>> UserExploreItemCache { get; } = [];
public static Dictionary<long, List<string>> UserExploreEventCache { get; } = [];
public static HashSet<Activity> Activities { get; } = []; public static HashSet<Activity> Activities { get; } = [];
public static List<string> ActivitiesCharacterCache { get; } = [];
public static List<string> ActivitiesItemCache { get; } = []; public static List<string> ActivitiesItemCache { get; } = [];
public static List<string> ActivitiesEventCache { get; } = [];
public static Dictionary<long, HashSet<string>> UserNotice { get; } = []; public static Dictionary<long, HashSet<string>> UserNotice { get; } = [];
public static Dictionary<int, Character> Bosses { get; } = []; public static Dictionary<int, Character> Bosses { get; } = [];
public static ServerPluginLoader? ServerPluginLoader { get; set; } = null; public static ServerPluginLoader? ServerPluginLoader { get; set; } = null;
@ -1754,12 +1758,12 @@ namespace Oshima.FunGame.OshimaServers.Service
{ {
if (quest.NeedyExploreItemName == item) if (quest.NeedyExploreItemName == item)
{ {
result = true;
quest.Progress += items.Count(); quest.Progress += items.Count();
if (quest.Progress >= quest.MaxProgress) if (quest.Progress >= quest.MaxProgress)
{ {
quest.Progress = quest.MaxProgress; quest.Progress = quest.MaxProgress;
quest.Status = QuestState.Completed; quest.Status = QuestState.Completed;
result = true;
} }
} }
} }
@ -1986,12 +1990,38 @@ namespace Oshima.FunGame.OshimaServers.Service
{ {
return "当前没有任何活动,敬请期待。"; return "当前没有任何活动,敬请期待。";
} }
lock (Activities)
{
Activities.Clear(); Activities.Clear();
foreach (Activity activity in activities.Values) foreach (Activity activity in activities.Values)
{ {
Activities.Add(activity); Activities.Add(activity);
} }
bool update = false; bool update = false;
if (ActivitiesCharacterCache.Count > 0)
{
List<string> willRemove = [];
IEnumerable<Activity> activityList = Activities.Where(a => a.Status == ActivityState.InProgress);
foreach (string item in ActivitiesCharacterCache.Distinct())
{
IEnumerable<string> items = ActivitiesCharacterCache.Where(str => str == item);
foreach (Quest quest in activityList.SelectMany(a => a.Quests).Where(q => q.Status == QuestState.InProgress))
{
if (quest.NeedyExploreCharacterName == item)
{
update = true;
quest.Progress += items.Count();
if (quest.Progress >= quest.MaxProgress)
{
quest.Progress = quest.MaxProgress;
quest.Status = QuestState.Completed;
}
}
}
willRemove.Add(item);
}
ActivitiesCharacterCache.RemoveAll(willRemove.Contains);
}
if (ActivitiesItemCache.Count > 0) if (ActivitiesItemCache.Count > 0)
{ {
List<string> willRemove = []; List<string> willRemove = [];
@ -1999,7 +2029,7 @@ namespace Oshima.FunGame.OshimaServers.Service
foreach (string item in ActivitiesItemCache.Distinct()) foreach (string item in ActivitiesItemCache.Distinct())
{ {
IEnumerable<string> items = ActivitiesItemCache.Where(str => str == item); IEnumerable<string> items = ActivitiesItemCache.Where(str => str == item);
foreach (Quest quest in activityList.SelectMany(a => a.Quests)) foreach (Quest quest in activityList.SelectMany(a => a.Quests).Where(q => q.Status == QuestState.InProgress))
{ {
if (quest.NeedyExploreItemName == item) if (quest.NeedyExploreItemName == item)
{ {
@ -2016,6 +2046,30 @@ namespace Oshima.FunGame.OshimaServers.Service
} }
ActivitiesItemCache.RemoveAll(willRemove.Contains); ActivitiesItemCache.RemoveAll(willRemove.Contains);
} }
if (ActivitiesEventCache.Count > 0)
{
List<string> willRemove = [];
IEnumerable<Activity> activityList = Activities.Where(a => a.Status == ActivityState.InProgress);
foreach (string item in ActivitiesEventCache.Distinct())
{
IEnumerable<string> items = ActivitiesEventCache.Where(str => str == item);
foreach (Quest quest in activityList.SelectMany(a => a.Quests).Where(q => q.Status == QuestState.InProgress))
{
if (quest.NeedyExploreEventName == item)
{
update = true;
quest.Progress += items.Count();
if (quest.Progress >= quest.MaxProgress)
{
quest.Progress = quest.MaxProgress;
quest.Status = QuestState.Completed;
}
}
}
willRemove.Add(item);
}
ActivitiesEventCache.RemoveAll(willRemove.Contains);
}
if (update) if (update)
{ {
foreach (Activity activity in Activities) foreach (Activity activity in Activities)
@ -2024,6 +2078,7 @@ namespace Oshima.FunGame.OshimaServers.Service
} }
activities.SaveConfig(); activities.SaveConfig();
} }
}
StringBuilder builder = new(); StringBuilder builder = new();
builder.AppendLine("★☆★ 活动中心 ★☆★"); builder.AppendLine("★☆★ 活动中心 ★☆★");
@ -2093,7 +2148,7 @@ namespace Oshima.FunGame.OshimaServers.Service
Dictionary<Character, int> characters = inventory Dictionary<Character, int> characters = inventory
.Select((character, index) => new { character, index }) .Select((character, index) => new { character, index })
.ToDictionary(x => x.character, x => x.index + 1); .ToDictionary(x => x.character, x => x.index + 1);
return $"{(squad.Length > 0 ? string.Join(separator, squad.Select(c => $"#{characters[c]}. {c}")) : "")}"; return $"{(squad.Length > 0 ? string.Join(separator, squad.Select(c => $"#{characters[c]}. {c.ToStringWithLevelWithOutUser()}")) : "")}";
} }
public static string GetCharacterGroupInfoByInventorySequence(IEnumerable<Character> inventory, IEnumerable<long> characterIds, string separator = "\r\n") public static string GetCharacterGroupInfoByInventorySequence(IEnumerable<Character> inventory, IEnumerable<long> characterIds, string separator = "\r\n")
@ -2107,7 +2162,7 @@ namespace Oshima.FunGame.OshimaServers.Service
characters[loop[i - 1]] = i; characters[loop[i - 1]] = i;
} }
} }
return $"{(characters.Count > 0 ? string.Join(separator, characters.Keys.Select(c => $"#{characters[c]}. {c}")) : "")}"; return $"{(characters.Count > 0 ? string.Join(separator, characters.Keys.Select(c => $"#{characters[c]}. {c.ToStringWithLevelWithOutUser()}")) : "")}";
} }
public static async Task<ExploreModel> GenerateExploreModel(OshimaRegion region, long[] characterIds, User user) public static async Task<ExploreModel> GenerateExploreModel(OshimaRegion region, long[] characterIds, User user)
@ -2119,13 +2174,61 @@ namespace Oshima.FunGame.OshimaServers.Service
CharacterIds = characterIds, CharacterIds = characterIds,
StartTime = DateTime.Now StartTime = DateTime.Now
}; };
int diff = region.Difficulty switch
{
RarityType.OneStar => 1,
RarityType.TwoStar => 2,
RarityType.ThreeStar => 3,
RarityType.FourStar => 4,
_ => 5
};
// 直接保存探索奖励,但是要等到探索结束后发放 // 直接保存探索奖励,但是要等到探索结束后发放
int random = Random.Shared.Next(FunGameConstant.ExploreString.Count); double randomDouble = Random.Shared.NextDouble();
string exploreString = FunGameConstant.ExploreString.Keys.ToArray()[random]; Dictionary<ExploreResult, double> probabilities = new(FunGameConstant.ExploreResultProbabilities);
switch (diff)
{
case 2:
probabilities[ExploreResult.General] -= 0.05;
probabilities[ExploreResult.Earned] -= 0.05;
probabilities[ExploreResult.Fight] += 0.1;
break;
case 3:
probabilities[ExploreResult.General] -= 0.1;
probabilities[ExploreResult.Earned] -= 0.05;
probabilities[ExploreResult.Nothing] -= 0.05;
probabilities[ExploreResult.Fight] += 0.2;
break;
case 4:
probabilities[ExploreResult.General] -= 0.2;
probabilities[ExploreResult.Earned] -= 0.1;
probabilities[ExploreResult.Nothing] -= 0.05;
probabilities[ExploreResult.Fight] += 0.35;
break;
case 5:
probabilities[ExploreResult.General] -= 0.3;
probabilities[ExploreResult.Earned] -= 0.15;
probabilities[ExploreResult.Nothing] -= 0.05;
probabilities[ExploreResult.Fight] += 0.5;
break;
default:
break;
}
double cumulative = 0;
model.Result = ExploreResult.Nothing;
foreach (ExploreResult key in probabilities.Keys)
{
cumulative += probabilities[key];
if (randomDouble <= cumulative)
{
model.Result = key;
break;
}
}
string exploreString = FunGameConstant.ExploreString[model.Result].OrderBy(o => Random.Shared.Next()).First();
// 出现的NPC // 出现的NPC
random = Random.Shared.Next(region.NPCs.Count + 1); int random = Random.Shared.Next(region.NPCs.Count + 1);
string npc = random == region.NPCs.Count ? GenerateRandomChineseUserName() : region.NPCs[random]; string npc = random == region.NPCs.Count ? GenerateRandomChineseUserName() : region.NPCs[random];
// 探索的子区域 // 探索的子区域
@ -2142,14 +2245,6 @@ namespace Oshima.FunGame.OshimaServers.Service
string item2 = items[random].Name; string item2 = items[random].Name;
// 筛选敌人 // 筛选敌人
int diff = region.Difficulty switch
{
RarityType.OneStar => 1,
RarityType.TwoStar => 2,
RarityType.ThreeStar => 3,
RarityType.FourStar => 4,
_ => 5
};
List<Character> enemys = []; List<Character> enemys = [];
Character enemy; Character enemy;
if (region.Characters.Count > 0 && region.Units.Count > 0) if (region.Characters.Count > 0 && region.Units.Count > 0)
@ -2197,7 +2292,6 @@ namespace Oshima.FunGame.OshimaServers.Service
// 生成奖励 // 生成奖励
string award = ""; string award = "";
model.Result = FunGameConstant.ExploreString[exploreString];
switch (model.Result) switch (model.Result)
{ {
case ExploreResult.General: case ExploreResult.General:
@ -2207,7 +2301,7 @@ namespace Oshima.FunGame.OshimaServers.Service
int credits = 0; int credits = 0;
for (int i = 0; i < characterCount; i++) for (int i = 0; i < characterCount; i++)
{ {
credits += Random.Shared.Next(500, 1000) * diff; credits += Random.Shared.Next(250, 400) * diff;
} }
model.CreditsAward = credits; model.CreditsAward = credits;
award = $" {credits} {General.GameplayEquilibriumConstant.InGameCurrency}"; award = $" {credits} {General.GameplayEquilibriumConstant.InGameCurrency}";
@ -2237,10 +2331,10 @@ namespace Oshima.FunGame.OshimaServers.Service
int exp = 0; int exp = 0;
for (int i = 0; i < characterCount; i++) for (int i = 0; i < characterCount; i++)
{ {
exp += Random.Shared.Next(300, 700) * diff; exp += Random.Shared.Next(100, 300) * diff;
} }
model.Awards["exp"] = exp; model.Awards["exp"] = exp;
award += $",并额外获得了 {exp} 点经验值(探索队员们平分)"; exploreString += $"额外获得了:{exp} 点经验值(探索队员们平分)!";
break; break;
case ExploreResult.Fight: case ExploreResult.Fight:
// 小队信息 // 小队信息
@ -2287,19 +2381,19 @@ namespace Oshima.FunGame.OshimaServers.Service
int credits = 0; int credits = 0;
for (int i = 0; i < characterCount; i++) for (int i = 0; i < characterCount; i++)
{ {
credits += Random.Shared.Next(1000, 1500) * diff; credits += Random.Shared.Next(400, 650) * diff;
} }
model.CreditsAward = credits; model.CreditsAward = credits;
exp = 0; exp = 0;
for (int i = 0; i < characterCount; i++) for (int i = 0; i < characterCount; i++)
{ {
exp += Random.Shared.Next(600, 1000) * diff; exp += Random.Shared.Next(250, 520) * diff;
} }
model.Awards["exp"] = exp; model.Awards["exp"] = exp;
int materials = 0; int materials = 0;
for (int i = 0; i < characterCount; i++) for (int i = 0; i < characterCount; i++)
{ {
materials += Random.Shared.Next(4, 7) * diff; materials += Random.Shared.Next(3, 7) * diff;
} }
model.MaterialsAward = materials; model.MaterialsAward = materials;
Item item = FunGameConstant.ExploreItems[region][Random.Shared.Next(FunGameConstant.ExploreItems[region].Count)]; Item item = FunGameConstant.ExploreItems[region][Random.Shared.Next(FunGameConstant.ExploreItems[region].Count)];
@ -2319,7 +2413,7 @@ namespace Oshima.FunGame.OshimaServers.Service
string itemquality = ItemSet.GetQualityTypeName(itemDrop.QualityType); string itemquality = ItemSet.GetQualityTypeName(itemDrop.QualityType);
string itemtype = ItemSet.GetItemTypeName(itemDrop.ItemType) + (itemDrop.ItemType == ItemType.Weapon && itemDrop.WeaponType != WeaponType.None ? "-" + ItemSet.GetWeaponTypeName(itemDrop.WeaponType) : ""); string itemtype = ItemSet.GetItemTypeName(itemDrop.ItemType) + (itemDrop.ItemType == ItemType.Weapon && itemDrop.WeaponType != WeaponType.None ? "-" + ItemSet.GetWeaponTypeName(itemDrop.WeaponType) : "");
if (itemtype != "") itemtype = $"|{itemtype}"; if (itemtype != "") itemtype = $"|{itemtype}";
award += $"!额外获得了:[{itemquality + itemtype}] {itemDrop.Name}"; award += $"!额外获得了:[{itemquality + itemtype}]{itemDrop.Name}";
} }
} }
exploreString = $"{exploreString}\r\n{string.Join("\r\n", msgs)}\r\n探索小队战胜了{enemy.Name}!获得了:{award}"; exploreString = $"{exploreString}\r\n{string.Join("\r\n", msgs)}\r\n探索小队战胜了{enemy.Name}!获得了:{award}";
@ -2347,7 +2441,7 @@ namespace Oshima.FunGame.OshimaServers.Service
string itemquality = ItemSet.GetQualityTypeName(itemEarned.QualityType); string itemquality = ItemSet.GetQualityTypeName(itemEarned.QualityType);
string itemtype = ItemSet.GetItemTypeName(itemEarned.ItemType) + (itemEarned.ItemType == ItemType.Weapon && itemEarned.WeaponType != WeaponType.None ? "-" + ItemSet.GetWeaponTypeName(itemEarned.WeaponType) : ""); string itemtype = ItemSet.GetItemTypeName(itemEarned.ItemType) + (itemEarned.ItemType == ItemType.Weapon && itemEarned.WeaponType != WeaponType.None ? "-" + ItemSet.GetWeaponTypeName(itemEarned.WeaponType) : "");
if (itemtype != "") itemtype = $"|{itemtype}"; if (itemtype != "") itemtype = $"|{itemtype}";
award += $"[{itemquality + itemtype}] {itemEarned.Name}"; award += $"[{itemquality + itemtype}]{itemEarned.Name}";
} }
break; break;
case ExploreResult.Event: case ExploreResult.Event:
@ -2432,7 +2526,7 @@ namespace Oshima.FunGame.OshimaServers.Service
List<Guid> remove = []; List<Guid> remove = [];
foreach (ExploreModel model in list) foreach (ExploreModel model in list)
{ {
if (model.StartTime.HasValue && (DateTime.Now - model.StartTime.Value).TotalMinutes > FunGameConstant.ExploreTime + 5) if (model.StartTime.HasValue && (DateTime.Now - model.StartTime.Value).TotalMinutes > FunGameConstant.ExploreTime + 2)
{ {
if (SettleExplore(model.Guid, list, user, out string msg)) if (SettleExplore(model.Guid, list, user, out string msg))
{ {

View File

@ -2525,6 +2525,19 @@ namespace Oshima.FunGame.WebAPI.Controllers
user2.Inventory.Materials += itemCount; user2.Inventory.Materials += itemCount;
msg = $"已为 [ {user2} ] 生成 {itemCount} {General.GameplayEquilibriumConstant.InGameMaterial}"; msg = $"已为 [ {user2} ] 生成 {itemCount} {General.GameplayEquilibriumConstant.InGameMaterial}";
} }
else if (itemName == "探索许可")
{
if (pc.TryGetValue("exploreTimes", out object? value) && int.TryParse(value.ToString(), out int exploreTimes))
{
exploreTimes += itemCount;
}
else
{
exploreTimes = FunGameConstant.MaxExploreTimes + itemCount;
}
pc.Add("exploreTimes", exploreTimes);
msg = $"已为 [ {user2} ] 生成 {itemCount} 个探索许可";
}
else if (itemName.Contains("魔法卡礼包")) else if (itemName.Contains("魔法卡礼包"))
{ {
foreach (string type in ItemSet.QualityTypeNameArray) foreach (string type in ItemSet.QualityTypeNameArray)
@ -5267,23 +5280,42 @@ namespace Oshima.FunGame.WebAPI.Controllers
msg = $"没有找到与输入序号相对应的角色:{string.Join("", invalid)}。"; msg = $"没有找到与输入序号相对应的角色:{string.Join("", invalid)}。";
} }
// 检查探索次数 // 检查探索许可
if (pc.TryGetValue("exploreTimes", out object? value) && int.TryParse(value.ToString(), out int exploreTimes)) int exploreTimes = 0;
int reduce = 1;
if (regionid > 0 && regionid <= FunGameConstant.Regions.Count && FunGameConstant.Regions.FirstOrDefault(r => r.Id == regionid) is OshimaRegion region)
{
int diff = region.Difficulty switch
{
RarityType.OneStar => 1,
RarityType.TwoStar => 2,
RarityType.ThreeStar => 3,
RarityType.FourStar => 4,
_ => 5
};
reduce = characterCount * diff;
if (pc.TryGetValue("exploreTimes", out object? value) && int.TryParse(value.ToString(), out exploreTimes))
{ {
if (exploreTimes <= 0) if (exploreTimes <= 0)
{ {
exploreTimes = 0; exploreTimes = 0;
msg = $"今日的探索次数已用完,无法再继续探索。"; msg = $"今日的探索许可已用完,无法再继续探索。";
} }
else if (characterCount > exploreTimes) else if (reduce > exploreTimes)
{ {
msg = $"你选择的角色数量超过了剩余的探索次数({exploreTimes} 次),请减少选择的角色数量。需要注意:探索角色越多,奖励越多,但是会扣除相应的探索次数。"; msg = $"本次探索需要消耗 {reduce} 个探索许可,超过了你的剩余探索许可数量({exploreTimes} 个),请减少选择的角色数量或更换探索地区。" +
$"\r\n需要注意探索难度星级一比一兑换探索许可并且参与探索的角色都需要消耗相同数量的探索许可。";
} }
} }
else else
{ {
exploreTimes = FunGameConstant.MaxExploreTimes; exploreTimes = FunGameConstant.MaxExploreTimes;
} }
}
else
{
return ($"没有找到与这个序号相对应的地区!", exploreId);
}
// 检查角色是否正在探索 // 检查角色是否正在探索
List<ExploreModel> list = pc.Get<List<ExploreModel>>("exploring") ?? []; List<ExploreModel> list = pc.Get<List<ExploreModel>>("exploring") ?? [];
@ -5294,14 +5326,14 @@ namespace Oshima.FunGame.WebAPI.Controllers
foreach (ExploreModel model in list) foreach (ExploreModel model in list)
{ {
// 可能要结算先前的超时探索 // 可能要结算先前的超时探索
if (model.StartTime.HasValue && (DateTime.Now - model.StartTime.Value).TotalMinutes > FunGameConstant.ExploreTime + 5) if (model.StartTime.HasValue && (DateTime.Now - model.StartTime.Value).TotalMinutes > FunGameConstant.ExploreTime + 2)
{ {
if (FunGameService.SettleExplore(model.Guid, list, user, out string notice)) if (FunGameService.SettleExplore(model.Guid, list, user, out string notice))
{ {
if (notice != "") if (notice != "")
{ {
if (msg2 != "") msg2 += "\r\n"; if (msg2 != "") msg2 += "\r\n";
msg2 += $"你上次未完成的探索已被自动结算{notice}"; msg2 += $"你上次未完成的探索已被自动结算{notice}";
} }
remove.Add(model.Guid); remove.Add(model.Guid);
} }
@ -5328,9 +5360,7 @@ namespace Oshima.FunGame.WebAPI.Controllers
if (msg == "") if (msg == "")
{ {
if (regionid > 0 && regionid <= FunGameConstant.Regions.Count && FunGameConstant.Regions.FirstOrDefault(r => r.Id == regionid) is OshimaRegion region) exploreTimes -= reduce;
{
exploreTimes -= characterCount;
msg = $"开始探索【{region.Name}】,探索时间预计 {FunGameConstant.ExploreTime} 分钟(系统会自动结算,届时会有提示)。" + msg = $"开始探索【{region.Name}】,探索时间预计 {FunGameConstant.ExploreTime} 分钟(系统会自动结算,届时会有提示)。" +
$"探索成员:[ {FunGameService.GetCharacterGroupInfoByInventorySequence(user.Inventory.Characters, characterIds, " ] / [ ")} ]"; $"探索成员:[ {FunGameService.GetCharacterGroupInfoByInventorySequence(user.Inventory.Characters, characterIds, " ] / [ ")} ]";
@ -5338,16 +5368,8 @@ namespace Oshima.FunGame.WebAPI.Controllers
exploreId = model.Guid; exploreId = model.Guid;
list.Add(model); list.Add(model);
if (exploreTimes > 0)
{
if (msg != "") msg += "\r\n"; if (msg != "") msg += "\r\n";
msg += $"本次扣除探索次数 {characterCount} 次,你的剩余探索次数:{exploreTimes} 次。需要注意:探索角色越多,奖励越多,但是会扣除相应的探索次数。"; msg += $"本次消耗探索许可 {reduce} 个,你的剩余探索许可:{exploreTimes} 个。需要注意:探索难度星级一比一兑换探索许可,并且参与探索的角色,都需要消耗相同数量的探索许可。";
}
}
else
{
return ($"没有找到与这个序号相对应的地区!", exploreId);
}
} }
user.LastTime = DateTime.Now; user.LastTime = DateTime.Now;
@ -5377,13 +5399,13 @@ namespace Oshima.FunGame.WebAPI.Controllers
{ {
User user = FunGameService.GetUser(pc); User user = FunGameService.GetUser(pc);
// 检查探索次数 // 检查探索许可
if (pc.TryGetValue("exploreTimes", out object? value) && int.TryParse(value.ToString(), out int exploreTimes)) if (pc.TryGetValue("exploreTimes", out object? value) && int.TryParse(value.ToString(), out int exploreTimes))
{ {
if (exploreTimes <= 0) if (exploreTimes <= 0)
{ {
exploreTimes = 0; exploreTimes = 0;
msg = $"今日的探索次数已用完,无法再继续探索。"; msg = $"今日的探索许可已用完,无法再继续探索。";
} }
} }
else else
@ -5414,7 +5436,7 @@ namespace Oshima.FunGame.WebAPI.Controllers
if (exploreTimes > 0) if (exploreTimes > 0)
{ {
if (msg != "") msg += "\r\n"; if (msg != "") msg += "\r\n";
msg += $"你的剩余探索次数:{exploreTimes} 次。"; msg += $"你的剩余探索许可:{exploreTimes} 个。";
} }
user.LastTime = DateTime.Now; user.LastTime = DateTime.Now;

View File

@ -83,6 +83,7 @@ namespace Oshima.FunGame.WebAPI.Models
public string OpenId { get; } public string OpenId { get; }
public string AuthorOpenId { get; } public string AuthorOpenId { get; }
public long FunGameUID { get; set; } public long FunGameUID { get; set; }
public bool UseNotice { get; set; }
} }
public class ThirdPartyMessage : IBotMessage public class ThirdPartyMessage : IBotMessage
@ -113,6 +114,9 @@ namespace Oshima.FunGame.WebAPI.Models
[JsonIgnore] [JsonIgnore]
public long FunGameUID { get; set; } = 0; public long FunGameUID { get; set; } = 0;
[JsonIgnore]
public bool UseNotice { get; set; } = true;
} }
public class C2CMessage : IBotMessage public class C2CMessage : IBotMessage
@ -135,6 +139,9 @@ namespace Oshima.FunGame.WebAPI.Models
[JsonIgnore] [JsonIgnore]
public long FunGameUID { get; set; } = 0; public long FunGameUID { get; set; } = 0;
[JsonIgnore]
public bool UseNotice { get; set; } = true;
public string Detail public string Detail
{ {
get => Content; get => Content;
@ -168,6 +175,9 @@ namespace Oshima.FunGame.WebAPI.Models
[JsonIgnore] [JsonIgnore]
public long FunGameUID { get; set; } = 0; public long FunGameUID { get; set; } = 0;
[JsonIgnore]
public bool UseNotice { get; set; } = true;
public string Detail public string Detail
{ {
get => Content; get => Content;

View File

@ -44,7 +44,7 @@ namespace Oshima.FunGame.WebAPI.Services
content = content.Trim(); content = content.Trim();
await Service.SendC2CMessageAsync(msg.OpenId, content, msgType, media, msg.Id, msgSeq); await Service.SendC2CMessageAsync(msg.OpenId, content, msgType, media, msg.Id, msgSeq);
} }
if (msg.FunGameUID > 0 && FunGameService.UserNotice.TryGetValue(msg.FunGameUID, out HashSet<string>? msgs) && msgs != null) if (msg.UseNotice && msg.FunGameUID > 0 && FunGameService.UserNotice.TryGetValue(msg.FunGameUID, out HashSet<string>? msgs) && msgs != null)
{ {
FunGameService.UserNotice.Remove(msg.FunGameUID); FunGameService.UserNotice.Remove(msg.FunGameUID);
await SendAsync(msg, "每日登录提醒", string.Join("\r\n", msgs), msgType, media, 5); await SendAsync(msg, "每日登录提醒", string.Join("\r\n", msgs), msgType, media, 5);
@ -53,6 +53,7 @@ namespace Oshima.FunGame.WebAPI.Services
private async Task SendHelp(IBotMessage e, Dictionary<string, string> helpDict, string helpName, int currentPage) private async Task SendHelp(IBotMessage e, Dictionary<string, string> helpDict, string helpName, int currentPage)
{ {
e.UseNotice = false;
int pageSize = 15; int pageSize = 15;
int totalPages = (helpDict.Count + pageSize - 1) / pageSize; int totalPages = (helpDict.Count + pageSize - 1) / pageSize;
@ -133,12 +134,14 @@ namespace Oshima.FunGame.WebAPI.Services
if (!e.IsGroup && e.Detail == "获取接入码") if (!e.IsGroup && e.Detail == "获取接入码")
{ {
e.UseNotice = false;
await SendAsync(e, "获取接入码", $"你的接入码为 {openid},请妥善保存!"); await SendAsync(e, "获取接入码", $"你的接入码为 {openid},请妥善保存!");
return true; return true;
} }
if (e.Detail == "查询服务器启动时间") if (e.Detail == "查询服务器启动时间")
{ {
e.UseNotice = false;
string msg = TestController.GetLastLoginTime(); string msg = TestController.GetLastLoginTime();
await SendAsync(e, "查询服务器启动时间", msg); await SendAsync(e, "查询服务器启动时间", msg);
return true; return true;
@ -146,6 +149,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("查询任务计划")) if (e.Detail.StartsWith("查询任务计划"))
{ {
e.UseNotice = false;
string msg = TestController.GetTaskScheduler(e.Detail.Replace("查询任务计划", "")); string msg = TestController.GetTaskScheduler(e.Detail.Replace("查询任务计划", ""));
await SendAsync(e, "查询任务计划", msg); await SendAsync(e, "查询任务计划", msg);
return true; return true;
@ -154,6 +158,7 @@ namespace Oshima.FunGame.WebAPI.Services
// 指令处理 // 指令处理
if (e.Detail == "帮助") if (e.Detail == "帮助")
{ {
e.UseNotice = false;
await SendAsync(e, "筽祀牻", @$"欢迎使用《筽祀牻》游戏指令帮助系统! await SendAsync(e, "筽祀牻", @$"欢迎使用《筽祀牻》游戏指令帮助系统!
{FunGameInfo.FunGame_Version} {FunGameInfo.FunGame_Version}
@ -213,6 +218,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("FunGame模拟", StringComparison.CurrentCultureIgnoreCase)) if (e.Detail.StartsWith("FunGame模拟", StringComparison.CurrentCultureIgnoreCase))
{ {
e.UseNotice = false;
if (!FunGameSimulation) if (!FunGameSimulation)
{ {
FunGameSimulation = true; FunGameSimulation = true;
@ -261,6 +267,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("混战模拟")) if (e.Detail.StartsWith("混战模拟"))
{ {
e.UseNotice = false;
int maxRespawnTimesMix = 1; int maxRespawnTimesMix = 1;
string detail = e.Detail.Replace("混战模拟", "").Trim(); string detail = e.Detail.Replace("混战模拟", "").Trim();
if (int.TryParse(detail, out int times)) if (int.TryParse(detail, out int times))
@ -315,12 +322,14 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail == "上次的完整日志") if (e.Detail == "上次的完整日志")
{ {
e.UseNotice = false;
await SendAsync(e, "筽祀牻", string.Join("\r\n", Controller.GetLast())); await SendAsync(e, "筽祀牻", string.Join("\r\n", Controller.GetLast()));
return result; return result;
} }
if (e.Detail.StartsWith("FunGame团队模拟", StringComparison.CurrentCultureIgnoreCase)) if (e.Detail.StartsWith("FunGame团队模拟", StringComparison.CurrentCultureIgnoreCase))
{ {
e.UseNotice = false;
if (!FunGameSimulation) if (!FunGameSimulation)
{ {
FunGameSimulation = true; FunGameSimulation = true;
@ -373,6 +382,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("查数据", StringComparison.CurrentCultureIgnoreCase)) if (e.Detail.StartsWith("查数据", StringComparison.CurrentCultureIgnoreCase))
{ {
e.UseNotice = false;
string detail = e.Detail.Replace("查数据", "").Trim(); string detail = e.Detail.Replace("查数据", "").Trim();
if (int.TryParse(detail, out int id)) if (int.TryParse(detail, out int id))
{ {
@ -387,6 +397,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("查团队数据", StringComparison.CurrentCultureIgnoreCase)) if (e.Detail.StartsWith("查团队数据", StringComparison.CurrentCultureIgnoreCase))
{ {
e.UseNotice = false;
string detail = e.Detail.Replace("查团队数据", "").Trim(); string detail = e.Detail.Replace("查团队数据", "").Trim();
if (int.TryParse(detail, out int id)) if (int.TryParse(detail, out int id))
{ {
@ -401,6 +412,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("查个人胜率", StringComparison.CurrentCultureIgnoreCase)) if (e.Detail.StartsWith("查个人胜率", StringComparison.CurrentCultureIgnoreCase))
{ {
e.UseNotice = false;
List<string> msgs = Controller.GetWinrateRank(); List<string> msgs = Controller.GetWinrateRank();
if (msgs.Count > 0) if (msgs.Count > 0)
{ {
@ -411,6 +423,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("查团队胜率", StringComparison.CurrentCultureIgnoreCase)) if (e.Detail.StartsWith("查团队胜率", StringComparison.CurrentCultureIgnoreCase))
{ {
e.UseNotice = false;
List<string> msgs = Controller.GetWinrateRank(true); List<string> msgs = Controller.GetWinrateRank(true);
if (msgs.Count > 0) if (msgs.Count > 0)
{ {
@ -421,6 +434,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("查角色", StringComparison.CurrentCultureIgnoreCase)) if (e.Detail.StartsWith("查角色", StringComparison.CurrentCultureIgnoreCase))
{ {
e.UseNotice = false;
string detail = e.Detail.Replace("查角色", "").Trim(); string detail = e.Detail.Replace("查角色", "").Trim();
if (int.TryParse(detail, out int id)) if (int.TryParse(detail, out int id))
{ {
@ -435,6 +449,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("查技能", StringComparison.CurrentCultureIgnoreCase)) if (e.Detail.StartsWith("查技能", StringComparison.CurrentCultureIgnoreCase))
{ {
e.UseNotice = false;
string detail = e.Detail.Replace("查技能", "").Trim(); string detail = e.Detail.Replace("查技能", "").Trim();
if (int.TryParse(detail, out int id)) if (int.TryParse(detail, out int id))
{ {
@ -457,6 +472,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("查物品", StringComparison.CurrentCultureIgnoreCase)) if (e.Detail.StartsWith("查物品", StringComparison.CurrentCultureIgnoreCase))
{ {
e.UseNotice = false;
string detail = e.Detail.Replace("查物品", "").Trim(); string detail = e.Detail.Replace("查物品", "").Trim();
if (int.TryParse(detail, out int id)) if (int.TryParse(detail, out int id))
{ {
@ -479,6 +495,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("生成")) if (e.Detail.StartsWith("生成"))
{ {
e.UseNotice = false;
string pattern = @"生成\s*(\d+)\s*个\s*([\s\S]+)(?:\s*给\s*(\d+))"; string pattern = @"生成\s*(\d+)\s*个\s*([\s\S]+)(?:\s*给\s*(\d+))";
Regex regex = new(pattern, RegexOptions.IgnoreCase); Regex regex = new(pattern, RegexOptions.IgnoreCase);
Match match = regex.Match(e.Detail); Match match = regex.Match(e.Detail);
@ -513,6 +530,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail == "生成魔法卡包") if (e.Detail == "生成魔法卡包")
{ {
e.UseNotice = false;
string msg = Controller.GenerateMagicCardPack(); string msg = Controller.GenerateMagicCardPack();
if (msg != "") if (msg != "")
{ {
@ -522,6 +540,7 @@ namespace Oshima.FunGame.WebAPI.Services
} }
else if (e.Detail == "生成魔法卡") else if (e.Detail == "生成魔法卡")
{ {
e.UseNotice = false;
string msg = Controller.GenerateMagicCard(); string msg = Controller.GenerateMagicCard();
if (msg != "") if (msg != "")
{ {
@ -532,6 +551,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail == "创建存档") if (e.Detail == "创建存档")
{ {
e.UseNotice = false;
string msg = Controller.CreateSaved(name: openid); string msg = Controller.CreateSaved(name: openid);
if (msg != "") if (msg != "")
{ {
@ -552,6 +572,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail == "我的主战") if (e.Detail == "我的主战")
{ {
e.UseNotice = false;
string msg = Controller.GetCharacterInfoFromInventory(uid, 0); string msg = Controller.GetCharacterInfoFromInventory(uid, 0);
if (msg != "") if (msg != "")
{ {
@ -562,6 +583,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail == "我的状态") if (e.Detail == "我的状态")
{ {
e.UseNotice = false;
string msg = Controller.ShowMainCharacterOrSquadStatus(uid); string msg = Controller.ShowMainCharacterOrSquadStatus(uid);
if (msg != "") if (msg != "")
{ {
@ -572,6 +594,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail == "小队状态" || e.Detail == "我的小队状态") if (e.Detail == "小队状态" || e.Detail == "我的小队状态")
{ {
e.UseNotice = false;
string msg = Controller.ShowMainCharacterOrSquadStatus(uid, true); string msg = Controller.ShowMainCharacterOrSquadStatus(uid, true);
if (msg != "") if (msg != "")
{ {
@ -582,6 +605,7 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail == "我的小队") if (e.Detail == "我的小队")
{ {
e.UseNotice = false;
string msg = Controller.ShowSquad(uid); string msg = Controller.ShowSquad(uid);
if (msg != "") if (msg != "")
{ {