using System; using System.Collections.Generic; using System.Linq; using Cielonos.MainGame.Inventory; using Sirenix.OdinInspector; using SLSFramework.General; using UnityEngine; namespace Cielonos.MainGame.Characters { public class BlockSubmodule : SubmoduleBase { public List blockSources; public bool canBlock; [ShowInInspector] public bool isBlocking => blockSources.Count > 0; [ShowInInspector] public bool isPerfectBlocking => blockSources.Any(source => source.hasPerfectBlock && source.isDuringPerfectBlock); public BlockSubmodule(ReactionSubcontroller owner) : base(owner) { blockSources = new List(); canBlock = true; } public void ApplyBlock(BlockSource source, bool refreshPerfect = false) { if (canBlock) { BlockSource existingSource = blockSources.Find(x => x.blockName == source.blockName); if (existingSource != null) { if (source.blockTime > existingSource.blockTime) { existingSource.blockTime = source.blockTime; } if (refreshPerfect && existingSource.hasPerfectBlock) { existingSource.isDuringPerfectBlock = true; existingSource.perfectTime = source.perfectTime; } return; } blockSources.AddByPriority(source); } } public void ApplyBlock(CharacterBase sourceCharacter, ItemBase sourceItem, string sourceName, int priority = 0, float blockTime = Mathf.Infinity, float perfectTime = 0.2f, bool refreshPerfect = false, string normalEffectName = "NormalBlock", string perfectEffectName = "PerfectBlock") { BlockSource newSource = new BlockSource(sourceCharacter, sourceItem, sourceName, priority, normalEffectName, perfectEffectName, blockTime, perfectTime); ApplyBlock(newSource, refreshPerfect); } public void RemoveBlock(string sourceName) { blockSources.RemoveAll(source => source.blockName == sourceName); } public BlockSource GetCurrentBlockSource() { return blockSources.Count > 0 ? blockSources[0] : null; } public void Update() { if (isBlocking) { blockSources.ForEach(source => { source.blockTime -= owner.owner.selfTimeSm.DeltaTime; if (source.hasPerfectBlock) { source.perfectTime -= owner.owner.selfTimeSm.DeltaTime; if (source.perfectTime <= 0) { source.isDuringPerfectBlock = false; } } }); blockSources.RemoveAll(source => source.blockTime <= 0); } } } public class BlockSource : IPrioritized { public int Priority { get; private set; } public CharacterBase sourceCharacter; public ItemBase sourceItem; public string blockName; public bool hasPerfectBlock; public bool isDuringPerfectBlock; public float perfectTime; public float blockTime; public string perfectEffectName; public Action onPerfectBlock; public string normalEffectName; public Action onNormalBlock; public BlockSource(CharacterBase sourceCharacter, ItemBase sourceItem, string blockName, int priority, string blockEffectName, float blockTime) { this.sourceCharacter = sourceCharacter; this.sourceItem = sourceItem; this.blockName = blockName; this.normalEffectName = blockEffectName; this.Priority = priority; this.blockTime = blockTime; this.hasPerfectBlock = false; this.isDuringPerfectBlock = false; } public BlockSource(CharacterBase sourceCharacter, ItemBase sourceItem, string blockName, int priority, string normalEffectName, string perfectEffectName, float blockTime, float perfectTime) { this.sourceCharacter = sourceCharacter; this.sourceItem = sourceItem; this.blockName = blockName; this.Priority = priority; this.blockTime = blockTime; this.hasPerfectBlock = true; this.isDuringPerfectBlock = true; this.perfectTime = perfectTime; this.perfectEffectName = perfectEffectName; this.normalEffectName = normalEffectName; } public void PerfectBlock(AttackAreaBase attackArea, Vector3 blockEffectPosition) { if (sourceItem != null) { sourceItem.audioContainer.PlaySoundFX("PerfectBlock"); sourceItem.feedbackSc["PerfectBlock"]?.Play(); GameObject pObj = sourceItem.blockData.InstantiateBlockEffect(perfectEffectName, sourceCharacter, blockEffectPosition, Quaternion.identity); pObj.GetComponent().Simulate(0.1f, true, true); pObj.GetComponent().Play();//TODO: 增加起点时间参数 } onPerfectBlock?.Invoke(attackArea); } public void NormalBlock(AttackAreaBase attackArea, Vector3 blockEffectPosition) { if (sourceItem != null) { sourceItem.audioContainer.PlaySoundFX("NormalBlock"); sourceItem.feedbackSc["NormalBlock"]?.Play(); sourceItem.blockData.InstantiateBlockEffect(normalEffectName, sourceCharacter, blockEffectPosition, Quaternion.identity); } onNormalBlock?.Invoke(attackArea); } } }