Files
Cielonos/Assets/Scripts/MainGame/Characters/Player/Items/Submodules/ComboSubmodule.cs

203 lines
6.9 KiB
C#
Raw Normal View History

2025-11-25 08:19:33 -05:00
using System;
using System.Collections.Generic;
using System.Linq;
2026-01-17 11:35:49 -05:00
using Cielonos.MainGame.Characters;
2025-11-25 08:19:33 -05:00
using UniRx;
using UnityEngine;
2026-03-20 12:07:44 -04:00
namespace Cielonos.MainGame.Characters.Inventory
2025-11-25 08:19:33 -05:00
{
public partial class ComboSubmodule : SubmoduleBase<ItemBase>
{
2026-01-17 11:35:49 -05:00
public Dictionary<string, ComboTree> comboTrees;
public ComboTree main => comboTrees["Main"];
public ComboTree this[string name] => comboTrees[name];
2025-11-25 08:19:33 -05:00
public ComboSubmodule(ItemBase owner, ComboData asset) : base(owner)
{
2026-01-17 11:35:49 -05:00
this.comboTrees = new Dictionary<string, ComboTree>();
foreach (KeyValuePair<string, ComboTreeData> treeData in asset.comboTrees)
2025-11-25 08:19:33 -05:00
{
2026-01-17 11:35:49 -05:00
comboTrees[treeData.Key] = treeData.Value.ToRuntime(this);
comboTrees[treeData.Key].Reset();
2025-11-25 08:19:33 -05:00
}
}
}
public partial class ComboSubmodule
{
2026-01-17 11:35:49 -05:00
public partial class ComboTree : SubmoduleBase<ComboSubmodule>
2025-11-25 08:19:33 -05:00
{
2026-01-17 11:35:49 -05:00
private Player player => owner.owner.player;
private IDisposable comboTimer;
private IDisposable suspender;
private float resetTime;
public List<Node> nodes;
2025-11-25 08:19:33 -05:00
public Node lastNode;
public Node currentNode;
2026-01-17 11:35:49 -05:00
public ComboTree(ComboSubmodule owner, float resetTime) : base(owner)
{
this.resetTime = resetTime;
this.nodes = new List<Node>();
}
2025-11-25 08:19:33 -05:00
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];
}
2026-01-17 11:35:49 -05:00
}
public partial class ComboTree
{
/// <summary>
/// 设置连击计时器,在指定时间后重置连击树
/// </summary>
/// <param name="overrideResetTime">连击计时器持续时间若小于等于0则使用默认时间</param>
public void Setup(float overrideResetTime = -1)
{
overrideResetTime = overrideResetTime <= 0 ? resetTime : overrideResetTime;
comboTimer = player.selfTimeSm.AddLocalTimer(overrideResetTime, Reset);
}
/// <summary>
/// 暂停连击计时器,在指定时间后继续重新设置连击计时器
/// </summary>
public void SuspendThenSetup(float duration)
{
comboTimer?.Dispose();
suspender?.Dispose();
suspender = player.selfTimeSm.AddLocalTimer(duration, () => Setup());
}
/// <summary>
/// 获取当前连招节点的引用名称
/// </summary>
public string GetCurrentNodeName()
{
return currentNode.referenceName;
}
/// <summary>
/// 获取当前连招节点的下一个节点的引用名称,如果没有符合条件的下一个节点,则返回首个节点的引用名称
/// </summary>
public string GetNextNodeName(string operation)
{
foreach (var branch in currentNode.branches.Where(branch => branch.operation == operation))
{
return nodes[branch.nextNodeIndex].referenceName;
}
return nodes[0].branches.Where(branch => branch.operation == operation)
.Select(branch => nodes[branch.nextNodeIndex].referenceName).FirstOrDefault();
}
/// <summary>
/// 根据操作指令进入下一个连招节点
/// </summary>
/// <param name="operation">操作指令字符串,例如"L""R"</param>
/// <param name="autoReset">若无法进入下一个节点,是否返回首个节点</param>
/// <returns>是否成功进入下一个节点</returns>
public bool NextCombo(string operation, bool autoReset = true)
{
if (currentNode.branches.Count == 0)
{
Reset();
}
2025-11-25 08:19:33 -05:00
2026-01-17 11:35:49 -05:00
foreach (var branch in currentNode.branches.Where(branch => branch.operation == operation))
{
lastNode = currentNode;
currentNode = nodes[branch.nextNodeIndex];
return true;
}
if (autoReset)
{
Reset();
NextCombo(operation);
}
return false;
}
/// <summary>
/// 直接设置连招节点
/// </summary>
/// <param name="index">节点索引</param>
public void SetCombo(int index)
{
lastNode = currentNode;
currentNode = nodes[index];
}
/// <summary>
/// 直接设置连招节点
/// </summary>
/// <param name="refName">节点引用名称</param>
public void SetCombo(string refName)
{
lastNode = currentNode;
currentNode = nodes.Find(x => x.referenceName == refName);
}
/// <summary>
/// 回退到上一个连招节点
/// </summary>
public void RevertCombo()
{
currentNode = lastNode;
}
}
public partial class ComboTree
{
2025-11-25 08:19:33 -05:00
[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;
}
}
}
}
}