补充事件参数 + 完善 UI 设计
- 事件节点在 EventNodeComponent.cs 的 StartEvent/EndEvent 会携带 runId/nodeId/nodeType/sequenceIndex - 商店节点在 ShopNodeComponent.cs 也会带同一套字段 - 战斗节点通过 CombatNodeComponent.cs 把上下文传进 CombatScheduler,再由 CombatRunningPhaseState.cs 发 NodeEnterEventArgs、由 CombatSchedulerFlowCoordinator.cs 发 NodeCompleteEventArgs - NodeCompleteEventArgs.cs 现在新增了 SequenceIndex - 各种 UI 的覆盖问题
This commit is contained in:
parent
5c6f9bf3a4
commit
47ed27bebb
|
|
@ -5,8 +5,8 @@
|
||||||
100 主菜单 MenuForm Medium False True
|
100 主菜单 MenuForm Medium False True
|
||||||
101 设置 SettingForm Medium False True
|
101 设置 SettingForm Medium False True
|
||||||
102 关于 AboutForm Medium False True
|
102 关于 AboutForm Medium False True
|
||||||
110 主界面 MainForm Medium False True
|
110 主界面 MainForm Medium False False
|
||||||
111 仓库UI RepoForm Medium False True
|
111 仓库UI RepoForm Medium False False
|
||||||
112 大地图UI NodeMapForm Medium False True
|
112 大地图UI NodeMapForm Medium False True
|
||||||
113 详细信息 ItemDescForm Medium True False
|
113 详细信息 ItemDescForm Medium True False
|
||||||
114 奖励选择UI RewardSelectForm Medium False True
|
114 奖励选择UI RewardSelectForm Medium False True
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using GameFramework.DataTable;
|
||||||
using GeometryTD.CustomEvent;
|
using GeometryTD.CustomEvent;
|
||||||
using GeometryTD.DataTable;
|
using GeometryTD.DataTable;
|
||||||
using GeometryTD.Definition;
|
using GeometryTD.Definition;
|
||||||
|
using GeometryTD.Procedure;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityGameFramework.Runtime;
|
using UnityGameFramework.Runtime;
|
||||||
|
|
||||||
|
|
@ -174,7 +175,12 @@ namespace GeometryTD.CustomComponent
|
||||||
EnsureCombatRuntimeInitialized();
|
EnsureCombatRuntimeInitialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartCombat(int levelId = 0)
|
public void StartCombat(
|
||||||
|
int levelId = 0,
|
||||||
|
string runId = null,
|
||||||
|
int nodeId = 0,
|
||||||
|
RunNodeType nodeType = RunNodeType.None,
|
||||||
|
int sequenceIndex = -1)
|
||||||
{
|
{
|
||||||
if (!EnsureCombatRuntimeInitialized())
|
if (!EnsureCombatRuntimeInitialized())
|
||||||
{
|
{
|
||||||
|
|
@ -221,7 +227,14 @@ namespace GeometryTD.CustomComponent
|
||||||
LastDefeatedEnemyCount = 0;
|
LastDefeatedEnemyCount = 0;
|
||||||
LastGainedCoin = 0;
|
LastGainedCoin = 0;
|
||||||
LastGainedGold = 0;
|
LastGainedGold = 0;
|
||||||
if (!_combatScheduler.Start(selectedLevel, phaseList, _selectedSpawnEntriesByPhaseId))
|
if (!_combatScheduler.Start(
|
||||||
|
selectedLevel,
|
||||||
|
phaseList,
|
||||||
|
_selectedSpawnEntriesByPhaseId,
|
||||||
|
runId,
|
||||||
|
nodeId,
|
||||||
|
nodeType,
|
||||||
|
sequenceIndex))
|
||||||
{
|
{
|
||||||
CurrentLevel = null;
|
CurrentLevel = null;
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ using GeometryTD.CustomEvent;
|
||||||
using GeometryTD.DataTable;
|
using GeometryTD.DataTable;
|
||||||
using GeometryTD.Definition;
|
using GeometryTD.Definition;
|
||||||
using GeometryTD.Entity;
|
using GeometryTD.Entity;
|
||||||
|
using GeometryTD.Procedure;
|
||||||
using GeometryTD.UI;
|
using GeometryTD.UI;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityGameFramework.Runtime;
|
using UnityGameFramework.Runtime;
|
||||||
|
|
@ -67,7 +68,11 @@ namespace GeometryTD.CustomComponent
|
||||||
public bool Start(
|
public bool Start(
|
||||||
DRLevel level,
|
DRLevel level,
|
||||||
IReadOnlyList<DRLevelPhase> phases,
|
IReadOnlyList<DRLevelPhase> phases,
|
||||||
IReadOnlyDictionary<int, IReadOnlyList<DRLevelSpawnEntry>> spawnEntriesByPhaseId)
|
IReadOnlyDictionary<int, IReadOnlyList<DRLevelSpawnEntry>> spawnEntriesByPhaseId,
|
||||||
|
string runId = null,
|
||||||
|
int nodeId = 0,
|
||||||
|
RunNodeType nodeType = RunNodeType.None,
|
||||||
|
int sequenceIndex = -1)
|
||||||
{
|
{
|
||||||
if (!_initialized || _context.Entity == null)
|
if (!_initialized || _context.Entity == null)
|
||||||
{
|
{
|
||||||
|
|
@ -89,6 +94,10 @@ namespace GeometryTD.CustomComponent
|
||||||
_context.IsFinishAsVictory = true;
|
_context.IsFinishAsVictory = true;
|
||||||
|
|
||||||
_context.CurrentLevel = level;
|
_context.CurrentLevel = level;
|
||||||
|
_context.RunId = runId;
|
||||||
|
_context.NodeId = nodeId;
|
||||||
|
_context.NodeType = nodeType;
|
||||||
|
_context.SequenceIndex = sequenceIndex;
|
||||||
_context.CombatInRunResourceManager.InitializeForCombat(level);
|
_context.CombatInRunResourceManager.InitializeForCombat(level);
|
||||||
for (int i = 0; i < phases.Count; i++)
|
for (int i = 0; i < phases.Count; i++)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System.Collections.Generic;
|
||||||
using GeometryTD.CustomEvent;
|
using GeometryTD.CustomEvent;
|
||||||
using GeometryTD.DataTable;
|
using GeometryTD.DataTable;
|
||||||
using GeometryTD.Definition;
|
using GeometryTD.Definition;
|
||||||
|
using GeometryTD.Procedure;
|
||||||
using GeometryTD.UI;
|
using GeometryTD.UI;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityGameFramework.Runtime;
|
using UnityGameFramework.Runtime;
|
||||||
|
|
@ -55,6 +56,10 @@ namespace GeometryTD.CustomComponent
|
||||||
_context.IsFinishAsVictory = true;
|
_context.IsFinishAsVictory = true;
|
||||||
_context.IsCompleted = false;
|
_context.IsCompleted = false;
|
||||||
_context.NodeEnterFired = false;
|
_context.NodeEnterFired = false;
|
||||||
|
_context.RunId = null;
|
||||||
|
_context.NodeId = 0;
|
||||||
|
_context.NodeType = RunNodeType.None;
|
||||||
|
_context.SequenceIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CleanupAllCombatEntities()
|
public void CleanupAllCombatEntities()
|
||||||
|
|
@ -196,7 +201,15 @@ namespace GeometryTD.CustomComponent
|
||||||
public void CompleteNormalCombatAndNotify(bool succeeded)
|
public void CompleteNormalCombatAndNotify(bool succeeded)
|
||||||
{
|
{
|
||||||
CompleteCombat(succeeded);
|
CompleteCombat(succeeded);
|
||||||
GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create());
|
GameEntry.Event.Fire(
|
||||||
|
this,
|
||||||
|
NodeCompleteEventArgs.Create(
|
||||||
|
_context.RunId,
|
||||||
|
_context.NodeId,
|
||||||
|
_context.NodeType,
|
||||||
|
_context.SequenceIndex,
|
||||||
|
succeeded,
|
||||||
|
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CompleteFailureCombatAndNotify()
|
public void CompleteFailureCombatAndNotify()
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using GeometryTD.DataTable;
|
using GeometryTD.DataTable;
|
||||||
using GeometryTD.Entity;
|
using GeometryTD.Entity;
|
||||||
|
using GeometryTD.Procedure;
|
||||||
using GeometryTD.UI;
|
using GeometryTD.UI;
|
||||||
using UnityGameFramework.Runtime;
|
using UnityGameFramework.Runtime;
|
||||||
|
|
||||||
|
|
@ -29,5 +30,9 @@ namespace GeometryTD.CustomComponent
|
||||||
public bool IsCompleted { get; set; }
|
public bool IsCompleted { get; set; }
|
||||||
public bool NodeEnterFired { get; set; }
|
public bool NodeEnterFired { get; set; }
|
||||||
public CombatSettlementContext SettlementContext { get; set; }
|
public CombatSettlementContext SettlementContext { get; set; }
|
||||||
|
public string RunId { get; set; }
|
||||||
|
public int NodeId { get; set; }
|
||||||
|
public RunNodeType NodeType { get; set; }
|
||||||
|
public int SequenceIndex { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,13 @@ namespace GeometryTD.CustomComponent
|
||||||
if (!Context.NodeEnterFired)
|
if (!Context.NodeEnterFired)
|
||||||
{
|
{
|
||||||
Context.NodeEnterFired = true;
|
Context.NodeEnterFired = true;
|
||||||
GameEntry.Event.Fire(Flow, NodeEnterEventArgs.Create());
|
GameEntry.Event.Fire(
|
||||||
|
Flow,
|
||||||
|
NodeEnterEventArgs.Create(
|
||||||
|
Context.RunId,
|
||||||
|
Context.NodeId,
|
||||||
|
Context.NodeType,
|
||||||
|
Context.SequenceIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.Info(
|
Log.Info(
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ using GameFramework.DataTable;
|
||||||
using GeometryTD.CustomEvent;
|
using GeometryTD.CustomEvent;
|
||||||
using GeometryTD.DataTable;
|
using GeometryTD.DataTable;
|
||||||
using GeometryTD.Definition;
|
using GeometryTD.Definition;
|
||||||
|
using GeometryTD.Procedure;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using GeometryTD.UI;
|
using GeometryTD.UI;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
@ -12,6 +13,11 @@ namespace GeometryTD.CustomComponent
|
||||||
{
|
{
|
||||||
public class EventNodeComponent : GameFrameworkComponent
|
public class EventNodeComponent : GameFrameworkComponent
|
||||||
{
|
{
|
||||||
|
private string _activeRunId;
|
||||||
|
private int _activeNodeId;
|
||||||
|
private RunNodeType _activeNodeType = RunNodeType.None;
|
||||||
|
private int _activeSequenceIndex = -1;
|
||||||
|
|
||||||
private readonly List<EventItem> _eventItems = new List<EventItem>();
|
private readonly List<EventItem> _eventItems = new List<EventItem>();
|
||||||
|
|
||||||
private EventFormUseCase _eventFormUseCase;
|
private EventFormUseCase _eventFormUseCase;
|
||||||
|
|
@ -47,7 +53,7 @@ namespace GeometryTD.CustomComponent
|
||||||
Log.Info("EventNodeComponent initialized with {0} events.", _eventItems.Count);
|
Log.Info("EventNodeComponent initialized with {0} events.", _eventItems.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartEvent()
|
public void StartEvent(string runId = null, int nodeId = 0, RunNodeType nodeType = RunNodeType.None, int sequenceIndex = -1)
|
||||||
{
|
{
|
||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
{
|
{
|
||||||
|
|
@ -69,15 +75,36 @@ namespace GeometryTD.CustomComponent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_activeRunId = runId;
|
||||||
|
_activeNodeId = nodeId;
|
||||||
|
_activeNodeType = nodeType;
|
||||||
|
_activeSequenceIndex = sequenceIndex;
|
||||||
_eventFormUseCase.SetCurrentEvent(randomEvent);
|
_eventFormUseCase.SetCurrentEvent(randomEvent);
|
||||||
GameEntry.UIRouter.OpenUI(UIFormType.EventForm);
|
GameEntry.UIRouter.OpenUI(UIFormType.EventForm);
|
||||||
GameEntry.Event.Fire(this, NodeEnterEventArgs.Create());
|
GameEntry.Event.Fire(this, NodeEnterEventArgs.Create(runId, nodeId, nodeType, sequenceIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EndEvent()
|
public void EndEvent()
|
||||||
{
|
{
|
||||||
GameEntry.UIRouter.CloseUI(UIFormType.EventForm);
|
GameEntry.UIRouter.CloseUI(UIFormType.EventForm);
|
||||||
GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create());
|
GameEntry.Event.Fire(
|
||||||
|
this,
|
||||||
|
NodeCompleteEventArgs.Create(
|
||||||
|
_activeRunId,
|
||||||
|
_activeNodeId,
|
||||||
|
_activeNodeType,
|
||||||
|
_activeSequenceIndex,
|
||||||
|
true,
|
||||||
|
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null));
|
||||||
|
ClearActiveNodeContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearActiveNodeContext()
|
||||||
|
{
|
||||||
|
_activeRunId = null;
|
||||||
|
_activeNodeId = 0;
|
||||||
|
_activeNodeType = RunNodeType.None;
|
||||||
|
_activeSequenceIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static EventOption[] ParseOptions(string optionsRaw)
|
private static EventOption[] ParseOptions(string optionsRaw)
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,17 @@ using GeometryTD.UI;
|
||||||
using UnityGameFramework.Runtime;
|
using UnityGameFramework.Runtime;
|
||||||
using GeometryTD.CustomEvent;
|
using GeometryTD.CustomEvent;
|
||||||
using GeometryTD.Definition;
|
using GeometryTD.Definition;
|
||||||
|
using GeometryTD.Procedure;
|
||||||
|
|
||||||
namespace GeometryTD.CustomComponent
|
namespace GeometryTD.CustomComponent
|
||||||
{
|
{
|
||||||
public class ShopNodeComponent : GameFrameworkComponent
|
public class ShopNodeComponent : GameFrameworkComponent
|
||||||
{
|
{
|
||||||
|
private string _activeRunId;
|
||||||
|
private int _activeNodeId;
|
||||||
|
private RunNodeType _activeNodeType = RunNodeType.None;
|
||||||
|
private int _activeSequenceIndex = -1;
|
||||||
|
|
||||||
private ShopFormUseCase _shopFormUseCase;
|
private ShopFormUseCase _shopFormUseCase;
|
||||||
private bool _initialized;
|
private bool _initialized;
|
||||||
|
|
||||||
|
|
@ -22,7 +28,7 @@ namespace GeometryTD.CustomComponent
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void StartShop()
|
public void StartShop(string runId = null, int nodeId = 0, RunNodeType nodeType = RunNodeType.None, int sequenceIndex = -1)
|
||||||
{
|
{
|
||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
{
|
{
|
||||||
|
|
@ -35,14 +41,35 @@ namespace GeometryTD.CustomComponent
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_activeRunId = runId;
|
||||||
|
_activeNodeId = nodeId;
|
||||||
|
_activeNodeType = nodeType;
|
||||||
|
_activeSequenceIndex = sequenceIndex;
|
||||||
GameEntry.UIRouter.OpenUI(UIFormType.ShopForm);
|
GameEntry.UIRouter.OpenUI(UIFormType.ShopForm);
|
||||||
GameEntry.Event.Fire(this, NodeEnterEventArgs.Create());
|
GameEntry.Event.Fire(this, NodeEnterEventArgs.Create(runId, nodeId, nodeType, sequenceIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EndShop()
|
public void EndShop()
|
||||||
{
|
{
|
||||||
GameEntry.UIRouter.CloseUI(UIFormType.ShopForm);
|
GameEntry.UIRouter.CloseUI(UIFormType.ShopForm);
|
||||||
GameEntry.Event.Fire(this, NodeCompleteEventArgs.Create());
|
GameEntry.Event.Fire(
|
||||||
|
this,
|
||||||
|
NodeCompleteEventArgs.Create(
|
||||||
|
_activeRunId,
|
||||||
|
_activeNodeId,
|
||||||
|
_activeNodeType,
|
||||||
|
_activeSequenceIndex,
|
||||||
|
true,
|
||||||
|
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null));
|
||||||
|
ClearActiveNodeContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ClearActiveNodeContext()
|
||||||
|
{
|
||||||
|
_activeRunId = null;
|
||||||
|
_activeNodeId = 0;
|
||||||
|
_activeNodeType = RunNodeType.None;
|
||||||
|
_activeSequenceIndex = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ namespace GeometryTD.CustomEvent
|
||||||
|
|
||||||
public RunNodeType NodeType { get; private set; }
|
public RunNodeType NodeType { get; private set; }
|
||||||
|
|
||||||
|
public int SequenceIndex { get; private set; }
|
||||||
|
|
||||||
public bool Succeeded { get; private set; }
|
public bool Succeeded { get; private set; }
|
||||||
|
|
||||||
public BackpackInventoryData InventorySnapshotAfterNode { get; private set; }
|
public BackpackInventoryData InventorySnapshotAfterNode { get; private set; }
|
||||||
|
|
@ -28,13 +30,14 @@ namespace GeometryTD.CustomEvent
|
||||||
|
|
||||||
public static NodeCompleteEventArgs Create()
|
public static NodeCompleteEventArgs Create()
|
||||||
{
|
{
|
||||||
return Create(null, 0, RunNodeType.None, true, null);
|
return Create(null, 0, RunNodeType.None, -1, true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NodeCompleteEventArgs Create(
|
public static NodeCompleteEventArgs Create(
|
||||||
string runId,
|
string runId,
|
||||||
int nodeId,
|
int nodeId,
|
||||||
RunNodeType nodeType,
|
RunNodeType nodeType,
|
||||||
|
int sequenceIndex,
|
||||||
bool succeeded,
|
bool succeeded,
|
||||||
BackpackInventoryData inventorySnapshotAfterNode)
|
BackpackInventoryData inventorySnapshotAfterNode)
|
||||||
{
|
{
|
||||||
|
|
@ -42,6 +45,7 @@ namespace GeometryTD.CustomEvent
|
||||||
args.RunId = runId;
|
args.RunId = runId;
|
||||||
args.NodeId = nodeId;
|
args.NodeId = nodeId;
|
||||||
args.NodeType = nodeType;
|
args.NodeType = nodeType;
|
||||||
|
args.SequenceIndex = sequenceIndex;
|
||||||
args.Succeeded = succeeded;
|
args.Succeeded = succeeded;
|
||||||
args.InventorySnapshotAfterNode = InventoryCloneUtility.CloneInventory(inventorySnapshotAfterNode);
|
args.InventorySnapshotAfterNode = InventoryCloneUtility.CloneInventory(inventorySnapshotAfterNode);
|
||||||
|
|
||||||
|
|
@ -53,6 +57,7 @@ namespace GeometryTD.CustomEvent
|
||||||
RunId = null;
|
RunId = null;
|
||||||
NodeId = 0;
|
NodeId = 0;
|
||||||
NodeType = RunNodeType.None;
|
NodeType = RunNodeType.None;
|
||||||
|
SequenceIndex = -1;
|
||||||
Succeeded = false;
|
Succeeded = false;
|
||||||
InventorySnapshotAfterNode = null;
|
InventorySnapshotAfterNode = null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,45 @@ namespace GeometryTD.Procedure
|
||||||
|
|
||||||
private void OnNodeEnter(object sender, GameEventArgs e)
|
private void OnNodeEnter(object sender, GameEventArgs e)
|
||||||
{
|
{
|
||||||
if (!(e is NodeEnterEventArgs))
|
if (!(e is NodeEnterEventArgs args))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(args.RunId) &&
|
||||||
|
_currentRunState != null &&
|
||||||
|
!string.Equals(args.RunId, _currentRunState.RunId))
|
||||||
|
{
|
||||||
|
Log.Warning(
|
||||||
|
"ProcedureMain.OnNodeEnter() ignored. EventRunId={0}, CurrentRunId={1}.",
|
||||||
|
args.RunId,
|
||||||
|
_currentRunState.RunId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunNodeState currentNode = _currentRunState?.CurrentNode;
|
||||||
|
if (currentNode != null &&
|
||||||
|
((args.NodeId > 0 && args.NodeId != currentNode.NodeId) ||
|
||||||
|
(args.NodeType != RunNodeType.None && args.NodeType != currentNode.NodeType) ||
|
||||||
|
(args.SequenceIndex >= 0 && args.SequenceIndex != currentNode.SequenceIndex)))
|
||||||
|
{
|
||||||
|
Log.Warning(
|
||||||
|
"ProcedureMain.OnNodeEnter() node mismatch. EventNodeId={0}, EventNodeType={1}, EventSequenceIndex={2}; CurrentNodeId={3}, CurrentNodeType={4}, CurrentSequenceIndex={5}.",
|
||||||
|
args.NodeId,
|
||||||
|
args.NodeType,
|
||||||
|
args.SequenceIndex,
|
||||||
|
currentNode.NodeId,
|
||||||
|
currentNode.NodeType,
|
||||||
|
currentNode.SequenceIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.Info(
|
||||||
|
"ProcedureMain.OnNodeEnter() accepted. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}.",
|
||||||
|
string.IsNullOrWhiteSpace(args.RunId) ? _currentRunState?.RunId : args.RunId,
|
||||||
|
args.NodeId,
|
||||||
|
args.NodeType,
|
||||||
|
args.SequenceIndex);
|
||||||
|
|
||||||
GameEntry.UIRouter.CloseUI(UIFormType.NodeMapForm);
|
GameEntry.UIRouter.CloseUI(UIFormType.NodeMapForm);
|
||||||
GameEntry.UIRouter.CloseUI(UIFormType.MainForm);
|
GameEntry.UIRouter.CloseUI(UIFormType.MainForm);
|
||||||
}
|
}
|
||||||
|
|
@ -94,13 +128,24 @@ namespace GeometryTD.Procedure
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(args.RunId) &&
|
||||||
|
_currentRunState != null &&
|
||||||
|
!string.Equals(args.RunId, _currentRunState.RunId))
|
||||||
|
{
|
||||||
|
Log.Warning(
|
||||||
|
"ProcedureMain.OnNodeComplete() ignored. EventRunId={0}, CurrentRunId={1}.",
|
||||||
|
args.RunId,
|
||||||
|
_currentRunState.RunId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BackpackInventoryData snapshot = args.InventorySnapshotAfterNode;
|
BackpackInventoryData snapshot = args.InventorySnapshotAfterNode;
|
||||||
if (snapshot == null && GameEntry.PlayerInventory != null)
|
if (snapshot == null && GameEntry.PlayerInventory != null)
|
||||||
{
|
{
|
||||||
snapshot = GameEntry.PlayerInventory.GetInventorySnapshot();
|
snapshot = GameEntry.PlayerInventory.GetInventorySnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
AdvanceRunState(true, snapshot);
|
AdvanceRunState(args.Succeeded, snapshot);
|
||||||
OpenHubUI();
|
OpenHubUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -153,16 +198,30 @@ namespace GeometryTD.Procedure
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GameEntry.CombatNode.StartCombat(currentNode.LinkedLevelId);
|
GameEntry.CombatNode.StartCombat(
|
||||||
|
currentNode.LinkedLevelId,
|
||||||
|
_currentRunState.RunId,
|
||||||
|
currentNode.NodeId,
|
||||||
|
currentNode.NodeType,
|
||||||
|
currentNode.SequenceIndex);
|
||||||
return;
|
return;
|
||||||
case RunNodeType.Event:
|
case RunNodeType.Event:
|
||||||
GameEntry.EventNode.StartEvent();
|
GameEntry.EventNode.StartEvent(
|
||||||
|
_currentRunState.RunId,
|
||||||
|
currentNode.NodeId,
|
||||||
|
currentNode.NodeType,
|
||||||
|
currentNode.SequenceIndex);
|
||||||
return;
|
return;
|
||||||
case RunNodeType.Shop:
|
case RunNodeType.Shop:
|
||||||
GameEntry.ShopNode.StartShop();
|
GameEntry.ShopNode.StartShop(
|
||||||
|
_currentRunState.RunId,
|
||||||
|
currentNode.NodeId,
|
||||||
|
currentNode.NodeType,
|
||||||
|
currentNode.SequenceIndex);
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
Log.Warning("ProcedureMain.OnNodeMapNodeEnterRequested() encountered unsupported node type: {0}.", currentNode.NodeType);
|
Log.Warning("ProcedureMain.OnNodeMapNodeEnterRequested() encountered unsupported node type: {0}.",
|
||||||
|
currentNode.NodeType);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -206,8 +265,8 @@ namespace GeometryTD.Procedure
|
||||||
private void OpenHubUI()
|
private void OpenHubUI()
|
||||||
{
|
{
|
||||||
_nodeMapFormUseCase?.SetRunState(_currentRunState);
|
_nodeMapFormUseCase?.SetRunState(_currentRunState);
|
||||||
GameEntry.UIRouter.OpenUI(UIFormType.MainForm);
|
|
||||||
GameEntry.UIRouter.OpenUI(UIFormType.NodeMapForm);
|
GameEntry.UIRouter.OpenUI(UIFormType.NodeMapForm);
|
||||||
|
GameEntry.UIRouter.OpenUI(UIFormType.MainForm);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -108,6 +108,7 @@ namespace GeometryTD.Tests.Editor
|
||||||
"run-1",
|
"run-1",
|
||||||
7,
|
7,
|
||||||
RunNodeType.Shop,
|
RunNodeType.Shop,
|
||||||
|
3,
|
||||||
true,
|
true,
|
||||||
inventory);
|
inventory);
|
||||||
|
|
||||||
|
|
@ -116,6 +117,7 @@ namespace GeometryTD.Tests.Editor
|
||||||
Assert.That(eventArgs.RunId, Is.EqualTo("run-1"));
|
Assert.That(eventArgs.RunId, Is.EqualTo("run-1"));
|
||||||
Assert.That(eventArgs.NodeId, Is.EqualTo(7));
|
Assert.That(eventArgs.NodeId, Is.EqualTo(7));
|
||||||
Assert.That(eventArgs.NodeType, Is.EqualTo(RunNodeType.Shop));
|
Assert.That(eventArgs.NodeType, Is.EqualTo(RunNodeType.Shop));
|
||||||
|
Assert.That(eventArgs.SequenceIndex, Is.EqualTo(3));
|
||||||
Assert.That(eventArgs.Succeeded, Is.True);
|
Assert.That(eventArgs.Succeeded, Is.True);
|
||||||
Assert.That(eventArgs.InventorySnapshotAfterNode.Gold, Is.EqualTo(66));
|
Assert.That(eventArgs.InventorySnapshotAfterNode.Gold, Is.EqualTo(66));
|
||||||
|
|
||||||
|
|
@ -124,6 +126,7 @@ namespace GeometryTD.Tests.Editor
|
||||||
Assert.That(eventArgs.RunId, Is.Null);
|
Assert.That(eventArgs.RunId, Is.Null);
|
||||||
Assert.That(eventArgs.NodeId, Is.EqualTo(0));
|
Assert.That(eventArgs.NodeId, Is.EqualTo(0));
|
||||||
Assert.That(eventArgs.NodeType, Is.EqualTo(RunNodeType.None));
|
Assert.That(eventArgs.NodeType, Is.EqualTo(RunNodeType.None));
|
||||||
|
Assert.That(eventArgs.SequenceIndex, Is.EqualTo(-1));
|
||||||
Assert.That(eventArgs.Succeeded, Is.False);
|
Assert.That(eventArgs.Succeeded, Is.False);
|
||||||
Assert.That(eventArgs.InventorySnapshotAfterNode, Is.Null);
|
Assert.That(eventArgs.InventorySnapshotAfterNode, Is.Null);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,12 +208,12 @@ PrefabInstance:
|
||||||
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SizeDelta.x
|
propertyPath: m_SizeDelta.x
|
||||||
value: 200
|
value: 160
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SizeDelta.y
|
propertyPath: m_SizeDelta.y
|
||||||
value: 200
|
value: 160
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
|
@ -275,6 +275,26 @@ PrefabInstance:
|
||||||
propertyPath: m_LocalEulerAnglesHint.z
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_SizeDelta.x
|
||||||
|
value: -30
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_SizeDelta.y
|
||||||
|
value: -30
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
|
|
@ -372,12 +392,12 @@ PrefabInstance:
|
||||||
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SizeDelta.x
|
propertyPath: m_SizeDelta.x
|
||||||
value: 200
|
value: 160
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
type: 3}
|
type: 3}
|
||||||
propertyPath: m_SizeDelta.y
|
propertyPath: m_SizeDelta.y
|
||||||
value: 200
|
value: 160
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
type: 3}
|
type: 3}
|
||||||
|
|
@ -439,6 +459,26 @@ PrefabInstance:
|
||||||
propertyPath: m_LocalEulerAnglesHint.z
|
propertyPath: m_LocalEulerAnglesHint.z
|
||||||
value: 0
|
value: 0
|
||||||
objectReference: {fileID: 0}
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_SizeDelta.x
|
||||||
|
value: -30
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_SizeDelta.y
|
||||||
|
value: -30
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.x
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
|
- target: {fileID: 7744090569424522082, guid: 2307f223279813546a43b221ddd496cc,
|
||||||
|
type: 3}
|
||||||
|
propertyPath: m_AnchoredPosition.y
|
||||||
|
value: 0
|
||||||
|
objectReference: {fileID: 0}
|
||||||
m_RemovedComponents: []
|
m_RemovedComponents: []
|
||||||
m_RemovedGameObjects: []
|
m_RemovedGameObjects: []
|
||||||
m_AddedGameObjects: []
|
m_AddedGameObjects: []
|
||||||
|
|
|
||||||
|
|
@ -999,7 +999,7 @@ MonoBehaviour:
|
||||||
m_Name:
|
m_Name:
|
||||||
m_EditorClassIdentifier:
|
m_EditorClassIdentifier:
|
||||||
m_Material: {fileID: 0}
|
m_Material: {fileID: 0}
|
||||||
m_Color: {r: 0.2, g: 0.2, b: 0.2, a: 0.5019608}
|
m_Color: {r: 0.2, g: 0.2, b: 0.2, a: 0.8}
|
||||||
m_RaycastTarget: 1
|
m_RaycastTarget: 1
|
||||||
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
|
||||||
m_Maskable: 1
|
m_Maskable: 1
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
和上一版相比,仓库已经把 Run 相关基础件进一步接到了 `ProcedureMain`,因此这份清单不再把重点放在“有没有 Run 模型”,而是聚焦下面这几个真实阻塞项:
|
和上一版相比,仓库已经把 Run 相关基础件进一步接到了 `ProcedureMain`,因此这份清单不再把重点放在“有没有 Run 模型”,而是聚焦下面这几个真实阻塞项:
|
||||||
|
|
||||||
- 已有 `ProcedureMain + TestMenuForm` 的临时 Run 推进闭环,但还没有正式节点地图 / 节点面板。
|
- 已有 `ProcedureMain + NodeMapForm` 的临时 Run 推进闭环,正式节点面板骨架已经接入流程。
|
||||||
- 固定 10 节点顺序已经开始驱动战斗 / 事件 / 商店入口,但节点事件上下文仍然是空载版本。
|
- 固定 10 节点顺序已经开始驱动战斗 / 事件 / 商店入口,但节点事件上下文仍然是空载版本。
|
||||||
- 出战入口已有“至少有参战塔”的最小校验,但还没收口成严格的最终合法性约束。
|
- 出战入口已有“至少有参战塔”的最小校验,但还没收口成严格的最终合法性约束。
|
||||||
- 品质 / Tag / 耐久仍然停留在部分实现状态,尚未和 M1 范围完全对齐。
|
- 品质 / Tag / 耐久仍然停留在部分实现状态,尚未和 M1 范围完全对齐。
|
||||||
|
|
@ -90,25 +90,42 @@
|
||||||
- `Assets/GameMain/Scripts/UI/Shop/Controller/ShopFormController.cs`
|
- `Assets/GameMain/Scripts/UI/Shop/Controller/ShopFormController.cs`
|
||||||
- `Assets/GameMain/Scripts/UI/Shop/View/ShopForm.cs`
|
- `Assets/GameMain/Scripts/UI/Shop/View/ShopForm.cs`
|
||||||
|
|
||||||
|
### 7. `NodeMapForm` 五层 UI 已经接入主流程
|
||||||
|
|
||||||
|
- 已新增 `NodeMapFormRawData / UseCase / Controller / Context / View` 和 `NodeItemContext / NodeItem`。
|
||||||
|
- `ProcedureMain` 已不再打开 `TestMenuForm`,而是打开 `NodeMapForm` 作为 Hub 节点入口。
|
||||||
|
- `NodeMapFormController` 会把 `NodeItem` 点击转换为 `NodeMapNodeEnterRequestedEventArgs`,再交给流程层决定是否进入节点。
|
||||||
|
- `NodeItem` 的 `Icon` 已改成通过 `SpriteCacheComponent` 按资源名异步获取,`Bg` 负责表示节点状态。
|
||||||
|
|
||||||
|
关键文件:
|
||||||
|
- `Assets/GameMain/Scripts/UI/Game/RawData/NodeMapFormRawData.cs`
|
||||||
|
- `Assets/GameMain/Scripts/UI/Game/UseCase/NodeMapFormUseCase.cs`
|
||||||
|
- `Assets/GameMain/Scripts/UI/Game/Controller/NodeMapFormController.cs`
|
||||||
|
- `Assets/GameMain/Scripts/UI/Game/Context/NodeMapFormContext.cs`
|
||||||
|
- `Assets/GameMain/Scripts/UI/Game/Context/NodeItemContext.cs`
|
||||||
|
- `Assets/GameMain/Scripts/UI/Game/View/NodeMapForm.cs`
|
||||||
|
- `Assets/GameMain/Scripts/UI/Game/View/NodeItem.cs`
|
||||||
|
- `Assets/GameMain/Scripts/Event/Game/NodeMapNodeEnterRequestedEventArgs.cs`
|
||||||
|
|
||||||
## 当前未完成
|
## 当前未完成
|
||||||
|
|
||||||
### 1. Run 主流程已经形成临时闭环,但还不是正式节点 UI
|
### 1. Run 主流程已经形成基于 `NodeMapForm` 的临时闭环,但还没完全收口
|
||||||
|
|
||||||
- `ProcedureMain` 进入后会创建 Run,并打开 `MainForm + TestMenuForm`。
|
- `ProcedureMain` 进入后会创建 Run,并打开 `MainForm + NodeMapForm`。
|
||||||
- `TestMenuForm` 已不再同时提供三种节点入口,而是通过 `TestMenuFormContext.CurrentNodeType` 只显示当前节点对应的唯一按钮。
|
- `NodeMapForm` 已经有五层结构,`NodeItem` 也能按当前 `RunState` 刷出 10 个节点。
|
||||||
- 点击按钮后由 `ProcedureMain` 根据当前 `RunState.CurrentNode` 决定是否允许进入战斗 / 事件 / 商店。
|
- 点击当前节点后,由 `NodeMapFormController` 发出 `NodeMapNodeEnterRequestedEventArgs`,再由 `ProcedureMain` 根据当前 `RunState.CurrentNode` 决定是否允许进入战斗 / 事件 / 商店。
|
||||||
- 节点完成或战斗失败后,`ProcedureMain` 会推进 `RunState`,再重新打开 Hub UI。
|
- 节点完成或战斗失败后,`ProcedureMain` 会推进 `RunState`,再重新打开 Hub UI。
|
||||||
- 因此当前已经能从开始游戏后按固定顺序推进一局的临时版本。
|
- 因此当前已经不是“测试菜单三选一”,而是“节点地图单入口”的临时版本。
|
||||||
|
|
||||||
当前缺口:
|
当前缺口:
|
||||||
- UI 仍是测试面板,不是正式节点地图或正式节点信息面板。
|
- `NodeMapForm` 已接入,但当前仍偏 MVP 骨架,缺节点连线、节点说明、Boss 特效等正式表现。
|
||||||
- `TestMenuFormContext` 目前只传 `CurrentNodeType`,还没有显示节点序号、总数、Boss 标记等关键信息。
|
- `NodeMapFormContext` 当前只提供基础进度和当前节点信息,还没有更完整的地图展示上下文。
|
||||||
- Run 完成后的正式结算 / 收尾表现仍未建立。
|
- Run 完成后的正式结算 / 收尾表现仍未建立。
|
||||||
|
|
||||||
关键文件:
|
关键文件:
|
||||||
- `Assets/GameMain/Scripts/Procedure/ProcedureMain.cs`
|
- `Assets/GameMain/Scripts/Procedure/ProcedureMain.cs`
|
||||||
- `Assets/GameMain/Scripts/UI/Menu/View/TestMenuForm.cs`
|
- `Assets/GameMain/Scripts/UI/Game/View/NodeMapForm.cs`
|
||||||
- `Assets/GameMain/Scripts/UI/Menu/Controller/TestMenuFormController.cs`
|
- `Assets/GameMain/Scripts/UI/Game/Controller/NodeMapFormController.cs`
|
||||||
|
|
||||||
### 2. 固定 10 节点序列已开始驱动真实流程,但上下文仍不完整
|
### 2. 固定 10 节点序列已开始驱动真实流程,但上下文仍不完整
|
||||||
|
|
||||||
|
|
@ -131,7 +148,7 @@
|
||||||
|
|
||||||
- 现在可以单独打开商店、随机生成组件、购买并退出。
|
- 现在可以单独打开商店、随机生成组件、购买并退出。
|
||||||
- 商店结束后已能通过 `ProcedureMain` 推进当前 `RunState`。
|
- 商店结束后已能通过 `ProcedureMain` 推进当前 `RunState`。
|
||||||
- 但退出后仍是回到 `MainForm + TestMenuForm`,而不是真实节点地图或正式节点选择界面。
|
- 但退出后当前回流的是 `MainForm + NodeMapForm` 的 MVP 节点面板,而不是完整表现版地图。
|
||||||
|
|
||||||
关键文件:
|
关键文件:
|
||||||
- `Assets/GameMain/Scripts/CustomComponent/ShopNodeComponent.cs`
|
- `Assets/GameMain/Scripts/CustomComponent/ShopNodeComponent.cs`
|
||||||
|
|
@ -183,21 +200,21 @@
|
||||||
|
|
||||||
结合静态代码检查,当前更接近下面这个状态:
|
结合静态代码检查,当前更接近下面这个状态:
|
||||||
|
|
||||||
- `P0-04`:基础模型已完成,并已接入 `ProcedureMain` 的临时 Run 闭环。
|
- `P0-04`:基础模型已完成,并已接入 `ProcedureMain + NodeMapForm` 的临时 Run 闭环。
|
||||||
- `P0-05`:固定 10 节点序列已由 builder + `ProcedureMain` 开始驱动实际流程,但缺完整事件上下文与正式节点 UI。
|
- `P0-05`:固定 10 节点序列已由 builder + `ProcedureMain + NodeMapForm` 驱动实际流程,但缺完整事件上下文与地图表现层。
|
||||||
- `P0-06`:节点进入、完成、失败后回 Hub 的临时闭环已存在,但“正式地图/节点界面 + 正式结算”仍未完成。
|
- `P0-06`:节点进入、完成、失败后回 `NodeMapForm` 的临时闭环已存在,但正式地图表现与正式结算仍未完成。
|
||||||
- `P0-10`:未完成。
|
- `P0-10`:未完成。
|
||||||
- `P0-11`:未完成。
|
- `P0-11`:未完成。
|
||||||
- `P0-12`:未完成。
|
- `P0-12`:未完成。
|
||||||
|
|
||||||
换句话说,仓库已经不再是“还没有 Run 模型 / 10 节点 / 商店最小实现”的状态;真正的缺口是“这些能力已经接成临时可跑版本,但还没收口成正式 M1 主流程表现层与上下文系统”。
|
换句话说,仓库已经不再是“还没有 Run 模型 / 10 节点 / 商店最小实现”的状态;真正的缺口是“这些能力已经接成 `NodeMapForm` 驱动的临时可跑版本,但还没收口成正式 M1 主流程表现层与上下文系统”。
|
||||||
|
|
||||||
## 推荐的后续执行顺序
|
## 推荐的后续执行顺序
|
||||||
|
|
||||||
1. 先把临时 Hub 升级成正式节点面板
|
1. 先把临时 Hub 升级成正式节点面板
|
||||||
- 保留 `ProcedureMain` 持有 Run 的做法
|
- 保留 `ProcedureMain` 持有 Run 的做法
|
||||||
- 不再把 `TestMenuForm` 当测试菜单,而是改成正式节点信息面板或节点地图
|
- 继续以 `NodeMapForm` 为基础补正式节点地图表现
|
||||||
- 至少补上当前节点序号、总节点数、节点名称、Boss 标记
|
- 至少补上节点连线、Boss 视觉强调、当前节点说明和完成态反馈
|
||||||
|
|
||||||
2. 再把节点事件改成带上下文的真实推进
|
2. 再把节点事件改成带上下文的真实推进
|
||||||
- `NodeEnterEventArgs` 和 `NodeCompleteEventArgs` 传递 `runId / nodeId / nodeType / sequenceIndex`
|
- `NodeEnterEventArgs` 和 `NodeCompleteEventArgs` 传递 `runId / nodeId / nodeType / sequenceIndex`
|
||||||
|
|
@ -218,7 +235,7 @@
|
||||||
|
|
||||||
## 当前做变更时要记住的约束
|
## 当前做变更时要记住的约束
|
||||||
|
|
||||||
- 不要再把 `TestMenuForm` 维持成“测试菜单”语义。
|
- 不要再把 Hub 退回 `TestMenuForm` 语义。
|
||||||
- 优先补“临时闭环 -> 正式节点 UI / 正式上下文”的收口,不要继续只加单点功能。
|
- 优先补“临时闭环 -> 正式节点 UI / 正式上下文”的收口,不要继续只加单点功能。
|
||||||
- 商店已经接入 Run,下一步重点不是继续扩商店,而是把 Hub/UI 做正式。
|
- 商店已经接入 Run,下一步重点不是继续扩商店,而是把 Hub/UI 做正式。
|
||||||
- 若 M1 最终不做完整耐久 / 红色品质,要先同步文档再改代码目标。
|
- 若 M1 最终不做完整耐久 / 红色品质,要先同步文档再改代码目标。
|
||||||
|
|
@ -233,8 +250,9 @@
|
||||||
- `Assets/GameMain/Scripts/Procedure/RunStateFactory.cs`
|
- `Assets/GameMain/Scripts/Procedure/RunStateFactory.cs`
|
||||||
- `Assets/GameMain/Scripts/Procedure/RunStateAdvanceService.cs`
|
- `Assets/GameMain/Scripts/Procedure/RunStateAdvanceService.cs`
|
||||||
- `Assets/GameMain/Scripts/Procedure/FixedRunNodeSequenceBuilder.cs`
|
- `Assets/GameMain/Scripts/Procedure/FixedRunNodeSequenceBuilder.cs`
|
||||||
- 临时 Hub / 节点入口:
|
- 当前 Hub / 节点入口:
|
||||||
- `Assets/GameMain/Scripts/UI/Menu/Controller/TestMenuFormController.cs`
|
- `Assets/GameMain/Scripts/UI/Game/Controller/NodeMapFormController.cs`
|
||||||
|
- `Assets/GameMain/Scripts/UI/Game/View/NodeMapForm.cs`
|
||||||
- 战斗节点 facade:
|
- 战斗节点 facade:
|
||||||
- `Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatNodeComponent.cs`
|
- `Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatNodeComponent.cs`
|
||||||
- 事件节点:
|
- 事件节点:
|
||||||
|
|
@ -251,4 +269,4 @@
|
||||||
|
|
||||||
- 这份清单基于 2026-03-08 的静态代码检查更新。
|
- 这份清单基于 2026-03-08 的静态代码检查更新。
|
||||||
- 本次已修正上一版中“Run 模型不存在”“10 节点未实现”“商店节点基本未实现”等过期判断。
|
- 本次已修正上一版中“Run 模型不存在”“10 节点未实现”“商店节点基本未实现”等过期判断。
|
||||||
- 当前最值得优先推进的是:`ProcedureMain 继续收口 Run 流程 -> 节点事件带上下文 -> 战斗按节点关卡进入 -> 出战校验`。
|
- 当前最值得优先推进的是:`NodeMapForm 继续收口表现层 -> 节点事件带上下文 -> 战斗按节点关卡进入 -> 出战校验`。
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@
|
||||||
| [x] | P0-01 | 冻结 MVP 范围(只保留:战斗节点/事件节点/商店节点/节点后组装) | `docs/MVP-Scope.md` | 明确“做/不做”清单,团队评审通过 |
|
| [x] | P0-01 | 冻结 MVP 范围(只保留:战斗节点/事件节点/商店节点/节点后组装) | `docs/MVP-Scope.md` | 明确“做/不做”清单,团队评审通过 |
|
||||||
| [x] | P0-02 | 补齐数据表:组件、配件、敌人、波次、节点、事件、商店商品 | `Assets/GameMain/DataTables/*.txt` | 游戏启动可无报错加载全部新增表 |
|
| [x] | P0-02 | 补齐数据表:组件、配件、敌人、波次、节点、事件、商店商品 | `Assets/GameMain/DataTables/*.txt` | 游戏启动可无报错加载全部新增表 |
|
||||||
| [x] | P0-03 | 新增/完善 DataRow 解析类 | `Assets/GameMain/Scripts/DataTable/*.cs` | 每个新增表都有对应 DR 类并成功解析 |
|
| [x] | P0-03 | 新增/完善 DataRow 解析类 | `Assets/GameMain/Scripts/DataTable/*.cs` | 每个新增表都有对应 DR 类并成功解析 |
|
||||||
| [~] | P0-04 | 建立单局 Run 状态模型(金币、生命、库存、当前节点) | `Assets/GameMain/Scripts/Procedure/` | 已有 `RunState` / 推进模型 / 测试,并已接入 `ProcedureMain` 的临时 Run 闭环,但还不是正式节点 UI |
|
| [~] | P0-04 | 建立单局 Run 状态模型(金币、生命、库存、当前节点) | `Assets/GameMain/Scripts/Procedure/` | 已有 `RunState` / 推进模型 / 测试,并已接入 `ProcedureMain + NodeMapForm` 的临时 Run 闭环 |
|
||||||
| [~] | P0-05 | 实现 10 节点地图生成(最后节点固定 Boss) | `Assets/GameMain/Scripts/Procedure/`<br>`Assets/GameMain/Scripts/Scene/` | 已有固定 10 节点序列 builder 与测试,且已开始驱动真实流程,但节点事件上下文与正式节点面板仍未完成 |
|
| [~] | P0-05 | 实现 10 节点地图生成(最后节点固定 Boss) | `Assets/GameMain/Scripts/Procedure/`<br>`Assets/GameMain/Scripts/Scene/` | 已有固定 10 节点序列 builder 与测试,且已由 `NodeMapForm` 驱动节点入口,但节点事件上下文与地图表现层仍未完成 |
|
||||||
| [~] | P0-06 | 实现节点选择与跳转流程(战斗/事件/商店) | `Assets/GameMain/Scripts/Procedure/` | `ProcedureMain + TestMenuForm` 的临时闭环已可推进战斗/事件/商店,但仍缺正式节点地图/节点面板与正式结算收尾 |
|
| [~] | P0-06 | 实现节点选择与跳转流程(战斗/事件/商店) | `Assets/GameMain/Scripts/Procedure/` | `ProcedureMain + NodeMapForm` 的临时闭环已可推进战斗/事件/商店,但仍缺完整地图表现、正式结算收尾与节点上下文回流 |
|
||||||
| [x] | P0-07 | 战斗节点基础玩法:放置塔、出怪、基地扣血、胜负判定 | `Assets/GameMain/Scripts/Entity/`<br>`Assets/GameMain/Scripts/Scene/` | 可完整打一场并得到胜利/失败结果 |
|
| [x] | P0-07 | 战斗节点基础玩法:放置塔、出怪、基地扣血、胜负判定 | `Assets/GameMain/Scripts/Entity/`<br>`Assets/GameMain/Scripts/Scene/` | 可完整打一场并得到胜利/失败结果 |
|
||||||
| [x] | P0-08 | 胜利波次与结算规则(100/80/50/<50) | `Assets/GameMain/Scripts/Procedure/` | 结算奖励与惩罚严格匹配设计文档 |
|
| [x] | P0-08 | 胜利波次与结算规则(100/80/50/<50) | `Assets/GameMain/Scripts/Procedure/` | 结算奖励与惩罚严格匹配设计文档 |
|
||||||
| [x] | P0-09 | 敌人掉落与关卡奖励(组件/配件/金币) | `Assets/GameMain/Scripts/Entity/` | 战斗结束能发放掉落并写入库存 |
|
| [x] | P0-09 | 敌人掉落与关卡奖励(组件/配件/金币) | `Assets/GameMain/Scripts/Entity/` | 战斗结束能发放掉落并写入库存 |
|
||||||
|
|
@ -55,7 +55,7 @@
|
||||||
|
|
||||||
## 本周建议开工顺序
|
## 本周建议开工顺序
|
||||||
|
|
||||||
1. 先把 `P0-04` ~ `P0-06` 从“临时闭环”收口成正式节点面板 / 节点地图,并补齐节点事件上下文
|
1. 先把 `P0-04` ~ `P0-06` 从“`NodeMapForm` 临时闭环”收口成正式节点地图表现,并补齐节点事件上下文
|
||||||
2. 完成 `P0-10`(把“至少有参战塔”提升为“满足完整合法参战条件才能出战”)
|
2. 完成 `P0-10`(把“至少有参战塔”提升为“满足完整合法参战条件才能出战”)
|
||||||
3. 再处理 `P0-11` ~ `P0-12`(品质 / Tag / 耐久是否纳入 M1 需先统一范围)
|
3. 再处理 `P0-11` ~ `P0-12`(品质 / Tag / 耐久是否纳入 M1 需先统一范围)
|
||||||
|
|
||||||
|
|
|
||||||
BIN
数据表/UIForm.xlsx
BIN
数据表/UIForm.xlsx
Binary file not shown.
Loading…
Reference in New Issue