192 lines
7.3 KiB
C#
192 lines
7.3 KiB
C#
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<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);
|
|
|
|
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 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<AttackAreaBase> onPerfectBlock;
|
|
public BreakthroughType normalBlockBreakType;
|
|
public string normalEffectName;
|
|
public Action<AttackAreaBase> 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.PlayFeedback("PerfectBlock");
|
|
pObj = sourceItem.blockData.InstantiateBlockEffect(perfectEffectName, sourceCharacter, blockEffectPosition, Quaternion.identity);
|
|
}
|
|
else
|
|
{
|
|
pObj = sourceCharacter.blockData.InstantiateBlockEffect(perfectEffectName, sourceCharacter, blockEffectPosition, Quaternion.identity);
|
|
}
|
|
|
|
pObj.GetComponent<ParticleSystem>().Simulate(0.1f, true, true);
|
|
pObj.GetComponent<ParticleSystem>().Play();//TODO: 增加起点时间参数
|
|
|
|
onPerfectBlock?.Invoke(attackArea);
|
|
}
|
|
|
|
public void NormalBlock(AttackAreaBase attackArea, Vector3 blockEffectPosition)
|
|
{
|
|
if (sourceItem != null)
|
|
{
|
|
sourceItem.audioContainer.PlaySoundFX("NormalBlock");
|
|
sourceItem.feedbackSc.PlayFeedback("NormalBlock");
|
|
sourceItem.blockData.InstantiateBlockEffect(normalEffectName, sourceCharacter, blockEffectPosition, Quaternion.identity);
|
|
}
|
|
else
|
|
{
|
|
sourceCharacter.blockData.InstantiateBlockEffect(normalEffectName, sourceCharacter, blockEffectPosition, Quaternion.identity);
|
|
}
|
|
|
|
onNormalBlock?.Invoke(attackArea);
|
|
}
|
|
}
|
|
} |