Class & SubClass import

This commit is contained in:
milimoe 2026-01-28 23:15:48 +08:00
parent 899356d698
commit 5f538987f7
Signed by: milimoe
GPG Key ID: 9554D37E4B8991D0
10 changed files with 337 additions and 20 deletions

View File

@ -125,7 +125,12 @@ namespace Milimoe.FunGame.Core.Entity
{
get
{
return Math.Max(1, field + ExLevel);
int level = field + ExLevel;
if (MaxLevel > 0)
{
level = Math.Min(level, MaxLevel);
}
return Math.Max(0, level);
}
set
{
@ -145,6 +150,11 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
public int ExLevel { get; set; } = 0;
/// <summary>
/// 自定义最大等级
/// </summary>
public int MaxLevel { get; set; } = 0;
/// <summary>
/// 经验值
/// </summary>
@ -909,6 +919,11 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
public Character? Master { get; set; } = null;
/// <summary>
/// 角色职业对象
/// </summary>
public CharacterClass Class { get; set; }
/// <summary>
/// 普通攻击对象
/// </summary>
@ -941,6 +956,7 @@ namespace Milimoe.FunGame.Core.Entity
MDF = new();
Shield = new();
NormalAttack = new(this);
Class = new(this);
}
internal static Character GetInstance()
@ -1289,6 +1305,7 @@ namespace Milimoe.FunGame.Core.Entity
}
if (isUp)
{
Class.OnLevelUp();
Effect[] effects = [.. Effects.Where(e => e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect e in effects)
{
@ -2010,6 +2027,7 @@ namespace Milimoe.FunGame.Core.Entity
PrimaryAttribute = PrimaryAttribute,
Level = Level,
ExLevel = ExLevel,
MaxLevel = MaxLevel,
LevelBreak = LevelBreak,
EXP = EXP,
InitialHP = InitialHP,
@ -2124,6 +2142,7 @@ namespace Milimoe.FunGame.Core.Entity
PrimaryAttribute = c.PrimaryAttribute;
Level = c.Level;
ExLevel = c.ExLevel;
MaxLevel = c.MaxLevel;
LevelBreak = c.LevelBreak;
EXP = c.EXP;
CharacterState = c.CharacterState;

View File

@ -0,0 +1,141 @@
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Entity
{
/// <summary>
/// 角色职业管理类
/// </summary>
/// <param name="character"></param>
public class CharacterClass(Character character)
{
/// <summary>
/// 所属的角色
/// </summary>
public Character Character { get; set; } = character;
/// <summary>
/// 职业点数
/// </summary>
public int ClassPoints { get; set; } = 1;
/// <summary>
/// 已选择职业
/// </summary>
public HashSet<Class> Classes { get; set; } = [];
/// <summary>
/// 已选择流派
/// </summary>
public HashSet<SubClass> SubClasses { get; set; } = [];
/// <summary>
/// 已激活战斗天赋
/// </summary>
public Skill? CombatTalent { get; set; } = null;
/// <summary>
/// 通过升级重新计算职业点数
/// </summary>
public void OnLevelUp()
{
ClassPoints = 0;
foreach (int level in Character.GameplayEquilibriumConstant.ClassPointsGetterList)
{
if (Character.Level >= level)
{
ClassPoints++;
}
}
if (ClassPoints == 0)
{
ClassPoints = 1;
}
}
/// <summary>
/// 重新构建角色职业,设置定位和技能等
/// </summary>
/// <param name="obj"></param>
public void ReBuildCharacterClass(ClassObject obj)
{
Character.FirstRoleType = RoleType.None;
Character.SecondRoleType = RoleType.None;
Character.ThirdRoleType = RoleType.None;
CombatTalent?.RemoveSkillFromCharacter(Character);
foreach (SubClass sc in SubClasses)
{
foreach (Skill skill in sc.InherentPassives)
{
skill.RemoveSkillFromCharacter(Character);
}
}
foreach (Class c in Classes)
{
foreach (Skill skill in c.PassiveSkills)
{
skill.RemoveSkillFromCharacter(Character);
}
foreach (Skill skill in c.Skills)
{
skill.RemoveSkillFromCharacter(Character);
}
foreach (Skill skill in c.Magics)
{
skill.RemoveSkillFromCharacter(Character);
}
foreach (Skill skill in c.SuperSkills)
{
skill.RemoveSkillFromCharacter(Character);
}
}
Classes.Clear();
SubClasses.Clear();
foreach (Class c in obj.Classes)
{
Classes.Add(c);
foreach (Skill skill in c.PassiveSkills)
{
skill.AddSkillToCharacter(Character);
}
foreach (Skill skill in c.Skills)
{
skill.AddSkillToCharacter(Character);
}
foreach (Skill skill in c.Magics)
{
skill.AddSkillToCharacter(Character);
}
foreach (Skill skill in c.SuperSkills)
{
skill.AddSkillToCharacter(Character);
}
}
foreach (SubClass sc in obj.SubClasses)
{
SubClasses.Add(sc);
foreach (Skill skill in sc.InherentPassives)
{
skill.AddSkillToCharacter(Character);
}
}
if (obj.CurrentCombatTalent != null)
{
CombatTalent = obj.CurrentCombatTalent;
CombatTalent.AddSkillToCharacter(Character);
}
}
}
/// <summary>
/// 决定如何构建角色的职业。这个类没有 JSON 转换器支持
/// </summary>
public class ClassObject(Class[] c, SubClass[] s)
{
public Class[] Classes { get; set; } = c;
public SubClass[] SubClasses { get; set; } = s;
public RoleType FirstRoleType { get; set; } = RoleType.None;
public RoleType SecondRoleType { get; set; } = RoleType.None;
public RoleType ThirdRoleType { get; set; } = RoleType.None;
public Skill? CurrentCombatTalent { get; set; } = null;
}
}

55
Entity/Character/Class.cs Normal file
View File

@ -0,0 +1,55 @@
using Milimoe.FunGame.Core.Interface.Entity;
namespace Milimoe.FunGame.Core.Entity
{
/// <summary>
/// 角色职业类
/// </summary>
public class Class : BaseEntity
{
/// <summary>
/// 职业名称
/// </summary>
public override string Name { get; set; } = "";
/// <summary>
/// 职业等级
/// </summary>
public int Level
{
get
{
return Math.Max(0, field);
}
set
{
field = Math.Max(0, value);
}
}
/// <summary>
/// 职业战技
/// </summary>
public HashSet<Skill> Skills { get; set; } = [];
/// <summary>
/// 职业魔法
/// </summary>
public HashSet<Skill> Magics { get; set; } = [];
/// <summary>
/// 职业被动
/// </summary>
public HashSet<Skill> PassiveSkills { get; set; } = [];
/// <summary>
/// 职业爆发技
/// </summary>
public HashSet<Skill> SuperSkills { get; set; } = [];
public override bool Equals(IBaseEntity? other)
{
return other is Class && other.GetIdName() == GetIdName();
}
}
}

View File

@ -0,0 +1,46 @@
using Milimoe.FunGame.Core.Interface.Entity;
using Milimoe.FunGame.Core.Library.Constant;
namespace Milimoe.FunGame.Core.Entity
{
/// <summary>
/// 子职业(流派/派别)
/// </summary>
public class SubClass(Class @class) : BaseEntity
{
/// <summary>
/// 流派名称
/// </summary>
public override string Name { get; set; } = "";
/// <summary>
/// 所属职业
/// </summary>
public Class Class => @class;
/// <summary>
/// 职业等级
/// </summary>
public int Level => @class.Level;
/// <summary>
/// 固有被动
/// </summary>
public HashSet<Skill> InherentPassives { get; set; } = [];
/// <summary>
/// 角色定位
/// </summary>
public HashSet<RoleType> RoleTypes { get; set; } = [];
/// <summary>
/// 战斗天赋
/// </summary>
public HashSet<Skill> CombatTalents { get; set; } = [];
public override bool Equals(IBaseEntity? other)
{
return other is SubClass && other.GetIdName() == GetIdName();
}
}
}

View File

@ -252,16 +252,11 @@ namespace Milimoe.FunGame.Core.Entity
{
foreach (Skill skill in Skills.Passives)
{
List<Effect> effects = [.. Character.Effects.Where(e => e.Skill == skill && e.IsInEffect).OrderByDescending(e => e.Priority)];
foreach (Effect e in effects)
{
Character.Effects.Remove(e);
e.OnEffectLost(Character);
}
skill.RemoveSkillFromCharacter(Character);
}
foreach (Skill skill in Skills.Magics)
{
Character.Skills.Remove(skill);
skill.RemoveSkillFromCharacter(Character);
}
switch (type)
{

View File

@ -56,7 +56,12 @@ namespace Milimoe.FunGame.Core.Entity
{
get
{
return Math.Max(0, field + ExLevel);
int level = field + ExLevel;
if (MaxLevel > 0)
{
level = Math.Min(level, MaxLevel);
}
return Math.Max(0, level);
}
set
{
@ -71,6 +76,11 @@ namespace Milimoe.FunGame.Core.Entity
/// </summary>
public int ExLevel { get; set; } = 0;
/// <summary>
/// 自定义最大等级
/// </summary>
public int MaxLevel { get; set; } = 0;
/// <summary>
/// 技能类型 [ 此项为最高优先级 ]
/// </summary>
@ -771,7 +781,7 @@ namespace Milimoe.FunGame.Core.Entity
}
/// <summary>
/// 被动技能需要重写此方法,返回被动特效给角色 [ 此方法会在技能学习时触发 ]
/// 被动技能需要重写此方法,返回被动特效给角色 [ 此方法会在技能学习时触发 ]
/// </summary>
/// <returns></returns>
public virtual IEnumerable<Effect> AddPassiveEffectToCharacter()
@ -779,6 +789,50 @@ namespace Milimoe.FunGame.Core.Entity
return [];
}
/// <summary>
/// 将技能添加到角色身上,如果是被动,则添加被动特效
/// </summary>
/// <param name="character">角色</param>
/// <returns></returns>
public void AddSkillToCharacter(Character character)
{
if (Level > 0)
{
Character = character;
foreach (Effect e in AddPassiveEffectToCharacter())
{
e.GamingQueue = GamingQueue;
Character.Effects.Add(e);
e.OnEffectGained(Character);
}
// 如果是纯被动技能,则不会添加到角色技能组中
if (IsActive)
{
Character.Skills.Add(this);
}
}
}
/// <summary>
/// 从角色身上移除技能
/// </summary>
/// <param name="character">角色</param>
/// <returns></returns>
public void RemoveSkillFromCharacter(Character character)
{
List<Effect> effects = [.. character.Effects.Where(e => e.Skill == this).OrderByDescending(e => e.Priority)];
foreach (Effect e in effects)
{
character.Effects.Remove(e);
if (e.IsInEffect) e.OnEffectLost(character);
}
character.Skills.Remove(this);
if (character == Character)
{
Character = null;
}
}
/// <summary>
/// 在复活时,因为复活是重新构建角色,如果需要继承死亡角色的技能数据,可以重写此方法并设置相关属性
/// </summary>

View File

@ -62,6 +62,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Character.ExLevel):
result.ExLevel = reader.GetInt32();
break;
case nameof(Character.MaxLevel):
result.MaxLevel = reader.GetInt32();
break;
case nameof(Character.LevelBreak):
result.LevelBreak = reader.GetInt32();
break;
@ -270,7 +273,8 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
writer.WriteNumber(nameof(Character.Promotion), value.Promotion);
writer.WriteNumber(nameof(Character.PrimaryAttribute), (int)value.PrimaryAttribute);
writer.WriteNumber(nameof(Character.Level), value.Level);
writer.WriteNumber(nameof(Character.ExLevel), value.ExLevel);
if (value.ExLevel > 0) writer.WriteNumber(nameof(Character.ExLevel), value.ExLevel);
if (value.MaxLevel > 0) writer.WriteNumber(nameof(Character.MaxLevel), value.MaxLevel);
writer.WriteNumber(nameof(Character.LevelBreak), value.LevelBreak);
writer.WriteNumber(nameof(Character.EXP), value.EXP);
writer.WriteBoolean(nameof(Character.IsNeutral), value.IsNeutral);

View File

@ -44,6 +44,9 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
case nameof(Skill.ExLevel):
result.ExLevel = reader.GetInt32();
break;
case nameof(Skill.MaxLevel):
result.MaxLevel = reader.GetInt32();
break;
case nameof(Skill.CastAnywhere):
result.CastAnywhere = reader.GetBoolean();
break;
@ -147,6 +150,7 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter
if (value.Slogan.Length > 0) writer.WriteString(nameof(Skill.Slogan), value.Slogan);
if (value.Level > 0) writer.WriteNumber(nameof(Skill.Level), value.Level);
if (value.ExLevel > 0) writer.WriteNumber(nameof(Skill.ExLevel), value.ExLevel);
if (value.MaxLevel > 0) writer.WriteNumber(nameof(Skill.MaxLevel), value.MaxLevel);
writer.WriteBoolean(nameof(Skill.CastAnywhere), value.CastAnywhere);
writer.WriteNumber(nameof(Skill.CastRange), value.CastRange);
if (value.CanSelectSelf) writer.WriteBoolean(nameof(Skill.CanSelectSelf), value.CanSelectSelf);

View File

@ -635,6 +635,11 @@ namespace Milimoe.FunGame.Core.Model
/// </summary>
public int DecisionPointsCostOther { get; set; } = 1;
/// <summary>
/// 角色升级时会获得职业点数,该属性设置可获得点数的等级
/// </summary>
public HashSet<int> ClassPointsGetterList { get; set; } = [1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55];
/// <summary>
/// 应用此游戏平衡常数给实体
/// </summary>

View File

@ -122,16 +122,10 @@ namespace Milimoe.FunGame.Core.Model.PrefabricatedEntity
if (NeuralCalibration != null)
{
character.Effects.Remove(NeuralCalibration);
NeuralCalibration.OnEffectLost(character);
}
if (CourageCommand != null)
{
character.Skills.Remove(CourageCommand);
}
if (Soulbound != null)
{
character.Skills.Remove(Soulbound);
if (NeuralCalibration.IsInEffect) NeuralCalibration.OnEffectLost(character);
}
CourageCommand?.RemoveSkillFromCharacter(character);
Soulbound?.RemoveSkillFromCharacter(character);
}
}
}