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 Effect : BaseEntity { /// /// 所属的技能 /// public Skill Skill { get; } /// /// 特殊效果类型 /// 注意:如果技能特效没有原生施加控制效果,请始终保持此属性为 。 /// public virtual EffectType EffectType { get; set; } = EffectType.None; /// /// 持续性的 /// 配合 使用,而不是 。 /// public virtual bool Durative { get; set; } = false; /// /// 持续时间 /// 配合 使用。 /// public virtual double Duration { get; set; } = 0; /// /// 持续时间(回合) /// 使用此属性需要将 设置为 false。 /// public virtual int DurationTurn { get; set; } = 0; /// /// 剩余持续时间 /// public double RemainDuration { get; set; } = 0; /// /// 剩余持续时间(回合) /// public int RemainDurationTurn { get; set; } = 0; /// /// 魔法类型 /// public virtual MagicType MagicType { get; set; } = MagicType.None; /// /// 效果描述 /// public virtual string Description { get; set; } = ""; /// /// 等级,跟随技能的等级 /// public int Level => Skill.Level; /// /// 此特效的施加者,用于溯源 /// public virtual Character? Source { get; set; } = null; /// /// 游戏中的行动顺序表实例,在技能效果被触发时,此实例会获得赋值,使用时需要判断其是否存在 /// public IGamingQueue? GamingQueue { get; set; } = null; /// /// 用于动态扩展特效的参数 /// public Dictionary Values { get; } = []; /// /// 输出文本或日志 /// public Action WriteLine { get { if (GamingQueue is null) return Console.WriteLine; else return GamingQueue.WriteLine; } } protected Effect(Skill skill, Dictionary? args = null) { Skill = skill; if (args != null) { foreach (string key in args.Keys) { Values[key] = args[key]; } } } internal Effect() { Skill = Factory.GetSkill(); } /// /// 获得此特效时 /// /// public virtual void OnEffectGained(Character character) { } /// /// 失去此特效时 /// /// public virtual void OnEffectLost(Character character) { } /// /// 在伤害计算前修改伤害类型 /// /// /// /// /// /// public virtual void AlterDamageTypeBeforeCalculation(Character character, Character enemy, ref bool isNormalAttack, ref bool isMagicDamage, ref MagicType magicType) { } /// /// 在伤害计算前修改预期伤害 /// /// /// /// /// /// /// /// /// 返回伤害增减值 public virtual double AlterExpectedDamageBeforeCalculation(Character character, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType, Dictionary totalDamageBonus) { return 0; } /// /// 在伤害计算完成后修改实际伤害 [ 允许取消伤害 ] /// /// /// /// /// /// /// /// /// /// /// 返回伤害增减值 public virtual double AlterActualDamageAfterCalculation(Character character, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType, DamageResult damageResult, ref bool isEvaded, Dictionary totalDamageBonus) { return 0; } /// /// 在完成普通攻击动作之后修改硬直时间 /// /// /// /// public virtual void AlterHardnessTimeAfterNormalAttack(Character character, ref double baseHardnessTime, ref bool isCheckProtected) { } /// /// 在完成释放技能动作之后修改硬直时间 /// /// /// /// /// public virtual void AlterHardnessTimeAfterCastSkill(Character character, Skill skill, ref double baseHardnessTime, ref bool isCheckProtected) { } /// /// 在造成伤害时,修改获得的能量 /// /// /// public virtual void AlterEPAfterDamage(Character character, ref double baseEP) { } /// /// 在受到伤害时,修改获得的能量 /// /// /// public virtual void AlterEPAfterGetDamage(Character character, ref double baseEP) { } /// /// 技能开始吟唱时 [ 爆发技插队可触发此项 ] /// /// /// public virtual void OnSkillCasting(Character caster, List targets) { } /// /// 技能吟唱被打断时 /// /// /// /// public virtual void OnSkillCastInterrupted(Character caster, Skill skill, Character interrupter) { } /// /// 吟唱结束后释放技能(魔法)/ 直接释放技能(战技/爆发技) /// /// /// /// public virtual void OnSkillCasted(Character caster, List targets, Dictionary others) { } /// /// 对目标触发技能效果 /// /// /// public virtual void OnSkillCasted(List targets, Dictionary others) { } /// /// 时间流逝时 /// /// /// public virtual void OnTimeElapsed(Character character, double elapsed) { } /// /// 在完成伤害结算后 /// /// /// /// /// /// /// /// public virtual void AfterDamageCalculation(Character character, Character enemy, double damage, bool isNormalAttack, bool isMagicDamage, MagicType magicType, DamageResult damageResult) { } /// /// 在特效持有者的回合开始前 /// /// /// /// /// /// public virtual void OnTurnStart(Character character, List enemys, List teammates, List skills, List items) { } /// /// 在特效持有者的回合结束后 /// /// public virtual void OnTurnEnd(Character character) { } /// /// 技能被升级时 /// /// /// public virtual void OnSkillLevelUp(Character character, double level) { } /// /// 特效持有者升级时 /// /// /// public virtual void OnOwnerLevelUp(Character owner, double level) { } /// /// 在完成死亡结算后 [ 全体广播 ] /// /// /// /// /// public virtual void AfterDeathCalculation(Character death, Character? killer, Dictionary continuousKilling, Dictionary earnedMoney) { } /// /// 闪避检定前触发 /// /// /// /// /// 返回 false 表示不进行闪避检定 public virtual bool BeforeEvadeCheck(Character actor, Character enemy, ref double throwingBonus) { return true; } /// /// 在触发闪避时 /// /// /// /// /// 返回 true 表示无视闪避 public virtual bool OnEvadedTriggered(Character actor, Character enemy, double dice) { return false; } /// /// 暴击检定前触发 /// /// /// /// /// 返回 false 表示不进行暴击检定 public virtual bool BeforeCriticalCheck(Character actor, Character enemy, ref double throwingBonus) { return true; } /// /// 在触发暴击时 /// /// /// /// public virtual void OnCriticalDamageTriggered(Character actor, Character enemy, double dice) { } /// /// 角色属性发生变化 /// /// public virtual void OnAttributeChanged(Character character) { } /// /// 行动开始前,修改可选择的 , , 列表 /// 注意 是副本,修改无效 /// /// /// /// /// /// /// public virtual void AlterSelectListBeforeAction(Character character, List enemys, List teammates, List skills, Dictionary continuousKilling, Dictionary earnedMoney) { } /// /// 开始选择目标前,修改可选择的 , 列表 /// 有两种,使用时注意判断是 还是 /// /// /// /// /// public virtual void AlterSelectListBeforeSelection(Character character, ISkill skill, List enemys, List teammates) { } /// /// 行动开始前,指定角色的行动,而不是使用顺序表自带的逻辑;或者修改对应的操作触发概率 /// /// /// /// /// /// /// /// /// public virtual CharacterActionType AlterActionTypeBeforeAction(Character character, CharacterState state, ref bool canUseItem, ref bool canCastSkill, ref double pUseItem, ref double pCastSkill, ref double pNormalAttack) { return CharacterActionType.None; } /// /// 对敌人造成技能伤害 [ 强烈建议使用此方法造成伤害而不是自行调用 ] /// /// /// /// /// /// /// public DamageResult DamageToEnemy(Character actor, Character enemy, bool isMagic, MagicType magicType, double expectedDamage) { if (GamingQueue is null) return DamageResult.Evaded; DamageResult result = !isMagic ? GamingQueue.CalculatePhysicalDamage(actor, enemy, false, expectedDamage, out double damage) : GamingQueue.CalculateMagicalDamage(actor, enemy, false, MagicType, expectedDamage, out damage); GamingQueue.DamageToEnemyAsync(actor, enemy, damage, false, isMagic, magicType, result); return result; } /// /// 治疗一个目标 [ 强烈建议使用此方法而不是自行调用 ] /// /// /// /// /// public void HealToTarget(Character actor, Character target, double heal, bool canRespawn = false) { GamingQueue?.HealToTargetAsync(actor, target, heal, canRespawn); } /// /// 打断施法 [ 尽可能的调用此方法而不是直接调用 ,以防止中断性变更 ] /// /// /// public void InterruptCasting(Character caster, Character interrupter) { GamingQueue?.InterruptCastingAsync(caster, interrupter); } /// /// 检查角色是否在 AI 控制状态 /// /// /// public bool IsCharacterInAIControlling(Character character) { return GamingQueue?.IsCharacterInAIControlling(character) ?? false; } /// /// 返回特效详情 /// /// public override string ToString() { StringBuilder builder = new(); string isDurative = ""; if (Durative) { isDurative = $"(剩余:{RemainDuration:0.##} 时间)"; } else if (DurationTurn > 0) { isDurative = "(剩余:" + RemainDurationTurn + " 回合)"; } builder.AppendLine("【" + Name + " - 等级 " + Level + "】" + Description + isDurative); return builder.ToString(); } /// /// 复制一个特效 /// /// public Effect Copy(Skill skill) { Dictionary args = new() { { "skill", skill }, { "values", Values } }; Effect copy = Factory.OpenFactory.GetInstance(Id, Name, args); copy.Id = Id; copy.Name = Name; copy.Description = Description; copy.EffectType = EffectType; copy.Durative = Durative; copy.Duration = Duration; copy.DurationTurn = DurationTurn; copy.MagicType = MagicType; copy.GamingQueue = GamingQueue; return copy; } /// /// 比较两个特效 /// /// /// public override bool Equals(IBaseEntity? other) { return other is Effect c && c.Id + "." + Name == Id + "." + Name; } } }