using System; using System.Collections.Generic; using System.Linq; using Cielonos.MainGame.Characters.Inventory; using Sirenix.OdinInspector; using SLSUtilities.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, BreakthroughType normalBreakType = BreakthroughType.Disruption, string normalEffectName = "NormalBlock", BreakthroughType perfectBreakType = BreakthroughType.Disruption, string perfectEffectName = "PerfectBlock") { BlockSource newSource = new BlockSource(sourceCharacter, sourceItem, sourceName, priority, blockTime, perfectTime, normalBreakType, normalEffectName, perfectBreakType, perfectEffectName); 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 bool HaveBlockSource(string sourceName) { return blockSources.Any(source => source.blockName == sourceName); } 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 BreakthroughType perfectBlockBreakType; public string perfectEffectName; public Action onPerfectBlock; public BreakthroughType normalBlockBreakType; public string normalEffectName; public Action onNormalBlock; public BlockSource(CharacterBase sourceCharacter, ItemBase sourceItem, string blockName, int priority, float blockTime, BreakthroughType normalBlockBreakType, string blockEffectName) { this.sourceCharacter = sourceCharacter; this.sourceItem = sourceItem; this.blockName = blockName; this.Priority = priority; this.hasPerfectBlock = false; this.isDuringPerfectBlock = false; this.blockTime = blockTime; this.normalEffectName = blockEffectName; this.normalBlockBreakType = normalBlockBreakType; } public BlockSource(CharacterBase sourceCharacter, ItemBase sourceItem, string blockName, int priority, float blockTime, float perfectTime, BreakthroughType normalBlockBreakType, string normalEffectName, BreakthroughType perfectBlockBreakType, string perfectEffectName) { this.sourceCharacter = sourceCharacter; this.sourceItem = sourceItem; this.blockName = blockName; this.Priority = priority; this.hasPerfectBlock = true; this.isDuringPerfectBlock = true; this.blockTime = blockTime; this.perfectTime = perfectTime; this.normalBlockBreakType = normalBlockBreakType; this.perfectEffectName = perfectEffectName; this.perfectBlockBreakType = perfectBlockBreakType; this.normalEffectName = normalEffectName; } public void PerfectBlock(AttackAreaBase attackArea, Vector3 blockEffectPosition) { GameObject pObj; if (sourceItem != null) { sourceItem.audioContainer.PlaySoundFX("PerfectBlock"); sourceItem.feedbackSc["PerfectBlock"]?.Play(); pObj = sourceItem.blockData.InstantiateBlockEffect(perfectEffectName, sourceCharacter, blockEffectPosition, Quaternion.identity); } else { pObj = sourceCharacter.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); } else { sourceCharacter.blockData.InstantiateBlockEffect(normalEffectName, sourceCharacter, blockEffectPosition, Quaternion.identity); } onNormalBlock?.Invoke(attackArea); } } }