优化角色系统、探索系统、魔法卡生成功能;添加酒馆功能和生成指定魔法卡功能

This commit is contained in:
milimoe 2025-07-17 01:20:52 +08:00
parent 485a8a0118
commit 5f52730115
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
5 changed files with 332 additions and 103 deletions

View File

@ -6,7 +6,7 @@ namespace Oshima.FunGame.OshimaModules.Characters
{ {
public class CustomCharacter : Character public class CustomCharacter : Character
{ {
public CustomCharacter(long user_id, string name, string firstname = "", string nickname = "") : base() public CustomCharacter(long user_id, string name, string firstname = "", string nickname = "", PrimaryAttribute primaryAttribute = PrimaryAttribute.None) : base()
{ {
Id = user_id; Id = user_id;
Name = name; Name = name;
@ -17,8 +17,34 @@ namespace Oshima.FunGame.OshimaModules.Characters
InitialHP = Random.Shared.Next(40, 86); InitialHP = Random.Shared.Next(40, 86);
InitialMP = Random.Shared.Next(20, 56); InitialMP = Random.Shared.Next(20, 56);
int value = 31; int reduce = 0;
int valueGrowth = 31; int reduceGrowth = 0;
if (primaryAttribute != PrimaryAttribute.None)
{
int attribute= Random.Shared.Next(15, 31);
int growth = Random.Shared.Next(15, 31);
switch (primaryAttribute)
{
case PrimaryAttribute.STR:
InitialSTR = attribute;
STRGrowth = Calculation.Round(Convert.ToDouble(growth) / 10, 2);
break;
case PrimaryAttribute.AGI:
InitialAGI = attribute;
AGIGrowth = Calculation.Round(Convert.ToDouble(growth) / 10, 2);
break;
case PrimaryAttribute.INT:
InitialINT = attribute;
INTGrowth = Calculation.Round(Convert.ToDouble(growth) / 10, 2);
break;
}
PrimaryAttribute = primaryAttribute;
reduce = attribute;
reduceGrowth = growth;
}
int value = 31 - reduce;
int valueGrowth = 31 - reduceGrowth;
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
{ {
if (value == 0) break; if (value == 0) break;
@ -27,15 +53,18 @@ namespace Oshima.FunGame.OshimaModules.Characters
switch (i) switch (i)
{ {
case 1: case 1:
if (primaryAttribute == PrimaryAttribute.AGI) continue;
InitialAGI = attribute; InitialAGI = attribute;
AGIGrowth = Calculation.Round(Convert.ToDouble(growth) / 10, 2); AGIGrowth = Calculation.Round(Convert.ToDouble(growth) / 10, 2);
break; break;
case 2: case 2:
if (primaryAttribute == PrimaryAttribute.INT) continue;
InitialINT = attribute; InitialINT = attribute;
INTGrowth = Calculation.Round(Convert.ToDouble(growth) / 10, 2); INTGrowth = Calculation.Round(Convert.ToDouble(growth) / 10, 2);
break; break;
case 0: case 0:
default: default:
if (primaryAttribute == PrimaryAttribute.STR) continue;
InitialSTR = attribute; InitialSTR = attribute;
STRGrowth = Calculation.Round(Convert.ToDouble(growth) / 10, 2); STRGrowth = Calculation.Round(Convert.ToDouble(growth) / 10, 2);
break; break;

View File

@ -24,7 +24,7 @@ namespace Oshima.FunGame.OshimaModules.Skills
{ {
public override long Id => Skill.Id; public override long Id => Skill.Id;
public override string Name => Skill.Name; public override string Name => Skill.Name;
public override string Description => $"每次普通攻击都将附带基于 {敏捷系数 * 100:0.##}% 敏捷 [ {敏捷伤害} ] 的魔法伤害。"; public override string Description => $"每次普通攻击都将附带基于 {敏捷系数 * 100:0.##}% 敏捷 [ {敏捷伤害:0.##} ] 点魔法伤害。";
private double => * Skill.Character?.AGI ?? 0; private double => * Skill.Character?.AGI ?? 0;
private readonly double = 2.5; private readonly double = 2.5;

View File

@ -122,96 +122,47 @@ namespace Oshima.FunGame.OshimaServers.Service
FunGameConstant.AllSkills.AddRange(FunGameConstant.SuperSkills); FunGameConstant.AllSkills.AddRange(FunGameConstant.SuperSkills);
} }
public static List<Item> GenerateMagicCards(int count, QualityType? qualityType = null) public static List<Item> GenerateMagicCards(int count, QualityType? qualityType = null, long[]? magicIds = null, (int str, int agi, int intelligence)[]? values = null)
{ {
List<Item> items = []; List<Item> items = [];
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
items.Add(GenerateMagicCard(qualityType)); long magicId = 0;
if (magicIds != null && magicIds.Length > i) magicId = magicIds[i];
(int str, int agi, int intelligence) = (0, 0, 0);
if (values != null && values.Length > i)
{
str = values[i].str;
agi = values[i].agi;
intelligence = values[i].intelligence;
}
items.Add(GenerateMagicCard(qualityType, magicId, str, agi, intelligence));
} }
return items; return items;
} }
public static Item GenerateMagicCard(QualityType? qualityType = null) public static Item GenerateMagicCard(QualityType? qualityType = null, long magicId = 0, int str = 0, int agi = 0, int intelligence = 0)
{ {
Item item = Factory.GetItem(); Item item = Factory.GetItem();
item.Id = Convert.ToInt64("16" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 8)); item.Id = Convert.ToInt64("16" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 8));
item.Name = GenerateRandomChineseName(); item.Name = GenerateRandomChineseName();
item.ItemType = ItemType.MagicCard; item.ItemType = ItemType.MagicCard;
item.RemainUseTimes = 1; item.RemainUseTimes = 1;
if (qualityType != null) item.QualityType = qualityType.Value;
int total; GenerateAndAddSkillToMagicCard(item, magicId, str, agi, intelligence);
if (qualityType != null)
{
total = qualityType switch
{
QualityType.Green => Random.Shared.Next(7, 13),
QualityType.Blue => Random.Shared.Next(13, 19),
QualityType.Purple => Random.Shared.Next(19, 25),
QualityType.Orange => Random.Shared.Next(25, 31),
QualityType.Red => Random.Shared.Next(31, 37),
QualityType.Gold => Random.Shared.Next(37, 43),
_ => Random.Shared.Next(1, 7)
};
item.QualityType = (QualityType)qualityType;
}
else
{
total = Random.Shared.Next(1, 43);
if (total > 6 && total <= 12)
{
item.QualityType = QualityType.Green;
}
else if (total > 12 && total <= 18)
{
item.QualityType = QualityType.Blue;
}
else if (total > 18 && total <= 24)
{
item.QualityType = QualityType.Purple;
}
else if (total > 24 && total <= 30)
{
item.QualityType = QualityType.Orange;
}
else if (total > 30 && total <= 36)
{
item.QualityType = QualityType.Red;
}
else if (total > 36 && total <= 42)
{
item.QualityType = QualityType.Gold;
}
}
GenerateAndAddSkillToMagicCard(item, total);
return item; return item;
} }
public static void GenerateAndAddSkillToMagicCard(Item item, int total) public static void GenerateAndAddSkillToMagicCard(Item item, long magicId = 0, int str = 0, int agi = 0, int intelligence = 0)
{ {
Skill magic = FunGameConstant.Magics[Random.Shared.Next(FunGameConstant.Magics.Count)].Copy(); int total = str + agi + intelligence;
magic.Guid = item.Guid; if (total == 0)
magic.Level = (int)item.QualityType switch
{ {
2 => 2, total = Random.Shared.Next(1, 43);
3 => 2,
4 => 3,
5 => 4,
6 => 5,
_ => 1
};
if (magic.Level > 1)
{
item.Name += $" +{magic.Level - 1}";
}
item.Skills.Active = magic;
// 初始化属性值
int str = 0, agi = 0, intelligence = 0;
// 随机决定将多少个属性赋给其中一个属性,确保至少一个不为零 // 随机决定将多少个属性赋给其中一个属性,确保至少一个不为零
int nonZeroAttributes = Random.Shared.Next(1, Math.Min(4, total + 1)); // 随机决定非零属性的数量,确保在 total = 1 时最多只有1个非零属性 int nonZeroAttributes = Random.Shared.Next(1, Math.Min(4, total + 1)); // 随机决定非零属性的数量,确保在 total = 1 时最多只有1个非零属性
@ -271,6 +222,57 @@ namespace Oshima.FunGame.OshimaServers.Service
agi = Random.Shared.Next(1, total - str); // 第二个属性的值 agi = Random.Shared.Next(1, total - str); // 第二个属性的值
intelligence = total - str - agi; // 剩下的值给第三个属性 intelligence = total - str - agi; // 剩下的值给第三个属性
} }
}
if (item.QualityType == QualityType.White)
{
if (total > 6 && total <= 12)
{
item.QualityType = QualityType.Green;
}
else if (total > 12 && total <= 18)
{
item.QualityType = QualityType.Blue;
}
else if (total > 18 && total <= 24)
{
item.QualityType = QualityType.Purple;
}
else if (total > 24 && total <= 30)
{
item.QualityType = QualityType.Orange;
}
else if (total > 30 && total <= 36)
{
item.QualityType = QualityType.Red;
}
else if (total > 36)
{
item.QualityType = QualityType.Gold;
}
}
Skill? magic = null;
if (magicId != 0)
{
magic = FunGameConstant.Magics.FirstOrDefault(m => m.Id == magicId);
}
magic ??= FunGameConstant.Magics[Random.Shared.Next(FunGameConstant.Magics.Count)].Copy();
magic.Guid = item.Guid;
magic.Level = (int)item.QualityType switch
{
2 => 2,
3 => 2,
4 => 3,
5 => 4,
6 => 5,
_ => 1
};
if (magic.Level > 1)
{
item.Name += $" +{magic.Level - 1}";
}
item.Skills.Active = magic;
Skill skill = Factory.OpenFactory.GetInstance<Skill>(item.Id, item.Name, []); Skill skill = Factory.OpenFactory.GetInstance<Skill>(item.Id, item.Name, []);
GenerateAndAddEffectsToMagicCard(skill, str, agi, intelligence); GenerateAndAddEffectsToMagicCard(skill, str, agi, intelligence);
@ -424,9 +426,9 @@ namespace Oshima.FunGame.OshimaServers.Service
return null; return null;
} }
public static Item? GenerateMagicCardPack(int magicCardCount, QualityType? qualityType = null) public static Item? GenerateMagicCardPack(int magicCardCount, QualityType? qualityType = null, long[]? magicIds = null, (int str, int agi, int intelligence)[]? values = null)
{ {
List<Item> magicCards = GenerateMagicCards(magicCardCount, qualityType); List<Item> magicCards = GenerateMagicCards(magicCardCount, qualityType, magicIds, values);
Item? magicCardPack = ConflateMagicCardPack(magicCards); Item? magicCardPack = ConflateMagicCardPack(magicCards);
return magicCardPack; return magicCardPack;
} }
@ -1495,10 +1497,11 @@ namespace Oshima.FunGame.OshimaServers.Service
Item[] shoes = [.. FunGameConstant.Equipment.Where(i => i.Id.ToString().StartsWith("13") && (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[] 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)]; Item[] consumables = [.. FunGameConstant.AllItems.Where(i => i.ItemType == ItemType.Consumable && i.IsInGameItem)];
string[] regionsBossName = [.. FunGameConstant.Regions.SelectMany(r => r.Characters).Select(c => c.Name)];
for (int i = 0; i < genCount; i++) for (int i = 0; i < genCount; i++)
{ {
int nowIndex = Bosses.Count > 0 ? Bosses.Keys.Max() + 1 : 1; int nowIndex = Bosses.Count > 0 ? Bosses.Keys.Max() + 1 : 1;
string bossName = GenerateRandomChineseUserName(); string bossName = regionsBossName[Random.Shared.Next(regionsBossName.Length)];
CustomCharacter boss = new(nowIndex, bossName, "", bossName); CustomCharacter boss = new(nowIndex, bossName, "", bossName);
int cutRate = Random.Shared.Next(3) switch int cutRate = Random.Shared.Next(3) switch
{ {
@ -1580,8 +1583,8 @@ namespace Oshima.FunGame.OshimaServers.Service
double exMP2 = 0.8; double exMP2 = 0.8;
if (!enhanceHPMP) if (!enhanceHPMP)
{ {
if (isUnit) exHP2 = -0.1; if (isUnit) exHP2 = 0.15;
else exHP2 = 0.5; else exHP2 = 0.01;
exMP2 = 0.2; exMP2 = 0.2;
} }
double exCR = 0.35; double exCR = 0.35;

View File

@ -2886,6 +2886,73 @@ namespace Oshima.FunGame.WebAPI.Controllers
} }
} }
[HttpPost("createmagiccard")]
public string CreateMagicCard([FromQuery] long? uid = null, [FromQuery] long? target = null, [FromQuery] string? quality = null, [FromQuery] long magicId = 0, [FromQuery] int count = 1, [FromQuery] int str = 0, [FromQuery] int agi = 0, [FromQuery] int intelligence = 0)
{
long userid = uid ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11));
if (count <= 0)
{
return "数量必须大于0";
}
long targetid = target ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11));
PluginConfig pc = new("saved", userid.ToString());
pc.LoadConfig();
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
string msg = "";
if (user.IsAdmin || userid > 0)
{
PluginConfig pc2 = new("saved", targetid.ToString());
pc2.LoadConfig();
if (pc2.Count > 0)
{
User user2 = FunGameService.GetUser(pc2);
if (FunGameConstant.Magics.FirstOrDefault(m => m.Id == magicId) is Skill magic)
{
foreach (string type in ItemSet.QualityTypeNameArray)
{
if (type == quality)
{
for (int i = 0; i < count; i++)
{
Item item = FunGameService.GenerateMagicCard(ItemSet.GetQualityTypeFromName(type), magic.Id, str, agi, intelligence);
item.User = user2;
user2.Inventory.Items.Add(item);
}
msg = $"已为 [ {user2} ] 生成 {count} 张 [ {magic.Name} ] 魔法卡{(str + agi + intelligence > 0 ? $" +{str} +{agi} +{intelligence}" : "")}。";
break;
}
}
}
else
{
return $"游戏中不存在 ID 为 {magicId} 的魔法技能,生成失败!";
}
pc2.Add("user", user2);
pc2.SaveConfig();
}
else
{
return $"目标 UID 不存在!";
}
}
else
{
return $"你没有权限使用此指令!";
}
return msg;
}
else
{
return noSaved;
}
}
[HttpPost("decomposeitem")] [HttpPost("decomposeitem")]
public string DecomposeItem([FromQuery] long? uid = null, [FromBody] int[]? items = null) public string DecomposeItem([FromQuery] long? uid = null, [FromBody] int[]? items = null)
{ {
@ -5869,6 +5936,64 @@ namespace Oshima.FunGame.WebAPI.Controllers
} }
} }
[HttpPost("pub")]
public string Pub([FromQuery] long? uid = null)
{
long userid = uid ?? Convert.ToInt64("10" + Verification.CreateVerifyCode(VerifyCodeType.NumberVerifyCode, 11));
PluginConfig pc = new("saved", userid.ToString());
pc.LoadConfig();
string msg = "";
if (pc.Count > 0)
{
User user = FunGameService.GetUser(pc);
int zero = user.Inventory.Characters.Count(c => c.EP <= 0);
int less100 = user.Inventory.Characters.Count(c => c.EP < 100 && c.EP > 0);
int less200 = user.Inventory.Characters.Count(c => c.EP >= 100 && c.EP < 200);
double zeroNeed = 1 * zero;
double less100Need = 0.6 * less100;
double less200Need = 0.2 * less200;
double total = zeroNeed + less100Need + less200Need;
if (total == 0)
{
msg = $"你暂时不需要酒馆的服务,欢迎下次光临。";
}
else if (user.Inventory.Materials >= total)
{
user.Inventory.Materials -= total;
foreach (Character character in user.Inventory.Characters)
{
character.EP = 200;
}
msg = $"欢迎来访酒馆,你的本次消费:{total} {General.GameplayEquilibriumConstant.InGameMaterial}。";
user.LastTime = DateTime.Now;
pc.Add("user", user);
pc.SaveConfig();
}
else
{
msg = $"你的 {General.GameplayEquilibriumConstant.InGameMaterial} 不足 {total} 呢!无法为你上酒!";
}
msg += $"{zero} 个 0 点能量值的角色,{less100} 个 100 点能量值以下的角色,{less200} 个 200 点能量值以下的角色)\r\n" +
$"收费标准:\r\n1 {General.GameplayEquilibriumConstant.InGameMaterial} / 0 点能量值的角色\r\n" +
$"0.6 {General.GameplayEquilibriumConstant.InGameMaterial} / 100 点能量值以下的角色\r\n" +
$"0.2 {General.GameplayEquilibriumConstant.InGameMaterial} / 200 点能量值以下的角色";
return msg;
}
else
{
return noSaved;
}
}
[HttpGet("getevents")] [HttpGet("getevents")]
public string GetEvents([FromQuery] long? id = null) public string GetEvents([FromQuery] long? id = null)
{ {

View File

@ -493,6 +493,68 @@ namespace Oshima.FunGame.WebAPI.Services
return result; return result;
} }
if (e.Detail.StartsWith("生成指定"))
{
e.UseNotice = false;
string pattern = @"生成指定(\w+)魔法卡\s*(\d+)\s*(?:(\d+)\s+(\d+)\s+(\d+)(?:\s+(\d+))?)?(?:\s+(\d+))?(?:\s*给\s*(\d+))?";
Regex regex = new(pattern, RegexOptions.IgnoreCase);
Match match = regex.Match(e.Detail);
if (match.Success)
{
string quality = match.Groups[1].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;
long targetUserID = uid;
// 检查参数数量的有效性
if (paramCount != 0 && paramCount != 1 && paramCount != 3 && paramCount != 4)
{
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);
agi = int.Parse(match.Groups[4].Value);
intelligence = int.Parse(match.Groups[5].Value);
if (paramCount == 4)
{
count = int.Parse(match.Groups[6].Value);
}
}
if (count <= 0)
{
await SendAsync(e, "熟圣之力", "数量不能为 0 或负数,请重新输入。");
return result;
}
if (match.Groups[8].Success)
{
targetUserID = long.Parse(match.Groups[8].Value);
}
string msg = Controller.CreateMagicCard(uid, targetUserID, quality, magicID, count, str, agi, intelligence);
if (msg != "")
{
await SendAsync(e, "熟圣之力", msg);
}
}
else
{
await SendAsync(e, "熟圣之力", "指令格式错误!正确格式:生成指定<品质>魔法卡 <MagicID> [str agi intelligence] [count]");
}
return result;
}
if (e.Detail.StartsWith("生成")) if (e.Detail.StartsWith("生成"))
{ {
e.UseNotice = false; e.UseNotice = false;
@ -528,23 +590,23 @@ namespace Oshima.FunGame.WebAPI.Services
} }
} }
if (e.Detail == "生成魔法卡包") if (e.Detail == "预览魔法卡包")
{ {
e.UseNotice = false; e.UseNotice = false;
string msg = Controller.GenerateMagicCardPack(); string msg = Controller.GenerateMagicCardPack();
if (msg != "") if (msg != "")
{ {
await SendAsync(e, "生成魔法卡包", msg); await SendAsync(e, "预览魔法卡包", msg);
} }
return result; return result;
} }
else if (e.Detail == "生成魔法卡") else if (e.Detail == "预览魔法卡")
{ {
e.UseNotice = false; e.UseNotice = false;
string msg = Controller.GenerateMagicCard(); string msg = Controller.GenerateMagicCard();
if (msg != "") if (msg != "")
{ {
await SendAsync(e, "生成魔法卡", msg); await SendAsync(e, "预览魔法卡", msg);
} }
return result; return result;
} }
@ -2231,6 +2293,16 @@ namespace Oshima.FunGame.WebAPI.Services
return result; return result;
} }
if (e.Detail == "酒馆" || e.Detail == "上酒")
{
string msg = Controller.Pub(uid);
if (msg != "")
{
await SendAsync(e, "酒馆", string.Join("\r\n", msg));
}
return result;
}
if (e.Detail == "毕业礼包") if (e.Detail == "毕业礼包")
{ {
if (FunGameService.Activities.FirstOrDefault(a => a.Name == "毕业季") is Activity activity && activity.Status == ActivityState.InProgress) if (FunGameService.Activities.FirstOrDefault(a => a.Name == "毕业季") is Activity activity && activity.Status == ActivityState.InProgress)