From 0f054839ca265486ace9828062f68cdf2a0c06ad Mon Sep 17 00:00:00 2001 From: milimoe Date: Wed, 28 Jan 2026 00:55:44 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E8=B1=81=E5=85=8D=E6=8C=81?= =?UTF-8?q?=E7=BB=AD=E6=97=B6=E9=97=B4=E7=9A=84=E4=BD=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- OshimaModules/Effects/EffectID.cs | 3 +- .../Effects/PassiveEffects/持续伤害.cs | 102 +++++++++++ .../Effects/SkillEffects/施加概率增益.cs | 163 ++++++++++++++++++ .../Effects/SkillEffects/施加概率负面.cs | 102 ++++++++++- 4 files changed, 366 insertions(+), 4 deletions(-) create mode 100644 OshimaModules/Effects/PassiveEffects/持续伤害.cs create mode 100644 OshimaModules/Effects/SkillEffects/施加概率增益.cs diff --git a/OshimaModules/Effects/EffectID.cs b/OshimaModules/Effects/EffectID.cs index 025ef19..3b8047a 100644 --- a/OshimaModules/Effects/EffectID.cs +++ b/OshimaModules/Effects/EffectID.cs @@ -273,6 +273,7 @@ 长期监视 = 4133, 时雨标记 = 4134, 宫监手标记 = 4135, - 复制技能 = 4136 + 复制技能 = 4136, + 持续伤害 = 4137 } } diff --git a/OshimaModules/Effects/PassiveEffects/持续伤害.cs b/OshimaModules/Effects/PassiveEffects/持续伤害.cs new file mode 100644 index 0000000..2c9901e --- /dev/null +++ b/OshimaModules/Effects/PassiveEffects/持续伤害.cs @@ -0,0 +1,102 @@ +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Model; +using Oshima.FunGame.OshimaModules.Effects.OpenEffects; + +namespace Oshima.FunGame.OshimaModules.Effects.PassiveEffects +{ + public class 持续伤害 : Effect + { + public override long Id => (long)PassiveEffectID.持续伤害; + public override string Name { get; set; } = "持续伤害"; + public override string Description => $"此角色正受到持续伤害,每{GameplayEquilibriumConstant.InGameTime}受到 {(_isPercentage ? $"{_durationDamagePercent * 100:0.##}% 当前生命值 [ {Damage:0.##} ]" : Damage.ToString("0.##"))} 点{CharacterSet.GetDamageTypeName(_damageType)}。来自:[ {Source} ] 的 [ {Skill.Name} ]"; + public override bool IsDebuff { get; set; } = true; + public override Character Source => _sourceCharacter; + public override bool Durative => _durative; + public override double Duration => _duration; + public override int DurationTurn => _durationTurn; + + private readonly Character _targetCharacter; + private readonly Character _sourceCharacter; + private readonly bool _durative; + private readonly double _duration; + private readonly int _durationTurn; + private readonly bool _isPercentage; + private readonly double _durationDamage; + private readonly double _durationDamagePercent; + private readonly DamageType _damageType = DamageType.Physical; + private readonly DamageCalculationOptions? _options = null; + private double Damage => _isPercentage ? _targetCharacter.HP * _durationDamagePercent : _durationDamage; + + public 持续伤害(Skill skill, Character targetCharacter, Character sourceCharacter, bool durative = false, double duration = 0, int durationTurn = 1, + bool isPercentage = true, double durationDamage = 100, double durationDamagePercent = 0.02, DamageType damageType = DamageType.Physical, DamageCalculationOptions? options = null) : base(skill) + { + GamingQueue = skill.GamingQueue; + _targetCharacter = targetCharacter; + _sourceCharacter = sourceCharacter; + _durative = durative; + _duration = duration; + _durationTurn = durationTurn; + _isPercentage = isPercentage; + _durationDamage = durationDamage; + _durationDamagePercent = durationDamagePercent; + _damageType = damageType; + _options = options; + } + + private double GetDamage(double hp, double elapsed) + { + if (hp <= 0) + { + return 0; + } + double damage = _isPercentage ? hp * _durationDamagePercent : _durationDamage; + return damage * elapsed; + } + + public override void OnTimeElapsed(Character character, double elapsed) + { + if (character == _targetCharacter && character.HP > 0) + { + double hp = character.HP; + double damage = GetDamage(hp, elapsed); + if (elapsed > 1) + { + damage = 0; + int loop = 0; + int elapsedSecond = (int)elapsed; + for (; loop < elapsedSecond; loop++) + { + double current = GetDamage(hp, 1); + damage += current; + hp -= current; + elapsed--; + } + if (elapsed > 0) + { + damage += GetDamage(hp, elapsed); + } + } + DamageToEnemy(Source, character, _damageType, MagicType, damage, _options); + } + } + + public override void OnEffectGained(Character character) + { + if (_durative && RemainDuration == 0) + { + RemainDuration = Duration; + } + else if (RemainDurationTurn == 0) + { + RemainDurationTurn = DurationTurn; + } + AddEffectTypeToCharacter(character, [EffectType]); + } + + public override void OnEffectLost(Character character) + { + RemoveEffectTypesFromCharacter(character); + } + } +} diff --git a/OshimaModules/Effects/SkillEffects/施加概率增益.cs b/OshimaModules/Effects/SkillEffects/施加概率增益.cs new file mode 100644 index 0000000..5533658 --- /dev/null +++ b/OshimaModules/Effects/SkillEffects/施加概率增益.cs @@ -0,0 +1,163 @@ +using Milimoe.FunGame.Core.Api.Utility; +using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Library.Common.Addon; +using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Model; +using Oshima.FunGame.OshimaModules.Effects.PassiveEffects; +using Oshima.FunGame.OshimaModules.Skills; + +namespace Oshima.FunGame.OshimaModules.Effects.SkillEffects +{ + public class 施加概率增益 : Effect + { + public override long Id => Skill.Id; + public override string Name => Skill.Name; + public override string Description + { + get + { + SetDescription(); + return $"{概率文本}对{Skill.TargetDescription()}施加{GetEffectTypeName(_effectType)} {持续时间}。{(_description != "" ? _description : "")}"; + } + } + public override EffectType EffectType => _effectType; + public override DispelledType DispelledType => _dispelledType; + public override bool ExemptDuration => true; + + private string 概率文本 => ActualProbability == 1 ? "" : $"{ActualProbability * 100:0.##}% 概率"; + private double ActualProbability => Calculation.PercentageCheck(Level > 0 ? (_probability + _probabilityLevelGrowth * (Level - 1) * MagicEfficacy) : _probability); + private string 持续时间 => _durative && _duration > 0 ? $"{实际持续时间:0.##}" + $" {GameplayEquilibriumConstant.InGameTime}" : (!_durative && _durationTurn > 0 ? 实际持续时间 + " 回合" : $"0 {GameplayEquilibriumConstant.InGameTime}"); + private double 实际持续时间 => _durative && _duration > 0 ? (_duration + _levelGrowth * (Level - 1) * MagicEfficacy) : (!_durative && _durationTurn > 0 ? ((int)Math.Round(_durationTurn + _levelGrowth * (Level - 1) * MagicEfficacy, 0, MidpointRounding.ToPositiveInfinity)) : 0); + private readonly EffectType _effectType; + private readonly bool _durative; + private readonly double _duration; + private readonly int _durationTurn; + private readonly double _levelGrowth; + private readonly double _probability; + private readonly double _probabilityLevelGrowth; + private readonly object[] _args; + private DispelledType _dispelledType = DispelledType.Weak; + private string _description = ""; + + public 施加概率增益(Skill skill, EffectType effectType, bool durative = false, double duration = 0, int durationTurn = 1, double levelGrowth = 0, double probability = 0, double probabilityLevelGrowth = 0, params object[] args) : base(skill) + { + GamingQueue = skill.GamingQueue; + _effectType = effectType; + _durative = durative; + _duration = duration; + _durationTurn = durationTurn; + _levelGrowth = levelGrowth; + _probability = probability; + _probabilityLevelGrowth = probabilityLevelGrowth; + _args = args; + SetDescription(); + } + + public override void OnSkillCasted(Character caster, List targets, List grids, Dictionary others) + { + foreach (Character target in targets) + { + if (target.HP <= 0 || Random.Shared.NextDouble() > ActualProbability) continue; + Effect? e = null; + double duration = _duration + _levelGrowth * (Level - 1); + int durationTurn = Convert.ToInt32(_durationTurn + _levelGrowth * (Level - 1)); + string tip = ""; + switch (_effectType) + { + case EffectType.HealOverTime: + bool isPercentage = false; + double durationHeal = 0; + double durationHealPercent = 0; + double durationHealLevelGrowth = 0; + if (_args.Length > 0 && _args[0] is bool _) + { + isPercentage = (bool)_args[0]; + } + if (_args.Length > 1 && _args[1] is double _) + { + durationHeal = (double)_args[1]; + } + if (_args.Length > 2 && _args[2] is double _) + { + durationHealPercent = (double)_args[2]; + } + if (_args.Length > 3 && _args[3] is double _) + { + durationHealLevelGrowth = (double)_args[3]; + } + if (isPercentage && durationHealPercent > 0 || !isPercentage && durationHeal > 0) + { + if (Level > 0) + { + durationHeal += durationHealLevelGrowth * (Level - 1); + durationHealPercent += durationHealLevelGrowth * (Level - 1); + } + string healString = $"每{GameplayEquilibriumConstant.InGameTime}回复 {(isPercentage ? $"{durationHealPercent * 100:0.##}% 当前生命值" : durationHeal.ToString("0.##"))} 点生命值"; + tip = $"[ {caster} ] 对 [ {target} ] 施加了{GetEffectTypeName(_effectType)}! [ {target} ] 每{GameplayEquilibriumConstant.InGameTime}{healString}!持续时间:{持续时间}!"; + e = new 持续回复(Skill, target, caster, _durative, duration, durationTurn, isPercentage, durationHeal, durationHealPercent) + { + EffectType = _effectType + }; + } + break; + default: + break; + } + if (e != null && !CheckExemption(caster, target, e)) + { + WriteLine(tip); + target.Effects.Add(e); + e.OnEffectGained(target); + GamingQueue?.LastRound.AddApplyEffects(target, e.EffectType); + } + } + } + + private void SetDescription() + { + switch (_effectType) + { + case EffectType.HealOverTime: + _dispelledType = DispelledType.Weak; + bool isPercentage = false; + double durationHeal = 0; + double durationHealPercent = 0; + double durationHealLevelGrowth = 0; + if (_args.Length > 0 && _args[0] is bool _) + { + isPercentage = (bool)_args[0]; + } + if (_args.Length > 1 && _args[1] is double _) + { + durationHeal = (double)_args[1]; + } + if (_args.Length > 2 && _args[2] is double _) + { + durationHealPercent = (double)_args[2]; + } + if (_args.Length > 3 && _args[3] is double _) + { + durationHealLevelGrowth = (double)_args[3]; + } + if (isPercentage && durationHealPercent > 0 || !isPercentage && durationHeal > 0) + { + if (Level > 0) durationHeal += durationHealLevelGrowth * (Level - 1); + if (Level > 0) durationHealPercent += durationHealLevelGrowth * (Level - 1); + string healString = $"每{GameplayEquilibriumConstant.InGameTime}回复 {(isPercentage ? $"{durationHealPercent * 100:0.##}% 当前生命值" : durationHeal.ToString("0.##"))} 点生命值"; + _description = $"{GetEffectTypeName(_effectType)}:每{GameplayEquilibriumConstant.InGameTime}{healString}!持续时间:{持续时间}!"; + } + break; + default: + break; + } + } + + private static string GetEffectTypeName(EffectType type) + { + return type switch + { + _ => SkillSet.GetEffectTypeName(type) + }; + } + } +} diff --git a/OshimaModules/Effects/SkillEffects/施加概率负面.cs b/OshimaModules/Effects/SkillEffects/施加概率负面.cs index 9dcbd49..22f9fe3 100644 --- a/OshimaModules/Effects/SkillEffects/施加概率负面.cs +++ b/OshimaModules/Effects/SkillEffects/施加概率负面.cs @@ -1,6 +1,8 @@ -using Milimoe.FunGame.Core.Entity; +using Milimoe.FunGame.Core.Api.Utility; +using Milimoe.FunGame.Core.Entity; using Milimoe.FunGame.Core.Library.Common.Addon; using Milimoe.FunGame.Core.Library.Constant; +using Milimoe.FunGame.Core.Model; using Oshima.FunGame.OshimaModules.Effects.PassiveEffects; using Oshima.FunGame.OshimaModules.Skills; @@ -15,14 +17,15 @@ namespace Oshima.FunGame.OshimaModules.Effects.SkillEffects get { SetDescription(); - return $"{ActualProbability * 100:0.##}% 概率对{Skill.TargetDescription()}造成{GetEffectTypeName(_effectType)} {持续时间}。{(_description != "" ? _description : "")}"; + return $"{概率文本}对{Skill.TargetDescription()}造成{GetEffectTypeName(_effectType)} {持续时间}。{(_description != "" ? _description : "")}"; } } public override EffectType EffectType => _effectType; public override DispelledType DispelledType => _dispelledType; public override bool ExemptDuration => true; - private double ActualProbability => Level > 0 ? (_probability + _probabilityLevelGrowth * (Level - 1) * MagicEfficacy) : _probability; + private string 概率文本 => ActualProbability == 1 ? "" : $"{ActualProbability * 100:0.##}% 概率"; + private double ActualProbability => Calculation.PercentageCheck(Level > 0 ? (_probability + _probabilityLevelGrowth * (Level - 1) * MagicEfficacy) : _probability); private string 持续时间 => _durative && _duration > 0 ? $"{实际持续时间:0.##}" + $" {GameplayEquilibriumConstant.InGameTime}" : (!_durative && _durationTurn > 0 ? 实际持续时间 + " 回合" : $"0 {GameplayEquilibriumConstant.InGameTime}"); private double 实际持续时间 => _durative && _duration > 0 ? (_duration + _levelGrowth * (Level - 1) * MagicEfficacy) : (!_durative && _durationTurn > 0 ? ((int)Math.Round(_durationTurn + _levelGrowth * (Level - 1) * MagicEfficacy, 0, MidpointRounding.ToPositiveInfinity)) : 0); private readonly EffectType _effectType; @@ -149,11 +152,63 @@ namespace Oshima.FunGame.OshimaModules.Effects.SkillEffects tip = $"[ {caster} ] 对 [ {target} ] 造成了缴械!持续时间:{持续时间}!"; e = new 缴械(Skill, caster, _durative, duration, durationTurn); break; + case EffectType.Burn: + case EffectType.Poison: + isPercentage = false; + durationDamage = 0; + durationDamagePercent = 0; + durationDamageLevelGrowth = 0; + damageType = DamageType.Magical; + DamageCalculationOptions? options = null; + if (_args.Length > 0 && _args[0] is bool _) + { + isPercentage = (bool)_args[0]; + } + if (_args.Length > 1 && _args[1] is double _) + { + durationDamage = (double)_args[1]; + } + if (_args.Length > 2 && _args[2] is double _) + { + durationDamagePercent = (double)_args[2]; + } + if (_args.Length > 3 && _args[3] is double _) + { + durationDamageLevelGrowth = (double)_args[3]; + } + if (_args.Length > 0 && _args[4] is DamageType _) + { + damageType = (DamageType)_args[4]; + } + if (_args.Length > 0 && _args[5] is DamageCalculationOptions _) + { + options = (DamageCalculationOptions)_args[5]; + } + if (isPercentage && durationDamagePercent > 0 || !isPercentage && durationDamage > 0) + { + if (Level > 0) durationDamage += durationDamageLevelGrowth * (Level - 1); + if (Level > 0) durationDamagePercent += durationDamageLevelGrowth * (Level - 1); + string damageString = isPercentage ? $"受到 {durationDamagePercent * 100:0.##}% 当前生命值的" : $"受到 {durationDamage:0.##} 点" + CharacterSet.GetDamageTypeName(damageType); + tip = $"[ {caster} ] 对 [ {target} ] 造成了{GetEffectTypeName(_effectType)}! [ {target} ] 每{GameplayEquilibriumConstant.InGameTime}{damageString}!持续时间:{持续时间}!"; + e = new 持续伤害(Skill, target, caster, _durative, duration, durationTurn, isPercentage, durationDamage, durationDamagePercent, damageType, options) + { + EffectType = _effectType + }; + } + break; + case EffectType.InterruptCasting: + e = new 打断施法(Skill); + break; default: break; } if (e != null && !CheckExemption(caster, target, e)) { + if (e is 打断施法 ddsf) + { + ddsf.OnSkillCasted(caster, [target], [], []); + continue; + } WriteLine(tip); target.Effects.Add(e); e.OnEffectGained(target); @@ -258,6 +313,45 @@ namespace Oshima.FunGame.OshimaModules.Effects.SkillEffects _dispelledType = DispelledType.Weak; _description = "缴械:无法普通攻击。"; break; + case EffectType.Burn: + case EffectType.Poison: + _dispelledType = DispelledType.Weak; + isPercentage = false; + durationDamage = 0; + durationDamagePercent = 0; + durationDamageLevelGrowth = 0; + damageType = DamageType.Magical; + if (_args.Length > 0 && _args[0] is bool _) + { + isPercentage = (bool)_args[0]; + } + if (_args.Length > 1 && _args[1] is double _) + { + durationDamage = (double)_args[1]; + } + if (_args.Length > 2 && _args[2] is double _) + { + durationDamagePercent = (double)_args[2]; + } + if (_args.Length > 3 && _args[3] is double _) + { + durationDamageLevelGrowth = (double)_args[3]; + } + if (_args.Length > 0 && _args[4] is DamageType _) + { + damageType = (DamageType)_args[4]; + } + if (isPercentage && durationDamagePercent > 0 || !isPercentage && durationDamage > 0) + { + if (Level > 0) durationDamage += durationDamageLevelGrowth * (Level - 1); + if (Level > 0) durationDamagePercent += durationDamageLevelGrowth * (Level - 1); + string damageString = isPercentage ? $"受到 {durationDamagePercent * 100:0.##}% 当前生命值的" : $"受到 {durationDamage:0.##} 点" + CharacterSet.GetDamageTypeName(damageType); + _description = $"{GetEffectTypeName(_effectType)}:每{GameplayEquilibriumConstant.InGameTime}{damageString}!持续时间:{持续时间}!"; + } + break; + case EffectType.InterruptCasting: + _description = "打断施法:中断其正在进行的吟唱。"; + break; default: break; } @@ -271,6 +365,8 @@ namespace Oshima.FunGame.OshimaModules.Effects.SkillEffects EffectType.Silence => "封技", EffectType.Bleed => "气绝", EffectType.Cripple => "战斗不能", + EffectType.Burn => "燃烧", + EffectType.Poison => "中毒", _ => SkillSet.GetEffectTypeName(type) }; }