固定 10 节点大关的生成层,但还没有接入主流程
- 新增了 FixedRunNodeSequenceBuilder.cs,现在 Plain 主题会固定生成 1战 2事 3战 4店 5战 6事 7战 8店 9事 10Boss。普通战斗节点的 LinkedLevelId 固定映射为 1 -> 2 -> 3 -> 1,第 10 个 Boss 节点固定绑定 Level 4。 - RunStateFactory.cs 增加了 CreateFixedRun(...),可以直接创建带 10 节点固定序列的 RunState。RunModel.cs 也补了几个只读查询:NodeCount、GetNodeBySequenceIndex(...)、IsBossNode(...),方便后面接真实流程。
This commit is contained in:
parent
5afcaafff7
commit
2b86582ff7
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using GeometryTD.Definition;
|
||||||
|
|
||||||
|
namespace GeometryTD.Procedure
|
||||||
|
{
|
||||||
|
public static class FixedRunNodeSequenceBuilder
|
||||||
|
{
|
||||||
|
private const int FixedNodeCount = 10;
|
||||||
|
private static readonly int[] PlainCombatLevelCycle = { 1, 2, 3, 1 };
|
||||||
|
|
||||||
|
public static IReadOnlyList<RunNodeSeed> Build(LevelThemeType themeType)
|
||||||
|
{
|
||||||
|
if (themeType != LevelThemeType.Plain)
|
||||||
|
{
|
||||||
|
return new List<RunNodeSeed>();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<RunNodeSeed> nodeSeeds = new List<RunNodeSeed>(FixedNodeCount)
|
||||||
|
{
|
||||||
|
CreateNodeSeed(1, 0, RunNodeType.Combat, themeType, PlainCombatLevelCycle[0]),
|
||||||
|
CreateNodeSeed(2, 1, RunNodeType.Event, themeType, 0),
|
||||||
|
CreateNodeSeed(3, 2, RunNodeType.Combat, themeType, PlainCombatLevelCycle[1]),
|
||||||
|
CreateNodeSeed(4, 3, RunNodeType.Shop, themeType, 0),
|
||||||
|
CreateNodeSeed(5, 4, RunNodeType.Combat, themeType, PlainCombatLevelCycle[2]),
|
||||||
|
CreateNodeSeed(6, 5, RunNodeType.Event, themeType, 0),
|
||||||
|
CreateNodeSeed(7, 6, RunNodeType.Combat, themeType, PlainCombatLevelCycle[3]),
|
||||||
|
CreateNodeSeed(8, 7, RunNodeType.Shop, themeType, 0),
|
||||||
|
CreateNodeSeed(9, 8, RunNodeType.Event, themeType, 0),
|
||||||
|
CreateNodeSeed(10, 9, RunNodeType.BossCombat, themeType, 4)
|
||||||
|
};
|
||||||
|
|
||||||
|
return nodeSeeds;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static RunNodeSeed CreateNodeSeed(
|
||||||
|
int nodeId,
|
||||||
|
int sequenceIndex,
|
||||||
|
RunNodeType nodeType,
|
||||||
|
LevelThemeType themeType,
|
||||||
|
int linkedLevelId)
|
||||||
|
{
|
||||||
|
return new RunNodeSeed
|
||||||
|
{
|
||||||
|
NodeId = nodeId,
|
||||||
|
SequenceIndex = sequenceIndex,
|
||||||
|
NodeType = nodeType,
|
||||||
|
ThemeType = themeType,
|
||||||
|
LinkedLevelId = linkedLevelId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 650d0ca3526d4b3db552d70292267456
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
|
|
@ -88,6 +88,8 @@ namespace GeometryTD.Procedure
|
||||||
|
|
||||||
public IReadOnlyList<RunNodeState> Nodes => _nodes;
|
public IReadOnlyList<RunNodeState> Nodes => _nodes;
|
||||||
|
|
||||||
|
public int NodeCount => _nodes.Count;
|
||||||
|
|
||||||
public RunNodeState CurrentNode
|
public RunNodeState CurrentNode
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
@ -103,6 +105,29 @@ namespace GeometryTD.Procedure
|
||||||
|
|
||||||
public bool CanEnterCurrentNode => !IsCompleted && CurrentNode != null && CurrentNode.Status == RunNodeStatus.Available;
|
public bool CanEnterCurrentNode => !IsCompleted && CurrentNode != null && CurrentNode.Status == RunNodeStatus.Available;
|
||||||
|
|
||||||
|
public RunNodeState GetNodeBySequenceIndex(int sequenceIndex)
|
||||||
|
{
|
||||||
|
if (sequenceIndex < 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (RunNodeState nodeState in _nodes)
|
||||||
|
{
|
||||||
|
if (nodeState.SequenceIndex == sequenceIndex)
|
||||||
|
{
|
||||||
|
return nodeState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsBossNode(RunNodeState nodeState)
|
||||||
|
{
|
||||||
|
return nodeState != null && nodeState.NodeType == RunNodeType.BossCombat;
|
||||||
|
}
|
||||||
|
|
||||||
public int CompletedNodeCount
|
public int CompletedNodeCount
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,15 @@ namespace GeometryTD.Procedure
|
||||||
{
|
{
|
||||||
public static class RunStateFactory
|
public static class RunStateFactory
|
||||||
{
|
{
|
||||||
|
public static RunState CreateFixedRun(
|
||||||
|
LevelThemeType themeType,
|
||||||
|
BackpackInventoryData initialInventorySnapshot,
|
||||||
|
string runId = null)
|
||||||
|
{
|
||||||
|
IReadOnlyList<RunNodeSeed> fixedNodeSeeds = FixedRunNodeSequenceBuilder.Build(themeType);
|
||||||
|
return Create(themeType, initialInventorySnapshot, fixedNodeSeeds, runId);
|
||||||
|
}
|
||||||
|
|
||||||
public static RunState Create(
|
public static RunState Create(
|
||||||
LevelThemeType themeType,
|
LevelThemeType themeType,
|
||||||
BackpackInventoryData initialInventorySnapshot,
|
BackpackInventoryData initialInventorySnapshot,
|
||||||
|
|
|
||||||
|
|
@ -127,5 +127,75 @@ namespace GeometryTD.Tests.Editor
|
||||||
Assert.That(eventArgs.Succeeded, Is.False);
|
Assert.That(eventArgs.Succeeded, Is.False);
|
||||||
Assert.That(eventArgs.InventorySnapshotAfterNode, Is.Null);
|
Assert.That(eventArgs.InventorySnapshotAfterNode, Is.Null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FixedRunNodeSequenceBuilder_Builds_Plain_Ten_Node_Sequence()
|
||||||
|
{
|
||||||
|
IReadOnlyList<RunNodeSeed> nodeSeeds = FixedRunNodeSequenceBuilder.Build(LevelThemeType.Plain);
|
||||||
|
|
||||||
|
Assert.That(nodeSeeds, Is.Not.Null);
|
||||||
|
Assert.That(nodeSeeds.Count, Is.EqualTo(10));
|
||||||
|
|
||||||
|
Assert.That(nodeSeeds[0].NodeType, Is.EqualTo(RunNodeType.Combat));
|
||||||
|
Assert.That(nodeSeeds[1].NodeType, Is.EqualTo(RunNodeType.Event));
|
||||||
|
Assert.That(nodeSeeds[2].NodeType, Is.EqualTo(RunNodeType.Combat));
|
||||||
|
Assert.That(nodeSeeds[3].NodeType, Is.EqualTo(RunNodeType.Shop));
|
||||||
|
Assert.That(nodeSeeds[4].NodeType, Is.EqualTo(RunNodeType.Combat));
|
||||||
|
Assert.That(nodeSeeds[5].NodeType, Is.EqualTo(RunNodeType.Event));
|
||||||
|
Assert.That(nodeSeeds[6].NodeType, Is.EqualTo(RunNodeType.Combat));
|
||||||
|
Assert.That(nodeSeeds[7].NodeType, Is.EqualTo(RunNodeType.Shop));
|
||||||
|
Assert.That(nodeSeeds[8].NodeType, Is.EqualTo(RunNodeType.Event));
|
||||||
|
Assert.That(nodeSeeds[9].NodeType, Is.EqualTo(RunNodeType.BossCombat));
|
||||||
|
|
||||||
|
Assert.That(nodeSeeds[0].LinkedLevelId, Is.EqualTo(1));
|
||||||
|
Assert.That(nodeSeeds[2].LinkedLevelId, Is.EqualTo(2));
|
||||||
|
Assert.That(nodeSeeds[4].LinkedLevelId, Is.EqualTo(3));
|
||||||
|
Assert.That(nodeSeeds[6].LinkedLevelId, Is.EqualTo(1));
|
||||||
|
Assert.That(nodeSeeds[9].LinkedLevelId, Is.EqualTo(4));
|
||||||
|
Assert.That(nodeSeeds[1].LinkedLevelId, Is.EqualTo(0));
|
||||||
|
Assert.That(nodeSeeds[3].LinkedLevelId, Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void FixedRunNodeSequenceBuilder_Returns_Empty_For_Unsupported_Theme()
|
||||||
|
{
|
||||||
|
IReadOnlyList<RunNodeSeed> nodeSeeds = FixedRunNodeSequenceBuilder.Build(LevelThemeType.Volcano);
|
||||||
|
|
||||||
|
Assert.That(nodeSeeds, Is.Not.Null);
|
||||||
|
Assert.That(nodeSeeds.Count, Is.EqualTo(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void CreateFixedRun_Creates_Ten_Node_Run_And_Completes_After_Ten_Advances()
|
||||||
|
{
|
||||||
|
RunState runState = RunStateFactory.CreateFixedRun(
|
||||||
|
LevelThemeType.Plain,
|
||||||
|
new BackpackInventoryData { Gold = 100 },
|
||||||
|
"fixed-run");
|
||||||
|
|
||||||
|
Assert.That(runState.RunId, Is.EqualTo("fixed-run"));
|
||||||
|
Assert.That(runState.NodeCount, Is.EqualTo(10));
|
||||||
|
Assert.That(runState.CurrentNodeIndex, Is.EqualTo(0));
|
||||||
|
Assert.That(runState.CurrentNode.NodeType, Is.EqualTo(RunNodeType.Combat));
|
||||||
|
Assert.That(runState.Nodes[0].Status, Is.EqualTo(RunNodeStatus.Available));
|
||||||
|
Assert.That(runState.Nodes[9].Status, Is.EqualTo(RunNodeStatus.Locked));
|
||||||
|
Assert.That(runState.GetNodeBySequenceIndex(9), Is.Not.Null);
|
||||||
|
Assert.That(RunState.IsBossNode(runState.GetNodeBySequenceIndex(9)), Is.True);
|
||||||
|
|
||||||
|
for (int i = 0; i < runState.NodeCount; i++)
|
||||||
|
{
|
||||||
|
bool advanced = RunStateAdvanceService.TryCompleteCurrentNode(
|
||||||
|
runState,
|
||||||
|
true,
|
||||||
|
new BackpackInventoryData { Gold = 100 + i });
|
||||||
|
|
||||||
|
Assert.That(advanced, Is.True);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.That(runState.IsCompleted, Is.True);
|
||||||
|
Assert.That(runState.CompletedNodeCount, Is.EqualTo(10));
|
||||||
|
Assert.That(runState.CurrentNodeIndex, Is.EqualTo(10));
|
||||||
|
Assert.That(runState.RunInventorySnapshot.Gold, Is.EqualTo(109));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue