using System.Text; using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; using Milimoe.FunGame.Core.Model; namespace Milimoe.FunGame.Core.Entity { /// /// 与 不同,构造技能时,建议继承此类再构造 /// public class Skill : BaseEntity, IActiveEnable { /// /// 此技能所属的角色 /// public Character? Character { get; set; } = null; /// /// 技能描述 /// public virtual string Description { get; set; } = ""; /// /// 技能的通用描述 /// public virtual string GeneralDescription { get; set; } = ""; /// /// 技能等级,等于 0 时可以称之为尚未学习 /// public int Level { get { return Math.Max(0, _Level); } set { int max = SkillSet.GetSkillMaxLevel(SkillType); _Level = Math.Min(Math.Max(0, value), max); OnLevelUp(); } } /// /// 技能类型 [ 此项为最高优先级 ] /// [InitRequired] public SkillType SkillType { get; set; } /// /// 是否是主动技能 [ 此项为高优先级 ] /// [InitRequired] public bool IsActive => SkillType != SkillType.Passive; /// /// 是否可用 [ 此项为高优先级 ] /// public bool Enable { get; set; } = true; /// /// 效果持续生效中 [ 此项为高优先级 ] [ 此项设置为true后不允许再次释放,防止重复释放 ] /// public bool IsInEffect { get; set; } = false; /// /// 是否是爆发技 [ 此项为高优先级 ] /// [InitRequired] public bool IsSuperSkill => SkillType == SkillType.SuperSkill; /// /// 是否属于魔法 [ 必须为 true ],反之为战技 /// [InitRequired] public bool IsMagic => SkillType == SkillType.Magic; /// /// 实际魔法消耗 [ 魔法 ] /// public double RealMPCost => Math.Max(0, MPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * 0.00125))); /// /// 魔法消耗 [ 魔法 ] /// [InitOptional] public virtual double MPCost { get; set; } = 0; /// /// 实际吟唱时间 [ 魔法 ] /// public double RealCastTime => Math.Max(0, CastTime * (1 - Calculation.PercentageCheck(Character?.AccelerationCoefficient ?? 0))); /// /// 吟唱时间 [ 魔法 ] /// [InitOptional] public virtual double CastTime { get; set; } = 0; /// /// 实际能量消耗 [ 战技 ] /// public double RealEPCost => IsSuperSkill ? EPCost : Math.Max(0, EPCost * (1 - Calculation.PercentageCheck((Character?.INT ?? 0) * 0.00075))); /// /// 能量消耗 [ 战技 ] /// [InitOptional] public virtual double EPCost { get; set; } = 0; /// /// 实际冷却时间 /// public double RealCD => Math.Max(0, CD * (1 - Character?.CDR ?? 0)); /// /// 冷却时间 /// [InitRequired] public virtual double CD { get; set; } = 0; /// /// 剩余冷却时间 [ 建议配合 属性使用 ] /// public double CurrentCD { get; set; } = 0; /// /// 硬直时间 /// [InitRequired] public virtual double HardnessTime { get; set; } = 0; /// /// 效果列表 /// public HashSet Effects { get; } = []; /// /// 其他参数 /// public Dictionary OtherArgs { get; } = []; /// /// 游戏中的行动顺序表实例,在技能效果被触发时,此实例会获得赋值,使用时需要判断其是否存在 /// public ActionQueue? ActionQueue { get; set; } = null; /// /// 技能是否属于某个物品 /// public Item? Item { get; set; } = null; /// /// 继承此类实现时,调用基类的构造函数 /// /// /// protected Skill(SkillType type, Character? character = null) { SkillType = type; Character = character; } /// /// 用于构造 JSON /// internal Skill() { } /// /// 触发技能升级 /// public void OnLevelUp() { if (!IsActive && Level > 0) { foreach (Effect e in AddInactiveEffectToCharacter()) { e.ActionQueue = ActionQueue; if (Character != null && !Character.Effects.Contains(e)) { Character.Effects.Add(e); e.OnEffectGained(Character); } } } } /// /// 当获得技能时 /// /// public void OnSkillGained(ActionQueue queue) { ActionQueue = queue; OnLevelUp(); } /// /// 技能开始吟唱时 [ 吟唱魔法、释放战技和爆发技、预释放爆发技均可触发 ] /// public void OnSkillCasting(ActionQueue queue, Character caster) { ActionQueue = queue; foreach (Effect e in Effects) { e.ActionQueue = ActionQueue; e.OnSkillCasting(caster); } } /// /// 触发技能效果 /// public void OnSkillCasted(ActionQueue queue, Character caster, List enemys, List teammates) { ActionQueue = queue; foreach (Effect e in Effects) { e.ActionQueue = ActionQueue; e.OnSkillCasted(caster, enemys, teammates, OtherArgs); } } /// /// 被动技能,需要重写此方法,返回被动特效给角色 [ 此方法会在技能学习时触发 ] /// /// public virtual IEnumerable AddInactiveEffectToCharacter() { return []; } /// /// 返回技能的详细说明 /// /// public override string ToString() { StringBuilder builder = new(); string type = IsSuperSkill ? "【爆发技】" : (IsMagic ? "【魔法】" : (IsActive ? "【主动】" : "【被动】")); string level = Level > 0 ? " - 等级 " + Level : " - 尚未学习"; builder.AppendLine(type + Name + level); builder.AppendLine("技能描述:" + Description); if (CurrentCD > 0) { builder.AppendLine($"正在冷却:剩余 {CurrentCD:0.##} 时间"); } if (!Enable) { builder.AppendLine("技能当前不可用"); } if (IsInEffect) { builder.AppendLine("效果结束前不可用"); } if (IsActive) { if (SkillType == SkillType.Item) { if (RealMPCost > 0) { builder.AppendLine($"魔法消耗:{RealMPCost:0.##}"); } if (RealEPCost > 0) { builder.AppendLine($"能量消耗:{RealEPCost:0.##}"); } } else { if (IsSuperSkill) { builder.AppendLine($"能量消耗:{RealEPCost:0.##}"); } else { if (IsMagic) { builder.AppendLine($"魔法消耗:{RealMPCost:0.##}"); builder.AppendLine($"吟唱时间:{RealCastTime:0.##}"); } else { builder.AppendLine($"能量消耗:{RealEPCost:0.##}"); } } } builder.AppendLine($"冷却时间:{RealCD:0.##}"); builder.AppendLine($"硬直时间:{HardnessTime:0.##}"); } return builder.ToString(); } /// /// Id.Name /// /// public string GetIdName() { return Id + "." + Name; } /// /// 判断两个技能是否相同 检查Id.Name /// /// /// public override bool Equals(IBaseEntity? other) { return other is Skill c && c.Id + "." + c.Name == Id + "." + Name; } /// /// 复制一个技能 /// /// public Skill Copy() { Skill s = new() { Id = Id, Name = Name, Description = Description, GeneralDescription = GeneralDescription, SkillType = SkillType, MPCost = MPCost, CastTime = CastTime, EPCost = EPCost, CD = CD, CurrentCD = CurrentCD, HardnessTime = HardnessTime, ActionQueue = ActionQueue }; foreach (Effect e in Effects) { Effect neweffect = e.Copy(s); s.Effects.Add(neweffect); } return s; } /// /// 等级 /// private int _Level = 0; } }