using System.Text; using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Core.Entity { /// /// 角色需要使用 Factory.Get 的方式来构造,并赋值 标记的属性 /// 在使用时仅需要调用 方法即可获得相同对象 /// public class Character : BaseEntity { /// /// 唯一标识符 /// public override Guid Guid { get; set; } = Guid.NewGuid(); /// /// 角色的姓 /// public override string Name { get; set; } = ""; /// /// 角色的名字 /// public string FirstName { get; set; } = ""; /// /// 角色的昵称 /// public string NickName { get; set; } = ""; /// /// 角色所属的玩家 /// public User User { get; set; } /// /// 角色的详细资料 /// public CharacterProfile Profile { get; set; } /// /// 角色的装备 /// public EquipSlot EquipSlot { get; set; } /// /// 魔法属性 /// public MagicType MagicType { get; set; } = MagicType.None; /// /// 角色定位1 /// public RoleType FirstRoleType { get; set; } = RoleType.None; /// /// 角色定位2 /// public RoleType SecondRoleType { get; set; } = RoleType.None; /// /// 角色定位3 /// public RoleType ThirdRoleType { get; set; } = RoleType.None; /// /// 角色评级 /// public RoleRating RoleRating { get { if (Promotion > GameplayEquilibriumConstant.PromotionsUpperLimit["S"]) { return RoleRating.X; } else if (Promotion > GameplayEquilibriumConstant.PromotionsUpperLimit["A+"] && Promotion <= GameplayEquilibriumConstant.PromotionsUpperLimit["S"]) { return RoleRating.S; } else if (Promotion > GameplayEquilibriumConstant.PromotionsUpperLimit["A"] && Promotion <= GameplayEquilibriumConstant.PromotionsUpperLimit["A+"]) { return RoleRating.APlus; } else if (Promotion > GameplayEquilibriumConstant.PromotionsUpperLimit["B"] && Promotion <= GameplayEquilibriumConstant.PromotionsUpperLimit["A"]) { return RoleRating.A; } else if (Promotion > GameplayEquilibriumConstant.PromotionsUpperLimit["C"] && Promotion <= GameplayEquilibriumConstant.PromotionsUpperLimit["B"]) { return RoleRating.B; } else if (Promotion > GameplayEquilibriumConstant.PromotionsUpperLimit["D"] && Promotion <= GameplayEquilibriumConstant.PromotionsUpperLimit["C"]) { return RoleRating.C; } else if (Promotion > GameplayEquilibriumConstant.PromotionsUpperLimit["E"] && Promotion <= GameplayEquilibriumConstant.PromotionsUpperLimit["D"]) { return RoleRating.D; } else { return RoleRating.E; } } } /// /// 晋升点数 /// public int Promotion { get; set; } = 100; /// /// 核心属性 /// public PrimaryAttribute PrimaryAttribute { get; set; } = PrimaryAttribute.None; /// /// 等级 /// public int Level { get { return _Level >= 1 ? _Level : 1; } set { _Level = Math.Min(Math.Max(1, value), GameplayEquilibriumConstant.MaxLevel); OnAttributeChanged(); Recovery(); } } /// /// 经验值 /// public double EXP { get; set; } = 0; /// /// 等级突破进度 [ 对应 中的索引 ] /// public int LevelBreak { get; set; } = -1; /// /// 角色目前所处的状态 [ 战斗相关 ] /// public CharacterState CharacterState { get; set; } = CharacterState.Actionable; /// /// 角色目前被特效施加的状态 [ 用于设置角色是否被控制的状态 ] /// public Dictionary> CharacterEffectStates { get; } = []; /// /// 角色目前被特效施加的控制效果 [ 用于特效判断是否需要在移除特效时更改角色状态 ] /// public Dictionary> CharacterEffectTypes { get; } = []; /// /// 角色是否是中立的 [ 战斗相关 ] /// public bool IsNeutral { get; set; } = false; /// /// 角色是否是不可选中的 [ 战斗相关 ] /// public bool IsUnselectable { get; set; } = false; /// /// 初始生命值 [ 初始设定 ] /// [InitRequired] public double InitialHP { get; set; } = 0; /// /// 基础生命值 [ 与初始设定和等级相关 ] [ 与基础力量相关 ] /// public double BaseHP => InitialHP + (Level - 1) * (GameplayEquilibriumConstant.LevelToHPFactor + GameplayEquilibriumConstant.HPGrowthFactor * InitialHP) + BaseSTR * GameplayEquilibriumConstant.STRtoHPFactor; /// /// 额外生命值 [ 与额外力量相关 ] /// public double ExHP => ExSTR * GameplayEquilibriumConstant.STRtoHPFactor; /// /// 额外生命值2 [ 与技能和物品相关 ] /// public double ExHP2 { get; set; } = 0; /// /// 额外生命值3 [ 额外生命值% ] /// public double ExHP3 => (BaseHP + ExHP + ExHP2) * ExHPPercentage; /// /// 额外生命值% [ 与技能和物品相关 ] /// public double ExHPPercentage { get; set; } = 0; /// /// 最大生命值 = 基础生命值 + 额外生命值 + 额外生命值2 + 额外生命值3 /// public double MaxHP => BaseHP + ExHP + ExHP2 + ExHP3; /// /// 当前生命值 [ 战斗相关 ] /// public double HP { get { return _HP < 0 ? 0 : (_HP > MaxHP ? MaxHP : _HP); } set { _HP = value; if (_HP > MaxHP) _HP = MaxHP; else if (_HP < 0) _HP = 0; } } /// /// 初始魔法值 [ 初始设定 ] /// [InitRequired] public double InitialMP { get; set; } = 0; /// /// 基础魔法值 [ 与初始设定和等级相关 ] [ 与基础智力相关 ] /// public double BaseMP => InitialMP + (Level - 1) * (GameplayEquilibriumConstant.LevelToMPFactor + GameplayEquilibriumConstant.MPGrowthFactor * InitialMP) + BaseINT * GameplayEquilibriumConstant.INTtoMPFactor; /// /// 额外魔法值 [ 与额外智力相关 ] /// public double ExMP => ExINT * GameplayEquilibriumConstant.INTtoMPFactor; /// /// 额外魔法值2 [ 与技能和物品相关 ] /// public double ExMP2 { get; set; } = 0; /// /// 额外魔法值3 [ 额外魔法值% ] /// public double ExMP3 => (BaseMP + ExMP + ExMP2) * ExMPPercentage; /// /// 额外魔法值% [ 与技能和物品相关 ] /// public double ExMPPercentage { get; set; } = 0; /// /// 最大魔法值 = 基础魔法值 + 额外魔法值 + 额外魔法值2 + 额外魔法值3 /// public double MaxMP => BaseMP + ExMP + ExMP2 + ExMP3; /// /// 当前魔法值 [ 战斗相关 ] /// public double MP { get { return _MP < 0 ? 0 : (_MP > MaxMP ? MaxMP : _MP); } set { _MP = value; if (_MP > MaxMP) _MP = MaxMP; else if (_MP < 0) _MP = 0; } } /// /// 当前爆发能量 [ 战斗相关 ] /// public double EP { get { return _EP < 0 ? 0 : (_EP > GameplayEquilibriumConstant.MaxEP ? GameplayEquilibriumConstant.MaxEP : _EP); } set { _EP = value; if (_EP > GameplayEquilibriumConstant.MaxEP) _EP = GameplayEquilibriumConstant.MaxEP; else if (_EP < 0) _EP = 0; } } /// /// 初始攻击力 [ 初始设定 ] /// [InitRequired] public double InitialATK { get; set; } = 0; /// /// 基础攻击力 [ 与初始设定和等级相关 ] [ 与核心属性相关 ] /// public double BaseATK { get { double atk = InitialATK + (Level - 1) * (GameplayEquilibriumConstant.LevelToATKFactor + GameplayEquilibriumConstant.ATKGrowthFactor * InitialATK); if (PrimaryAttribute == PrimaryAttribute.AGI) { return atk + BaseAGI; } else if (PrimaryAttribute == PrimaryAttribute.INT) { return atk + BaseINT; } else // 默认STR { return atk + BaseSTR; } } } /// /// 额外攻击力 [ 与额外核心属性相关 ] /// public double ExATK { get { if (PrimaryAttribute == PrimaryAttribute.AGI) { return ExAGI; } else if (PrimaryAttribute == PrimaryAttribute.INT) { return ExINT; } else // 默认STR { return ExSTR; } } } /// /// 额外攻击力2 [ 与技能和物品相关 ] /// public double ExATK2 { get; set; } = 0; /// /// 额外攻击力3 [ 额外攻击力% ] /// public double ExATK3 => (BaseATK + ExATK + ExATK2) * ExATKPercentage; /// /// 额外攻击力% [ 与技能和物品相关 ] /// public double ExATKPercentage { get; set; } = 0; /// /// 攻击力 = 基础攻击力 + 额外攻击力 + 额外攻击力2 + 额外攻击力3 /// public double ATK => BaseATK + ExATK + ExATK2 + ExATK3; /// /// 初始物理护甲 [ 初始设定 ] /// [InitRequired] public double InitialDEF { get; set; } = 0; /// /// 基础物理护甲 [ 与初始设定相关 ] [ 与基础力量相关 ] /// public double BaseDEF => InitialDEF + BaseSTR * GameplayEquilibriumConstant.STRtoDEFFactor; /// /// 额外物理护甲 [ 与额外力量相关 ] /// public double ExDEF => ExSTR * GameplayEquilibriumConstant.STRtoDEFFactor; /// /// 额外物理护甲2 [ 与技能和物品相关 ] /// public double ExDEF2 { get; set; } = 0; /// /// 额外物理护甲3 [ 额外物理护甲% ] /// public double ExDEF3 => (BaseDEF + ExDEF + ExDEF2) * ExDEFPercentage; /// /// 额外物理护甲% [ 与技能和物品相关 ] /// public double ExDEFPercentage { get; set; } = 0; /// /// 物理护甲 = 基础物理护甲 + 额外物理护甲 + 额外物理护甲2 + 额外物理护甲3 /// public double DEF => BaseDEF + ExDEF + ExDEF2 + ExDEF3; /// /// 物理伤害减免(%) = [ 与物理护甲相关 ] + 额外物理伤害减免(%) /// public double PDR { get { double value = (DEF / (DEF + GameplayEquilibriumConstant.DEFReductionFactor)) + ExPDR; return Calculation.PercentageCheck(value); } } /// /// 额外物理伤害减免(%) [ 与技能和物品相关 ] /// public double ExPDR { get; set; } = 0; /// /// 魔法抗性(%) [ 与技能和物品相关 ] /// public MagicResistance MDF { get; set; } /// /// 物理穿透(%) [ 与技能和物品相关 ] /// public double PhysicalPenetration { get { return Calculation.PercentageCheck(_PhysicalPenetration); } set { _PhysicalPenetration = Calculation.PercentageCheck(value); } } /// /// 魔法穿透(%) [ 与技能和物品相关 ] /// public double MagicalPenetration { get { return Calculation.PercentageCheck(_MagicalPenetration); } set { _MagicalPenetration = Calculation.PercentageCheck(value); } } /// /// 初始生命回复力 [ 初始设定 ] /// [InitRequired] public double InitialHR { get; set; } = 0; /// /// 生命回复力 = [ 与初始设定相关 ] [ 与力量相关 ] + 额外生命回复力 /// public double HR => InitialHR + STR * GameplayEquilibriumConstant.STRtoHRFactor + ExHR; /// /// 额外生命回复力 [ 与技能和物品相关 ] /// public double ExHR { get; set; } = 0; /// /// 初始魔法回复力 [ 初始设定 ] /// [InitRequired] public double InitialMR { get; set; } = 0; /// /// 魔法回复力 = [ 与初始设定相关 ] [ 与智力相关 ] + 额外魔法回复力 /// public double MR => InitialMR + INT * GameplayEquilibriumConstant.INTtoMRFactor + ExMR; /// /// 额外魔法回复力 [ 与技能和物品相关 ] /// public double ExMR { get; set; } = 0; /// /// 能量回复力 [ 与技能和物品相关 ] /// public double ER { get; set; } = 0; /// /// 核心属性的值 [ 核心属性相关 ] /// public double PrimaryAttributeValue { get { if (PrimaryAttribute == PrimaryAttribute.AGI) { return AGI; } else if (PrimaryAttribute == PrimaryAttribute.INT) { return INT; } else { return STR; } } } /// /// 基础核心属性的值 [ 核心属性相关 ] /// public double BasePrimaryAttributeValue { get { if (PrimaryAttribute == PrimaryAttribute.AGI) { return BaseAGI; } else if (PrimaryAttribute == PrimaryAttribute.INT) { return BaseINT; } else { return BaseSTR; } } } /// /// 额外核心属性的值 [ 核心属性相关 ] /// public double ExPrimaryAttributeValue { get { if (PrimaryAttribute == PrimaryAttribute.AGI) { return ExAGI; } else if (PrimaryAttribute == PrimaryAttribute.INT) { return ExINT; } else { return ExSTR; } } } /// /// 初始力量 [ 初始设定 ] /// [InitRequired] public double InitialSTR { get; set; } = 0; /// /// 初始敏捷 [ 初始设定 ] /// [InitRequired] public double InitialAGI { get; set; } = 0; /// /// 初始智力 [ 初始设定 ] /// [InitRequired] public double InitialINT { get; set; } = 0; /// /// 基础力量 [ 与初始设定和等级相关 ] /// public double BaseSTR => InitialSTR + STRGrowth * (Level - 1); /// /// 基础敏捷 [ 与初始设定和等级相关 ] /// public double BaseAGI => InitialAGI + AGIGrowth * (Level - 1); /// /// 基础智力 [ 与初始设定和等级相关 ] /// public double BaseINT => InitialINT + INTGrowth * (Level - 1); /// /// 额外力量 [ 与技能和物品相关 ] /// public double ExSTR { get; set; } = 0; /// /// 额外敏捷 [ 与技能和物品相关 ] /// public double ExAGI { get; set; } = 0; /// /// 额外智力 [ 与技能和物品相关 ] /// public double ExINT { get; set; } = 0; /// /// 额外力量2 [ 额外力量% ] /// public double ExSTR2 => (BaseSTR + ExSTR) * ExSTRPercentage; /// /// 额外敏捷2 [ 额外敏捷% ] /// public double ExAGI2 => (BaseAGI + ExAGI) * ExAGIPercentage; /// /// 额外智力2 [ 额外智力% ] /// public double ExINT2 => (BaseINT + ExINT) * ExINTPercentage; /// /// 额外力量% [ 与技能和物品相关 ] /// public double ExSTRPercentage { get; set; } = 0; /// /// 额外敏捷% [ 与技能和物品相关 ] /// public double ExAGIPercentage { get; set; } = 0; /// /// 额外智力% [ 与技能和物品相关 ] /// public double ExINTPercentage { get; set; } = 0; /// /// 力量 = 基础力量 + 额外力量 + 额外力量2 /// public double STR => BaseSTR + ExSTR + ExSTR2; /// /// 敏捷 = 基础敏捷 + 额外敏捷 + 额外敏捷2 /// public double AGI => BaseAGI + ExAGI + ExAGI2; /// /// 智力 = 基础智力 + 额外智力 + 额外智力2 /// public double INT => BaseINT + ExINT + ExINT2; /// /// 力量成长值(+BaseSTR/Lv) /// public double STRGrowth { get; set; } = 0; /// /// 敏捷成长值(+BaseAGI/Lv) /// public double AGIGrowth { get; set; } = 0; /// /// 智力成长值(+BaseINT/Lv) /// public double INTGrowth { get; set; } = 0; /// /// 行动速度 [ 初始设定 ] /// [InitRequired] public double InitialSPD { get; set; } = 0; /// /// 行动速度 = [ 与初始设定相关 ][ 与敏捷相关 ] + 额外行动速度 /// public double SPD => InitialSPD + AGI * GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD; /// /// 额外行动速度 [ 与技能和物品相关 ] /// public double ExSPD { get; set; } = 0; /// /// 行动系数(%) = [ 与速度相关 ] + 额外行动系数(%) /// public double ActionCoefficient { get { double value = SPD / GameplayEquilibriumConstant.SPDUpperLimit + ExActionCoefficient; return Calculation.PercentageCheck(value); } } /// /// 额外行动系数(%) [ 与技能和物品相关 ] /// public double ExActionCoefficient { get; set; } = 0; /// /// 加速系数(%) = [ 与智力相关 ] + 额外加速系数(%) /// public double AccelerationCoefficient { get { double value = INT * GameplayEquilibriumConstant.INTtoAccelerationCoefficientMultiplier + ExAccelerationCoefficient; return Calculation.PercentageCheck(value); } } /// /// 额外加速系数(%) [ 与技能和物品相关 ] /// public double ExAccelerationCoefficient { get; set; } = 0; /// /// 冷却缩减(%) = [ 与智力相关 ] + 额外冷却缩减(%) /// public double CDR { get { double value = INT * GameplayEquilibriumConstant.INTtoCDRMultiplier + ExCDR; return Calculation.PercentageCheck(value); } } /// /// 额外冷却缩减(%) [ 与技能和物品相关 ] /// public double ExCDR { get; set; } = 0; /// /// 攻击距离 [ 与技能和物品相关 ] [ 单位:格 ] /// [InitOptional] public double ATR { get; set; } = 1; /// /// 暴击率(%) = [ 与敏捷相关 ] + 额外暴击率(%) /// public double CritRate { get { double value = GameplayEquilibriumConstant.CritRate + AGI * GameplayEquilibriumConstant.AGItoCritRateMultiplier + ExCritRate; return Calculation.PercentageCheck(value); } } /// /// 额外暴击率(%) [ 与技能和物品相关 ] /// public double ExCritRate { get; set; } = 0; /// /// 暴击伤害(%) = [ 与力量相关 ] + 额外暴击伤害(%) /// public double CritDMG { get { return GameplayEquilibriumConstant.CritDMG + STR * GameplayEquilibriumConstant.STRtoCritDMGMultiplier + ExCritDMG; } } /// /// 额外暴击伤害(%) [ 与技能和物品相关 ] /// public double ExCritDMG { get; set; } = 0; /// /// 闪避率(%) = [ 与敏捷相关 ] + 额外闪避率(%) /// public double EvadeRate { get { double value = GameplayEquilibriumConstant.EvadeRate + AGI * GameplayEquilibriumConstant.AGItoEvadeRateMultiplier + ExEvadeRate; return Calculation.PercentageCheck(value); } } /// /// 额外闪避率(%) [ 与技能和物品相关 ] /// public double ExEvadeRate { get; set; } = 0; /// /// 普通攻击对象 /// public NormalAttack NormalAttack { get; } /// /// 角色的技能列表 /// public HashSet Skills { get; } = []; /// /// 角色的持续性特效列表 /// public HashSet Effects { get; } = []; /// /// 角色携带的物品 /// public HashSet Items { get; } = []; /** * ===== 私有变量 ===== */ /// /// 等级 /// private int _Level = 1; /// /// 生命值 /// private double _HP = 0; /// /// 魔法值 /// private double _MP = 0; /// /// 能量值 /// private double _EP = 0; /// /// 物理穿透 /// private double _PhysicalPenetration = 0; /// /// 魔法穿透 /// private double _MagicalPenetration = 0; protected Character() { User = General.UnknownUserInstance; Profile = new(Name, FirstName, NickName); InitialHP = GameplayEquilibriumConstant.InitialHP; InitialMP = GameplayEquilibriumConstant.InitialMP; InitialATK = GameplayEquilibriumConstant.InitialATK; InitialDEF = GameplayEquilibriumConstant.InitialDEF; EquipSlot = new(); MDF = new(); NormalAttack = new(this); } internal static Character GetInstance() { return new(); } /// /// 回复状态至满 /// /// public void Recovery(double EP = -1) { HP = MaxHP; MP = MaxMP; if (EP != -1) this.EP = EP; } /// /// 按时间回复状态 /// /// /// public void Recovery(int time, double EP = -1) { if (time > 0) { HP = Math.Min(MaxHP, HP + HR * time); MP = Math.Min(MaxMP, MP + MR * time); if (EP != -1) this.EP = EP; } } /// /// 按当前百分比回复状态(一般在属性变化时调用) /// /// /// /// /// public void Recovery(double pastHP, double pastMP, double pastMaxHP, double pastMaxMP) { double pHP = pastHP / pastMaxHP; double pMP = pastMP / pastMaxMP; HP = MaxHP * pHP; MP = MaxMP * pMP; } /// /// 为角色装备物品(必须使用此方法而不是自己去给EquipSlot里的物品赋值) /// 此方法装备到指定栏位,并返回被替换的装备(如果有的话) /// /// /// /// public bool Equip(Item item, EquipSlotType slot, out Item? previous) { previous = null; bool result = false; double pastHP = HP; double pastMaxHP = MaxHP; double pastMP = MP; double pastMaxMP = MaxMP; switch (slot) { case EquipSlotType.MagicCardPack: if (item.ItemType == ItemType.MagicCardPack) { previous = UnEquip(EquipSlotType.MagicCardPack); EquipSlot.MagicCardPack = item; item.OnItemEquip(this, EquipSlotType.MagicCardPack); result = true; } break; case EquipSlotType.Weapon: if (item.ItemType == ItemType.Weapon) { previous = UnEquip(EquipSlotType.Weapon); EquipSlot.Weapon = item; item.OnItemEquip(this, EquipSlotType.Weapon); result = true; } break; case EquipSlotType.Armor: if (item.ItemType == ItemType.Armor) { previous = UnEquip(EquipSlotType.Armor); EquipSlot.Armor = item; item.OnItemEquip(this, EquipSlotType.Armor); result = true; } break; case EquipSlotType.Shoes: if (item.ItemType == ItemType.Shoes) { previous = UnEquip(EquipSlotType.Shoes); EquipSlot.Shoes = item; item.OnItemEquip(this, EquipSlotType.Shoes); result = true; } break; case EquipSlotType.Accessory1: if (item.ItemType == ItemType.Accessory) { previous = UnEquip(EquipSlotType.Accessory1); EquipSlot.Accessory1 = item; EquipSlot.LastEquipSlotType = EquipSlotType.Accessory1; item.OnItemEquip(this, EquipSlotType.Accessory1); result = true; } break; case EquipSlotType.Accessory2: if (item.ItemType == ItemType.Accessory) { previous = UnEquip(EquipSlotType.Accessory2); EquipSlot.Accessory2 = item; EquipSlot.LastEquipSlotType = EquipSlotType.Accessory2; item.OnItemEquip(this, EquipSlotType.Accessory2); result = true; } break; } if (result) { OnAttributeChanged(); Recovery(pastHP, pastMP, pastMaxHP, pastMaxMP); } return result; } /// /// 为角色装备物品(必须使用此方法而不是自己去给EquipSlot里的物品赋值) /// 此方法为根据物品类型,优先空位自动装备 /// /// public bool Equip(Item item) { switch (item.ItemType) { case ItemType.MagicCardPack: return Equip(item, EquipSlotType.MagicCardPack, out _); case ItemType.Weapon: return Equip(item, EquipSlotType.Weapon, out _); case ItemType.Armor: return Equip(item, EquipSlotType.Armor, out _); case ItemType.Shoes: return Equip(item, EquipSlotType.Shoes, out _); case ItemType.Accessory: if (EquipSlot.Accessory1 is null) { return Equip(item, EquipSlotType.Accessory1, out _); } else if (EquipSlot.Accessory1 != null && EquipSlot.Accessory2 is null) { return Equip(item, EquipSlotType.Accessory2, out _); } else if (EquipSlot.Accessory1 != null && EquipSlot.Accessory2 != null && EquipSlot.LastEquipSlotType == EquipSlotType.Accessory1) { return Equip(item, EquipSlotType.Accessory2, out _); } else { return Equip(item, EquipSlotType.Accessory1, out _); } } return false; } /// /// 为角色装备物品(必须使用此方法而不是自己去给EquipSlot里的物品赋值) /// 此方法为根据物品类型,优先空位自动装备 /// 此方法可返回被替换的装备(如果有的话) /// /// /// public bool Equip(Item item, out Item? previous) { previous = null; switch (item.ItemType) { case ItemType.MagicCardPack: return Equip(item, EquipSlotType.MagicCardPack, out previous); case ItemType.Weapon: return Equip(item, EquipSlotType.Weapon, out previous); case ItemType.Armor: return Equip(item, EquipSlotType.Armor, out previous); case ItemType.Shoes: return Equip(item, EquipSlotType.Shoes, out previous); case ItemType.Accessory: if (EquipSlot.Accessory1 is null) { return Equip(item, EquipSlotType.Accessory1, out previous); } else if (EquipSlot.Accessory1 != null && EquipSlot.Accessory2 is null) { return Equip(item, EquipSlotType.Accessory2, out previous); } else if (EquipSlot.Accessory1 != null && EquipSlot.Accessory2 != null && EquipSlot.LastEquipSlotType == EquipSlotType.Accessory1) { return Equip(item, EquipSlotType.Accessory2, out previous); } else { return Equip(item, EquipSlotType.Accessory1, out previous); } } return false; } /// /// 取消装备,返回被取消的物品对象 /// /// /// public Item? UnEquip(EquipSlotType type) { Item? result = null; double pastHP = HP; double pastMaxHP = MaxHP; double pastMP = MP; double pastMaxMP = MaxMP; switch (type) { case EquipSlotType.MagicCardPack: if (EquipSlot.MagicCardPack != null) { result = EquipSlot.MagicCardPack; EquipSlot.MagicCardPack.OnItemUnEquip(EquipSlotType.MagicCardPack); } break; case EquipSlotType.Weapon: if (EquipSlot.Weapon != null) { result = EquipSlot.Weapon; EquipSlot.Weapon.OnItemUnEquip(EquipSlotType.Weapon); } break; case EquipSlotType.Armor: if (EquipSlot.Armor != null) { result = EquipSlot.Armor; EquipSlot.Armor.OnItemUnEquip(EquipSlotType.Armor); } break; case EquipSlotType.Shoes: if (EquipSlot.Shoes != null) { result = EquipSlot.Shoes; EquipSlot.Shoes.OnItemUnEquip(EquipSlotType.Shoes); } break; case EquipSlotType.Accessory1: if (EquipSlot.Accessory1 != null) { result = EquipSlot.Accessory1; EquipSlot.Accessory1.OnItemUnEquip(EquipSlotType.Accessory1); } break; case EquipSlotType.Accessory2: if (EquipSlot.Accessory2 != null) { result = EquipSlot.Accessory2; EquipSlot.Accessory2.OnItemUnEquip(EquipSlotType.Accessory2); } break; } if (result != null) { OnAttributeChanged(); Recovery(pastHP, pastMP, pastMaxHP, pastMaxMP); } return result; } /// /// 角色升级 /// /// /// public void OnLevelUp(int level = 0, bool checkLevelBreak = true) { int count = 0; while (true) { // 传入 level 表示最多升级多少次,0 为用完所有溢出的经验值 if (level != 0 && count++ >= level) { break; } if (GameplayEquilibriumConstant.UseLevelBreak && checkLevelBreak) { // 检查角色突破进度 int[] breaks = [.. GameplayEquilibriumConstant.LevelBreakList]; int nextBreak = LevelBreak + 1; if (nextBreak < breaks.Length && Level >= breaks[nextBreak]) { // 需要突破才能继续升级 break; } } if (Level > 0 && Level < GameplayEquilibriumConstant.MaxLevel && GameplayEquilibriumConstant.EXPUpperLimit.TryGetValue(Level, out double need) && EXP >= need) { EXP -= need; Level++; OnAttributeChanged(); Recovery(); } else { break; } } } /// /// 角色突破,允许继续升级 /// public void OnLevelBreak() { if (GameplayEquilibriumConstant.UseLevelBreak) { // 检查角色突破进度 int[] levels = [.. GameplayEquilibriumConstant.LevelBreakList]; while (LevelBreak + 1 < levels.Length && Level >= levels[LevelBreak + 1]) { LevelBreak++; } } } /// /// 角色的属性发生变化,会影响特殊效果的计算 /// public void OnAttributeChanged() { List effects = [.. Effects.Where(e => e.Level > 0)]; foreach (Effect effect in effects) { effect.OnAttributeChanged(this); } } /// /// 比较一个角色(只比较 ) /// /// /// public override bool Equals(IBaseEntity? other) { return other is Character c && c.ToString() == ToString(); } /// /// 获取角色实例的昵称以及所属玩家,如果没有昵称,则用名字代替 /// /// public override string ToString() { string str = NickName != "" ? NickName : GetName(); if (User != null && User.Username != "") { str += "(" + User.Username + ")"; } return str; } /// /// 获取角色实例的名字、昵称 /// /// public string ToStringWithOutUser() { string str = GetName(); if (NickName != "") { if (str != "") str += ", "; str += NickName; } return str; } /// /// 获取角色实例的名字、昵称以及所属玩家 /// /// public string ToStringWithUser() { string str = GetName(); if (NickName != "") { if (str != "") str += ", "; str += NickName; } if (User != null && User.Username != "") { str += "(" + User.Username + ")"; } return str; } /// /// 获取角色实例的名字、昵称以及所属玩家,包含等级 /// /// public string ToStringWithLevel() { string str = GetName(); if (NickName != "") { if (str != "") str += ", "; str += NickName; } str += " - 等级 " + Level; if (User != null && User.Username != "") { str += "(" + User.Username + ")"; } return str; } /// /// 获取角色实例的名字、昵称以及等级 /// /// public string ToStringWithLevelWithOutUser() { string str = GetName(); if (NickName != "") { if (str != "") str += ", "; str += NickName; } str += " - 等级 " + Level; return str; } /// /// 获取角色的名字 /// /// /// 如果 = false,返回 ;反之,返回 + public string GetName(bool full = true) { if (full) { bool isChineseName = NetworkUtility.IsChineseName(Name + FirstName); string str = isChineseName ? (Name + FirstName).Trim() : (Name + " " + FirstName).Trim(); return str; } else { return FirstName; } } /// /// 获取角色的详细信息 /// /// public string GetInfo(bool showUser = true, bool showGrowth = true, bool showEXP = false) { StringBuilder builder = new(); builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); if (showEXP) { builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}(突破进度:{LevelBreak + 1} / {GameplayEquilibriumConstant.LevelBreakList.Count})"); builder.AppendLine($"经验值:{EXP}{(Level != GameplayEquilibriumConstant.MaxLevel && GameplayEquilibriumConstant.EXPUpperLimit.TryGetValue(Level, out double need) ? " / " + need : "")}"); } double exHP = ExHP + ExHP2 + ExHP3; builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); builder.AppendLine($"能量值:{EP:0.##} / {GameplayEquilibriumConstant.MaxEP:0.##}"); double exATK = ExATK + ExATK2 + ExATK3; builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : "")); double exDEF = ExDEF + ExDEF2 + ExDEF3; builder.AppendLine($"物理护甲:{DEF:0.##}" + (exDEF != 0 ? $" [{BaseDEF:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exDEF):0.##}]" : "") + $" ({PDR * 100:0.##}%)"); double mdf = Calculation.Round4Digits((MDF.None + MDF.Starmark + MDF.PurityNatural + MDF.PurityContemporary + MDF.Bright + MDF.Shadow + MDF.Element + MDF.Fleabane + MDF.Particle) / 9) * 100; if (Calculation.IsApproximatelyZero(mdf)) mdf = 0; builder.AppendLine($"魔法抗性:{mdf:0.##}%(平均)"); double exSPD = AGI * GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD; builder.AppendLine($"行动速度:{SPD:0.##}" + (exSPD != 0 ? $" [{InitialSPD:0.##} {(exSPD >= 0 ? "+" : "-")} {Math.Abs(exSPD):0.##}]" : "") + $" ({ActionCoefficient * 100:0.##}%)"); builder.AppendLine($"核心属性:{CharacterSet.GetPrimaryAttributeName(PrimaryAttribute)}"); double exSTR = ExSTR + ExSTR2; builder.AppendLine($"力量:{STR:0.##}" + (exSTR != 0 ? $" [{BaseSTR:0.##} {(exSTR >= 0 ? "+" : "-")} {Math.Abs(exSTR):0.##}]" : "") + (showGrowth ? $"({(STRGrowth >= 0 ? "+" : "-")}{Math.Abs(STRGrowth)}/Lv)" : "")); double exAGI = ExAGI + ExAGI2; builder.AppendLine($"敏捷:{AGI:0.##}" + (exAGI != 0 ? $" [{BaseAGI:0.##} {(exAGI >= 0 ? "+" : "-")} {Math.Abs(exAGI):0.##}]" : "") + (showGrowth ? $"({(AGIGrowth >= 0 ? "+" : "-")}{Math.Abs(AGIGrowth)}/Lv)" : "")); double exINT = ExINT + ExINT2; builder.AppendLine($"智力:{INT:0.##}" + (exINT != 0 ? $" [{BaseINT:0.##} {(exINT >= 0 ? "+" : "-")} {Math.Abs(exINT):0.##}]" : "") + (showGrowth ? $"({(INTGrowth >= 0 ? "+" : "-")}{Math.Abs(INTGrowth)}/Lv)" : "")); builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * GameplayEquilibriumConstant.STRtoHRFactor:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):0.##}]" : "")); builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR != 0 ? $" [{InitialMR + INT * GameplayEquilibriumConstant.INTtoMRFactor:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : "")); builder.AppendLine($"暴击率:{CritRate * 100:0.##}%"); builder.AppendLine($"暴击伤害:{CritDMG * 100:0.##}%"); builder.AppendLine($"闪避率:{EvadeRate * 100:0.##}%"); builder.AppendLine($"冷却缩减:{CDR * 100:0.##}%"); builder.AppendLine($"加速系数:{AccelerationCoefficient * 100:0.##}%"); builder.AppendLine($"物理穿透:{PhysicalPenetration * 100:0.##}%"); builder.AppendLine($"魔法穿透:{MagicalPenetration * 100:0.##}%"); builder.AppendLine($"魔法消耗减少:{INT * GameplayEquilibriumConstant.INTtoCastMPReduce * 100:0.##}%"); builder.AppendLine($"能量消耗减少:{INT * GameplayEquilibriumConstant.INTtoCastEPReduce * 100:0.##}%"); if (CharacterState != CharacterState.Actionable) { builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); } if (IsNeutral) { builder.AppendLine("角色是无敌的"); } if (IsUnselectable) { builder.AppendLine("角色是不可选中的"); } builder.AppendLine("== 普通攻击 =="); builder.Append(NormalAttack.ToString()); if (Skills.Count > 0) { builder.AppendLine("== 角色技能 =="); foreach (Skill skill in Skills) { builder.Append(skill.ToString()); } } if (EquipSlot.Any()) { builder.AppendLine("== 装备栏 =="); if (EquipSlot.MagicCardPack != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.MagicCardPack.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.MagicCardPack) + ":" + EquipSlot.MagicCardPack.Name); builder.AppendLine(EquipSlot.MagicCardPack.Description); } if (EquipSlot.Weapon != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Weapon.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Weapon) + ":" + EquipSlot.Weapon.Name); builder.AppendLine(EquipSlot.Weapon.Description); } if (EquipSlot.Armor != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Armor.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Armor) + ":" + EquipSlot.Armor.Name); builder.AppendLine(EquipSlot.Armor.Description); } if (EquipSlot.Shoes != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Shoes.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Shoes) + ":" + EquipSlot.Shoes.Name); builder.AppendLine(EquipSlot.Shoes.Description); } if (EquipSlot.Accessory1 != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Accessory1.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Accessory1) + ":" + EquipSlot.Accessory1.Name); builder.AppendLine(EquipSlot.Accessory1.Description); } if (EquipSlot.Accessory2 != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Accessory2.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Accessory2) + ":" + EquipSlot.Accessory2.Name); builder.AppendLine(EquipSlot.Accessory2.Description); } } if (Items.Count > 0) { builder.AppendLine("== 角色背包 =="); foreach (Item item in Items) { builder.Append(item.ToString()); } } if (Effects.Where(e => e.EffectType != EffectType.Item).Any()) { builder.AppendLine("== 状态栏 =="); foreach (Effect effect in Effects.Where(e => e.EffectType != EffectType.Item)) { builder.Append(effect.ToString()); } } return builder.ToString(); } /// /// 获取角色的简略信息 /// /// public string GetSimpleInfo(bool showUser = true, bool showGrowth = true, bool showEXP = false, bool showBasicOnly = false) { StringBuilder builder = new(); builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); if (showEXP) { builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}(突破进度:{LevelBreak + 1} / {GameplayEquilibriumConstant.LevelBreakList.Count})"); builder.AppendLine($"经验值:{EXP}{(Level != GameplayEquilibriumConstant.MaxLevel && GameplayEquilibriumConstant.EXPUpperLimit.TryGetValue(Level, out double need) ? " / " + need : "")}"); } double exHP = ExHP + ExHP2 + ExHP3; builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); builder.AppendLine($"能量值:{EP:0.##} / {GameplayEquilibriumConstant.MaxEP:0.##}"); double exATK = ExATK + ExATK2 + ExATK3; builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : "")); double exDEF = ExDEF + ExDEF2 + ExDEF3; builder.AppendLine($"物理护甲:{DEF:0.##}" + (exDEF != 0 ? $" [{BaseDEF:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exDEF):0.##}]" : "") + $" ({PDR * 100:0.##}%)"); double mdf = Calculation.Round4Digits((MDF.None + MDF.Starmark + MDF.PurityNatural + MDF.PurityContemporary + MDF.Bright + MDF.Shadow + MDF.Element + MDF.Fleabane + MDF.Particle) / 9) * 100; if (Calculation.IsApproximatelyZero(mdf)) mdf = 0; builder.AppendLine($"魔法抗性:{mdf:0.##}%(平均)"); if (showBasicOnly) { builder.AppendLine($"核心属性:{PrimaryAttributeValue:0.##}({CharacterSet.GetPrimaryAttributeName(PrimaryAttribute)})"); } else { double exSPD = AGI * GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD; builder.AppendLine($"行动速度:{SPD:0.##}" + (exSPD != 0 ? $" [{InitialSPD:0.##} {(exSPD >= 0 ? "+" : "-")} {Math.Abs(exSPD):0.##}]" : "") + $" ({ActionCoefficient * 100:0.##}%)"); builder.AppendLine($"核心属性:{CharacterSet.GetPrimaryAttributeName(PrimaryAttribute)}"); double exSTR = ExSTR + ExSTR2; builder.AppendLine($"力量:{STR:0.##}" + (exSTR != 0 ? $" [{BaseSTR:0.##} {(exSTR >= 0 ? "+" : "-")} {Math.Abs(exSTR):0.##}]" : "") + (showGrowth ? $"({(STRGrowth >= 0 ? "+" : "-")}{Math.Abs(STRGrowth)}/Lv)" : "")); double exAGI = ExAGI + ExAGI2; builder.AppendLine($"敏捷:{AGI:0.##}" + (exAGI != 0 ? $" [{BaseAGI:0.##} {(exAGI >= 0 ? "+" : "-")} {Math.Abs(exAGI):0.##}]" : "") + (showGrowth ? $"({(AGIGrowth >= 0 ? "+" : "-")}{Math.Abs(AGIGrowth)}/Lv)" : "")); double exINT = ExINT + ExINT2; builder.AppendLine($"智力:{INT:0.##}" + (exINT != 0 ? $" [{BaseINT:0.##} {(exINT >= 0 ? "+" : "-")} {Math.Abs(exINT):0.##}]" : "") + (showGrowth ? $"({(INTGrowth >= 0 ? "+" : "-")}{Math.Abs(INTGrowth)}/Lv)" : "")); } builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * GameplayEquilibriumConstant.STRtoHRFactor:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):0.##}]" : "")); builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR != 0 ? $" [{InitialMR + INT * GameplayEquilibriumConstant.INTtoMRFactor:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : "")); if (!showBasicOnly) { if (CharacterState != CharacterState.Actionable) { builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); } if (IsNeutral) { builder.AppendLine("角色是无敌的"); } if (IsUnselectable) { builder.AppendLine("角色是不可选中的"); } if (Skills.Count > 0) { builder.AppendLine("== 角色技能 =="); builder.AppendLine(string.Join(",", Skills.Select(s => s.Name))); } if (EquipSlot.Any()) { builder.AppendLine("== 已装备槽位 =="); List types = []; if (EquipSlot.MagicCardPack != null) { types.Add(EquipSlotType.MagicCardPack); } if (EquipSlot.Weapon != null) { types.Add(EquipSlotType.Weapon); } if (EquipSlot.Armor != null) { types.Add(EquipSlotType.Armor); } if (EquipSlot.Shoes != null) { types.Add(EquipSlotType.Shoes); } if (EquipSlot.Accessory1 != null) { types.Add(EquipSlotType.Accessory1); } if (EquipSlot.Accessory2 != null) { types.Add(EquipSlotType.Accessory2); } builder.AppendLine(string.Join(",", types.Select(ItemSet.GetEquipSlotTypeName))); } if (Effects.Where(e => e.EffectType != EffectType.Item).Any()) { builder.AppendLine("== 状态栏 =="); builder.Append(string.Join(",", Effects.Where(e => e.EffectType != EffectType.Item).Select(e => e.Name))); } } return builder.ToString(); } /// /// 获取战斗状态的信息 /// /// /// public string GetInBattleInfo(double hardnessTimes) { StringBuilder builder = new(); builder.AppendLine(ToStringWithLevel()); double exHP = ExHP + ExHP2 + ExHP3; builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); builder.AppendLine($"能量值:{EP:0.##} / {GameplayEquilibriumConstant.MaxEP:0.##}"); double exATK = ExATK + ExATK2 + ExATK3; builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : "")); builder.AppendLine($"核心属性:{PrimaryAttributeValue:0.##}" + (ExPrimaryAttributeValue != 0 ? $" [{BasePrimaryAttributeValue:0.##} {(ExPrimaryAttributeValue >= 0 ? "+" : "-")} {Math.Abs(ExPrimaryAttributeValue):0.##}]" : "")); if (CharacterState != CharacterState.Actionable) { builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); } if (IsNeutral) { builder.AppendLine("角色是中立单位,处于无敌状态"); } if (IsUnselectable) { builder.AppendLine("角色是不可选中的"); } builder.AppendLine($"硬直时间:{hardnessTimes:0.##}"); if (Effects.Where(e => e.EffectType != EffectType.Item).Any()) { builder.AppendLine("== 状态栏 =="); foreach (Effect effect in Effects.Where(e => e.EffectType != EffectType.Item)) { builder.Append(effect.ToString()); } } return builder.ToString(); } /// /// 获取战斗状态的信息(简略版) /// /// /// public string GetSimpleInBattleInfo(double hardnessTimes) { StringBuilder builder = new(); builder.AppendLine(ToStringWithLevel()); double exHP = ExHP + ExHP2 + ExHP3; builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); builder.AppendLine($"能量值:{EP:0.##} / {GameplayEquilibriumConstant.MaxEP:0.##}"); double exATK = ExATK + ExATK2 + ExATK3; builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : "")); builder.AppendLine($"核心属性:{PrimaryAttributeValue:0.##}" + (ExPrimaryAttributeValue != 0 ? $" [{BasePrimaryAttributeValue:0.##} {(ExPrimaryAttributeValue >= 0 ? "+" : "-")} {Math.Abs(ExPrimaryAttributeValue):0.##}]" : "")); builder.AppendLine($"硬直时间:{hardnessTimes:0.##}"); if (Effects.Where(e => e.EffectType != EffectType.Item).Any()) { builder.AppendLine("== 状态栏 =="); builder.Append(string.Join(",", Effects.Where(e => e.EffectType != EffectType.Item).Select(e => e.Name))); } return builder.ToString(); } /// /// 获取角色的技能信息 /// /// public string GetSkillInfo(bool showUser = true) { StringBuilder builder = new(); builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); if (CharacterState != CharacterState.Actionable) { builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); } if (IsNeutral) { builder.AppendLine("角色是无敌的"); } if (IsUnselectable) { builder.AppendLine("角色是不可选中的"); } builder.AppendLine("== 普通攻击 =="); builder.Append(NormalAttack.ToString()); if (Skills.Count > 0) { builder.AppendLine("== 角色技能 =="); foreach (Skill skill in Skills) { builder.Append(skill.ToString()); } } if (Effects.Where(e => e.EffectType != EffectType.Item).Any()) { builder.AppendLine("== 状态栏 =="); foreach (Effect effect in Effects.Where(e => e.EffectType != EffectType.Item)) { builder.Append(effect.ToString()); } } return builder.ToString(); } /// /// 获取角色的物品信息 /// /// public string GetItemInfo(bool showUser = true, bool showGrowth = true, bool showEXP = false) { StringBuilder builder = new(); builder.AppendLine(showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser()); if (showEXP) { builder.AppendLine($"等级:{Level} / {GameplayEquilibriumConstant.MaxLevel}(突破进度:{LevelBreak + 1} / {GameplayEquilibriumConstant.LevelBreakList.Count})"); builder.AppendLine($"经验值:{EXP}{(Level != GameplayEquilibriumConstant.MaxLevel && GameplayEquilibriumConstant.EXPUpperLimit.TryGetValue(Level, out double need) ? " / " + need : "")}"); } double exHP = ExHP + ExHP2 + ExHP3; builder.AppendLine($"生命值:{HP:0.##} / {MaxHP:0.##}" + (exHP != 0 ? $" [{BaseHP:0.##} {(exHP >= 0 ? "+" : "-")} {Math.Abs(exHP):0.##}]" : "")); double exMP = ExMP + ExMP2 + ExMP3; builder.AppendLine($"魔法值:{MP:0.##} / {MaxMP:0.##}" + (exMP != 0 ? $" [{BaseMP:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exMP):0.##}]" : "")); builder.AppendLine($"能量值:{EP:0.##} / {GameplayEquilibriumConstant.MaxEP:0.##}"); double exATK = ExATK + ExATK2 + ExATK3; builder.AppendLine($"攻击力:{ATK:0.##}" + (exATK != 0 ? $" [{BaseATK:0.##} {(exATK >= 0 ? "+" : "-")} {Math.Abs(exATK):0.##}]" : "")); double exDEF = ExDEF + ExDEF2 + ExDEF3; builder.AppendLine($"物理护甲:{DEF:0.##}" + (exDEF != 0 ? $" [{BaseDEF:0.##} {(exMP >= 0 ? "+" : "-")} {Math.Abs(exDEF):0.##}]" : "") + $" ({PDR * 100:0.##}%)"); double mdf = Calculation.Round4Digits((MDF.None + MDF.Starmark + MDF.PurityNatural + MDF.PurityContemporary + MDF.Bright + MDF.Shadow + MDF.Element + MDF.Fleabane + MDF.Particle) / 9) * 100; if (Calculation.IsApproximatelyZero(mdf)) mdf = 0; builder.AppendLine($"魔法抗性:{mdf:0.##}%(平均)"); double exSPD = AGI * GameplayEquilibriumConstant.AGItoSPDMultiplier + ExSPD; builder.AppendLine($"行动速度:{SPD:0.##}" + (exSPD != 0 ? $" [{InitialSPD:0.##} {(exSPD >= 0 ? "+" : "-")} {Math.Abs(exSPD):0.##}]" : "") + $" ({ActionCoefficient * 100:0.##}%)"); builder.AppendLine($"核心属性:{CharacterSet.GetPrimaryAttributeName(PrimaryAttribute)}"); double exSTR = ExSTR + ExSTR2; builder.AppendLine($"力量:{STR:0.##}" + (exSTR != 0 ? $" [{BaseSTR:0.##} {(exSTR >= 0 ? "+" : "-")} {Math.Abs(exSTR):0.##}]" : "") + (showGrowth ? $"({(STRGrowth >= 0 ? "+" : "-")}{Math.Abs(STRGrowth)}/Lv)" : "")); double exAGI = ExAGI + ExAGI2; builder.AppendLine($"敏捷:{AGI:0.##}" + (exAGI != 0 ? $" [{BaseAGI:0.##} {(exAGI >= 0 ? "+" : "-")} {Math.Abs(exAGI):0.##}]" : "") + (showGrowth ? $"({(AGIGrowth >= 0 ? "+" : "-")}{Math.Abs(AGIGrowth)}/Lv)" : "")); double exINT = ExINT + ExINT2; builder.AppendLine($"智力:{INT:0.##}" + (exINT != 0 ? $" [{BaseINT:0.##} {(exINT >= 0 ? "+" : "-")} {Math.Abs(exINT):0.##}]" : "") + (showGrowth ? $"({(INTGrowth >= 0 ? "+" : "-")}{Math.Abs(INTGrowth)}/Lv)" : "")); builder.AppendLine($"生命回复:{HR:0.##}" + (ExHR != 0 ? $" [{InitialHR + STR * GameplayEquilibriumConstant.STRtoHRFactor:0.##} {(ExHR >= 0 ? "+" : "-")} {Math.Abs(ExHR):0.##}]" : "")); builder.AppendLine($"魔法回复:{MR:0.##}" + (ExMR != 0 ? $" [{InitialMR + INT * GameplayEquilibriumConstant.INTtoMRFactor:0.##} {(ExMR >= 0 ? "+" : "-")} {Math.Abs(ExMR):0.##}]" : "")); builder.AppendLine($"暴击率:{CritRate * 100:0.##}%"); builder.AppendLine($"暴击伤害:{CritDMG * 100:0.##}%"); builder.AppendLine($"闪避率:{EvadeRate * 100:0.##}%"); builder.AppendLine($"冷却缩减:{CDR * 100:0.##}%"); builder.AppendLine($"加速系数:{AccelerationCoefficient * 100:0.##}%"); builder.AppendLine($"物理穿透:{PhysicalPenetration * 100:0.##}%"); builder.AppendLine($"魔法穿透:{MagicalPenetration * 100:0.##}%"); builder.AppendLine($"魔法消耗减少:{INT * GameplayEquilibriumConstant.INTtoCastMPReduce * 100:0.##}%"); builder.AppendLine($"能量消耗减少:{INT * GameplayEquilibriumConstant.INTtoCastEPReduce * 100:0.##}%"); if (EquipSlot.Any()) { builder.AppendLine("== 装备栏 =="); if (EquipSlot.MagicCardPack != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.MagicCardPack.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.MagicCardPack) + ":" + EquipSlot.MagicCardPack.Name); builder.AppendLine(EquipSlot.MagicCardPack.Description); } if (EquipSlot.Weapon != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Weapon.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Weapon) + ":" + EquipSlot.Weapon.Name); builder.AppendLine(EquipSlot.Weapon.Description); } if (EquipSlot.Armor != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Armor.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Armor) + ":" + EquipSlot.Armor.Name); builder.AppendLine(EquipSlot.Armor.Description); } if (EquipSlot.Shoes != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Shoes.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Shoes) + ":" + EquipSlot.Shoes.Name); builder.AppendLine(EquipSlot.Shoes.Description); } if (EquipSlot.Accessory1 != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Accessory1.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Accessory1) + ":" + EquipSlot.Accessory1.Name); builder.AppendLine(EquipSlot.Accessory1.Description); } if (EquipSlot.Accessory2 != null) { builder.AppendLine($"[{ItemSet.GetQualityTypeName(EquipSlot.Accessory2.QualityType)}]" + ItemSet.GetEquipSlotTypeName(EquipSlotType.Accessory2) + ":" + EquipSlot.Accessory2.Name); builder.AppendLine(EquipSlot.Accessory2.Description); } } if (Items.Count > 0) { builder.AppendLine("== 角色背包 =="); foreach (Item item in Items) { builder.Append(item.ToString()); } } return builder.ToString(); } /// /// 更新角色的状态 /// /// public CharacterState UpdateCharacterState() { bool isNotActionable = false; bool isActionRestricted = false; bool isBattleRestricted = false; bool isSkillRestricted = false; IEnumerable states = CharacterEffectStates.Values.SelectMany(list => list); // 根据持有的特效判断角色所处的状态 isNotActionable = states.Any(state => state == CharacterState.NotActionable); isActionRestricted = states.Any(state => state == CharacterState.ActionRestricted); isBattleRestricted = states.Any(state => state == CharacterState.BattleRestricted); isSkillRestricted = states.Any(state => state == CharacterState.SkillRestricted); IEnumerable types = CharacterEffectTypes.Values.SelectMany(list => list); // 判断角色的控制效果 IsUnselectable = types.Any(type => type == EffectType.Unselectable); bool isControl = isNotActionable || isActionRestricted || isBattleRestricted || isSkillRestricted; bool isCasting = CharacterState == CharacterState.Casting; bool isPreCastSuperSkill = CharacterState == CharacterState.PreCastSuperSkill; if (isNotActionable) { CharacterState = CharacterState.NotActionable; } else if (isActionRestricted) { CharacterState = CharacterState.ActionRestricted; } else if (isBattleRestricted) { CharacterState = CharacterState.BattleRestricted; } else if (isSkillRestricted) { CharacterState = CharacterState.SkillRestricted; } if (!isControl && !isCasting && !isPreCastSuperSkill) { CharacterState = CharacterState.Actionable; } return CharacterState; } /// /// 复制一个角色 /// [ 推荐从模组中复制后使用对象 ] /// /// public Character Copy(bool copyEx = false) { Character c = new() { Id = Id, Name = Name, Guid = Guid, FirstName = FirstName, NickName = NickName, Profile = Profile.Copy(), MagicType = MagicType, FirstRoleType = FirstRoleType, SecondRoleType = SecondRoleType, ThirdRoleType = ThirdRoleType, Promotion = Promotion, PrimaryAttribute = PrimaryAttribute, Level = Level, LevelBreak = LevelBreak, EXP = EXP, InitialHP = InitialHP, InitialMP = InitialMP, EP = EP, InitialATK = InitialATK, InitialDEF = InitialDEF, MDF = MDF.Copy(), PhysicalPenetration = PhysicalPenetration, MagicalPenetration = MagicalPenetration, InitialHR = InitialHR, InitialMR = InitialMR, ER = ER, InitialSTR = InitialSTR, InitialAGI = InitialAGI, InitialINT = InitialINT, STRGrowth = STRGrowth, AGIGrowth = AGIGrowth, INTGrowth = INTGrowth, InitialSPD = InitialSPD, ATR = ATR, }; if (copyEx) { c.ExHP2 = ExHP2; c.ExHPPercentage = ExHPPercentage; c.ExMP2 = ExMP2; c.ExMPPercentage = ExMPPercentage; c.ExATK2 = ExATK2; c.ExATKPercentage = ExATKPercentage; c.ExDEF2 = ExDEF2; c.ExDEFPercentage = ExDEFPercentage; c.ExHR = ExHR; c.ExMR = ExMR; c.ExSTRPercentage = ExSTRPercentage; c.ExAGIPercentage = ExAGIPercentage; c.ExINTPercentage = ExINTPercentage; c.ExSTR = ExSTR; c.ExAGI = ExAGI; c.ExINT = ExINT; c.ExSPD = ExSPD; c.ExActionCoefficient = ExActionCoefficient; c.ExAccelerationCoefficient = ExAccelerationCoefficient; c.ExCDR = ExCDR; c.ExCritRate = ExCritRate; c.ExCritDMG = ExCritDMG; c.ExEvadeRate = ExEvadeRate; } foreach (Skill skill in Skills) { Skill newskill = skill.Copy(); newskill.Character = c; c.Skills.Add(newskill); } foreach (Item item in Items) { Item newitem = item.Copy(); newitem.Character = c; c.Items.Add(newitem); } c.Recovery(); return c; } /// /// 复活此角色,回复出厂状态 /// 注意:此方法仅用于角色的复活,如果需要完全重构相同角色,请使用 /// /// 需要一个原始的角色用于还原状态 /// public void Respawn(Character original) { Item? mcp = UnEquip(EquipSlotType.MagicCardPack); Item? w = UnEquip(EquipSlotType.Weapon); Item? a = UnEquip(EquipSlotType.Armor); Item? s = UnEquip(EquipSlotType.Shoes); Item? ac1 = UnEquip(EquipSlotType.Accessory1); Item? ac2 = UnEquip(EquipSlotType.Accessory2); List skills = [.. Skills]; List items = [.. Items]; Character c = original.Copy(); List effects = [.. Effects]; foreach (Effect e in effects) { e.OnEffectLost(this); } Effects.Clear(); Skills.Clear(); Items.Clear(); Id = c.Id; Guid = c.Guid; Name = c.Name; FirstName = c.FirstName; NickName = c.NickName; Profile = c.Profile.Copy(); MagicType = c.MagicType; FirstRoleType = c.FirstRoleType; SecondRoleType = c.SecondRoleType; ThirdRoleType = c.ThirdRoleType; Promotion = c.Promotion; PrimaryAttribute = c.PrimaryAttribute; Level = c.Level; LevelBreak = c.LevelBreak; EXP = c.EXP; CharacterState = c.CharacterState; CharacterEffectStates.Clear(); CharacterEffectTypes.Clear(); IsUnselectable = false; UpdateCharacterState(); InitialHP = c.InitialHP; ExHP2 = c.ExHP2; ExHPPercentage = c.ExHPPercentage; InitialMP = c.InitialMP; ExMP2 = c.ExMP2; ExMPPercentage = c.ExMPPercentage; EP = c.EP; InitialATK = c.InitialATK; ExATK2 = c.ExATK2; InitialDEF = c.InitialDEF; ExDEF2 = c.ExDEF2; MDF = c.MDF.Copy(); PhysicalPenetration = c.PhysicalPenetration; MagicalPenetration = c.MagicalPenetration; InitialHR = c.InitialHR; ExHR = c.ExHR; InitialMR = c.InitialMR; ExMR = c.ExMR; ER = c.ER; InitialSTR = c.InitialSTR; InitialAGI = c.InitialAGI; InitialINT = c.InitialINT; ExSTR = c.ExSTR; ExAGI = c.ExAGI; ExINT = c.ExINT; STRGrowth = c.STRGrowth; AGIGrowth = c.AGIGrowth; INTGrowth = c.INTGrowth; InitialSPD = c.InitialSPD; ExSPD = c.ExSPD; ExActionCoefficient = c.ExActionCoefficient; ExAccelerationCoefficient = c.ExAccelerationCoefficient; ExCDR = c.ExCDR; ATR = c.ATR; ExCritRate = c.ExCritRate; ExCritDMG = c.ExCritDMG; ExEvadeRate = c.ExEvadeRate; foreach (Skill skill in skills) { Skill newskill = skill.Copy(); newskill.Character = this; newskill.Level = skill.Level; newskill.CurrentCD = 0; Skills.Add(newskill); } foreach (Item item in items) { Item newitem = item.Copy(true); newitem.Character = this; Items.Add(newitem); } if (mcp != null) Equip(mcp); if (w != null) Equip(w); if (a != null) Equip(a); if (s != null) Equip(s); if (ac1 != null) Equip(ac1); if (ac2 != null) Equip(ac2); Recovery(0D); } } }