using System; using System.Collections.Generic; using System.Linq; using Cielonos.MainGame.Inventory; using Sirenix.OdinInspector; using SLSUtilities.General; using SLSUtilities.WwiseAssistance; 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 float afterPerfectBlockTimer; public float afterNormalBlockTimer; 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 RemoveBlock(string sourceName) { blockSources.RemoveAll(source => source.blockName == sourceName); } public bool TryGetBlockSource(string sourceName, out BlockSource blockSource) { blockSource = blockSources.Find(source => source.blockName == sourceName); return blockSource != null; } public BlockSource GetBlockSource(string sourceName) { return blockSources.Find(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) { foreach (BlockSource source in blockSources) { source.blockTime -= owner.owner.selfTimeSm.DeltaTime; source.triggerTime -= 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); } afterPerfectBlockTimer -= owner.owner.selfTimeSm.DeltaTime; afterNormalBlockTimer -= owner.owner.selfTimeSm.DeltaTime; } } 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 float blockBufferTime = 0.25f; public Breakthrough.Type perfectBlockType; public GameObject perfectBlockEffect; public uint perfectBlockSound; public Action onPerfectBlock; public Breakthrough.Type normalBlockType; public GameObject normalBlockEffect; public uint normalBlockSound; public Action onNormalBlock; public float triggerTime; public BlockSource(CharacterBase sourceCharacter, ItemBase sourceItem, BlockData data) { this.sourceCharacter = sourceCharacter; this.sourceItem = sourceItem; this.blockName = data.blockName; this.Priority = data.blockPriority; this.hasPerfectBlock = data.perfectTime > 0f; this.isDuringPerfectBlock = data.perfectTime > 0f; this.blockTime = data.defaultBlockTime; this.perfectTime = data.perfectTime; if (data.advancedBreakthroughSettings) { this.normalBlockType = data.normalBlockType; this.perfectBlockType = data.perfectBlockType; } else { this.normalBlockType = data.overallBlockType; this.perfectBlockType = data.overallBlockType; } this.perfectBlockEffect = data.perfectBlockEffect; this.perfectBlockSound = data.perfectBlockSound; this.normalBlockEffect = data.normalBlockEffect; this.normalBlockSound = data.normalBlockSound; this.triggerTime = 0.06f; } public void PerfectBlock(AttackAreaBase attackArea, Vector3 blockEffectPosition) { if(triggerTime > 0f) return; triggerTime = 0.04f; if (sourceItem != null) { AudioManager.Post(perfectBlockSound, sourceCharacter.gameObject); sourceItem.feedbackSc.PlayFeedback("PerfectBlock"); } VFXObject.Spawn(perfectBlockEffect, sourceCharacter, blockEffectPosition, Quaternion.identity); //pObj.GetComponent().Simulate(0.1f, true, true); //pObj.GetComponent().Play();//TODO: 增加起点时间参数 sourceCharacter.reactionSc.blockSm.afterPerfectBlockTimer = blockBufferTime + 0.25f; onPerfectBlock?.Invoke(attackArea); } public void NormalBlock(AttackAreaBase attackArea, Vector3 blockEffectPosition) { if (triggerTime > 0f) return; triggerTime = 0.04f; if (sourceItem != null) { AudioManager.Post(normalBlockSound, sourceCharacter.gameObject); sourceItem.feedbackSc.PlayFeedback("NormalBlock"); } VFXObject.Spawn(normalBlockEffect, sourceCharacter, blockEffectPosition, Quaternion.identity); sourceCharacter.reactionSc.blockSm.afterNormalBlockTimer = blockBufferTime + 0.25f; onNormalBlock?.Invoke(attackArea); } } }