From 9b1a62c6bf01d4dfc1a480cae4a43f6db7d78eed Mon Sep 17 00:00:00 2001 From: milimoe Date: Fri, 27 Jun 2025 00:02:22 +0800 Subject: [PATCH] =?UTF-8?q?=E5=85=8D=E7=96=AB=E7=8A=B6=E6=80=81=E9=87=8D?= =?UTF-8?q?=E5=81=9A=EF=BC=8C=E4=BF=AE=E6=94=B9=E6=A3=80=E5=AE=9A=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=9B=E4=BC=98=E5=8C=96=E5=87=BB=E6=9D=80=E9=98=9F?= =?UTF-8?q?=E5=8F=8B=E7=9A=84=E5=8F=8D=E9=A6=88=E5=92=8C=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E5=86=97=E4=BD=99=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Entity/Character/Character.cs | 119 ++++++++---------- Entity/Skill/Effect.cs | 9 +- Entity/Skill/NormalAttack.cs | 15 ++- Entity/Skill/Skill.cs | 36 +++++- .../JsonConverter/NormalAttackConverter.cs | 5 +- .../Common/JsonConverter/SkillConverter.cs | 8 ++ Library/Constant/ConstantSet.cs | 12 ++ Library/Constant/TypeEnum.cs | 13 +- Model/GamingQueue.cs | 64 ++++++---- Model/TeamGamingQueue.cs | 12 +- 10 files changed, 177 insertions(+), 116 deletions(-) diff --git a/Entity/Character/Character.cs b/Entity/Character/Character.cs index 8378251..b1e1cde 100644 --- a/Entity/Character/Character.cs +++ b/Entity/Character/Character.cs @@ -1415,20 +1415,7 @@ namespace Milimoe.FunGame.Core.Entity 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("角色是不可选中的"); - } + GetStatusInfo(builder); builder.AppendLine("== 普通攻击 =="); builder.Append(NormalAttack.ToString()); @@ -1514,20 +1501,7 @@ namespace Milimoe.FunGame.Core.Entity if (!showBasicOnly) { - if (CharacterState != CharacterState.Actionable) - { - builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); - } - - if (IsNeutral) - { - builder.AppendLine("角色是无敌的"); - } - - if (IsUnselectable) - { - builder.AppendLine("角色是不可选中的"); - } + GetStatusInfo(builder); if (Skills.Count > 0) { @@ -1600,20 +1574,7 @@ namespace Milimoe.FunGame.Core.Entity 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("角色是不可选中的"); - } + GetStatusInfo(builder); builder.AppendLine($"硬直时间:{hardnessTimes:0.##}"); @@ -1674,20 +1635,7 @@ namespace Milimoe.FunGame.Core.Entity builder.AppendLine((HP == 0 ? "[ 死亡 ] " : "") + (showUser ? ToStringWithLevel() : ToStringWithLevelWithOutUser())); - if (CharacterState != CharacterState.Actionable) - { - builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); - } - - if (IsNeutral) - { - builder.AppendLine("角色是无敌的"); - } - - if (IsUnselectable) - { - builder.AppendLine("角色是不可选中的"); - } + GetStatusInfo(builder); builder.AppendLine("== 普通攻击 =="); builder.Append(NormalAttack.ToString()); @@ -1777,6 +1725,44 @@ namespace Milimoe.FunGame.Core.Entity return builder.ToString(); } + private void GetStatusInfo(StringBuilder builder) + { + if (CharacterState != CharacterState.Actionable) + { + builder.AppendLine(CharacterSet.GetCharacterState(CharacterState)); + } + + if ((ImmuneType & ImmuneType.Physical) != ImmuneType.None) + { + builder.AppendLine("角色现在物理免疫"); + } + + if ((ImmuneType & ImmuneType.Magical) != ImmuneType.None) + { + builder.AppendLine("角色现在魔法免疫"); + } + + if ((ImmuneType & ImmuneType.Skilled) != ImmuneType.None) + { + builder.AppendLine("角色现在技能免疫"); + } + + if ((ImmuneType & ImmuneType.All) != ImmuneType.None) + { + builder.AppendLine("角色现在完全免疫"); + } + + if (IsNeutral) + { + builder.AppendLine("角色是无敌的"); + } + + if (IsUnselectable) + { + builder.AppendLine("角色是不可选中的"); + } + } + /// /// 获取角色装备栏信息 /// @@ -1888,30 +1874,27 @@ namespace Milimoe.FunGame.Core.Entity IsUnselectable = types.Any(type => type == EffectType.Unselectable); IEnumerable immunes = CharacterImmuneTypes.Values.SelectMany(list => list); - // 判断角色的免疫状态 + // 判断角色的免疫状态,需要注意的是 All 不会覆盖任何其他类型,因为它是一种独立的类型 bool isAllImmune = immunes.Any(type => type == ImmuneType.All); bool isPhysicalImmune = immunes.Any(type => type == ImmuneType.Physical); bool isMagicalImmune = immunes.Any(type => type == ImmuneType.Magical); bool isSkilledImmune = immunes.Any(type => type == ImmuneType.Skilled); + ImmuneType = ImmuneType.None; if (isAllImmune) { - ImmuneType = ImmuneType.All; + ImmuneType |= ImmuneType.All; } - else if (isPhysicalImmune) + if (isPhysicalImmune) { - ImmuneType = ImmuneType.Physical; + ImmuneType |= ImmuneType.Physical; } - else if (isMagicalImmune) + if (isMagicalImmune) { - ImmuneType = ImmuneType.Magical; + ImmuneType |= ImmuneType.Magical; } - else if (isSkilledImmune) + if (isSkilledImmune) { - ImmuneType = ImmuneType.Skilled; - } - else - { - ImmuneType = ImmuneType.None; + ImmuneType |= ImmuneType.Skilled; } bool isControl = isNotActionable || isActionRestricted || isBattleRestricted || isSkillRestricted || isAttackRestricted; diff --git a/Entity/Skill/Effect.cs b/Entity/Skill/Effect.cs index b2df164..f5ba582 100644 --- a/Entity/Skill/Effect.cs +++ b/Entity/Skill/Effect.cs @@ -565,8 +565,9 @@ namespace Milimoe.FunGame.Core.Entity /// /// /// + /// /// - public virtual CharacterActionType AlterActionTypeBeforeAction(Character character, CharacterState state, ref bool canUseItem, ref bool canCastSkill, ref double pUseItem, ref double pCastSkill, ref double pNormalAttack) + public virtual CharacterActionType AlterActionTypeBeforeAction(Character character, CharacterState state, ref bool canUseItem, ref bool canCastSkill, ref double pUseItem, ref double pCastSkill, ref double pNormalAttack, ref bool forceAction) { return CharacterActionType.None; } @@ -745,12 +746,12 @@ namespace Milimoe.FunGame.Core.Entity /// /// 在免疫检定时 /// - /// - /// + /// + /// /// /// /// false:免疫检定不通过 - public virtual bool OnImmuneCheck(Character actor, Character enemy, ISkill skill, Item? item = null) + public virtual bool OnImmuneCheck(Character character, Character target, ISkill skill, Item? item = null) { return true; } diff --git a/Entity/Skill/NormalAttack.cs b/Entity/Skill/NormalAttack.cs index eb3551a..f8d39c5 100644 --- a/Entity/Skill/NormalAttack.cs +++ b/Entity/Skill/NormalAttack.cs @@ -241,13 +241,20 @@ namespace Milimoe.FunGame.Core.Entity selectable.Add(caster); } - if (CanSelectEnemy) + foreach (Character character in enemys) { - selectable.AddRange(enemys); + if (CanSelectEnemy && ((character.ImmuneType & ImmuneType.All) != ImmuneType.All || IgnoreImmune == ImmuneType.All)) + { + selectable.Add(character); + } } - if (CanSelectTeammate) + + foreach (Character character in teammates) { - selectable.AddRange(teammates); + if (CanSelectTeammate && ((character.ImmuneType & ImmuneType.All) != ImmuneType.All || IgnoreImmune == ImmuneType.All)) + { + selectable.Add(character); + } } return selectable; diff --git a/Entity/Skill/Skill.cs b/Entity/Skill/Skill.cs index d4f9fd1..f56e688 100644 --- a/Entity/Skill/Skill.cs +++ b/Entity/Skill/Skill.cs @@ -208,10 +208,20 @@ namespace Milimoe.FunGame.Core.Entity [InitRequired] public virtual double HardnessTime { get; set; } = 0; + /// + /// 额外硬直时间 [ 技能和物品相关 ] + /// + 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 double RealHardnessTime => Math.Max(0, (HardnessTime + ExHardnessTime) * (1 + ExHardnessTime2) * (1 - Calculation.PercentageCheck(Character?.ActionCoefficient ?? 0))); /// /// 效果列表 @@ -319,14 +329,30 @@ namespace Milimoe.FunGame.Core.Entity selectable.Add(caster); } - if (CanSelectEnemy) + ImmuneType checkType = ImmuneType.Skilled | ImmuneType.All; + if (IsMagic) { - selectable.AddRange(enemys); + checkType |= ImmuneType.Magical; } - if (CanSelectTeammate) + foreach (Character character in enemys) { - selectable.AddRange(teammates); + IEnumerable effects = character.Effects.Where(e => e.IsInEffect); + if (CanSelectEnemy && ((character.ImmuneType & checkType) == ImmuneType.None || + effects.Any(e => e.IgnoreImmune == ImmuneType.All || e.IgnoreImmune == ImmuneType.Skilled || (IsMagic && e.IgnoreImmune == ImmuneType.Magical)))) + { + selectable.Add(character); + } + } + + foreach (Character character in teammates) + { + IEnumerable effects = character.Effects.Where(e => e.IsInEffect); + if (CanSelectTeammate && ((character.ImmuneType & checkType) == ImmuneType.None || + effects.Any(e => e.IgnoreImmune == ImmuneType.All || e.IgnoreImmune == ImmuneType.Skilled || (IsMagic && e.IgnoreImmune == ImmuneType.Magical)))) + { + selectable.Add(character); + } } // 其他条件 diff --git a/Library/Common/JsonConverter/NormalAttackConverter.cs b/Library/Common/JsonConverter/NormalAttackConverter.cs index 6e8f3c0..ed2435a 100644 --- a/Library/Common/JsonConverter/NormalAttackConverter.cs +++ b/Library/Common/JsonConverter/NormalAttackConverter.cs @@ -49,7 +49,10 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter writer.WriteStartObject(); writer.WriteNumber(nameof(NormalAttack.Level), value.Level); - writer.WriteNumber(nameof(NormalAttack.HardnessTime), value.HardnessTime); + writer.WriteNumber(nameof(NormalAttack.ExDamage), value.ExDamage); + writer.WriteNumber(nameof(NormalAttack.ExDamage2), value.ExDamage2); + writer.WriteNumber(nameof(NormalAttack.ExHardnessTime), value.ExHardnessTime); + writer.WriteNumber(nameof(NormalAttack.ExHardnessTime2), value.ExHardnessTime2); writer.WriteBoolean(nameof(NormalAttack.IsMagic), value.IsMagic); writer.WriteNumber(nameof(NormalAttack.MagicType), (int)value.MagicType); writer.WriteNumber(nameof(NormalAttack.IgnoreImmune), (int)value.IgnoreImmune); diff --git a/Library/Common/JsonConverter/SkillConverter.cs b/Library/Common/JsonConverter/SkillConverter.cs index beb16ea..f1f1ae2 100644 --- a/Library/Common/JsonConverter/SkillConverter.cs +++ b/Library/Common/JsonConverter/SkillConverter.cs @@ -86,6 +86,12 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter case nameof(Skill.HardnessTime): result.HardnessTime = reader.GetDouble(); break; + case nameof(Skill.ExHardnessTime): + result.ExHardnessTime = reader.GetDouble(); + break; + case nameof(Skill.ExHardnessTime2): + result.ExHardnessTime2 = reader.GetDouble(); + break; case nameof(Skill.Effects): HashSet effects = NetworkUtility.JsonDeserialize>(ref reader, options) ?? []; foreach (Effect effect in effects) @@ -134,6 +140,8 @@ namespace Milimoe.FunGame.Core.Library.Common.JsonConverter if (value.CD > 0) writer.WriteNumber(nameof(Skill.CD), value.CD); if (value.CurrentCD > 0) writer.WriteNumber(nameof(Skill.CurrentCD), value.CurrentCD); if (value.HardnessTime > 0) writer.WriteNumber(nameof(Skill.HardnessTime), value.HardnessTime); + if (value.ExHardnessTime != 0) writer.WriteNumber(nameof(Skill.ExHardnessTime), value.ExHardnessTime); + if (value.ExHardnessTime2 != 0) writer.WriteNumber(nameof(Skill.ExHardnessTime2), value.ExHardnessTime2); writer.WritePropertyName(nameof(Skill.Effects)); JsonSerializer.Serialize(writer, value.Effects, options); writer.WritePropertyName(nameof(Skill.Values)); diff --git a/Library/Constant/ConstantSet.cs b/Library/Constant/ConstantSet.cs index fd18c8b..293e36e 100644 --- a/Library/Constant/ConstantSet.cs +++ b/Library/Constant/ConstantSet.cs @@ -465,6 +465,18 @@ namespace Milimoe.FunGame.Core.Library.Constant _ => "物理伤害" }; } + + public static string GetImmuneTypeName(ImmuneType type) + { + return type switch + { + ImmuneType.Physical => "物理免疫", + ImmuneType.Magical => "魔法免疫", + ImmuneType.Skilled => "技能免疫", + ImmuneType.All => "完全免疫", + _ => "" + }; + } } public class ItemSet diff --git a/Library/Constant/TypeEnum.cs b/Library/Constant/TypeEnum.cs index 2e9e730..d734c85 100644 --- a/Library/Constant/TypeEnum.cs +++ b/Library/Constant/TypeEnum.cs @@ -1021,14 +1021,15 @@ namespace Milimoe.FunGame.Core.Library.Constant /// /// 标准实现的免疫类型 /// + [Flags] public enum ImmuneType { - None, - Physical, - Magical, - Skilled, - All, - Special + None = 0, + Physical = 1 << 0, + Magical = 1 << 1, + Skilled = 1 << 2, + All = 1 << 3, + Special = 1 << 4 } public enum ShieldType diff --git a/Model/GamingQueue.cs b/Model/GamingQueue.cs index 906dcf4..f40ace3 100644 --- a/Model/GamingQueue.cs +++ b/Model/GamingQueue.cs @@ -804,6 +804,7 @@ namespace Milimoe.FunGame.Core.Model bool isAI = CharactersInAI.Contains(character); while (!decided && (!isAI || cancelTimes > 0)) { + cancelTimes--; type = CharacterActionType.None; // 是否能使用物品和释放技能 @@ -815,7 +816,9 @@ namespace Milimoe.FunGame.Core.Model double pCastSkill = 0.33; double pNormalAttack = 0.34; - cancelTimes--; + // 是否强制执行(跳过状态检查等) + bool forceAction = false; + // 不允许在吟唱和预释放状态下,修改角色的行动 if (character.CharacterState != CharacterState.Casting && character.CharacterState != CharacterState.PreCastSuperSkill) { @@ -823,7 +826,7 @@ namespace Milimoe.FunGame.Core.Model effects = [.. character.Effects.Where(e => e.IsInEffect)]; foreach (Effect effect in effects) { - actionTypeTemp = effect.AlterActionTypeBeforeAction(character, character.CharacterState, ref canUseItem, ref canCastSkill, ref pUseItem, ref pCastSkill, ref pNormalAttack); + actionTypeTemp = effect.AlterActionTypeBeforeAction(character, character.CharacterState, ref canUseItem, ref canCastSkill, ref pUseItem, ref pCastSkill, ref pNormalAttack, ref forceAction); } if (actionTypeTemp != CharacterActionType.None && actionTypeTemp != CharacterActionType.CastSkill && actionTypeTemp != CharacterActionType.CastSuperSkill) { @@ -943,10 +946,10 @@ namespace Milimoe.FunGame.Core.Model if (type == CharacterActionType.NormalAttack) { - if (character.CharacterState == CharacterState.NotActionable || + if (!forceAction && (character.CharacterState == CharacterState.NotActionable || character.CharacterState == CharacterState.ActionRestricted || character.CharacterState == CharacterState.BattleRestricted || - character.CharacterState == CharacterState.AttackRestricted) + character.CharacterState == CharacterState.AttackRestricted)) { WriteLine($"角色 [ {character} ] 状态为:{CharacterSet.GetCharacterState(character.CharacterState)},无法使用普通攻击!"); } @@ -973,10 +976,10 @@ namespace Milimoe.FunGame.Core.Model } else if (type == CharacterActionType.PreCastSkill) { - if (character.CharacterState == CharacterState.NotActionable || + if (!forceAction && (character.CharacterState == CharacterState.NotActionable || character.CharacterState == CharacterState.ActionRestricted || character.CharacterState == CharacterState.BattleRestricted || - character.CharacterState == CharacterState.SkillRestricted) + character.CharacterState == CharacterState.SkillRestricted)) { WriteLine($"角色 [ {character} ] 状态为:{CharacterSet.GetCharacterState(character.CharacterState)},无法释放技能!"); } @@ -1471,29 +1474,27 @@ namespace Milimoe.FunGame.Core.Model // 此变量为是否无视免疫 bool ignore = false; // 技能免疫无法免疫普通攻击,但是魔法免疫和物理免疫可以 - isImmune = (isNormalAttack && (enemy.ImmuneType == ImmuneType.All || enemy.ImmuneType == ImmuneType.Physical || enemy.ImmuneType == ImmuneType.Magical)) || - (!isNormalAttack && (enemy.ImmuneType == ImmuneType.All || enemy.ImmuneType == ImmuneType.Physical || enemy.ImmuneType == ImmuneType.Magical || enemy.ImmuneType == ImmuneType.Skilled)); + isImmune = (enemy.ImmuneType & ImmuneType.All) == ImmuneType.All || + (!isNormalAttack && (enemy.ImmuneType & ImmuneType.Skilled) == ImmuneType.Skilled) || + (damageType == DamageType.Physical && (enemy.ImmuneType & ImmuneType.Physical) == ImmuneType.Physical) || + (damageType == DamageType.Magical && (enemy.ImmuneType & ImmuneType.Magical) == ImmuneType.Magical); if (isImmune) { + if (isNormalAttack) + { + if (actor.NormalAttack.IgnoreImmune == ImmuneType.All || + (damageType == DamageType.Physical && actor.NormalAttack.IgnoreImmune == ImmuneType.Physical) || + (damageType == DamageType.Magical && actor.NormalAttack.IgnoreImmune == ImmuneType.Magical)) + { + ignore = true; + } + } effects = [.. characters.SelectMany(c => c.Effects.Where(e => e.IsInEffect)).Distinct()]; foreach (Effect effect in effects) { - if (isNormalAttack) + if (!effect.OnDamageImmuneCheck(actor, enemy, isNormalAttack, damageType, magicType, damage)) { - if (actor.NormalAttack.IgnoreImmune == ImmuneType.All || - (damageType == DamageType.Physical && actor.NormalAttack.IgnoreImmune == ImmuneType.Physical) || - (damageType == DamageType.Magical && actor.NormalAttack.IgnoreImmune == ImmuneType.Magical) || - !effect.OnDamageImmuneCheck(actor, enemy, isNormalAttack, damageType, magicType, damage)) - { - ignore = true; - } - } - else - { - if (!effect.OnDamageImmuneCheck(actor, enemy, isNormalAttack, damageType, magicType, damage)) - { - ignore = true; - } + ignore = true; } } } @@ -1944,7 +1945,15 @@ namespace Milimoe.FunGame.Core.Model } _stats[death].Deaths += 1; - string msg = $"[ {killer} ] 反补了 [ {death} ]!"; + string msg = $"[ {killer} ] 反补了 [ {death} ]![ {killer} ] 受到了击杀队友惩罚,扣除 200 {GameplayEquilibriumConstant.InGameCurrency}并且当前连杀计数减少一次!!"; + if (!_earnedMoney.TryAdd(killer, -200)) + { + _earnedMoney[killer] -= 200; + } + if (_continuousKilling.TryGetValue(killer, out int times) && times > 0) + { + _continuousKilling[killer] -= 1; + } LastRound.DeathContinuousKilling.Add(msg); WriteLine(msg); @@ -2987,7 +2996,8 @@ namespace Milimoe.FunGame.Core.Model foreach (Character target in loop) { bool ignore = false; - bool isImmune = target.ImmuneType == ImmuneType.Magical || target.ImmuneType == ImmuneType.Skilled || target.ImmuneType == ImmuneType.All; + bool isImmune = (skill.IsMagic && (target.ImmuneType & ImmuneType.Magical) == ImmuneType.Magical) || + (target.ImmuneType & ImmuneType.Skilled) == ImmuneType.Skilled || (target.ImmuneType & ImmuneType.All) == ImmuneType.All; if (isImmune) { Character[] characters = [character, target]; @@ -3004,11 +3014,11 @@ namespace Milimoe.FunGame.Core.Model if (ignore) { isImmune = false; - targets.Remove(target); } if (isImmune) { - WriteLine($"[ {target} ] 免疫了此技能!"); + targets.Remove(target); + WriteLine($"[ {character} ] 想要对 [ {target} ] 释放技能 [ {skill.Name} ],但是被 [ {target} ] 免疫了!"); await OnCharacterImmunedAsync(character, target, skill, item); } } diff --git a/Model/TeamGamingQueue.cs b/Model/TeamGamingQueue.cs index 21c742b..ef4d197 100644 --- a/Model/TeamGamingQueue.cs +++ b/Model/TeamGamingQueue.cs @@ -114,10 +114,20 @@ namespace Milimoe.FunGame.Core.Model /// protected override async Task OnDeathCalculation(Character death, Character killer) { + if (killer == death) + { + return; + } Team? team = GetTeam(killer); if (team != null) { - team.Score++; + Team? team2 = GetTeam(death); + if (team == team2) + { + WriteLine($"[ {team} ] 受到了击杀队友惩罚!减少死亡竞赛得分!!"); + team.Score--; + } + else team.Score++; } else await Task.CompletedTask; }