using System; using System.Collections.Generic; using System.Linq; using UniRx; using UnityEngine; namespace Cielonos.MainGame.Inventory { public partial class ComboSubmodule : SubmoduleBase { 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(); } /// /// 设置连击计时器,在指定时间后重置连击树 /// /// 连击计时器持续时间,若小于等于0则使用默认时间 public void Setup(float disappearTime = -1) { disappearTime = disappearTime <= 0 ? defaultDisappearTime : disappearTime; comboTimer = Observable.Timer(TimeSpan.FromSeconds(disappearTime)) .First() .Subscribe(_ => { comboTree.Reset(); }); } /// /// 暂停连击计时器,在指定时间后继续重新设置连击计时器 /// public void SuspendThenSetup(float duration) { comboTimer?.Dispose(); suspender?.Dispose(); suspender = Observable.Timer(TimeSpan.FromSeconds(duration)) .First() .Subscribe(_ => Setup()); } /// /// 获取当前连招节点的引用名称 /// public string GetCurrentNodeName() { return comboTree.currentNode.referenceName; } /// /// 根据操作指令进入下一个连招节点 /// /// 操作指令字符串,例如"L","R" /// 若无法进入下一个节点,是否返回首个节点 /// 是否成功进入下一个节点 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; } /// /// 直接设置连招节点 /// /// 节点索引 public void SetCombo(int index) { comboTree.lastNode = comboTree.currentNode; comboTree.currentNode = comboTree.nodes[index]; } /// /// 直接设置连招节点 /// /// 节点引用名称 public void SetCombo(string refName) { comboTree.lastNode = comboTree.currentNode; comboTree.currentNode = comboTree.nodes.Find(x => x.referenceName == refName); } /// /// 回退到上一个连招节点 /// public void RevertCombo() { comboTree.currentNode = comboTree.lastNode; } /// /// 重置连招树到初始节点 /// public void ResetCombo() { comboTree.Reset(); } } public partial class ComboSubmodule { [Serializable] public class ComboTree { public List 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 branches; public Node(int nodeIndex, string referenceName) { this.nodeIndex = nodeIndex; this.referenceName = referenceName; this.branches = new List(); } } [Serializable] public class Branch { public int nextNodeIndex; public string operation; public Branch(int nextNodeIndex, string operation) { this.nextNodeIndex = nextNodeIndex; this.operation = operation; } } } } }