diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml
index 639f4b5..d2d22c0 100644
--- a/.github/workflows/dotnet.yml
+++ b/.github/workflows/dotnet.yml
@@ -21,17 +21,17 @@ jobs:
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
- dotnet-version: 8.0.x
+ dotnet-version: 9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
- run: dotnet build --no-restore
+ run: dotnet build --no-restore --configuration Release
- name: Test
- run: dotnet test --no-build --verbosity normal
+ run: dotnet test --no-build --configuration Release --verbosity normal
- name: Prepare files for latest branch
run: |
mkdir -p latest
- cp -r ./bin/Debug/net8.0/FunGame.Core.dll ./bin/Debug/net8.0/FunGame.Core.xml ./bin/Debug/net8.0/FunGame.Core.deps.json ./latest/
+ cp -r ./bin/Release/net9.0/FunGame.Core.dll ./bin/Release/net9.0/FunGame.Core.xml ./bin/Release/net9.0/FunGame.Core.deps.json ./latest/
- name: Commit and push to latest
if: success()
run: |
diff --git a/Api/EnityFactory/UserFactory.cs b/Api/EnityFactory/UserFactory.cs
index 7d91384..dd8b2bf 100644
--- a/Api/EnityFactory/UserFactory.cs
+++ b/Api/EnityFactory/UserFactory.cs
@@ -13,9 +13,9 @@ namespace Milimoe.FunGame.Core.Api.EntityFactory
return General.UnknownUserInstance;
}
- public static User Create(long Id = 0, string Username = "", DateTime? RegTime = null, DateTime? LastTime = null, string Email = "", string NickName = "", bool IsAdmin = false, bool IsOperator = false, bool IsEnable = true, double Credits = 0, double Materials = 0, double GameTime = 0, string AutoKey = "")
+ public static User Create(long Id = 0, string Username = "", DateTime? RegTime = null, DateTime? LastTime = null, string Email = "", string NickName = "", bool IsAdmin = false, bool IsOperator = false, bool IsEnable = true, double GameTime = 0, string AutoKey = "")
{
- return new(Id, Username, RegTime, LastTime, Email, NickName, IsAdmin, IsOperator, IsEnable, Credits, Materials, GameTime, AutoKey);
+ return new(Id, Username, RegTime, LastTime, Email, NickName, IsAdmin, IsOperator, IsEnable, GameTime, AutoKey);
}
public static User Create(UserType type)
diff --git a/Api/Utility/Factory.cs b/Api/Utility/Factory.cs
index 4a9ad5d..af62498 100644
--- a/Api/Utility/Factory.cs
+++ b/Api/Utility/Factory.cs
@@ -500,14 +500,12 @@ namespace Milimoe.FunGame.Core.Api.Utility
///
///
///
- ///
- ///
///
///
///
- public static User GetUser(long Id = 0, string Username = "", DateTime? RegTime = null, DateTime? LastTime = null, string Email = "", string NickName = "", bool IsAdmin = false, bool IsOperator = false, bool IsEnable = true, double Credits = 0, double Materials = 0, double GameTime = 0, string AutoKey = "")
+ public static User GetUser(long Id = 0, string Username = "", DateTime? RegTime = null, DateTime? LastTime = null, string Email = "", string NickName = "", bool IsAdmin = false, bool IsOperator = false, bool IsEnable = true, double GameTime = 0, string AutoKey = "")
{
- return UserFactory.Create(Id, Username, RegTime, LastTime, Email, NickName, IsAdmin, IsOperator, IsEnable, Credits, Materials, GameTime, AutoKey);
+ return UserFactory.Create(Id, Username, RegTime, LastTime, Email, NickName, IsAdmin, IsOperator, IsEnable, GameTime, AutoKey);
}
///
@@ -542,11 +540,9 @@ namespace Milimoe.FunGame.Core.Api.Utility
bool IsAdmin = Convert.ToInt32(dr[UserQuery.Column_IsAdmin]) == 1;
bool IsOperator = Convert.ToInt32(dr[UserQuery.Column_IsOperator]) == 1;
bool IsEnable = Convert.ToInt32(dr[UserQuery.Column_IsEnable]) == 1;
- double Credits = Convert.ToDouble(dr[UserQuery.Column_Credits]);
- double Materials = Convert.ToDouble(dr[UserQuery.Column_Materials]);
double GameTime = Convert.ToDouble(dr[UserQuery.Column_GameTime]);
string AutoKey = (string)dr[UserQuery.Column_AutoKey];
- return UserFactory.Create(Id, Username, RegTime, LastTime, Email, NickName, IsAdmin, IsOperator, IsEnable, Credits, Materials, GameTime, AutoKey);
+ return UserFactory.Create(Id, Username, RegTime, LastTime, Email, NickName, IsAdmin, IsOperator, IsEnable, GameTime, AutoKey);
}
return UserFactory.Create();
}
diff --git a/Entity/Character/Character.cs b/Entity/Character/Character.cs
index 01c773b..fd01609 100644
--- a/Entity/Character/Character.cs
+++ b/Entity/Character/Character.cs
@@ -1054,9 +1054,25 @@ namespace Milimoe.FunGame.Core.Entity
if (str != "") str += ", ";
str += NickName;
}
+ str += " - 等级 " + Level;
if (User != null && User.Username != "")
{
- str += "(" + User.Username + ")";
+ str += "(" + User.Username + ")";
+ }
+ return str;
+ }
+
+ ///
+ /// 获取角色实例的名字、昵称以及等级
+ ///
+ ///
+ public string ToStringWithLevelWithOutUser()
+ {
+ string str = GetName();
+ if (NickName != "")
+ {
+ if (str != "") str += ", ";
+ str += NickName;
}
str += " - 等级 " + Level;
return str;
@@ -1085,11 +1101,11 @@ namespace Milimoe.FunGame.Core.Entity
/// 获取角色的详细信息
///
///
- public string GetInfo()
+ public string GetInfo(bool showUser = true)
{
StringBuilder builder = new();
- builder.AppendLine(ToStringWithLevel());
+ builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser());
builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (ExHP + ExHP2 > 0 ? $" [{BaseHP:0.##} + {(ExHP + ExHP2):0.##}]" : ""));
builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (ExMP + ExMP2 > 0 ? $" [{BaseMP:0.##} + {(ExMP + ExMP2):0.##}]" : ""));
builder.AppendLine($"能量值:{EP:0.##} / {General.GameplayEquilibriumConstant.MaxEP:0.##}");
@@ -1372,6 +1388,7 @@ namespace Milimoe.FunGame.Core.Entity
///
/// 复活此角色,回复出厂状态
+ /// 注意:此方法仅用于角色的复活,如果需要完全重构相同角色,请使用
///
/// 需要一个原始的角色用于还原状态
///
diff --git a/Entity/Character/CharacterBuilder.cs b/Entity/Character/CharacterBuilder.cs
index d2f72aa..b864e6b 100644
--- a/Entity/Character/CharacterBuilder.cs
+++ b/Entity/Character/CharacterBuilder.cs
@@ -3,27 +3,107 @@ using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Entity
{
- public class CharacterBuilder(long id, string name, string firstName, string nickName, PrimaryAttribute primaryAttribute, double initialATK, double initialHP, double initialMP, double initialSTR, double strGrowth, double initialAGI, double agiGrowth, double initialINT, double intGrowth, double initialSPD, double initialHR, double initialMR)
+ public class CharacterBuilder
{
- public long Id { get; set; } = id;
- public string Name { get; set; } = name;
- public string FirstName { get; set; } = firstName;
- public string NickName { get; set; } = nickName;
- public PrimaryAttribute PrimaryAttribute { get; set; } = primaryAttribute;
- public double InitialATK { get; set; } = initialATK;
- public double InitialHP { get; set; } = initialHP;
- public double InitialMP { get; set; } = initialMP;
- public double InitialSTR { get; set; } = initialSTR;
- public double STRGrowth { get; set; } = strGrowth;
- public double InitialAGI { get; set; } = initialAGI;
- public double AGIGrowth { get; set; } = agiGrowth;
- public double InitialINT { get; set; } = initialINT;
- public double INTGrowth { get; set; } = intGrowth;
- public double InitialSPD { get; set; } = initialSPD;
- public double InitialHR { get; set; } = initialHR;
- public double InitialMR { get; set; } = initialMR;
+ public long Id { get; set; }
+ public string Name { get; set; }
+ public string FirstName { get; set; }
+ public string NickName { get; set; }
+ public PrimaryAttribute PrimaryAttribute { get; set; }
+ public double InitialATK { get; set; }
+ public double InitialDEF { get; set; }
+ public double InitialHP { get; set; }
+ public double InitialMP { get; set; }
+ public double InitialSTR { get; set; }
+ public double STRGrowth { get; set; }
+ public double InitialAGI { get; set; }
+ public double AGIGrowth { get; set; }
+ public double InitialINT { get; set; }
+ public double INTGrowth { get; set; }
+ public double InitialSPD { get; set; }
+ public double InitialHR { get; set; }
+ public double InitialMR { get; set; }
- public Character Build(int level, IEnumerable skills, IEnumerable- items, EquipSlot? equips = null)
+ ///
+ /// 基于初始属性创建角色构建器
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public CharacterBuilder(long id, string name, string firstName, string nickName, PrimaryAttribute primaryAttribute, double initialATK, double initialDEF, double initialHP, double initialMP, double initialSTR, double strGrowth, double initialAGI, double agiGrowth, double initialINT, double intGrowth, double initialSPD, double initialHR, double initialMR)
+ {
+ Id = id;
+ Name = name;
+ FirstName = firstName;
+ NickName = nickName;
+ PrimaryAttribute = primaryAttribute;
+ InitialATK = initialATK;
+ InitialDEF = initialDEF;
+ InitialHP = initialHP;
+ InitialMP = initialMP;
+ InitialSTR = initialSTR;
+ STRGrowth = strGrowth;
+ InitialAGI = initialAGI;
+ AGIGrowth = agiGrowth;
+ InitialINT = initialINT;
+ INTGrowth = intGrowth;
+ InitialSPD = initialSPD;
+ InitialHR = initialHR;
+ InitialMR = initialMR;
+ }
+
+ ///
+ /// 基于模板角色创建角色构建器
+ ///
+ ///
+ public CharacterBuilder(Character character)
+ {
+ Id = character.Id;
+ Name = character.Name;
+ FirstName = character.FirstName;
+ NickName = character.NickName;
+ PrimaryAttribute = character.PrimaryAttribute;
+ InitialATK = character.InitialATK;
+ InitialDEF = character.InitialDEF;
+ InitialHP = character.InitialHP;
+ InitialMP = character.InitialMP;
+ InitialSTR = character.InitialSTR;
+ STRGrowth = character.STRGrowth;
+ InitialAGI = character.InitialAGI;
+ AGIGrowth = character.AGIGrowth;
+ InitialINT = character.InitialINT;
+ INTGrowth = character.INTGrowth;
+ InitialSPD = character.InitialSPD;
+ InitialHR = character.InitialHR;
+ InitialMR = character.InitialMR;
+ }
+
+ ///
+ /// 基于初始条件构建新的角色
+ /// 需要传入等级、技能、物品,可选构建装备
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// 构建的新角色
+ public Character Build(int level, IEnumerable skills, IEnumerable
- items, bool newItemGuid = true, EquipSlot? equips = null)
{
Character character = Factory.GetCharacter();
character.Id = Id;
@@ -32,6 +112,7 @@ namespace Milimoe.FunGame.Core.Entity
character.NickName = NickName;
character.PrimaryAttribute = PrimaryAttribute;
character.InitialATK = InitialATK;
+ character.InitialDEF = InitialDEF;
character.InitialHP = InitialHP;
character.InitialMP = InitialMP;
character.InitialSTR = InitialSTR;
@@ -49,15 +130,23 @@ namespace Milimoe.FunGame.Core.Entity
}
foreach (Skill skill in skills)
{
- Skill newskill = skill.Copy();
- newskill.Character = character;
- newskill.Level = skill.Level;
- newskill.CurrentCD = 0;
- character.Skills.Add(newskill);
+ // 主动技能的Guid表示与其关联的物品
+ if (skill.Guid == Guid.Empty)
+ {
+ Skill newskill = skill.Copy();
+ newskill.Character = character;
+ newskill.Level = skill.Level;
+ if (skill.CurrentCD > 0 && !skill.Enable)
+ {
+ newskill.Enable = true;
+ newskill.CurrentCD = 0;
+ }
+ character.Skills.Add(newskill);
+ }
}
foreach (Item item in items)
{
- Item newitem = item.Copy(true);
+ Item newitem = item.Copy(true, !newItemGuid);
newitem.Character = character;
character.Items.Add(newitem);
}
@@ -69,13 +158,53 @@ namespace Milimoe.FunGame.Core.Entity
Item? s = equips.Shoes;
Item? ac1 = equips.Accessory1;
Item? ac2 = equips.Accessory2;
- if (mcp != null) character.Equip(mcp);
- if (w != null) character.Equip(w);
- if (a != null) character.Equip(a);
- if (s != null) character.Equip(s);
- if (ac1 != null) character.Equip(ac1);
- if (ac2 != null) character.Equip(ac2);
+ if (mcp != null)
+ {
+ mcp = mcp.Copy(true, !newItemGuid);
+ character.Equip(mcp);
+ }
+ if (w != null)
+ {
+ w = w.Copy(true, !newItemGuid);
+ character.Equip(w);
+ }
+ if (a != null)
+ {
+ a = a.Copy(true, !newItemGuid);
+ character.Equip(a);
+ }
+ if (s != null)
+ {
+ s = s.Copy(true, !newItemGuid);
+ character.Equip(s);
+ }
+ if (ac1 != null)
+ {
+ ac1 = ac1.Copy(true, !newItemGuid);
+ character.Equip(ac1);
+ }
+ if (ac2 != null)
+ {
+ ac2 = ac2.Copy(true, !newItemGuid);
+ character.Equip(ac2);
+ }
}
+ character.Recovery();
+ return character;
+ }
+
+ ///
+ /// 使用 角色构建
+ /// 新角色将获得参考角色的等级、技能、装备和身上的物品
+ ///
+ ///
+ ///
+ /// 构建的新角色
+ public static Character Build(Character reference, bool newItemGuid = true)
+ {
+ Character character = new CharacterBuilder(reference).Build(reference.Level, reference.Skills, reference.Items, newItemGuid, reference.EquipSlot);
+ character.NormalAttack.Level = reference.Level;
+ character.NormalAttack.SetMagicType(reference.NormalAttack.IsMagic, reference.NormalAttack.MagicType);
return character;
}
}
diff --git a/Entity/Item/Item.cs b/Entity/Item/Item.cs
index 6b9e57d..d1e80f3 100644
--- a/Entity/Item/Item.cs
+++ b/Entity/Item/Item.cs
@@ -36,6 +36,25 @@ namespace Milimoe.FunGame.Core.Entity
///
public virtual ItemType ItemType { get; set; } = ItemType.Others;
+ ///
+ /// 是否是装备
+ ///
+ public bool IsEquipment
+ {
+ get
+ {
+ return ItemType switch
+ {
+ ItemType.MagicCardPack => true,
+ ItemType.Weapon => true,
+ ItemType.Armor => true,
+ ItemType.Shoes => true,
+ ItemType.Accessory => true,
+ _ => false
+ };
+ }
+ }
+
///
/// 是否允许装备
///
@@ -407,15 +426,12 @@ namespace Milimoe.FunGame.Core.Entity
}
else
{
- List sellandtrade = [""];
+ List sellandtrade = [];
+
if (IsSellable)
{
sellandtrade.Add("可出售");
}
- if (IsTradable)
- {
- sellandtrade.Add("可交易");
- }
if (!IsSellable && NextSellableTime != DateTime.MinValue)
{
@@ -426,6 +442,11 @@ namespace Milimoe.FunGame.Core.Entity
sellandtrade.Add("不可出售");
}
+ if (IsTradable)
+ {
+ sellandtrade.Add("可交易");
+ }
+
if (!IsTradable && NextTradableTime != DateTime.MinValue)
{
builder.AppendLine($"此物品将在 {NextTradableTime.ToString(General.GeneralDateTimeFormatChinese)} 后可交易");
@@ -435,7 +456,7 @@ namespace Milimoe.FunGame.Core.Entity
sellandtrade.Add("不可交易");
}
- builder.AppendLine(string.Join(" ", sellandtrade).Trim());
+ if (sellandtrade.Count > 0) builder.AppendLine(string.Join(" ", sellandtrade).Trim());
}
if (isShowGeneralDescription && GeneralDescription != "")
@@ -467,6 +488,46 @@ namespace Milimoe.FunGame.Core.Entity
return builder.ToString();
}
+ public string ToStringInventory(bool showAll)
+ {
+ StringBuilder builder = new();
+
+ if (showAll)
+ {
+ builder.Append($"{ToString()}");
+ if (IsEquipment && Character != null) builder.AppendLine($"装备于:{Character.ToStringWithLevelWithOutUser()}");
+ builder.AppendLine();
+ }
+ else
+ {
+ List sellandtrade = [];
+
+ if (!IsSellable && NextSellableTime != DateTime.MinValue)
+ {
+ builder.AppendLine($"此物品将在 {NextSellableTime.ToString(General.GeneralDateTimeFormatChinese)} 后可出售");
+ }
+ else if (!IsSellable)
+ {
+ sellandtrade.Add("不可出售");
+ }
+
+ if (!IsTradable && NextTradableTime != DateTime.MinValue)
+ {
+ builder.AppendLine($"此物品将在 {NextTradableTime.ToString(General.GeneralDateTimeFormatChinese)} 后可交易");
+ }
+ else if (!IsTradable)
+ {
+ sellandtrade.Add("不可交易");
+ }
+
+ if (sellandtrade.Count > 0) builder.AppendLine(string.Join(" ", sellandtrade).Trim());
+ if (Description != "") builder.AppendLine($"{Description}");
+ if (IsEquipment && Character != null) builder.AppendLine($"装备于:{Character.ToStringWithLevelWithOutUser()}");
+ }
+
+ return builder.ToString();
+ }
+
///
/// 判断两个物品是否相同 检查Id.Name
///
@@ -498,13 +559,13 @@ namespace Milimoe.FunGame.Core.Entity
/// 复制一个物品
///
///
- public Item Copy(bool copyLevel = false)
+ public Item Copy(bool copyLevel = false, bool copyGuid = false)
{
Item item = Factory.OpenFactory.GetInstance
- (Id, Name, []);
SetPropertyToItemModuleNew(item);
item.Id = Id;
item.Name = Name;
- item.Guid = Guid;
+ if (copyGuid) item.Guid = Guid;
item.Description = Description;
item.GeneralDescription = GeneralDescription;
item.BackgroundStory = BackgroundStory;
diff --git a/Entity/Skill/Effect.cs b/Entity/Skill/Effect.cs
index 4d57522..0e624fb 100644
--- a/Entity/Skill/Effect.cs
+++ b/Entity/Skill/Effect.cs
@@ -149,9 +149,11 @@ namespace Milimoe.FunGame.Core.Entity
///
///
///
- public virtual void AlterExpectedDamageBeforeCalculation(Character character, Character enemy, ref double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType)
+ ///
+ /// 返回伤害增减值
+ public virtual double AlterExpectedDamageBeforeCalculation(Character character, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType, Dictionary totalDamageBonus)
{
-
+ return 0;
}
///
@@ -164,10 +166,12 @@ namespace Milimoe.FunGame.Core.Entity
///
///
///
- /// 返回 true 表示取消此伤害,等同于闪避
- public virtual bool AlterActualDamageAfterCalculation(Character character, Character enemy, ref double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType, DamageResult damageResult)
+ ///
+ ///
+ /// 返回伤害增减值
+ public virtual double AlterActualDamageAfterCalculation(Character character, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType, DamageResult damageResult, ref bool isEvaded, Dictionary totalDamageBonus)
{
- return false;
+ return 0;
}
///
diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs
index c6e0ce9..5b3e048 100644
--- a/Entity/Skill/Skill.cs
+++ b/Entity/Skill/Skill.cs
@@ -11,6 +11,12 @@ namespace Milimoe.FunGame.Core.Entity
///
public class Skill : BaseEntity, IActiveEnable
{
+ ///
+ /// 唯一标识符 [ 只有物品技能需要赋值,用于表示与其关联的物品: ]
+ /// 其他情况请保持此属性为
+ ///
+ public override Guid Guid { get; set; } = Guid.Empty;
+
///
/// 此技能所属的角色
///
diff --git a/Entity/System/Inventory.cs b/Entity/System/Inventory.cs
index 00c6d7a..15ff057 100644
--- a/Entity/System/Inventory.cs
+++ b/Entity/System/Inventory.cs
@@ -1,17 +1,99 @@
-namespace Milimoe.FunGame.Core.Entity
+using System.Text;
+using Milimoe.FunGame.Core.Library.Constant;
+using Milimoe.FunGame.Core.Model;
+
+namespace Milimoe.FunGame.Core.Entity
{
public class Inventory
{
+ ///
+ /// 库存 ID 与用户 ID 绑定
+ ///
public long Id => User.Id;
+
+ ///
+ /// 库存的名称,默认为 “的库存”;可更改
+ ///
public string Name { get; set; } = "";
+
+ ///
+ /// 库存属于哪个玩家
+ ///
public User User { get; }
- public Dictionary Characters { get; } = [];
- public Dictionary Items { get; } = [];
+
+ ///
+ /// 玩家持有 的数量
+ ///
+ public double Credits { get; set; } = 0;
+
+ ///
+ /// 玩家持有 的数量
+ ///
+ public double Materials { get; set; } = 0;
+
+ ///
+ /// 玩家拥有的角色
+ ///
+ public HashSet Characters { get; } = [];
+
+ ///
+ /// 玩家拥有的物品
+ ///
+ public HashSet
- Items { get; } = [];
internal Inventory(User user)
{
User = user;
Name = user.Username + "的库存";
}
+
+ public override string ToString()
+ {
+ return Name + $"({User})";
+ }
+
+ public string ToString(bool showAll)
+ {
+ StringBuilder builder = new();
+
+ builder.AppendLine($"☆★☆ {Name} ☆★☆");
+ builder.AppendLine($"{General.GameplayEquilibriumConstant.InGameCurrency}:{Credits:0.00}");
+ builder.AppendLine($"{General.GameplayEquilibriumConstant.InGameMaterial}:{Materials:0.00}");
+
+ builder.AppendLine($"======= 角色 =======");
+ Character[] characters = [.. Characters];
+ for (int i = 1; i <= characters.Length; i++)
+ {
+ Character character = characters[i - 1];
+ if (showAll)
+ {
+ builder.AppendLine($"===== 第 {i} 个角色 =====");
+ builder.AppendLine($"{character.GetInfo(false)}");
+ }
+ else
+ {
+ builder.AppendLine($"{i}. {character.ToStringWithLevelWithOutUser()}");
+ }
+ }
+
+ builder.AppendLine($"======= 物品 =======");
+ Item[] items = [.. Items];
+ for (int i = 1; i <= items.Length; i++)
+ {
+ Item item = items[i - 1];
+ if (showAll)
+ {
+ builder.AppendLine($"===== 第 {i} 个物品 =====");
+ }
+ else
+ {
+ builder.AppendLine($"{i}. [{ItemSet.GetQualityTypeName(item.QualityType)}|{ItemSet.GetItemTypeName(item.ItemType)}] {item.Name}");
+ }
+ builder.AppendLine($"{item.ToStringInventory(showAll).Trim()}");
+ if (showAll) builder.AppendLine();
+ }
+
+ return builder.ToString();
+ }
}
}
diff --git a/Entity/User/User.cs b/Entity/User/User.cs
index 6ff3d08..de0d214 100644
--- a/Entity/User/User.cs
+++ b/Entity/User/User.cs
@@ -14,8 +14,6 @@ namespace Milimoe.FunGame.Core.Entity
public bool IsAdmin { get; set; } = false;
public bool IsOperator { get; set; } = false;
public bool IsEnable { get; set; } = true;
- public double Credits { get; set; } = 0;
- public double Materials { get; set; } = 0;
public double GameTime { get; set; } = 0;
public string AutoKey { get; set; } = "";
public UserStatistics Statistics { get; }
@@ -27,7 +25,7 @@ namespace Milimoe.FunGame.Core.Entity
Inventory = new(this);
}
- internal User(long Id = 0, string Username = "", DateTime? RegTime = null, DateTime? LastTime = null, string Email = "", string NickName = "", bool IsAdmin = false, bool IsOperator = false, bool IsEnable = true, double Credits = 0, double Materials = 0, double GameTime = 0, string AutoKey = "")
+ internal User(long Id = 0, string Username = "", DateTime? RegTime = null, DateTime? LastTime = null, string Email = "", string NickName = "", bool IsAdmin = false, bool IsOperator = false, bool IsEnable = true, double GameTime = 0, string AutoKey = "")
{
this.Id = Id;
this.Username = Username;
@@ -38,8 +36,6 @@ namespace Milimoe.FunGame.Core.Entity
this.IsAdmin = IsAdmin;
this.IsOperator = IsOperator;
this.IsEnable = IsEnable;
- this.Credits = Credits;
- this.Materials = Materials;
this.GameTime = GameTime;
this.AutoKey = AutoKey;
Statistics = new(this);
diff --git a/FunGame.Core.csproj b/FunGame.Core.csproj
index c452b13..df0babf 100644
--- a/FunGame.Core.csproj
+++ b/FunGame.Core.csproj
@@ -1,32 +1,32 @@
-
- Library
- net8.0
- enable
- enable
- bin\
- Milimoe
- Milimoe
- 1.0
- 1.0
- ..\bin
- Core
- Milimoe.$(MSBuildProjectName.Replace(" ", "_"))
- true
- $(MSBuildProjectName)
- True
-
-
+
+ Library
+ net9.0
+ enable
+ enable
+ bin\
+ Milimoe
+ Milimoe
+ 1.0
+ 1.0
+ ..\bin
+ Core
+ Milimoe.$(MSBuildProjectName.Replace(" ", "_"))
+ true
+ $(MSBuildProjectName)
+ True
+
+
-
- embedded
- 1701;1702;CS1591;CS1587;IDE0130
-
+
+ embedded
+ 1701;1702;CS1591;CS1587;IDE0130
+
-
- embedded
- 1701;1702;CS1591;CS1587;IDE0130
-
+
+ embedded
+ 1701;1702;CS1591;CS1587;IDE0130
+
diff --git a/Library/Common/JsonConverter/InventoryConverter.cs b/Library/Common/JsonConverter/InventoryConverter.cs
index 6d96a6f..0cdcc69 100644
--- a/Library/Common/JsonConverter/InventoryConverter.cs
+++ b/Library/Common/JsonConverter/InventoryConverter.cs
@@ -19,18 +19,24 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Inventory.Name):
result.Name = reader.GetString() ?? "";
break;
+ case nameof(Inventory.Credits):
+ result.Credits = reader.GetDouble();
+ break;
+ case nameof(Inventory.Materials):
+ result.Materials = reader.GetDouble();
+ break;
case nameof(Inventory.Characters):
- Dictionary characters = NetworkUtility.JsonDeserialize>(ref reader, options) ?? [];
- foreach (string key in characters.Keys)
+ HashSet characters = NetworkUtility.JsonDeserialize>(ref reader, options) ?? [];
+ foreach (Character character in characters)
{
- result.Characters[key] = characters[key];
+ result.Characters.Add(character);
}
break;
case nameof(Inventory.Items):
- Dictionary items = NetworkUtility.JsonDeserialize>(ref reader, options) ?? [];
- foreach (string key in items.Keys)
+ HashSet
- items = NetworkUtility.JsonDeserialize>(ref reader, options) ?? [];
+ foreach (Item item in items)
{
- result.Items[key] = items[key];
+ result.Items.Add(item);
}
break;
}
@@ -41,6 +47,8 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
writer.WriteStartObject();
writer.WriteString(nameof(Inventory.Name), value.Name);
+ writer.WriteNumber(nameof(Inventory.Credits), value.Credits);
+ writer.WriteNumber(nameof(Inventory.Materials), value.Materials);
writer.WritePropertyName(nameof(Inventory.Characters));
JsonSerializer.Serialize(writer, value.Characters, options);
writer.WritePropertyName(nameof(Inventory.Items));
diff --git a/Library/Common/JsonConverter/SkillConverter.cs b/Library/Common/JsonConverter/SkillConverter.cs
index 73fb483..3197324 100644
--- a/Library/Common/JsonConverter/SkillConverter.cs
+++ b/Library/Common/JsonConverter/SkillConverter.cs
@@ -23,6 +23,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Skill.Name):
result.Name = reader.GetString() ?? "";
break;
+ case nameof(Skill.Guid):
+ result.Guid = reader.GetGuid();
+ break;
case nameof(Skill.Description):
result.Description = reader.GetString() ?? "";
break;
@@ -106,6 +109,11 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
writer.WriteNumber(nameof(Skill.Id), (int)value.Id);
writer.WriteString(nameof(Skill.Name), value.Name);
+ if (value.Guid != Guid.Empty)
+ {
+ writer.WritePropertyName(nameof(Skill.Guid));
+ JsonSerializer.Serialize(writer, value.Guid, options);
+ }
writer.WriteString(nameof(Skill.Description), value.Description);
if (value.GeneralDescription.Length > 0) writer.WriteString(nameof(Skill.GeneralDescription), value.GeneralDescription);
if (value.Slogan.Length > 0) writer.WriteString(nameof(Skill.Slogan), value.Slogan);
diff --git a/Library/Common/JsonConverter/UserConverter.cs b/Library/Common/JsonConverter/UserConverter.cs
index d8ef325..fed1d8a 100644
--- a/Library/Common/JsonConverter/UserConverter.cs
+++ b/Library/Common/JsonConverter/UserConverter.cs
@@ -56,12 +56,6 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case UserQuery.Column_IsEnable:
result.IsEnable = reader.GetBoolean();
break;
- case UserQuery.Column_Credits:
- result.Credits = reader.GetDouble();
- break;
- case UserQuery.Column_Materials:
- result.Materials = reader.GetDouble();
- break;
case UserQuery.Column_GameTime:
result.GameTime = reader.GetDouble();
break;
@@ -71,13 +65,15 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Inventory):
Inventory inventory = NetworkUtility.JsonDeserialize(ref reader, options) ?? Factory.GetInventory();
result.Inventory.Name = inventory.Name;
- foreach (string key in inventory.Characters.Keys)
+ result.Inventory.Credits = inventory.Credits;
+ result.Inventory.Materials = inventory.Materials;
+ foreach (Character character in inventory.Characters)
{
- result.Inventory.Characters[key] = inventory.Characters[key];
+ result.Inventory.Characters.Add(character);
}
- foreach (string key in inventory.Items.Keys)
+ foreach (Item item in inventory.Items)
{
- result.Inventory.Items[key] = inventory.Items[key];
+ result.Inventory.Items.Add(item);
}
break;
}
@@ -96,8 +92,6 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
writer.WriteBoolean(UserQuery.Column_IsAdmin, value.IsAdmin);
writer.WriteBoolean(UserQuery.Column_IsOperator, value.IsOperator);
writer.WriteBoolean(UserQuery.Column_IsEnable, value.IsEnable);
- writer.WriteNumber(UserQuery.Column_Credits, value.Credits);
- writer.WriteNumber(UserQuery.Column_Materials, value.Materials);
writer.WriteNumber(UserQuery.Column_GameTime, value.GameTime);
writer.WriteString(UserQuery.Column_AutoKey, value.AutoKey);
writer.WritePropertyName(nameof(Inventory));
diff --git a/Library/SQLScript/Entity/UserQuery.cs b/Library/SQLScript/Entity/UserQuery.cs
index f83af9e..8ff64e0 100644
--- a/Library/SQLScript/Entity/UserQuery.cs
+++ b/Library/SQLScript/Entity/UserQuery.cs
@@ -14,8 +14,6 @@
public const string Column_IsAdmin = "IsAdmin";
public const string Column_IsOperator = "IsOperator";
public const string Column_IsEnable = "IsEnable";
- public const string Column_Credits = "Credits";
- public const string Column_Materials = "Materials";
public const string Column_GameTime = "GameTime";
public const string Column_AutoKey = "AutoKey";
public const string Select_Users = $"{Command_Select} {Command_All} {Command_From} {TableName}";
diff --git a/Library/SQLScript/fungame.sql b/Library/SQLScript/fungame.sql
new file mode 100644
index 0000000..e95c156
--- /dev/null
+++ b/Library/SQLScript/fungame.sql
@@ -0,0 +1,76 @@
+SET FOREIGN_KEY_CHECKS=0;
+
+-- ----------------------------
+-- Table structure for forgetverifycodes
+-- ----------------------------
+DROP TABLE IF EXISTS `forgetverifycodes`;
+CREATE TABLE `forgetverifycodes` (
+ `Username` varchar(255) DEFAULT NULL,
+ `Email` varchar(255) DEFAULT NULL,
+ `ForgetVerifyCode` varchar(255) DEFAULT NULL,
+ `SendTime` datetime DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- ----------------------------
+-- Table structure for regverifycodes
+-- ----------------------------
+DROP TABLE IF EXISTS `regverifycodes`;
+CREATE TABLE `regverifycodes` (
+ `Username` varchar(255) DEFAULT NULL,
+ `Email` varchar(255) DEFAULT NULL,
+ `RegVerifyCode` varchar(255) DEFAULT NULL,
+ `RegTime` datetime DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- ----------------------------
+-- Table structure for rooms
+-- ----------------------------
+DROP TABLE IF EXISTS `rooms`;
+CREATE TABLE `rooms` (
+ `Id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `Roomid` varchar(255) NOT NULL DEFAULT '-1',
+ `CreateTime` datetime NOT NULL,
+ `RoomMaster` bigint(20) NOT NULL DEFAULT '0',
+ `RoomType` int(8) DEFAULT '0',
+ `GameModule` varchar(255) DEFAULT '',
+ `GameMap` varchar(255) DEFAULT '',
+ `RoomState` int(8) DEFAULT '0',
+ `IsRank` int(1) DEFAULT '0',
+ `HasPass` int(1) DEFAULT '0',
+ `Password` varchar(255) DEFAULT '',
+ `MaxUsers` int(8) DEFAULT '0',
+ PRIMARY KEY (`Id`,`Roomid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- ----------------------------
+-- Table structure for serverloginlogs
+-- ----------------------------
+DROP TABLE IF EXISTS `serverloginlogs`;
+CREATE TABLE `serverloginlogs` (
+ `ServerName` varchar(255) DEFAULT NULL,
+ `ServerKey` varchar(255) DEFAULT NULL,
+ `LoginTime` datetime DEFAULT NULL
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+
+-- ----------------------------
+-- Table structure for users
+-- ----------------------------
+DROP TABLE IF EXISTS `users`;
+CREATE TABLE `users` (
+ `UID` bigint(20) NOT NULL AUTO_INCREMENT,
+ `Username` varchar(255) NOT NULL,
+ `Password` varchar(255) NOT NULL,
+ `RegTime` datetime DEFAULT NULL,
+ `LastTime` datetime DEFAULT NULL,
+ `LastIP` varchar(255) DEFAULT '',
+ `Email` varchar(255) NOT NULL DEFAULT '',
+ `Nickname` varchar(255) DEFAULT '',
+ `IsAdmin` int(1) DEFAULT '0',
+ `IsOperator` int(1) DEFAULT '0',
+ `IsEnable` int(1) DEFAULT '1',
+ `Credits` decimal(20,0) DEFAULT '0',
+ `Materials` decimal(20,0) DEFAULT '0',
+ `GameTime` decimal(20,0) DEFAULT '0',
+ `AutoKey` varchar(255) DEFAULT '',
+ PRIMARY KEY (`UID`,`Username`,`Email`)
+) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8mb4;
diff --git a/Library/SQLScript/fungame_sqlite.sql b/Library/SQLScript/fungame_sqlite.sql
new file mode 100644
index 0000000..a6d8e1c
--- /dev/null
+++ b/Library/SQLScript/fungame_sqlite.sql
@@ -0,0 +1,73 @@
+PRAGMA foreign_keys = OFF;
+
+-- ----------------------------
+-- Table structure for forgetverifycodes
+-- ----------------------------
+DROP TABLE IF EXISTS "main"."forgetverifycodes";
+CREATE TABLE forgetverifycodes (
+ Username TEXT,
+ Email TEXT,
+ ForgetVerifyCode TEXT,
+ SendTime DATETIME
+);
+
+-- ----------------------------
+-- Table structure for regverifycodes
+-- ----------------------------
+DROP TABLE IF EXISTS "main"."regverifycodes";
+CREATE TABLE regverifycodes (
+ Username TEXT,
+ Email TEXT,
+ RegVerifyCode TEXT,
+ RegTime DATETIME
+);
+
+-- ----------------------------
+-- Table structure for rooms
+-- ----------------------------
+DROP TABLE IF EXISTS "main"."rooms";
+CREATE TABLE "rooms" (
+"Id" INTEGER PRIMARY KEY AUTOINCREMENT,
+"Roomid" TEXT NOT NULL DEFAULT '-1',
+"CreateTime" DATETIME NOT NULL,
+"RoomMaster" INTEGER NOT NULL DEFAULT 0,
+"RoomType" INTEGER DEFAULT 0,
+"GameModule" TEXT DEFAULT '',
+"GameMap" TEXT DEFAULT '',
+"RoomState" INTEGER DEFAULT 0,
+"IsRank" INTEGER DEFAULT 0,
+"HasPass" INTEGER DEFAULT 0,
+"Password" TEXT DEFAULT ''
+);
+
+-- ----------------------------
+-- Table structure for serverloginlogs
+-- ----------------------------
+DROP TABLE IF EXISTS "main"."serverloginlogs";
+CREATE TABLE serverloginlogs (
+ ServerName TEXT,
+ ServerKey TEXT,
+ LoginTime DATETIME
+);
+
+-- ----------------------------
+-- Table structure for users
+-- ----------------------------
+DROP TABLE IF EXISTS "main"."users";
+CREATE TABLE users (
+ UID INTEGER PRIMARY KEY AUTOINCREMENT,
+ Username TEXT NOT NULL,
+ Password TEXT NOT NULL,
+ RegTime DATETIME,
+ LastTime DATETIME,
+ LastIP TEXT DEFAULT '',
+ Email TEXT NOT NULL DEFAULT '',
+ Nickname TEXT DEFAULT '',
+ IsAdmin INTEGER DEFAULT 0,
+ IsOperator INTEGER DEFAULT 0,
+ IsEnable INTEGER DEFAULT 1,
+ Credits REAL DEFAULT 0,
+ Materials REAL DEFAULT 0,
+ GameTime REAL DEFAULT 0,
+ AutoKey TEXT DEFAULT ''
+);
diff --git a/Model/ActionQueue.cs b/Model/ActionQueue.cs
index afb70cc..8205bd8 100644
--- a/Model/ActionQueue.cs
+++ b/Model/ActionQueue.cs
@@ -492,6 +492,12 @@ namespace Milimoe.FunGame.Core.Model
{
_queue.Remove(character);
_cutCount.Remove(character);
+
+ // 进入下一回合
+ TotalRound++;
+ LastRound = new(TotalRound);
+ Rounds.Add(LastRound);
+
return character;
}
@@ -1048,11 +1054,6 @@ namespace Milimoe.FunGame.Core.Model
WriteLine("\r\n");
- // 在时间流逝后,进入下一回合
- TotalRound++;
- LastRound = new(TotalRound);
- Rounds.Add(LastRound);
-
return timeToReduce;
}
@@ -1078,16 +1079,20 @@ namespace Milimoe.FunGame.Core.Model
{
LastRound.IsCritical[enemy] = true;
}
+
bool isEvaded = damageResult == DamageResult.Evaded;
+ Dictionary totalDamageBonus = [];
List effects = actor.Effects.Union(enemy.Effects).Where(e => e.Level > 0).ToList();
foreach (Effect effect in effects)
{
- if (effect.AlterActualDamageAfterCalculation(actor, enemy, ref damage, isNormalAttack, isMagicDamage, magicType, damageResult))
+ double damageBonus = effect.AlterActualDamageAfterCalculation(actor, enemy, damage, isNormalAttack, isMagicDamage, magicType, damageResult, ref isEvaded, totalDamageBonus);
+ totalDamageBonus[effect] = damageBonus;
+ if (isEvaded)
{
- isEvaded = true;
damageResult = DamageResult.Evaded;
}
}
+ damage += totalDamageBonus.Sum(kv => kv.Value);
// 闪避了就没伤害了
if (!isEvaded)
@@ -1215,11 +1220,14 @@ namespace Milimoe.FunGame.Core.Model
return CalculateMagicalDamage(actor, enemy, isNormalAttack, magicType, expectedDamage, out finalDamage);
}
+ Dictionary totalDamageBonus = [];
effects = actor.Effects.Union(enemy.Effects).Where(e => e.Level > 0).ToList();
foreach (Effect effect in effects)
{
- effect.AlterExpectedDamageBeforeCalculation(actor, enemy, ref expectedDamage, isNormalAttack, false, MagicType.None);
+ double damageBonus = effect.AlterExpectedDamageBeforeCalculation(actor, enemy, expectedDamage, isNormalAttack, false, MagicType.None, totalDamageBonus);
+ totalDamageBonus[effect] = damageBonus;
}
+ expectedDamage += totalDamageBonus.Sum(kv => kv.Value);
double dice = Random.Shared.NextDouble();
double throwingBonus = 0;
@@ -1317,11 +1325,14 @@ namespace Milimoe.FunGame.Core.Model
return CalculatePhysicalDamage(actor, enemy, isNormalAttack, expectedDamage, out finalDamage);
}
+ Dictionary totalDamageBonus = [];
effects = actor.Effects.Union(enemy.Effects).Where(e => e.Level > 0).ToList();
foreach (Effect effect in effects)
{
- effect.AlterExpectedDamageBeforeCalculation(actor, enemy, ref expectedDamage, isNormalAttack, true, magicType);
+ double damageBonus = effect.AlterExpectedDamageBeforeCalculation(actor, enemy, expectedDamage, isNormalAttack, true, magicType, totalDamageBonus);
+ totalDamageBonus[effect] = damageBonus;
}
+ expectedDamage += totalDamageBonus.Sum(kv => kv.Value);
double dice = Random.Shared.NextDouble();
double throwingBonus = 0;
@@ -1457,6 +1468,7 @@ namespace Milimoe.FunGame.Core.Model
{
// 没有其他的团队了,游戏结束
EndGameInfo(killTeam);
+ return;
}
if (MaxScoreToWin > 0 && killTeam.Score >= MaxScoreToWin)
{
@@ -1465,6 +1477,7 @@ namespace Milimoe.FunGame.Core.Model
_eliminatedTeams.Clear();
_eliminatedTeams.AddRange(combinedTeams.OrderByDescending(t => t.Score));
EndGameInfo(killTeam);
+ return;
}
}
}
diff --git a/Model/EquilibriumConstant.cs b/Model/EquilibriumConstant.cs
index 7f8cef7..67cd9aa 100644
--- a/Model/EquilibriumConstant.cs
+++ b/Model/EquilibriumConstant.cs
@@ -9,6 +9,11 @@
/// 游戏货币名称
///
public string InGameCurrency { get; set; } = "金币";
+
+ ///
+ /// 游戏材料名称(第二货币)
+ ///
+ public string InGameMaterial { get; set; } = "材料";
///
/// 晋升点数上限