添加秘境挑战,优化探索奖励

This commit is contained in:
milimoe 2025-07-18 00:02:15 +08:00
parent 6957cd58e5
commit bacc342385
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
6 changed files with 604 additions and 66 deletions

View File

@ -10,4 +10,18 @@
Misfortune, Misfortune,
GreatMisfortune GreatMisfortune
} }
public enum InstanceType
{
Explore,
Currency,
Material,
RegionItem,
EXP,
CharacterLevelBreak,
SkillLevelUp,
RogueLike,
Team,
PVP
}
} }

View File

@ -24,6 +24,8 @@ namespace Oshima.FunGame.OshimaServers.Service
public static List<Item> Equipment { get; } = []; public static List<Item> Equipment { get; } = [];
public static List<Item> Items { get; } = []; public static List<Item> Items { get; } = [];
public static List<Item> DrawCardItems { get; } = []; public static List<Item> DrawCardItems { get; } = [];
public static List<Item> CharacterLevelBreakItems { get; } = [];
public static List<Item> SkillLevelUpItems { get; } = [];
public static Dictionary<OshimaRegion, List<Item>> ExploreItems { get; } = []; public static Dictionary<OshimaRegion, List<Item>> ExploreItems { get; } = [];
public static List<Skill> ItemSkills { get; } = []; public static List<Skill> ItemSkills { get; } = [];
public static List<Item> AllItems { get; } = []; public static List<Item> AllItems { get; } = [];
@ -303,6 +305,26 @@ namespace Oshima.FunGame.OshimaServers.Service
new () new ()
]; ];
private readonly static Dictionary<int, double> _precomputeTotalExperience = [];
public static Dictionary<int, double> PrecomputeTotalExperience
{
get
{
if (_precomputeTotalExperience.Count == 0)
{
double sum = 0;
_precomputeTotalExperience[0] = 0;
for (int i = 2; i <= General.GameplayEquilibriumConstant.MaxLevel; i++)
{
sum += General.GameplayEquilibriumConstant.EXPUpperLimit[i - 1];
_precomputeTotalExperience[i] = sum;
}
return _precomputeTotalExperience;
}
return _precomputeTotalExperience;
}
}
public static Dictionary<ExploreResult, double> ExploreResultProbabilities { get; } = new() public static Dictionary<ExploreResult, double> ExploreResultProbabilities { get; } = new()
{ {
{ ExploreResult.General, 0.45 }, { ExploreResult.General, 0.45 },
@ -376,6 +398,8 @@ namespace Oshima.FunGame.OshimaServers.Service
{ QualityType.Gold, (67000, 130000) } { QualityType.Gold, (67000, 130000) }
}; };
public static string[] GreekAlphabet { get; } = ["α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "σ", "τ", "υ", "φ", "χ", "ψ", "ω"];
public static string[] CommonSurnames { get; } = [ public static string[] CommonSurnames { get; } = [
"顾", "沈", "陆", "楚", "白", "苏", "叶", "萧", "莫", "司马", "欧阳", "顾", "沈", "陆", "楚", "白", "苏", "叶", "萧", "莫", "司马", "欧阳",
"上官", "慕容", "尉迟", "司徒", "轩辕", "端木", "南宫", "长孙", "百里", "上官", "慕容", "尉迟", "司徒", "轩辕", "端木", "南宫", "长孙", "百里",

View File

@ -69,7 +69,7 @@
{"生命之泉", "使用金币回复角色状态"}, {"生命之泉", "使用金币回复角色状态"},
}; };
public static Dictionary<string, string> QuestHelp { get; } = new() { public static Dictionary<string, string> PlayHelp { get; } = new() {
{"任务列表", "查看今日任务列表"}, {"任务列表", "查看今日任务列表"},
{"做任务 <任务序号>", "开始指定任务"}, {"做任务 <任务序号>", "开始指定任务"},
{"任务信息", "查看进行中任务详情"}, {"任务信息", "查看进行中任务详情"},
@ -79,6 +79,12 @@
{"查地区 <地区序号>", "查看指定地区信息"}, {"查地区 <地区序号>", "查看指定地区信息"},
{"探索 <地区序号> <{角色序号...}>", "探索指定地区(可多角色)"}, {"探索 <地区序号> <{角色序号...}>", "探索指定地区(可多角色)"},
{"探索结算", "结算所有未完成的探索"}, {"探索结算", "结算所有未完成的探索"},
{"挑战金币秘境 <难度>", "以小队挑战金币秘境秘境难度1-5"},
{"挑战材料秘境 <难度>", "以小队挑战材料秘境秘境难度1-5"},
{"挑战经验秘境 <难度>", "以小队挑战经验秘境秘境难度1-5"},
{"挑战地区秘境 <难度>", "以小队挑战地区锻造材料秘境秘境难度1-5"},
{"挑战突破秘境 <难度>", "以小队挑战角色突破材料秘境秘境难度1-5"},
{"挑战技能秘境 <难度>", "以小队挑战技能升级材料秘境秘境难度1-5"},
}; };
public static Dictionary<string, string> ClubHelp { get; } = new() { public static Dictionary<string, string> ClubHelp { get; } = new() {

View File

@ -1,3 +1,4 @@
using System.Reflection;
using System.Text; using System.Text;
using Milimoe.FunGame.Core.Api.Transmittal; using Milimoe.FunGame.Core.Api.Transmittal;
using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Api.Utility;
@ -76,6 +77,8 @@ namespace Oshima.FunGame.OshimaServers.Service
} }
FunGameConstant.DrawCardItems.AddRange(FunGameConstant.AllItems.Where(i => !FunGameConstant.ItemCanNotDrawCard.Contains(i.ItemType))); 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.AllItems.AddRange(FunGameConstant.ExploreItems.Values.SelectMany(list => list)); FunGameConstant.AllItems.AddRange(FunGameConstant.ExploreItems.Values.SelectMany(list => list));
@ -1961,22 +1964,7 @@ namespace Oshima.FunGame.OshimaServers.Service
{ {
if (FunGameConstant.AllItems.FirstOrDefault(i => i.Name == item.Name) != null) if (FunGameConstant.AllItems.FirstOrDefault(i => i.Name == item.Name) != null)
{ {
Item newItem = item.Copy(); AddItemToUserInventory(user, item);
newItem.User = user;
if (newItem.QualityType >= QualityType.Orange) newItem.IsLock = true;
SetSellAndTradeTime(newItem);
int min = 0, max = 0;
if (FunGameConstant.PriceRanges.TryGetValue(item.QualityType, out (int Min, int Max) range))
{
(min, max) = (range.Min, range.Max);
}
double price = Random.Shared.Next(min, max) * 0.35;
newItem.Price = price;
user.Inventory.Items.Add(newItem);
// 连接到任务系统
AddExploreItemCache(user.Id, item.Name);
// 连接到活动系统
ActivitiesItemCache.Add(item.Name);
} }
} }
} }
@ -2556,7 +2544,7 @@ 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(100, 300) * diff; exp += Random.Shared.Next(300, 750) * diff;
} }
model.Awards["exp"] = exp; model.Awards["exp"] = exp;
exploreString += $"额外获得了:{exp} 点经验值(探索队员们平分)!"; exploreString += $"额外获得了:{exp} 点经验值(探索队员们平分)!";
@ -2595,7 +2583,8 @@ namespace Oshima.FunGame.OshimaServers.Service
// 开始战斗 // 开始战斗
Team team1 = new($"{user.Username}的探索小队", squad); Team team1 = new($"{user.Username}的探索小队", squad);
Team team2 = new($"{region.Name}", enemys); Team team2 = new($"{region.Name}", enemys);
List<string> msgs = await FunGameActionQueue.NewAndStartTeamGame([team1, team2], showAllRound: true); FunGameActionQueue actionQueue = new();
List<string> msgs = await actionQueue.StartTeamGame([team1, team2], showAllRound: true);
if (msgs.Count > 2) if (msgs.Count > 2)
{ {
msgs = msgs[^2..]; msgs = msgs[^2..];
@ -2608,11 +2597,15 @@ namespace Oshima.FunGame.OshimaServers.Service
{ {
credits += Random.Shared.Next(400, 650) * diff; credits += Random.Shared.Next(400, 650) * diff;
} }
if (actionQueue.GamingQueue.EarnedMoney.Count > 0)
{
credits += actionQueue.GamingQueue.EarnedMoney.Where(kv => squad.Contains(kv.Key)).Sum(kv => kv.Value);
}
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(250, 520) * diff; exp += Random.Shared.Next(370, 860) * diff;
} }
model.Awards["exp"] = exp; model.Awards["exp"] = exp;
int materials = 0; int materials = 0;
@ -2628,7 +2621,7 @@ namespace Oshima.FunGame.OshimaServers.Service
count += Math.Max(1, Random.Shared.Next(1, 4) * diff / 2); count += Math.Max(1, Random.Shared.Next(1, 4) * diff / 2);
} }
model.Awards[item.Name] = count; model.Awards[item.Name] = count;
award = $"{credits} {General.GameplayEquilibriumConstant.InGameCurrency}" + $"{exp} 点经验值(探索队员们平分)," + award = $"{credits} {General.GameplayEquilibriumConstant.InGameCurrency}(包含战斗中击杀奖励)" + $"{exp} 点经验值(探索队员们平分)," +
$"{materials} {General.GameplayEquilibriumConstant.InGameMaterial}" + $"以及 {count} 个{item.Name}"; $"{materials} {General.GameplayEquilibriumConstant.InGameMaterial}" + $"以及 {count} 个{item.Name}";
if (Random.Shared.NextDouble() > 0.6) if (Random.Shared.NextDouble() > 0.6)
{ {
@ -2751,22 +2744,7 @@ namespace Oshima.FunGame.OshimaServers.Service
{ {
for (int i = 0; i < model.Awards[name]; i++) for (int i = 0; i < model.Awards[name]; i++)
{ {
Item newItem = item.Copy(); AddItemToUserInventory(user, item);
newItem.User = user;
if (newItem.QualityType >= QualityType.Orange) newItem.IsLock = true;
SetSellAndTradeTime(newItem);
int min = 0, max = 0;
if (FunGameConstant.PriceRanges.TryGetValue(item.QualityType, out (int Min, int Max) range))
{
(min, max) = (range.Min, range.Max);
}
double price = Random.Shared.Next(min, max) * 0.35;
newItem.Price = price;
user.Inventory.Items.Add(newItem);
// 连接到任务系统
AddExploreItemCache(user.Id, item.Name);
// 连接到活动系统
ActivitiesItemCache.Add(item.Name);
} }
} }
} }
@ -3350,5 +3328,345 @@ namespace Oshima.FunGame.OshimaServers.Service
} }
return "服务器繁忙,请稍后再试。"; 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)
{
Item newItem = item.Copy();
newItem.User = user;
if (hasLock && newItem.QualityType >= QualityType.Orange) newItem.IsLock = true;
if (hasSellAndTradeTime) SetSellAndTradeTime(newItem);
if (hasPrice)
{
if (price == 0)
{
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;
}
newItem.Price = price;
}
user.Inventory.Items.Add(newItem);
// 连接到任务系统
if (toExploreCache) AddExploreItemCache(user.Id, item.Name);
// 连接到活动系统
if (toActivitiesCache) ActivitiesItemCache.Add(item.Name);
}
public static async Task<string> FightInstance(InstanceType type, int difficulty, User user, Character[] squad)
{
if (difficulty <= 0) difficulty = 1;
else if (difficulty > 5) difficulty = 5;
StringBuilder builder = new();
// 生成敌人
int enemyCount = difficulty switch
{
1 => 2,
2 => 3,
3 => 4,
4 => 5,
_ => 6
};
List<Character> enemys = [];
for (int i = 0; i < enemyCount; i++)
{
Character? enemy = FunGameConstant.Regions.SelectMany(r => r.Units).OrderBy(o => Random.Shared.Next()).FirstOrDefault();
if (enemy != null)
{
enemy = enemy.Copy();
int dcount = enemys.Count(e => e.Name == enemy.Name);
if (dcount > 0 && FunGameConstant.GreekAlphabet.Length > dcount) enemy.Name += FunGameConstant.GreekAlphabet[dcount - 1];
enemys.Add(enemy);
}
}
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)];
Item[] accessory = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("14") && (int)i.QualityType == 5)];
Item[] consumables = [.. FunGameConstant.AllItems.Where(i => i.ItemType == ItemType.Consumable && i.IsInGameItem)];
int cLevel = difficulty * 8;
int sLevel = difficulty;
int mLevel = difficulty + 1;
int naLevel = mLevel;
foreach (Character enemy_loop in enemys)
{
EnhanceBoss(enemy_loop, weapons, armors, shoes, accessory, consumables, cLevel, sLevel, mLevel, naLevel, false, false, true);
}
// 开始战斗
Team team1 = new($"{user.Username}的小队", squad);
Team team2 = new($"{General.GameplayEquilibriumConstant.InGameCurrency}秘境", enemys);
FunGameActionQueue actionQueue = new();
List<string> msgs = await actionQueue.StartTeamGame([team1, team2], showAllRound: true);
if (msgs.Count > 2)
{
msgs = msgs[^2..];
}
int award = 0;
int characterCount = squad.Length;
builder.AppendLine($"☆--- {team2.Name}挑战 ---☆");
builder.AppendLine(string.Join("\r\n", msgs));
if (enemys.All(c => c.HP <= 0))
{
builder.Append($"探索小队战胜了敌人!获得了:");
switch (type)
{
case InstanceType.Currency:
for (int i = 0; i < characterCount; i++)
{
award += Random.Shared.Next(550, 1050) * difficulty;
}
user.Inventory.Credits += award;
// 这个只是展示,实际上在战斗过程中已经加过了
if (actionQueue.GamingQueue.EarnedMoney.Count > 0)
{
award += actionQueue.GamingQueue.EarnedMoney.Where(kv => squad.Contains(kv.Key)).Sum(kv => kv.Value);
}
builder.AppendLine($"{award} {General.GameplayEquilibriumConstant.InGameCurrency}(包含战斗中击杀奖励)!");
break;
case InstanceType.Material:
for (int i = 0; i < characterCount; i++)
{
award += Random.Shared.Next(4, 9) * difficulty;
}
user.Inventory.Materials += award;
builder.AppendLine($"{award} {General.GameplayEquilibriumConstant.InGameMaterial}");
break;
case InstanceType.EXP:
for (int i = 0; i < characterCount; i++)
{
award += Random.Shared.Next(570, 1260) * difficulty;
}
double overflowExp = 0;
double avgExp = award / characterCount;
int small = 0, medium = 0, large = 0;
award = 0;
foreach (Character character in squad)
{
double currentExp = FunGameConstant.PrecomputeTotalExperience[character.Level] + character.EXP;
if (currentExp + avgExp > FunGameConstant.PrecomputeTotalExperience[General.GameplayEquilibriumConstant.MaxLevel])
{
overflowExp = Math.Min(FunGameConstant.PrecomputeTotalExperience[General.GameplayEquilibriumConstant.MaxLevel], currentExp) + avgExp - FunGameConstant.PrecomputeTotalExperience[General.GameplayEquilibriumConstant.MaxLevel];
while (overflowExp > 0)
{
if (overflowExp >= 1000)
{
large++;
overflowExp -= 1000;
}
else if (overflowExp >= 500)
{
medium++;
overflowExp -= 500;
}
else if (overflowExp >= 200)
{
small++;
overflowExp -= 200;
}
else
{
small++;
overflowExp = 0;
}
}
}
else
{
character.EXP += avgExp;
award += (int)avgExp;
}
}
List<string> expBook = [];
if (large > 0)
{
expBook.Add($"{large} 个大经验书");
for (int i = 0; i < large; i++)
{
AddItemToUserInventory(user, new ());
}
}
if (medium > 0)
{
expBook.Add($"{medium} 个中经验书");
for (int i = 0; i < medium; i++)
{
AddItemToUserInventory(user, new ());
}
}
if (small > 0)
{
expBook.Add($"{small} 个小经验书");
for (int i = 0; i < small; i++)
{
AddItemToUserInventory(user, new ());
}
}
builder.AppendLine($"{award} 点经验值(分配给经验未满的角色们){(expBook.Count > 0 ? $"{string.Join("、", expBook)}" : "")}");
break;
case InstanceType.RegionItem:
List<string> 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);
}
builder.AppendLine($"{string.Join("", regionItems)}");
break;
case InstanceType.CharacterLevelBreak:
List<string> 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);
}
builder.AppendLine($"{string.Join("", characterLevelBreakItems)}");
break;
case InstanceType.SkillLevelUp:
List<string> 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);
}
builder.AppendLine($"{string.Join("", skillLevelUpItems)}");
break;
default:
break;
}
}
else
{
builder.Append($"小队未能战胜敌人,");
IEnumerable<Character> deadEnemys = enemys.Where(c => c.HP <= 0);
if (!deadEnemys.Any())
{
builder.AppendLine("无法获取秘境奖励!");
}
else
{
builder.Append("但是获得了战斗失败补偿:");
// 根据死亡敌人的数量生成补偿奖励
int count = deadEnemys.Count();
switch (type)
{
case InstanceType.Currency:
award = 100 * difficulty * count;
user.Inventory.Credits += award;
// 这个只是展示,实际上在战斗过程中已经加过了
if (actionQueue.GamingQueue.EarnedMoney.Count > 0)
{
award += actionQueue.GamingQueue.EarnedMoney.Where(kv => squad.Contains(kv.Key)).Sum(kv => kv.Value);
}
builder.AppendLine($"{award} {General.GameplayEquilibriumConstant.InGameCurrency}(包含战斗中击杀奖励)!");
break;
case InstanceType.Material:
award = (int)(0.5 * difficulty * count);
if (award <= 0) award = 1;
user.Inventory.Materials += award;
builder.AppendLine($"{award} {General.GameplayEquilibriumConstant.InGameMaterial}");
break;
case InstanceType.EXP:
award = 300 * difficulty * count;
double overflowExp = 0;
double avgExp = (award / characterCount);
int small = 0, medium = 0, large = 0;
award = 0;
foreach (Character character in squad)
{
double currentExp = FunGameConstant.PrecomputeTotalExperience[character.Level] + character.EXP;
if (currentExp + avgExp > FunGameConstant.PrecomputeTotalExperience[General.GameplayEquilibriumConstant.MaxLevel])
{
overflowExp = Math.Min(FunGameConstant.PrecomputeTotalExperience[General.GameplayEquilibriumConstant.MaxLevel], currentExp) + avgExp - FunGameConstant.PrecomputeTotalExperience[General.GameplayEquilibriumConstant.MaxLevel];
while (overflowExp > 0)
{
if (overflowExp >= 1000)
{
large++;
overflowExp -= 1000;
}
else if (overflowExp >= 500)
{
medium++;
overflowExp -= 500;
}
else if (overflowExp >= 200)
{
small++;
overflowExp -= 200;
}
else
{
small++;
overflowExp = 0;
}
}
}
else
{
character.EXP += avgExp;
award += (int)avgExp;
}
}
List<string> expBook = [];
if (large > 0)
{
expBook.Add($"{large} 个大经验书");
for (int i = 0; i < large; i++)
{
AddItemToUserInventory(user, new ());
}
}
if (medium > 0)
{
expBook.Add($"{medium} 个中经验书");
for (int i = 0; i < medium; i++)
{
AddItemToUserInventory(user, new ());
}
}
if (small > 0)
{
expBook.Add($"{small} 个小经验书");
for (int i = 0; i < small; i++)
{
AddItemToUserInventory(user, new ());
}
}
builder.AppendLine($"{award} 点经验值(分配给经验未满的角色们){(expBook.Count > 0 ? $"{string.Join("、", expBook)}" : "")}");
break;
case InstanceType.RegionItem:
List<string> 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)];
award = 1;
regionItems.Add($"{award} 个 {item.Name}(来自{region.Name}");
AddItemToUserInventory(user, item);
}
builder.AppendLine($"{string.Join("", regionItems)}");
break;
default:
break;
}
}
}
return builder.ToString().Trim();
}
} }
} }

View File

@ -10,6 +10,7 @@ using Milimoe.FunGame.Core.Library.Common.Event;
using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Library.SQLScript.Entity; using Milimoe.FunGame.Core.Library.SQLScript.Entity;
using Oshima.Core.Configs; using Oshima.Core.Configs;
using Oshima.Core.Constant;
using Oshima.FunGame.OshimaModules.Characters; using Oshima.FunGame.OshimaModules.Characters;
using Oshima.FunGame.OshimaModules.Items; using Oshima.FunGame.OshimaModules.Items;
using Oshima.FunGame.OshimaModules.Regions; using Oshima.FunGame.OshimaModules.Regions;
@ -1703,10 +1704,10 @@ namespace Oshima.FunGame.WebAPI.Controllers
itemsCanUsedIndex = string.Join("", itemsCanUsed.Select(kv => kv.Key)); itemsCanUsedIndex = string.Join("", itemsCanUsed.Select(kv => kv.Key));
} }
var itemsSellable = items.Where(kv => kv.Value.IsSellable); var itemsSellable = items.Where(kv => kv.Value.IsSellable && !kv.Value.IsLock);
string itemsSellableIndex = string.Join("", itemsSellable.Select(kv => kv.Key)); string itemsSellableIndex = string.Join("", itemsSellable.Select(kv => kv.Key));
var itemsTradable = items.Where(kv => kv.Value.IsTradable); var itemsTradable = items.Where(kv => kv.Value.IsTradable && !kv.Value.IsLock);
string itemsTradableIndex = string.Join("", itemsTradable.Select(kv => kv.Key)); string itemsTradableIndex = string.Join("", itemsTradable.Select(kv => kv.Key));
str += $"物品序号:{itemsIndex}\r\n"; str += $"物品序号:{itemsIndex}\r\n";
@ -6808,9 +6809,12 @@ namespace Oshima.FunGame.WebAPI.Controllers
msg = "你没有权限使用此指令。"; msg = "你没有权限使用此指令。";
} }
if (user.Id != target)
{
user.LastTime = DateTime.Now; user.LastTime = DateTime.Now;
pc.Add("user", user); pc.Add("user", user);
pc.SaveConfig(); pc.SaveConfig();
}
return msg; return msg;
} }
@ -6924,6 +6928,90 @@ namespace Oshima.FunGame.WebAPI.Controllers
} }
} }
[HttpPost("fightinstance")]
public async Task<string> FightInstance([FromQuery] long? uid = null, [FromQuery] int type = 0, [FromQuery] int difficulty = 1)
{
long userid = uid ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11));
try
{
PluginConfig pc = new("saved", userid.ToString());
pc.LoadConfig();
string msg = "";
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
int exploreTimes = 0;
int[] supportedInstanceType = [(int)InstanceType.Currency, (int)InstanceType.Material, (int)InstanceType.EXP, (int)InstanceType.RegionItem];
if (!supportedInstanceType.Contains(type))
{
msg = $"秘境类型无效。";
}
else if (user.Inventory.Squad.Count == 0)
{
msg = $"你尚未设置小队请先设置1-4名角色";
}
else
{
Character[] squad = [.. user.Inventory.Characters.Where(c => user.Inventory.Squad.Contains(c.Id))];
if (squad.All(c => c.HP < c.MaxHP * 0.1))
{
msg = $"小队角色均重伤未愈,当前生命值低于 10%,请先等待生命值自动回复或重组小队!\r\n" +
$"当前小队角色如下:\r\n{FunGameService.GetSquadInfo(user.Inventory.Characters, user.Inventory.Squad)}";
}
else
{
// 检查探索许可
int reduce = difficulty * squad.Length;
if (pc.TryGetValue("exploreTimes", out object? value) && int.TryParse(value.ToString(), out exploreTimes))
{
if (exploreTimes <= 0)
{
exploreTimes = 0;
msg = $"今日的探索许可已用完,无法再继续挑战秘境。";
}
else if (reduce > exploreTimes)
{
msg = $"本次秘境挑战需要消耗 {reduce} 个探索许可,超过了你的剩余探索许可数量({exploreTimes} 个),请减少小队的角色数量或更改难度系数。" +
$"\r\n需要注意难度系数一比一兑换探索许可并且参与挑战的角色都需要消耗相同数量的探索许可。";
}
}
else
{
exploreTimes = FunGameConstant.MaxExploreTimes;
}
if (msg == "")
{
exploreTimes -= reduce;
msg = await FunGameService.FightInstance((InstanceType)type, difficulty, user, squad);
if (msg != "") msg += "\r\n";
msg += $"本次秘境挑战消耗探索许可 {reduce} 个,你的剩余探索许可:{exploreTimes} 个。";
}
}
}
user.LastTime = DateTime.Now;
pc.Add("user", user);
pc.Add("exploreTimes", exploreTimes);
pc.SaveConfig();
return msg;
}
else
{
return noSaved;
}
}
catch (Exception e)
{
Logger.LogError(e, "Error: {e}", e);
return busy;
}
}
[HttpPost("template")] [HttpPost("template")]
public string Template([FromQuery] long? uid = null) public string Template([FromQuery] long? uid = null)
{ {

View File

@ -7,6 +7,7 @@ using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Entity;
using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Library.Constant;
using Oshima.Core.Configs; using Oshima.Core.Configs;
using Oshima.Core.Constant;
using Oshima.FunGame.OshimaServers.Service; using Oshima.FunGame.OshimaServers.Service;
using Oshima.FunGame.WebAPI.Constant; using Oshima.FunGame.WebAPI.Constant;
using Oshima.FunGame.WebAPI.Controllers; using Oshima.FunGame.WebAPI.Controllers;
@ -30,7 +31,7 @@ namespace Oshima.FunGame.WebAPI.Services
Statics.RunningPlugin?.Controller.WriteLine(title, Milimoe.FunGame.Core.Library.Constant.LogLevel.Debug); Statics.RunningPlugin?.Controller.WriteLine(title, Milimoe.FunGame.Core.Library.Constant.LogLevel.Debug);
if (msg is ThirdPartyMessage third) if (msg is ThirdPartyMessage third)
{ {
third.Result = "\r\n" + content.Trim(); third.Result += "\r\n" + content.Trim();
third.IsCompleted = true; third.IsCompleted = true;
return; return;
} }
@ -168,7 +169,7 @@ namespace Oshima.FunGame.WebAPI.Services
2 2
3 3
4 4
5 5
6 6
7 7
8 8
@ -195,10 +196,10 @@ namespace Oshima.FunGame.WebAPI.Services
int page = e.Detail.Length > 4 && int.TryParse(e.Detail[4..], out int p) ? p : 1; int page = e.Detail.Length > 4 && int.TryParse(e.Detail[4..], out int p) ? p : 1;
await SendHelp(e, FunGameOrderList.BattleHelp, "战斗帮助", page); await SendHelp(e, FunGameOrderList.BattleHelp, "战斗帮助", page);
} }
else if (e.Detail.StartsWith("任务帮助")) else if (e.Detail.StartsWith("玩法帮助"))
{ {
int page = e.Detail.Length > 4 && int.TryParse(e.Detail[4..], out int p) ? p : 1; int page = e.Detail.Length > 4 && int.TryParse(e.Detail[4..], out int p) ? p : 1;
await SendHelp(e, FunGameOrderList.QuestHelp, "任务帮助", page); await SendHelp(e, FunGameOrderList.PlayHelp, "玩法帮助", page);
} }
else if (e.Detail.StartsWith("社团帮助")) else if (e.Detail.StartsWith("社团帮助"))
{ {
@ -496,40 +497,35 @@ namespace Oshima.FunGame.WebAPI.Services
if (e.Detail.StartsWith("生成指定")) if (e.Detail.StartsWith("生成指定"))
{ {
e.UseNotice = false; e.UseNotice = false;
string pattern = @"生成指定(\w+)魔法卡\s*(\d+)\s*(?:(\d+)\s+(\d+)\s+(\d+)(?:\s+(\d+))?)?(?:\s+(\d+))?(?:\s*给\s*(\d+))?"; string pattern = @"生成指定(\w+)魔法卡\s*(\d+)(?:(?:\s*(\d+)\s+(\d+)\s+(\d+)(?:\s+(\d+))?)|(?:\s*(\d+)(?!\s*\d)))?(?:\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);
if (match.Success) if (match.Success && ((match.Groups[3].Success && match.Groups[4].Success && match.Groups[5].Success) || match.Groups[7].Success))
{ {
string quality = match.Groups[1].Value; string quality = match.Groups[1].Value;
long magicID = long.Parse(match.Groups[2].Value); long magicID = long.Parse(match.Groups[2].Value);
int paramCount = match.Groups.Cast<Group>().Count(g => g.Success && g.Index > match.Groups[2].Index && g.Index < (match.Groups[8].Success ? match.Groups[8].Index : int.MaxValue));
int str = 0, agi = 0, intelligence = 0, count = 1; int str = 0, agi = 0, intelligence = 0, count = 1;
long targetUserID = uid; long targetUserID = uid;
// 检查参数数量的有效性 // 检查是否匹配到 str agi intelligence 模式 (Group 3, 4, 5)
if (paramCount != 0 && paramCount != 1 && paramCount != 3 && paramCount != 4) if (match.Groups[3].Success && match.Groups[4].Success && match.Groups[5].Success)
{
await SendAsync(e, "熟圣之力", "参数数量错误!可选参数必须为 1个count、3个str, agi, intelligence或4个str, agi, intelligence, count。");
return result;
}
if (paramCount == 1)
{
count = int.Parse(match.Groups[6].Success ? match.Groups[6].Value : match.Groups[7].Value);
}
else if (paramCount == 3 || paramCount == 4)
{ {
str = int.Parse(match.Groups[3].Value); str = int.Parse(match.Groups[3].Value);
agi = int.Parse(match.Groups[4].Value); agi = int.Parse(match.Groups[4].Value);
intelligence = int.Parse(match.Groups[5].Value); intelligence = int.Parse(match.Groups[5].Value);
if (paramCount == 4)
// 如果此模式下有 count (Group 6)
if (match.Groups[6].Success)
{ {
count = int.Parse(match.Groups[6].Value); count = int.Parse(match.Groups[6].Value);
} }
} }
// 否则,检查是否匹配到单独的 count 模式 (Group 7)
else if (match.Groups[7].Success)
{
count = int.Parse(match.Groups[7].Value);
}
if (count <= 0) if (count <= 0)
{ {
@ -550,7 +546,8 @@ namespace Oshima.FunGame.WebAPI.Services
} }
else else
{ {
await SendAsync(e, "熟圣之力", "指令格式错误!正确格式:生成指定<品质>魔法卡 <MagicID> [str agi intelligence] [count]"); await SendAsync(e, "熟圣之力", "指令格式错误!请检查格式:\r\n1、生成指定<品质>魔法卡 <MagicID> [str agi intelligence] [count] [给 <TargetID>]\r\n" +
"2、生成指定<品质>魔法卡 <MagicID> [count] [给 <TargetID>]\r\n注意[str agi intelligence] 可选块的三个参数都必须完整提供。");
} }
return result; return result;
} }
@ -1578,7 +1575,7 @@ namespace Oshima.FunGame.WebAPI.Services
msgs = await Controller.FightCustom2(uid, detail.Trim(), true); msgs = await Controller.FightCustom2(uid, detail.Trim(), true);
} }
List<string> real = []; List<string> real = [];
if (msgs.Count >= 2) if (msgs.Count > 2)
{ {
if (msgs.Count < 20) if (msgs.Count < 20)
{ {
@ -1602,8 +1599,9 @@ namespace Oshima.FunGame.WebAPI.Services
} }
else else
{ {
real.Add(msgs[^2]); real.Add(string.Join("\r\n", msgs[^8..^2]));
} }
real.Add(msgs[^2]);
real.Add(msgs[^1]); real.Add(msgs[^1]);
} }
else else
@ -2634,6 +2632,96 @@ namespace Oshima.FunGame.WebAPI.Services
return result; return result;
} }
if (e.Detail.StartsWith("挑战金币秘境"))
{
string detail = e.Detail.Replace("挑战金币秘境", "").Trim();
string msg = "";
if (int.TryParse(detail, out int diff))
{
msg = await Controller.FightInstance(uid, (int)InstanceType.Currency, diff);
if (msg.Trim() != "")
{
await SendAsync(e, "挑战金币秘境", msg);
}
}
return result;
}
if (e.Detail.StartsWith("挑战材料秘境"))
{
string detail = e.Detail.Replace("挑战材料秘境", "").Trim();
string msg = "";
if (int.TryParse(detail, out int diff))
{
msg = await Controller.FightInstance(uid, (int)InstanceType.Material, diff);
if (msg.Trim() != "")
{
await SendAsync(e, "挑战材料秘境", msg);
}
}
return result;
}
if (e.Detail.StartsWith("挑战经验秘境"))
{
string detail = e.Detail.Replace("挑战经验秘境", "").Trim();
string msg = "";
if (int.TryParse(detail, out int diff))
{
msg = await Controller.FightInstance(uid, (int)InstanceType.EXP, diff);
if (msg.Trim() != "")
{
await SendAsync(e, "挑战经验秘境", msg);
}
}
return result;
}
if (e.Detail.StartsWith("挑战地区秘境"))
{
string detail = e.Detail.Replace("挑战地区秘境", "").Trim();
string msg = "";
if (int.TryParse(detail, out int diff))
{
msg = await Controller.FightInstance(uid, (int)InstanceType.RegionItem, diff);
if (msg.Trim() != "")
{
await SendAsync(e, "挑战地区秘境", msg);
}
}
return result;
}
if (e.Detail.StartsWith("挑战突破秘境"))
{
string detail = e.Detail.Replace("挑战突破秘境", "").Trim();
string msg = "";
if (int.TryParse(detail, out int diff))
{
msg = await Controller.FightInstance(uid, (int)InstanceType.CharacterLevelBreak, diff);
if (msg.Trim() != "")
{
await SendAsync(e, "挑战突破秘境", msg);
}
}
return result;
}
if (e.Detail.StartsWith("挑战技能秘境"))
{
string detail = e.Detail.Replace("挑战技能秘境", "").Trim();
string msg = "";
if (int.TryParse(detail, out int diff))
{
msg = await Controller.FightInstance(uid, (int)InstanceType.SkillLevelUp, diff);
if (msg.Trim() != "")
{
await SendAsync(e, "挑战技能秘境", msg);
}
}
return result;
}
if (uid == GeneralSettings.Master && e.Detail.StartsWith("重载FunGame", StringComparison.CurrentCultureIgnoreCase)) if (uid == GeneralSettings.Master && e.Detail.StartsWith("重载FunGame", StringComparison.CurrentCultureIgnoreCase))
{ {
string msg = Controller.Relaod(uid); string msg = Controller.Relaod(uid);