S4-07 process 2
当前 `Tag.txt -> DRTag -> TagGenerationRuleRegistry` 已形成组件 Tag 生成规则闭环: - `InventoryTagRuleService` 不再主要依赖内部 `MinRarity` 硬编码,而是统一消费 `DRTag` 提供的 `MinRarity + Weight` - `ShopFormUseCase`、`EnemyDropResolver`、`InventorySeedUtility` 也已切回这一统一入口。 - 现阶段的职责边界明确为:`Tag.txt` 负责基础字典与生成规则,`TagConfig.txt` 负责触发阶段、描述与效果参数。
This commit is contained in:
@@ -204,6 +204,15 @@ namespace GeometryTD.Procedure
|
||||
TagConfigRegistry.LoadFromRows(tagConfigTable.GetAllDataRows());
|
||||
}
|
||||
}
|
||||
|
||||
if (ne.DataTableAssetName == AssetUtility.GetDataTableAsset("Tag", false))
|
||||
{
|
||||
var tagTable = GameEntry.DataTable.GetDataTable<DRTag>();
|
||||
if (tagTable != null)
|
||||
{
|
||||
TagGenerationRuleRegistry.LoadFromRows(tagTable.GetAllDataRows());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLoadDataTableFailure(object sender, GameEventArgs e)
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f18d07456c02b1546b198ed25ba69e18
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+4
-240
@@ -1,4 +1,3 @@
|
||||
using System.Text;
|
||||
using GameFramework.Event;
|
||||
using GameFramework.Fsm;
|
||||
using GameFramework.Procedure;
|
||||
@@ -9,243 +8,6 @@ using UnityGameFramework.Runtime;
|
||||
|
||||
namespace GeometryTD.Procedure
|
||||
{
|
||||
public enum ProcedureMainFlowPhase
|
||||
{
|
||||
Hub = 0,
|
||||
NodeActive = 1,
|
||||
RunCompletedPendingFinish = 2
|
||||
}
|
||||
|
||||
public enum ProcedureMainRunAdvanceResult
|
||||
{
|
||||
NoChange = 0,
|
||||
NodeException = 1,
|
||||
AdvancedToNextNode = 2,
|
||||
RunCompleted = 3
|
||||
}
|
||||
|
||||
public enum ProcedureMainRunCompletionResult
|
||||
{
|
||||
NoChange = 0,
|
||||
ShowCompletionDialog = 1,
|
||||
ReturnToMenu = 2
|
||||
}
|
||||
|
||||
public enum ProcedureMainCombatEntryBlockReason
|
||||
{
|
||||
None = 0,
|
||||
InventoryUnavailable = 1,
|
||||
NoValidParticipantTower = 2
|
||||
}
|
||||
|
||||
public sealed class ProcedureMainCombatEntryValidationResult
|
||||
{
|
||||
public bool CanEnterCombat => BlockReason == ProcedureMainCombatEntryBlockReason.None;
|
||||
|
||||
public ProcedureMainCombatEntryBlockReason BlockReason { get; set; }
|
||||
|
||||
public CombatParticipantTowerValidationSummary ValidationSummary { get; set; }
|
||||
}
|
||||
|
||||
public static class ProcedureMainRunFlowService
|
||||
{
|
||||
public static ProcedureMainRunAdvanceResult TryAdvanceRun(
|
||||
RunState runState,
|
||||
RunNodeCompletionStatus completionStatus,
|
||||
BackpackInventoryData snapshot)
|
||||
{
|
||||
if (!RunStateAdvanceService.TryCompleteCurrentNode(runState, completionStatus, snapshot))
|
||||
{
|
||||
return ProcedureMainRunAdvanceResult.NoChange;
|
||||
}
|
||||
|
||||
if (runState != null && runState.IsCompleted)
|
||||
{
|
||||
return ProcedureMainRunAdvanceResult.RunCompleted;
|
||||
}
|
||||
|
||||
return completionStatus == RunNodeCompletionStatus.Exception
|
||||
? ProcedureMainRunAdvanceResult.NodeException
|
||||
: ProcedureMainRunAdvanceResult.AdvancedToNextNode;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProcedureMainRunCompletionService
|
||||
{
|
||||
public static ProcedureMainRunCompletionResult TryEnterCompletedPendingFinish(bool isCompletionDialogShown)
|
||||
{
|
||||
return isCompletionDialogShown
|
||||
? ProcedureMainRunCompletionResult.NoChange
|
||||
: ProcedureMainRunCompletionResult.ShowCompletionDialog;
|
||||
}
|
||||
|
||||
public static ProcedureMainRunCompletionResult TryConfirmReturnToMenu(
|
||||
ProcedureMainFlowPhase flowPhase,
|
||||
bool isReturnToMenuPending)
|
||||
{
|
||||
if (flowPhase != ProcedureMainFlowPhase.RunCompletedPendingFinish || isReturnToMenuPending)
|
||||
{
|
||||
return ProcedureMainRunCompletionResult.NoChange;
|
||||
}
|
||||
|
||||
return ProcedureMainRunCompletionResult.ReturnToMenu;
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProcedureMainNodeEventGuardService
|
||||
{
|
||||
public static bool MatchesCurrentNode(
|
||||
RunState runState,
|
||||
int nodeId,
|
||||
RunNodeType nodeType,
|
||||
int sequenceIndex)
|
||||
{
|
||||
RunNodeState currentNode = runState?.CurrentNode;
|
||||
if (currentNode == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (nodeId <= 0 || nodeId == currentNode.NodeId) &&
|
||||
(nodeType == RunNodeType.None || nodeType == currentNode.NodeType) &&
|
||||
(sequenceIndex < 0 || sequenceIndex == currentNode.SequenceIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public static class ProcedureMainCombatEntryValidationService
|
||||
{
|
||||
public static ProcedureMainCombatEntryValidationResult Validate(BackpackInventoryData inventory)
|
||||
{
|
||||
if (inventory == null)
|
||||
{
|
||||
return new ProcedureMainCombatEntryValidationResult
|
||||
{
|
||||
BlockReason = ProcedureMainCombatEntryBlockReason.InventoryUnavailable,
|
||||
ValidationSummary = new CombatParticipantTowerValidationSummary()
|
||||
};
|
||||
}
|
||||
|
||||
CombatParticipantTowerValidationSummary summary =
|
||||
CombatParticipantTowerValidationService.ValidateParticipantTowers(inventory);
|
||||
|
||||
return new ProcedureMainCombatEntryValidationResult
|
||||
{
|
||||
BlockReason = summary.HasAnyValidParticipantTower
|
||||
? ProcedureMainCombatEntryBlockReason.None
|
||||
: ProcedureMainCombatEntryBlockReason.NoValidParticipantTower,
|
||||
ValidationSummary = summary
|
||||
};
|
||||
}
|
||||
|
||||
public static string BuildInvalidParticipantTowerLog(
|
||||
CombatParticipantTowerValidationSummary summary)
|
||||
{
|
||||
if (summary?.InvalidResults == null || summary.InvalidResults.Count <= 0)
|
||||
{
|
||||
return "none";
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < summary.InvalidResults.Count; i++)
|
||||
{
|
||||
CombatParticipantTowerValidationResult result = summary.InvalidResults[i];
|
||||
if (result == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (builder.Length > 0)
|
||||
{
|
||||
builder.Append(", ");
|
||||
}
|
||||
|
||||
builder.Append('#');
|
||||
builder.Append(result.TowerInstanceId);
|
||||
builder.Append(':');
|
||||
builder.Append(result.FailureReason);
|
||||
}
|
||||
|
||||
return builder.Length > 0 ? builder.ToString() : "none";
|
||||
}
|
||||
|
||||
public static DialogFormRawData BuildBlockedCombatDialogRawData(
|
||||
ProcedureMainCombatEntryValidationResult validationResult)
|
||||
{
|
||||
return new DialogFormRawData
|
||||
{
|
||||
Mode = 1,
|
||||
Title = "无法进入战斗",
|
||||
Message = BuildBlockedCombatDialogMessage(validationResult),
|
||||
PauseGame = false,
|
||||
ConfirmText = "知道了"
|
||||
};
|
||||
}
|
||||
|
||||
private static string BuildBlockedCombatDialogMessage(
|
||||
ProcedureMainCombatEntryValidationResult validationResult)
|
||||
{
|
||||
if (validationResult == null)
|
||||
{
|
||||
return "当前无法确认出战信息,请稍后重试。";
|
||||
}
|
||||
|
||||
switch (validationResult.BlockReason)
|
||||
{
|
||||
case ProcedureMainCombatEntryBlockReason.InventoryUnavailable:
|
||||
return "当前无法读取库存快照,暂时不能进入战斗。请重新进入本轮流程后再试。";
|
||||
case ProcedureMainCombatEntryBlockReason.NoValidParticipantTower:
|
||||
return BuildNoValidParticipantTowerMessage(validationResult.ValidationSummary);
|
||||
default:
|
||||
return "当前出战校验未通过,暂时不能进入战斗。";
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildNoValidParticipantTowerMessage(
|
||||
CombatParticipantTowerValidationSummary summary)
|
||||
{
|
||||
if (summary?.InvalidResults == null || summary.InvalidResults.Count <= 0)
|
||||
{
|
||||
return "参战区至少需要 1 座完整装配了枪口、轴承、底座的塔,才能进入战斗。";
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.Append("参战区没有可出战的完整塔。");
|
||||
for (int i = 0; i < summary.InvalidResults.Count; i++)
|
||||
{
|
||||
CombatParticipantTowerValidationResult result = summary.InvalidResults[i];
|
||||
if (result == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.Append('\n');
|
||||
builder.Append("塔 #");
|
||||
builder.Append(result.TowerInstanceId);
|
||||
builder.Append(' ');
|
||||
builder.Append(GetFailureReasonMessage(result.FailureReason));
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static string GetFailureReasonMessage(CombatParticipantTowerValidationFailureReason failureReason)
|
||||
{
|
||||
switch (failureReason)
|
||||
{
|
||||
case CombatParticipantTowerValidationFailureReason.TowerMissing:
|
||||
return "已不存在,无法参战。";
|
||||
case CombatParticipantTowerValidationFailureReason.MissingMuzzleComponent:
|
||||
return "缺少枪口组件。";
|
||||
case CombatParticipantTowerValidationFailureReason.MissingBearingComponent:
|
||||
return "缺少轴承组件。";
|
||||
case CombatParticipantTowerValidationFailureReason.MissingBaseComponent:
|
||||
return "缺少底座组件。";
|
||||
default:
|
||||
return "不满足当前参战条件。";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcedureMain : ProcedureBase
|
||||
{
|
||||
public override bool UseNativeDialog => false;
|
||||
@@ -467,7 +229,9 @@ namespace GeometryTD.Procedure
|
||||
case RunNodeType.BossCombat:
|
||||
ProcedureMainCombatEntryValidationResult validationResult =
|
||||
ProcedureMainCombatEntryValidationService.Validate(
|
||||
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null);
|
||||
GameEntry.PlayerInventory != null
|
||||
? GameEntry.PlayerInventory.GetInventorySnapshot()
|
||||
: null);
|
||||
if (!validationResult.CanEnterCombat)
|
||||
{
|
||||
LogCombatEntryBlocked(currentNode, validationResult);
|
||||
@@ -659,4 +423,4 @@ namespace GeometryTD.Procedure
|
||||
_isReturnToMenuPending = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
using GeometryTD.Definition;
|
||||
|
||||
namespace GeometryTD.Procedure
|
||||
{
|
||||
public sealed class ProcedureMainCombatEntryValidationResult
|
||||
{
|
||||
public bool CanEnterCombat => BlockReason == ProcedureMainCombatEntryBlockReason.None;
|
||||
|
||||
public ProcedureMainCombatEntryBlockReason BlockReason { get; set; }
|
||||
|
||||
public CombatParticipantTowerValidationSummary ValidationSummary { get; set; }
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5699aa9933294974875bfce1d34d1d4b
|
||||
timeCreated: 1773198121
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
using System.Text;
|
||||
using GeometryTD.Definition;
|
||||
using GeometryTD.UI;
|
||||
|
||||
namespace GeometryTD.Procedure
|
||||
{
|
||||
public static class ProcedureMainCombatEntryValidationService
|
||||
{
|
||||
public static ProcedureMainCombatEntryValidationResult Validate(BackpackInventoryData inventory)
|
||||
{
|
||||
if (inventory == null)
|
||||
{
|
||||
return new ProcedureMainCombatEntryValidationResult
|
||||
{
|
||||
BlockReason = ProcedureMainCombatEntryBlockReason.InventoryUnavailable,
|
||||
ValidationSummary = new CombatParticipantTowerValidationSummary()
|
||||
};
|
||||
}
|
||||
|
||||
CombatParticipantTowerValidationSummary summary =
|
||||
CombatParticipantTowerValidationService.ValidateParticipantTowers(inventory);
|
||||
|
||||
return new ProcedureMainCombatEntryValidationResult
|
||||
{
|
||||
BlockReason = summary.HasAnyValidParticipantTower
|
||||
? ProcedureMainCombatEntryBlockReason.None
|
||||
: ProcedureMainCombatEntryBlockReason.NoValidParticipantTower,
|
||||
ValidationSummary = summary
|
||||
};
|
||||
}
|
||||
|
||||
public static string BuildInvalidParticipantTowerLog(
|
||||
CombatParticipantTowerValidationSummary summary)
|
||||
{
|
||||
if (summary?.InvalidResults == null || summary.InvalidResults.Count <= 0)
|
||||
{
|
||||
return "none";
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < summary.InvalidResults.Count; i++)
|
||||
{
|
||||
CombatParticipantTowerValidationResult result = summary.InvalidResults[i];
|
||||
if (result == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (builder.Length > 0)
|
||||
{
|
||||
builder.Append(", ");
|
||||
}
|
||||
|
||||
builder.Append('#');
|
||||
builder.Append(result.TowerInstanceId);
|
||||
builder.Append(':');
|
||||
builder.Append(result.FailureReason);
|
||||
}
|
||||
|
||||
return builder.Length > 0 ? builder.ToString() : "none";
|
||||
}
|
||||
|
||||
public static DialogFormRawData BuildBlockedCombatDialogRawData(
|
||||
ProcedureMainCombatEntryValidationResult validationResult)
|
||||
{
|
||||
return new DialogFormRawData
|
||||
{
|
||||
Mode = 1,
|
||||
Title = "无法进入战斗",
|
||||
Message = BuildBlockedCombatDialogMessage(validationResult),
|
||||
PauseGame = false,
|
||||
ConfirmText = "知道了"
|
||||
};
|
||||
}
|
||||
|
||||
private static string BuildBlockedCombatDialogMessage(
|
||||
ProcedureMainCombatEntryValidationResult validationResult)
|
||||
{
|
||||
if (validationResult == null)
|
||||
{
|
||||
return "当前无法确认出战信息,请稍后重试。";
|
||||
}
|
||||
|
||||
switch (validationResult.BlockReason)
|
||||
{
|
||||
case ProcedureMainCombatEntryBlockReason.InventoryUnavailable:
|
||||
return "当前无法读取库存快照,暂时不能进入战斗。请重新进入本轮流程后再试。";
|
||||
case ProcedureMainCombatEntryBlockReason.NoValidParticipantTower:
|
||||
return BuildNoValidParticipantTowerMessage(validationResult.ValidationSummary);
|
||||
default:
|
||||
return "当前出战校验未通过,暂时不能进入战斗。";
|
||||
}
|
||||
}
|
||||
|
||||
private static string BuildNoValidParticipantTowerMessage(
|
||||
CombatParticipantTowerValidationSummary summary)
|
||||
{
|
||||
if (summary?.InvalidResults == null || summary.InvalidResults.Count <= 0)
|
||||
{
|
||||
return "参战区至少需要 1 座完整装配了枪口、轴承、底座的塔,才能进入战斗。";
|
||||
}
|
||||
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.Append("参战区没有可出战的完整塔。");
|
||||
for (int i = 0; i < summary.InvalidResults.Count; i++)
|
||||
{
|
||||
CombatParticipantTowerValidationResult result = summary.InvalidResults[i];
|
||||
if (result == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
builder.Append('\n');
|
||||
builder.Append("塔 #");
|
||||
builder.Append(result.TowerInstanceId);
|
||||
builder.Append(' ');
|
||||
builder.Append(GetFailureReasonMessage(result.FailureReason));
|
||||
}
|
||||
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
private static string GetFailureReasonMessage(CombatParticipantTowerValidationFailureReason failureReason)
|
||||
{
|
||||
switch (failureReason)
|
||||
{
|
||||
case CombatParticipantTowerValidationFailureReason.TowerMissing:
|
||||
return "已不存在,无法参战。";
|
||||
case CombatParticipantTowerValidationFailureReason.MissingMuzzleComponent:
|
||||
return "缺少枪口组件。";
|
||||
case CombatParticipantTowerValidationFailureReason.MissingBearingComponent:
|
||||
return "缺少轴承组件。";
|
||||
case CombatParticipantTowerValidationFailureReason.MissingBaseComponent:
|
||||
return "缺少底座组件。";
|
||||
default:
|
||||
return "不满足当前参战条件。";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: be3e90d1a1874e26af6d1555c301aa26
|
||||
timeCreated: 1773198334
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace GeometryTD.Procedure
|
||||
{
|
||||
public static class ProcedureMainNodeEventGuardService
|
||||
{
|
||||
public static bool MatchesCurrentNode(
|
||||
RunState runState,
|
||||
int nodeId,
|
||||
RunNodeType nodeType,
|
||||
int sequenceIndex)
|
||||
{
|
||||
RunNodeState currentNode = runState?.CurrentNode;
|
||||
if (currentNode == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return (nodeId <= 0 || nodeId == currentNode.NodeId) &&
|
||||
(nodeType == RunNodeType.None || nodeType == currentNode.NodeType) &&
|
||||
(sequenceIndex < 0 || sequenceIndex == currentNode.SequenceIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 212a0e12be2248bf9415a779414312a1
|
||||
timeCreated: 1773198194
|
||||
@@ -0,0 +1,26 @@
|
||||
using GeometryTD.Definition;
|
||||
|
||||
namespace GeometryTD.Procedure
|
||||
{
|
||||
public static class ProcedureMainRunCompletionService
|
||||
{
|
||||
public static ProcedureMainRunCompletionResult TryEnterCompletedPendingFinish(bool isCompletionDialogShown)
|
||||
{
|
||||
return isCompletionDialogShown
|
||||
? ProcedureMainRunCompletionResult.NoChange
|
||||
: ProcedureMainRunCompletionResult.ShowCompletionDialog;
|
||||
}
|
||||
|
||||
public static ProcedureMainRunCompletionResult TryConfirmReturnToMenu(
|
||||
ProcedureMainFlowPhase flowPhase,
|
||||
bool isReturnToMenuPending)
|
||||
{
|
||||
if (flowPhase != ProcedureMainFlowPhase.RunCompletedPendingFinish || isReturnToMenuPending)
|
||||
{
|
||||
return ProcedureMainRunCompletionResult.NoChange;
|
||||
}
|
||||
|
||||
return ProcedureMainRunCompletionResult.ReturnToMenu;
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d565626cc594843989da76a623a1698
|
||||
timeCreated: 1773198165
|
||||
@@ -0,0 +1,27 @@
|
||||
using GeometryTD.Definition;
|
||||
|
||||
namespace GeometryTD.Procedure
|
||||
{
|
||||
public static class ProcedureMainRunFlowService
|
||||
{
|
||||
public static ProcedureMainRunAdvanceResult TryAdvanceRun(
|
||||
RunState runState,
|
||||
RunNodeCompletionStatus completionStatus,
|
||||
BackpackInventoryData snapshot)
|
||||
{
|
||||
if (!RunStateAdvanceService.TryCompleteCurrentNode(runState, completionStatus, snapshot))
|
||||
{
|
||||
return ProcedureMainRunAdvanceResult.NoChange;
|
||||
}
|
||||
|
||||
if (runState != null && runState.IsCompleted)
|
||||
{
|
||||
return ProcedureMainRunAdvanceResult.RunCompleted;
|
||||
}
|
||||
|
||||
return completionStatus == RunNodeCompletionStatus.Exception
|
||||
? ProcedureMainRunAdvanceResult.NodeException
|
||||
: ProcedureMainRunAdvanceResult.AdvancedToNextNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f62dcb2d97fe4f0c884e6eab3d500edf
|
||||
timeCreated: 1773198145
|
||||
Reference in New Issue
Block a user