using System; using System.Collections.Generic; using System.Linq; using Cielonos.MainGame.Buffs.Character; using Cielonos.MainGame.Characters; using Sirenix.OdinInspector; using SLSUtilities.FunctionalAnimation; using SLSUtilities.General; using SLSUtilities.WwiseAssistance; using SoftCircuits.Collections; using UnityEngine; using UnityEngine.Serialization; namespace Cielonos.MainGame.FunctionalAnimation { [Serializable] public class SetBreakthroughResistance : FuncAnimPayloadBase { /// /// 在强力动作的原始抗性等级确定后、Buff 创建前调用的有序修正器。 /// 通过 key 管理注册和注销,并按 Priority 顺序将前一个结果传给后一个回调。 /// public static readonly OrderedDictionary> onResolveBreakthroughableType = new(); public override bool IsCombatOnly => true; [InfoBox("设置角色的突破抗性状态,同时开启或关闭轮廓线效果。\n角色会被突破类型相同或更高的攻击打断,不会被低于该突破类型的攻击打断。")] [FormerlySerializedAs("outlineSwitch")] [Tooltip("是否开启")] public bool isEnabling = true; [FormerlySerializedAs("applyFXs")] [ShowIf("isEnabling")] [Tooltip("是否开启音效和特效,特效默认为VFXData配置的WarningDisruption或WarningForced")] public bool applyFx = true; [Tooltip("是否从行为树参数获取突破类型")] [ShowIf("isEnabling")] public bool getFromBehaviorTree = true; [Tooltip("突破类型")] [HideIf("getFromBehaviorTree")] public Breakthrough.Type breakthroughableType = Breakthrough.Type.Heavy; [Tooltip("是否使用详细设置")] public bool detailedSettings = false; [Tooltip("轮廓线宽度")] [ShowIf("@this.detailedSettings && this.isEnabling")] public float outlineWidth = 0.05f; [Tooltip("轮廓线淡入淡出时间")] [ShowIf("detailedSettings")] public float outlineFadeDuration = 0.1f; public override void Invoke() { RenderSubcontrollerBase renderSc = Character.renderSc; Breakthrough.Type resolvedBreakthroughableType = breakthroughableType; if (getFromBehaviorTree) { BehaviorSubcontroller behaviorSc = (Character as Automata)!.behaviorSc; string typeName = behaviorSc.mainBehaviorTree.GetVariable("BreakthroughableType").Value; if (string.IsNullOrEmpty(typeName)) { resolvedBreakthroughableType = Breakthrough.Type.Heavy; } else { resolvedBreakthroughableType = Enum.TryParse(typeName, out Breakthrough.Type parsedType) ? parsedType : Breakthrough.Type.Heavy; } } if (isEnabling) { if (Character is Automata automata) { resolvedBreakthroughableType = ResolveBreakthroughableType(automata, resolvedBreakthroughableType); } new BreakthroughResistanceModification(resolvedBreakthroughableType).Apply(Character); if (applyFx) { if (resolvedBreakthroughableType == Breakthrough.Type.Heavy) { AudioManager.Post(AK.EVENTS.WARNING_ATTACK_HEAVYLEVEL, Character.gameObject); Character.vfxData.SpawnVFX("WarningHeavy", Character, Character.transform); } else if (resolvedBreakthroughableType == Breakthrough.Type.Disruption) { AudioManager.Post(AK.EVENTS.WARNING_ATTACK_DISRUPTIONLEVEL, Character.gameObject); Character.vfxData.SpawnVFX("WarningDisruption", Character, Character.transform); } else if (resolvedBreakthroughableType == Breakthrough.Type.Forced) { AudioManager.Post(AK.EVENTS.WARNING_ATTACK_FORCEDLEVEL, Character.gameObject); Character.vfxData.SpawnVFX("WarningForced", Character, Character.transform); } } } else { Character.buffSm.GetBuff()?.Remove(); } } private static Breakthrough.Type ResolveBreakthroughableType(Automata target, Breakthrough.Type originalType) { // 多个修正器按 Priority 顺序串行处理,后一个修正器接收前一个的结果。 Breakthrough.Type resolvedType = originalType; foreach (string key in onResolveBreakthroughableType.Keys.ToList()) { PrioritizedFunc resolver = onResolveBreakthroughableType[key]; resolvedType = resolver.Invoke(target, resolvedType); if (resolver.ShouldRemove) { onResolveBreakthroughableType.Remove(key); } } return resolvedType; } private void SetResistance(Breakthrough.Type type, bool isResistant) { foreach (var lowerType in Breakthrough.GetLowerTypes(type)) { Character.reactionSc.breakthroughResistances[lowerType].Modify(isResistant); } Character.reactionSc.breakthroughResistances[type].Modify(!isResistant); foreach (var higherType in Breakthrough.GetHigherTypes(type)) { Character.reactionSc.breakthroughResistances[higherType].Modify(!isResistant); } } } }