Files
Cielonos/Assets/Scripts/MainGame/Characters/Base/Subcontrollers/Reaction/BlockSubmodule.cs

199 lines
7.1 KiB
C#
Raw Normal View History

2025-11-25 08:19:33 -05:00
using System;
using System.Collections.Generic;
using System.Linq;
2026-05-23 08:27:50 -04:00
using Cielonos.MainGame.Inventory;
2025-11-25 08:19:33 -05:00
using Sirenix.OdinInspector;
2026-02-13 09:22:11 -05:00
using SLSUtilities.General;
2026-05-10 11:47:55 -04:00
using SLSUtilities.WwiseAssistance;
2025-11-25 08:19:33 -05:00
using UnityEngine;
namespace Cielonos.MainGame.Characters
{
public class BlockSubmodule : SubmoduleBase<ReactionSubcontroller>
{
public List<BlockSource> blockSources;
public bool canBlock;
[ShowInInspector]
public bool isBlocking => blockSources.Count > 0;
[ShowInInspector]
public bool isPerfectBlocking => blockSources.Any(source => source.hasPerfectBlock && source.isDuringPerfectBlock);
2026-05-10 11:47:55 -04:00
public float afterPerfectBlockTimer;
public float afterNormalBlockTimer;
2025-11-25 08:19:33 -05:00
public BlockSubmodule(ReactionSubcontroller owner) : base(owner)
{
blockSources = new List<BlockSource>();
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);
}
2026-05-10 11:47:55 -04:00
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);
}
2025-11-25 08:19:33 -05:00
public BlockSource GetCurrentBlockSource()
{
return blockSources.Count > 0 ? blockSources[0] : null;
}
2026-02-13 09:22:11 -05:00
public bool HaveBlockSource(string sourceName)
{
return blockSources.Any(source => source.blockName == sourceName);
}
2025-11-25 08:19:33 -05:00
public void Update()
{
if (isBlocking)
{
2026-05-10 11:47:55 -04:00
foreach (BlockSource source in blockSources)
2025-11-25 08:19:33 -05:00
{
source.blockTime -= owner.owner.selfTimeSm.DeltaTime;
2026-05-23 08:27:50 -04:00
source.triggerTime -= owner.owner.selfTimeSm.DeltaTime;
2025-11-25 08:19:33 -05:00
if (source.hasPerfectBlock)
{
source.perfectTime -= owner.owner.selfTimeSm.DeltaTime;
if (source.perfectTime <= 0)
{
source.isDuringPerfectBlock = false;
}
}
2026-05-10 11:47:55 -04:00
}
2025-11-25 08:19:33 -05:00
blockSources.RemoveAll(source => source.blockTime <= 0);
}
2026-05-10 11:47:55 -04:00
afterPerfectBlockTimer -= owner.owner.selfTimeSm.DeltaTime;
afterNormalBlockTimer -= owner.owner.selfTimeSm.DeltaTime;
2025-11-25 08:19:33 -05:00
}
}
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;
2026-05-23 08:27:50 -04:00
public float blockBufferTime = 0.25f;
2026-03-20 12:07:44 -04:00
2026-05-23 08:27:50 -04:00
public Breakthrough.Type perfectBlockType;
2026-05-10 11:47:55 -04:00
public GameObject perfectBlockEffect;
public uint perfectBlockSound;
2025-12-08 05:27:53 -05:00
public Action<AttackAreaBase> onPerfectBlock;
2026-05-10 11:47:55 -04:00
2026-05-23 08:27:50 -04:00
public Breakthrough.Type normalBlockType;
2026-05-10 11:47:55 -04:00
public GameObject normalBlockEffect;
public uint normalBlockSound;
2025-12-08 05:27:53 -05:00
public Action<AttackAreaBase> onNormalBlock;
2026-05-23 08:27:50 -04:00
public float triggerTime;
2026-05-10 11:47:55 -04:00
public BlockSource(CharacterBase sourceCharacter, ItemBase sourceItem, BlockData data)
2025-11-25 08:19:33 -05:00
{
this.sourceCharacter = sourceCharacter;
this.sourceItem = sourceItem;
2026-05-10 11:47:55 -04:00
this.blockName = data.blockName;
2026-03-20 12:07:44 -04:00
2026-05-10 11:47:55 -04:00
this.Priority = data.blockPriority;
this.hasPerfectBlock = data.perfectTime > 0f;
this.isDuringPerfectBlock = data.perfectTime > 0f;
2026-03-20 12:07:44 -04:00
2026-05-10 11:47:55 -04:00
this.blockTime = data.defaultBlockTime;
this.perfectTime = data.perfectTime;
2026-05-23 08:27:50 -04:00
if (data.advancedBreakthroughSettings)
{
this.normalBlockType = data.normalBlockType;
this.perfectBlockType = data.perfectBlockType;
}
else
{
this.normalBlockType = data.overallBlockType;
this.perfectBlockType = data.overallBlockType;
}
2026-05-10 11:47:55 -04:00
this.perfectBlockEffect = data.perfectBlockEffect;
this.perfectBlockSound = data.perfectBlockSound;
this.normalBlockEffect = data.normalBlockEffect;
this.normalBlockSound = data.normalBlockSound;
2026-05-23 08:27:50 -04:00
this.triggerTime = 0.06f;
2025-11-25 08:19:33 -05:00
}
2025-12-08 05:27:53 -05:00
public void PerfectBlock(AttackAreaBase attackArea, Vector3 blockEffectPosition)
2025-11-25 08:19:33 -05:00
{
2026-05-23 08:27:50 -04:00
if(triggerTime > 0f) return;
triggerTime = 0.04f;
2025-11-25 08:19:33 -05:00
if (sourceItem != null)
{
2026-05-10 11:47:55 -04:00
AudioManager.Post(perfectBlockSound, sourceCharacter.gameObject);
2026-04-29 06:16:07 -04:00
sourceItem.feedbackSc.PlayFeedback("PerfectBlock");
2026-03-20 12:07:44 -04:00
}
2026-05-10 11:47:55 -04:00
VFXObject.Spawn(perfectBlockEffect, sourceCharacter, blockEffectPosition, Quaternion.identity);
//pObj.GetComponent<ParticleSystem>().Simulate(0.1f, true, true);
//pObj.GetComponent<ParticleSystem>().Play();//TODO: 增加起点时间参数
2026-05-23 08:27:50 -04:00
sourceCharacter.reactionSc.blockSm.afterPerfectBlockTimer = blockBufferTime + 0.25f;
2025-12-08 05:27:53 -05:00
onPerfectBlock?.Invoke(attackArea);
2025-11-25 08:19:33 -05:00
}
2025-12-08 05:27:53 -05:00
public void NormalBlock(AttackAreaBase attackArea, Vector3 blockEffectPosition)
2025-11-25 08:19:33 -05:00
{
2026-05-23 08:27:50 -04:00
if (triggerTime > 0f) return;
triggerTime = 0.04f;
2025-11-25 08:19:33 -05:00
if (sourceItem != null)
{
2026-05-10 11:47:55 -04:00
AudioManager.Post(normalBlockSound, sourceCharacter.gameObject);
2026-04-29 06:16:07 -04:00
sourceItem.feedbackSc.PlayFeedback("NormalBlock");
2026-03-20 12:07:44 -04:00
}
2025-11-25 08:19:33 -05:00
2026-05-10 11:47:55 -04:00
VFXObject.Spawn(normalBlockEffect, sourceCharacter, blockEffectPosition, Quaternion.identity);
2026-05-23 08:27:50 -04:00
sourceCharacter.reactionSc.blockSm.afterNormalBlockTimer = blockBufferTime + 0.25f;
2025-12-08 05:27:53 -05:00
onNormalBlock?.Invoke(attackArea);
2025-11-25 08:19:33 -05:00
}
}
}