using System.Text; using Milimoe.FunGame.Core.Api.Utility; using Milimoe.FunGame.Core.Interface.Base; using Milimoe.FunGame.Core.Interface.Entity; using Milimoe.FunGame.Core.Library.Constant; namespace Milimoe.FunGame.Core.Entity { public class NormalAttack(Character character, bool isMagic = false, MagicType magicType = MagicType.None) : BaseEntity, ISkill { /// /// 普通攻击名称 /// public override string Name => "普通攻击"; /// /// 普通攻击说明 /// public string Description => $"对目标敌人造成 {BaseDamageMultiplier * 100:0.##}% 攻击力 [ {Damage:0.##} ] 点{(IsMagic ? CharacterSet.GetMagicDamageName(MagicType) : "物理伤害")}。"; /// /// 普通攻击的通用说明 /// public string GeneralDescription => $"对目标敌人造成基于总攻击力的{(IsMagic ? CharacterSet.GetMagicDamageName(MagicType) : "物理伤害")}。"; /// /// 所属的角色 /// public Character Character { get; } = character; /// /// 基础普通攻击伤害倍率 [ 武器类型相关 ] /// private double BaseDamageMultiplier { get { double baseMultiplier = 1.0 + 0.05 * (Level - 1); if (Character.EquipSlot.Weapon != null) { baseMultiplier = Character.EquipSlot.Weapon.WeaponType switch { WeaponType.OneHandedSword => 1.0, WeaponType.TwoHandedSword => 1.2, WeaponType.Bow => 0.9, WeaponType.Pistol => 0.8, WeaponType.Rifle => 1.1, WeaponType.DualDaggers => 0.85, WeaponType.Talisman => 1.0, WeaponType.Staff => 1.15, WeaponType.Polearm => 0.95, WeaponType.Gauntlet => 1.05, WeaponType.HiddenWeapon => 0.9, _ => 1.0 }; double levelBonus = Character.EquipSlot.Weapon.WeaponType switch { WeaponType.TwoHandedSword => 0.06, WeaponType.Staff => 0.056, WeaponType.Bow => 0.045, WeaponType.Pistol => 0.0375, WeaponType.DualDaggers => 0.0375, WeaponType.Polearm => 0.044, WeaponType.HiddenWeapon => 0.044, _ => 0.05 }; baseMultiplier += levelBonus * (Level - 1); } return baseMultiplier; } } /// /// 普通攻击的伤害 /// public double Damage => Character.ATK * BaseDamageMultiplier * (1 + ExDamage2) + ExDamage; /// /// 额外普通攻击伤害 [ 技能和物品相关 ] /// public double ExDamage { get; set; } = 0; /// /// 额外普通攻击伤害% [ 技能和物品相关 ] /// public double ExDamage2 { get; set; } = 0; /// /// 普通攻击等级 /// public int Level { get { return Math.Max(1, _Level); } set { _Level = Math.Min(Math.Max(1, value), GameplayEquilibriumConstant.MaxNormalAttackLevel); } } /// /// 是否是魔法伤害 /// public bool IsMagic => _IsMagic; /// /// 魔法伤害需要指定魔法类型 /// public MagicType MagicType => _MagicType; /// /// 是否可用 /// public bool Enable { get; set; } = true; /// /// 是否在持续生效,为 true 时不允许再次使用。普通攻击始终为 false /// public bool IsInEffect => false; /// /// 无视免疫类型 /// public ImmuneType IgnoreImmune { get; set; } = ImmuneType.None; /// /// 硬直时间 [ 武器类型相关 ] /// public double HardnessTime { get { double ht = 10; if (Character.EquipSlot.Weapon != null) { ht = Character.EquipSlot.Weapon.WeaponType switch { WeaponType.OneHandedSword => 8, WeaponType.TwoHandedSword => 12, WeaponType.Bow => 9, WeaponType.Pistol => 6, WeaponType.Rifle => 11, WeaponType.DualDaggers => 7, WeaponType.Talisman => 10, WeaponType.Staff => 12, WeaponType.Polearm => 10, WeaponType.Gauntlet => 8, WeaponType.HiddenWeapon => 7, _ => 10, }; } return ht * (1 + ExHardnessTime2) + ExHardnessTime; } } /// /// 额外硬直时间 [ 技能和物品相关 ] /// public double ExHardnessTime { get; set; } = 0; /// /// 额外硬直时间% [ 技能和物品相关 ] /// public double ExHardnessTime2 { get; set; } = 0; /// /// 实际硬直时间 /// public double RealHardnessTime => Math.Max(0, HardnessTime * (1 - Calculation.PercentageCheck(Character?.ActionCoefficient ?? 0))); /// /// 可选取自身 /// public bool CanSelectSelf { get; set; } = false; /// /// 可选取敌对角色 /// public bool CanSelectEnemy { get; set; } = true; /// /// 可选取友方角色 /// public bool CanSelectTeammate { get; set; } = false; /// /// 可选取的作用目标数量 /// public int CanSelectTargetCount { get; set; } = 1; /// /// 可选取的作用范围 /// public double CanSelectTargetRange { get; set; } = 0; /// /// 普通攻击没有魔法消耗 /// public double RealMPCost => 0; /// /// 普通攻击没有吟唱时间 /// public double RealCastTime => 0; /// /// 普通攻击没有能量消耗 /// public double RealEPCost => 0; /// /// 普通攻击没有冷却时间 /// public double RealCD => 0; /// /// 普通攻击没有冷却时间 /// public double CurrentCD => 0; /// /// 绑定到特效的普通攻击扩展。键为特效,值为对应的普攻扩展对象。 /// public Dictionary NormalAttackOfEffects { get; } = []; /// /// 获取可选择的目标列表 /// /// /// /// /// public List GetSelectableTargets(Character caster, List enemys, List teammates) { List selectable = []; if (CanSelectSelf) { selectable.Add(caster); } foreach (Character character in enemys) { if (CanSelectEnemy && ((character.ImmuneType & ImmuneType.All) != ImmuneType.All || IgnoreImmune == ImmuneType.All)) { selectable.Add(character); } } foreach (Character character in teammates) { if (CanSelectTeammate && ((character.ImmuneType & ImmuneType.All) != ImmuneType.All || IgnoreImmune == ImmuneType.All)) { selectable.Add(character); } } return selectable; } /// /// 对目标(或多个目标)发起普通攻击 /// /// /// /// public void Attack(IGamingQueue queue, Character attacker, params IEnumerable enemys) { if (!Enable) { return; } foreach (Character enemy in enemys) { if (enemy.HP > 0) { queue.WriteLine($"[ {Character} ] 对 [ {enemy} ] 发起了普通攻击!"); double expected = Damage; int changeCount = 0; DamageResult result = IsMagic ? queue.CalculateMagicalDamage(attacker, enemy, true, MagicType, expected, out double damage, ref changeCount) : queue.CalculatePhysicalDamage(attacker, enemy, true, expected, out damage, ref changeCount); queue.DamageToEnemyAsync(attacker, enemy, damage, true, IsMagic ? DamageType.Magical : DamageType.Physical, MagicType, result); } } } /// /// 修改基础伤害类型。不一定转换成功,要看是否有特效覆盖 /// /// /// /// public void SetMagicType(bool? isMagic, MagicType? magicType = null, IGamingQueue? queue = null) { _ExIsMagic = isMagic; if (isMagic.HasValue && isMagic.Value) { magicType ??= MagicType.None; } _ExMagicType = magicType; ResolveMagicType(queue); } /// /// 修改伤害类型。不一定转换成功,要看是否有其他特效覆盖 /// /// /// public void SetMagicType(NormalAttackOfEffect naoe, IGamingQueue? queue = null) { NormalAttackOfEffects[naoe.Effect] = naoe; ResolveMagicType(queue); } /// /// 移除特效对伤害类型的更改 /// /// /// public void UnsetMagicType(Effect effect, IGamingQueue? queue = null) { NormalAttackOfEffects.Remove(effect); ResolveMagicType(queue); } /// /// 计算是否是魔法伤害和当前的魔法类型 /// internal void ResolveMagicType(IGamingQueue? queue = null) { bool past = _IsMagic; MagicType pastType = _MagicType; if (NormalAttackOfEffects.Count > 0) { if (NormalAttackOfEffects.Values.OrderByDescending(n => n.Priority).FirstOrDefault() is NormalAttackOfEffect naoe) { _IsMagic = naoe.IsMagic; _MagicType = naoe.MagicType; } } else if (_ExIsMagic.HasValue && _ExMagicType.HasValue) { _IsMagic = _ExIsMagic.Value; _MagicType = _ExMagicType.Value; } else { _IsMagic = false; _MagicType = MagicType.None; if (Character.EquipSlot.Weapon != null) { WeaponType type = Character.EquipSlot.Weapon.WeaponType; if (type == WeaponType.Talisman || type == WeaponType.Staff) { _IsMagic = true; } } } if (queue != null && (past != _IsMagic || pastType != _MagicType)) { queue.WriteLine($"[ {Character} ] 的普通攻击类型已转变为:{(_IsMagic ? CharacterSet.GetMagicDamageName(_MagicType) : "物理伤害")}!"); } } /// /// 比较两个普攻对象 /// /// /// public override bool Equals(IBaseEntity? other) { return other is NormalAttack c && c.Name == Name; } /// /// 输出信息 /// /// /// public string GetInfo(bool showOriginal = false) { StringBuilder builder = new(); builder.AppendLine($"{Name} - 等级 {Level}"); builder.AppendLine($"描述:{Description}"); builder.AppendLine($"硬直时间:{RealHardnessTime:0.##}{(showOriginal && RealHardnessTime != HardnessTime ? $"(原始值:{HardnessTime})" : "")}"); return builder.ToString(); } /// /// 输出信息 /// /// public override string ToString() => GetInfo(true); /// /// 等级 /// private int _Level = 0; /// /// 是否是魔法伤害 [ 生效型 ] /// private bool _IsMagic = isMagic; /// /// 魔法类型 [ 生效型 ] /// private MagicType _MagicType = magicType; /// /// 是否是魔法伤害 [ 修改型 ] /// private bool? _ExIsMagic = null; /// /// 魔法类型 [ 修改型 ] /// private MagicType? _ExMagicType = null; } /// /// 绑定到特效的普通攻击扩展。这个类没有 JSON 转换器支持。 /// public class NormalAttackOfEffect(Effect effect, bool isMagic, MagicType type, int priority) { public Effect Effect { get; set; } = effect; public bool IsMagic { get; set; } = isMagic; public MagicType MagicType { get; set; } = type; public int Priority { get; set; } = priority; } }