using System; using System.Collections.Generic; using GeometryTD.CustomUtility; using GeometryTD.Definition; using GeometryTD.Factory; namespace GeometryTD.Procedure { public enum RunNodeType { None = 0, Combat = 1, Event = 2, Shop = 3, BossCombat = 4 } public enum RunNodeStatus { Locked = 0, Available = 1, Completed = 2, Exception = 3, Skipped = 4 } public enum RunNodeCompletionStatus { None = 0, Completed = 1, Exception = 2 } [Serializable] public sealed class RunNodeSeed { public int NodeId { get; set; } public RunNodeType NodeType { get; set; } public LevelThemeType ThemeType { get; set; } public int LinkedLevelId { get; set; } public int SequenceIndex { get; set; } = -1; } [Serializable] public sealed class RunNodeState { public int NodeId { get; internal set; } public RunNodeType NodeType { get; internal set; } public LevelThemeType ThemeType { get; internal set; } public int LinkedLevelId { get; internal set; } public RunNodeStatus Status { get; internal set; } public int SequenceIndex { get; internal set; } internal RunNodeState Clone() { return new RunNodeState { NodeId = NodeId, NodeType = NodeType, ThemeType = ThemeType, LinkedLevelId = LinkedLevelId, Status = Status, SequenceIndex = SequenceIndex }; } } [Serializable] public sealed class RunState { private readonly List _nodes; internal RunState( string runId, int runSeed, LevelThemeType themeType, List nodes, BackpackInventoryData runInventorySnapshot) { RunId = string.IsNullOrWhiteSpace(runId) ? Guid.NewGuid().ToString("N") : runId; RunSeed = runSeed == 0 ? RunStateFactory.CreateRunSeed() : runSeed; ThemeType = themeType; _nodes = nodes ?? new List(); RunInventorySnapshot = InventoryCloneUtility.CloneInventory(runInventorySnapshot); CurrentNodeIndex = _nodes.Count > 0 ? 0 : -1; IsCompleted = _nodes.Count <= 0; } public string RunId { get; internal set; } public int RunSeed { get; internal set; } public LevelThemeType ThemeType { get; internal set; } public int CurrentNodeIndex { get; internal set; } public bool IsCompleted { get; internal set; } public BackpackInventoryData RunInventorySnapshot { get; internal set; } public IReadOnlyList Nodes => _nodes; public int NodeCount => _nodes.Count; public RunNodeState CurrentNode { get { if (CurrentNodeIndex < 0 || CurrentNodeIndex >= _nodes.Count) { return null; } return _nodes[CurrentNodeIndex]; } } 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 { get { int count = 0; foreach (var nodeState in _nodes) { if (nodeState.Status == RunNodeStatus.Completed) { count++; } } return count; } } internal void ReplaceInventorySnapshot(BackpackInventoryData inventorySnapshot) { RunInventorySnapshot = InventoryCloneUtility.CloneInventory(inventorySnapshot); } } }