191 lines
6.0 KiB
C#
191 lines
6.0 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using UniRx;
|
||
using UnityEngine;
|
||
|
||
namespace Cielonos.MainGame.Inventory
|
||
{
|
||
public partial class ComboSubmodule : SubmoduleBase<ItemBase>
|
||
{
|
||
private IDisposable comboTimer;
|
||
private IDisposable suspender;
|
||
private float defaultDisappearTime;
|
||
|
||
public ComboTree comboTree;
|
||
|
||
public ComboSubmodule(ItemBase owner, ComboData asset) : base(owner)
|
||
{
|
||
this.defaultDisappearTime = asset.defaultDisappearTime;
|
||
this.comboTree = asset.tree.ToRuntime();
|
||
this.comboTree.Reset();
|
||
}
|
||
|
||
public ComboSubmodule(ItemBase owner, float disappearTime) : base(owner)
|
||
{
|
||
this.defaultDisappearTime = disappearTime;
|
||
this.comboTree = new ComboTree();
|
||
this.comboTree.AddNode(0, "Root");
|
||
this.comboTree.Reset();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 设置连击计时器,在指定时间后重置连击树
|
||
/// </summary>
|
||
/// <param name="disappearTime">连击计时器持续时间,若小于等于0则使用默认时间</param>
|
||
public void Setup(float disappearTime = -1)
|
||
{
|
||
disappearTime = disappearTime <= 0 ? defaultDisappearTime : disappearTime;
|
||
|
||
comboTimer = Observable.Timer(TimeSpan.FromSeconds(disappearTime))
|
||
.First()
|
||
.Subscribe(_ => { comboTree.Reset(); });
|
||
}
|
||
|
||
/// <summary>
|
||
/// 暂停连击计时器,在指定时间后继续重新设置连击计时器
|
||
/// </summary>
|
||
public void SuspendThenSetup(float duration)
|
||
{
|
||
comboTimer?.Dispose();
|
||
suspender?.Dispose();
|
||
suspender = Observable.Timer(TimeSpan.FromSeconds(duration))
|
||
.First()
|
||
.Subscribe(_ => Setup());
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前连招节点的引用名称
|
||
/// </summary>
|
||
public string GetCurrentNodeName()
|
||
{
|
||
return comboTree.currentNode.referenceName;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 根据操作指令进入下一个连招节点
|
||
/// </summary>
|
||
/// <param name="operation">操作指令字符串,例如"L","R"</param>
|
||
/// <param name="autoReset">若无法进入下一个节点,是否返回首个节点</param>
|
||
/// <returns>是否成功进入下一个节点</returns>
|
||
public bool NextCombo(string operation, bool autoReset = true)
|
||
{
|
||
if (comboTree.currentNode.branches.Count == 0)
|
||
{
|
||
comboTree.Reset();
|
||
}
|
||
|
||
foreach (var branch in comboTree.currentNode.branches.Where(branch => branch.operation == operation))
|
||
{
|
||
comboTree.lastNode = comboTree.currentNode;
|
||
comboTree.currentNode = comboTree.nodes[branch.nextNodeIndex];
|
||
return true;
|
||
}
|
||
|
||
if (autoReset)
|
||
{
|
||
comboTree.Reset();
|
||
NextCombo(operation);
|
||
}
|
||
|
||
return false;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 直接设置连招节点
|
||
/// </summary>
|
||
/// <param name="index">节点索引</param>
|
||
public void SetCombo(int index)
|
||
{
|
||
comboTree.lastNode = comboTree.currentNode;
|
||
comboTree.currentNode = comboTree.nodes[index];
|
||
}
|
||
|
||
/// <summary>
|
||
/// 直接设置连招节点
|
||
/// </summary>
|
||
/// <param name="refName">节点引用名称</param>
|
||
public void SetCombo(string refName)
|
||
{
|
||
comboTree.lastNode = comboTree.currentNode;
|
||
comboTree.currentNode = comboTree.nodes.Find(x => x.referenceName == refName);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 回退到上一个连招节点
|
||
/// </summary>
|
||
public void RevertCombo()
|
||
{
|
||
comboTree.currentNode = comboTree.lastNode;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 重置连招树到初始节点
|
||
/// </summary>
|
||
public void ResetCombo()
|
||
{
|
||
comboTree.Reset();
|
||
}
|
||
}
|
||
|
||
public partial class ComboSubmodule
|
||
{
|
||
[Serializable]
|
||
public class ComboTree
|
||
{
|
||
public List<Node> nodes = new();
|
||
public Node lastNode;
|
||
public Node currentNode;
|
||
|
||
public void AddNode(int index, string referenceName)
|
||
{
|
||
nodes.Add(new Node(index, referenceName));
|
||
}
|
||
|
||
public void AddBranch(int nodeIndex, int nextNodeIndex, string operation)
|
||
{
|
||
nodes[nodeIndex].branches.Add(new Branch(nextNodeIndex, operation));
|
||
}
|
||
|
||
public void RemoveBranch(int nodeIndex, int nextNodeIndex, string operation)
|
||
{
|
||
int branchIndex = nodes[nodeIndex].branches.FindIndex(x => x.nextNodeIndex == nextNodeIndex && x.operation == operation);
|
||
nodes[nodeIndex].branches.RemoveAt(branchIndex);
|
||
}
|
||
|
||
public void Reset()
|
||
{
|
||
currentNode = nodes[0];
|
||
}
|
||
|
||
[Serializable]
|
||
public class Node
|
||
{
|
||
public int nodeIndex;
|
||
public string referenceName;
|
||
|
||
public List<Branch> branches;
|
||
|
||
public Node(int nodeIndex, string referenceName)
|
||
{
|
||
this.nodeIndex = nodeIndex;
|
||
this.referenceName = referenceName;
|
||
this.branches = new List<Branch>();
|
||
}
|
||
}
|
||
|
||
[Serializable]
|
||
public class Branch
|
||
{
|
||
public int nextNodeIndex;
|
||
public string operation;
|
||
|
||
public Branch(int nextNodeIndex, string operation)
|
||
{
|
||
this.nextNodeIndex = nextNodeIndex;
|
||
this.operation = operation;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
} |