补充事件参数 + 完善 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:
SepComet
2026-03-08 11:51:00 +08:00
parent 5c6f9bf3a4
commit 47ed27bebb
16 changed files with 277 additions and 52 deletions
+2 -2
View File
@@ -5,8 +5,8 @@
100 主菜单 MenuForm Medium False True
101 设置 SettingForm Medium False True
102 关于 AboutForm Medium False True
110 主界面 MainForm Medium False True
111 仓库UI RepoForm Medium False True
110 主界面 MainForm Medium False False
111 仓库UI RepoForm Medium False False
112 大地图UI NodeMapForm Medium False True
113 详细信息 ItemDescForm Medium True False
114 奖励选择UI RewardSelectForm Medium False True
@@ -3,6 +3,7 @@ using GameFramework.DataTable;
using GeometryTD.CustomEvent;
using GeometryTD.DataTable;
using GeometryTD.Definition;
using GeometryTD.Procedure;
using UnityEngine;
using UnityGameFramework.Runtime;
@@ -174,7 +175,12 @@ namespace GeometryTD.CustomComponent
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())
{
@@ -221,7 +227,14 @@ namespace GeometryTD.CustomComponent
LastDefeatedEnemyCount = 0;
LastGainedCoin = 0;
LastGainedGold = 0;
if (!_combatScheduler.Start(selectedLevel, phaseList, _selectedSpawnEntriesByPhaseId))
if (!_combatScheduler.Start(
selectedLevel,
phaseList,
_selectedSpawnEntriesByPhaseId,
runId,
nodeId,
nodeType,
sequenceIndex))
{
CurrentLevel = null;
return;
@@ -4,6 +4,7 @@ using GeometryTD.CustomEvent;
using GeometryTD.DataTable;
using GeometryTD.Definition;
using GeometryTD.Entity;
using GeometryTD.Procedure;
using GeometryTD.UI;
using UnityEngine;
using UnityGameFramework.Runtime;
@@ -67,7 +68,11 @@ namespace GeometryTD.CustomComponent
public bool Start(
DRLevel level,
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)
{
@@ -89,6 +94,10 @@ namespace GeometryTD.CustomComponent
_context.IsFinishAsVictory = true;
_context.CurrentLevel = level;
_context.RunId = runId;
_context.NodeId = nodeId;
_context.NodeType = nodeType;
_context.SequenceIndex = sequenceIndex;
_context.CombatInRunResourceManager.InitializeForCombat(level);
for (int i = 0; i < phases.Count; i++)
{
@@ -2,6 +2,7 @@ using System.Collections.Generic;
using GeometryTD.CustomEvent;
using GeometryTD.DataTable;
using GeometryTD.Definition;
using GeometryTD.Procedure;
using GeometryTD.UI;
using UnityEngine;
using UnityGameFramework.Runtime;
@@ -55,6 +56,10 @@ namespace GeometryTD.CustomComponent
_context.IsFinishAsVictory = true;
_context.IsCompleted = false;
_context.NodeEnterFired = false;
_context.RunId = null;
_context.NodeId = 0;
_context.NodeType = RunNodeType.None;
_context.SequenceIndex = -1;
}
public void CleanupAllCombatEntities()
@@ -196,7 +201,15 @@ namespace GeometryTD.CustomComponent
public void CompleteNormalCombatAndNotify(bool 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()
@@ -2,6 +2,7 @@ using System;
using System.Collections.Generic;
using GeometryTD.DataTable;
using GeometryTD.Entity;
using GeometryTD.Procedure;
using GeometryTD.UI;
using UnityGameFramework.Runtime;
@@ -29,5 +30,9 @@ namespace GeometryTD.CustomComponent
public bool IsCompleted { get; set; }
public bool NodeEnterFired { 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)
{
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(
@@ -3,6 +3,7 @@ using GameFramework.DataTable;
using GeometryTD.CustomEvent;
using GeometryTD.DataTable;
using GeometryTD.Definition;
using GeometryTD.Procedure;
using Newtonsoft.Json.Linq;
using GeometryTD.UI;
using UnityEngine;
@@ -12,6 +13,11 @@ namespace GeometryTD.CustomComponent
{
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 EventFormUseCase _eventFormUseCase;
@@ -47,7 +53,7 @@ namespace GeometryTD.CustomComponent
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)
{
@@ -69,15 +75,36 @@ namespace GeometryTD.CustomComponent
return;
}
_activeRunId = runId;
_activeNodeId = nodeId;
_activeNodeType = nodeType;
_activeSequenceIndex = sequenceIndex;
_eventFormUseCase.SetCurrentEvent(randomEvent);
GameEntry.UIRouter.OpenUI(UIFormType.EventForm);
GameEntry.Event.Fire(this, NodeEnterEventArgs.Create());
GameEntry.Event.Fire(this, NodeEnterEventArgs.Create(runId, nodeId, nodeType, sequenceIndex));
}
public void EndEvent()
{
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)
@@ -2,11 +2,17 @@ using GeometryTD.UI;
using UnityGameFramework.Runtime;
using GeometryTD.CustomEvent;
using GeometryTD.Definition;
using GeometryTD.Procedure;
namespace GeometryTD.CustomComponent
{
public class ShopNodeComponent : GameFrameworkComponent
{
private string _activeRunId;
private int _activeNodeId;
private RunNodeType _activeNodeType = RunNodeType.None;
private int _activeSequenceIndex = -1;
private ShopFormUseCase _shopFormUseCase;
private bool _initialized;
@@ -22,7 +28,7 @@ namespace GeometryTD.CustomComponent
_initialized = true;
}
public void StartShop()
public void StartShop(string runId = null, int nodeId = 0, RunNodeType nodeType = RunNodeType.None, int sequenceIndex = -1)
{
if (!_initialized)
{
@@ -35,14 +41,35 @@ namespace GeometryTD.CustomComponent
return;
}
_activeRunId = runId;
_activeNodeId = nodeId;
_activeNodeType = nodeType;
_activeSequenceIndex = sequenceIndex;
GameEntry.UIRouter.OpenUI(UIFormType.ShopForm);
GameEntry.Event.Fire(this, NodeEnterEventArgs.Create());
GameEntry.Event.Fire(this, NodeEnterEventArgs.Create(runId, nodeId, nodeType, sequenceIndex));
}
public void EndShop()
{
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 int SequenceIndex { get; private set; }
public bool Succeeded { get; private set; }
public BackpackInventoryData InventorySnapshotAfterNode { get; private set; }
@@ -28,13 +30,14 @@ namespace GeometryTD.CustomEvent
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(
string runId,
int nodeId,
RunNodeType nodeType,
int sequenceIndex,
bool succeeded,
BackpackInventoryData inventorySnapshotAfterNode)
{
@@ -42,6 +45,7 @@ namespace GeometryTD.CustomEvent
args.RunId = runId;
args.NodeId = nodeId;
args.NodeType = nodeType;
args.SequenceIndex = sequenceIndex;
args.Succeeded = succeeded;
args.InventorySnapshotAfterNode = InventoryCloneUtility.CloneInventory(inventorySnapshotAfterNode);
@@ -53,6 +57,7 @@ namespace GeometryTD.CustomEvent
RunId = null;
NodeId = 0;
NodeType = RunNodeType.None;
SequenceIndex = -1;
Succeeded = false;
InventorySnapshotAfterNode = null;
}
@@ -78,11 +78,45 @@ namespace GeometryTD.Procedure
private void OnNodeEnter(object sender, GameEventArgs e)
{
if (!(e is NodeEnterEventArgs))
if (!(e is NodeEnterEventArgs args))
{
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.MainForm);
}
@@ -94,13 +128,24 @@ namespace GeometryTD.Procedure
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;
if (snapshot == null && GameEntry.PlayerInventory != null)
{
snapshot = GameEntry.PlayerInventory.GetInventorySnapshot();
}
AdvanceRunState(true, snapshot);
AdvanceRunState(args.Succeeded, snapshot);
OpenHubUI();
}
@@ -153,16 +198,30 @@ namespace GeometryTD.Procedure
return;
}
GameEntry.CombatNode.StartCombat(currentNode.LinkedLevelId);
GameEntry.CombatNode.StartCombat(
currentNode.LinkedLevelId,
_currentRunState.RunId,
currentNode.NodeId,
currentNode.NodeType,
currentNode.SequenceIndex);
return;
case RunNodeType.Event:
GameEntry.EventNode.StartEvent();
GameEntry.EventNode.StartEvent(
_currentRunState.RunId,
currentNode.NodeId,
currentNode.NodeType,
currentNode.SequenceIndex);
return;
case RunNodeType.Shop:
GameEntry.ShopNode.StartShop();
GameEntry.ShopNode.StartShop(
_currentRunState.RunId,
currentNode.NodeId,
currentNode.NodeType,
currentNode.SequenceIndex);
return;
default:
Log.Warning("ProcedureMain.OnNodeMapNodeEnterRequested() encountered unsupported node type: {0}.", currentNode.NodeType);
Log.Warning("ProcedureMain.OnNodeMapNodeEnterRequested() encountered unsupported node type: {0}.",
currentNode.NodeType);
return;
}
}
@@ -206,8 +265,8 @@ namespace GeometryTD.Procedure
private void OpenHubUI()
{
_nodeMapFormUseCase?.SetRunState(_currentRunState);
GameEntry.UIRouter.OpenUI(UIFormType.MainForm);
GameEntry.UIRouter.OpenUI(UIFormType.NodeMapForm);
GameEntry.UIRouter.OpenUI(UIFormType.MainForm);
}
}
}
}
@@ -108,6 +108,7 @@ namespace GeometryTD.Tests.Editor
"run-1",
7,
RunNodeType.Shop,
3,
true,
inventory);
@@ -116,6 +117,7 @@ namespace GeometryTD.Tests.Editor
Assert.That(eventArgs.RunId, Is.EqualTo("run-1"));
Assert.That(eventArgs.NodeId, Is.EqualTo(7));
Assert.That(eventArgs.NodeType, Is.EqualTo(RunNodeType.Shop));
Assert.That(eventArgs.SequenceIndex, Is.EqualTo(3));
Assert.That(eventArgs.Succeeded, Is.True);
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.NodeId, Is.EqualTo(0));
Assert.That(eventArgs.NodeType, Is.EqualTo(RunNodeType.None));
Assert.That(eventArgs.SequenceIndex, Is.EqualTo(-1));
Assert.That(eventArgs.Succeeded, Is.False);
Assert.That(eventArgs.InventorySnapshotAfterNode, Is.Null);
}
+44 -4
View File
@@ -208,12 +208,12 @@ PrefabInstance:
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_SizeDelta.x
value: 200
value: 160
objectReference: {fileID: 0}
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_SizeDelta.y
value: 200
value: 160
objectReference: {fileID: 0}
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
@@ -275,6 +275,26 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 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_RemovedGameObjects: []
m_AddedGameObjects: []
@@ -372,12 +392,12 @@ PrefabInstance:
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_SizeDelta.x
value: 200
value: 160
objectReference: {fileID: 0}
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
propertyPath: m_SizeDelta.y
value: 200
value: 160
objectReference: {fileID: 0}
- target: {fileID: 4491355866364659447, guid: 2307f223279813546a43b221ddd496cc,
type: 3}
@@ -439,6 +459,26 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 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_RemovedGameObjects: []
m_AddedGameObjects: []
+1 -1
View File
@@ -999,7 +999,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
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_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1