阶段 S3 - 收口出战合法性
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
using System.Text;
|
||||
using GameFramework.Event;
|
||||
using GameFramework.Fsm;
|
||||
using GameFramework.Procedure;
|
||||
@@ -30,6 +31,22 @@ namespace GeometryTD.Procedure
|
||||
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(
|
||||
@@ -95,6 +112,140 @@ 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 "不满足当前参战条件。";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class ProcedureMain : ProcedureBase
|
||||
{
|
||||
public override bool UseNativeDialog => false;
|
||||
@@ -314,9 +465,13 @@ namespace GeometryTD.Procedure
|
||||
{
|
||||
case RunNodeType.Combat:
|
||||
case RunNodeType.BossCombat:
|
||||
if (!HasAvailableParticipantTower())
|
||||
ProcedureMainCombatEntryValidationResult validationResult =
|
||||
ProcedureMainCombatEntryValidationService.Validate(
|
||||
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null);
|
||||
if (!validationResult.CanEnterCombat)
|
||||
{
|
||||
Log.Warning("ProcedureMain blocked combat start. No participant tower is available.");
|
||||
LogCombatEntryBlocked(currentNode, validationResult);
|
||||
OpenBlockedCombatDialog(validationResult);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -348,6 +503,51 @@ namespace GeometryTD.Procedure
|
||||
}
|
||||
}
|
||||
|
||||
private void OpenBlockedCombatDialog(ProcedureMainCombatEntryValidationResult validationResult)
|
||||
{
|
||||
GameEntry.UIRouter.CloseUI(UIFormType.DialogForm);
|
||||
GameEntry.UIRouter.OpenUI(
|
||||
UIFormType.DialogForm,
|
||||
ProcedureMainCombatEntryValidationService.BuildBlockedCombatDialogRawData(validationResult));
|
||||
}
|
||||
|
||||
private void LogCombatEntryBlocked(
|
||||
RunNodeState currentNode,
|
||||
ProcedureMainCombatEntryValidationResult validationResult)
|
||||
{
|
||||
switch (validationResult?.BlockReason)
|
||||
{
|
||||
case ProcedureMainCombatEntryBlockReason.InventoryUnavailable:
|
||||
Log.Warning(
|
||||
"ProcedureMain blocked combat start. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}, Reason={4}.",
|
||||
_currentRunState?.RunId,
|
||||
currentNode?.NodeId ?? 0,
|
||||
currentNode?.NodeType ?? RunNodeType.None,
|
||||
currentNode?.SequenceIndex ?? -1,
|
||||
ProcedureMainCombatEntryBlockReason.InventoryUnavailable);
|
||||
return;
|
||||
case ProcedureMainCombatEntryBlockReason.NoValidParticipantTower:
|
||||
Log.Warning(
|
||||
"ProcedureMain blocked combat start. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}, Reason={4}, InvalidParticipantTowers={5}.",
|
||||
_currentRunState?.RunId,
|
||||
currentNode?.NodeId ?? 0,
|
||||
currentNode?.NodeType ?? RunNodeType.None,
|
||||
currentNode?.SequenceIndex ?? -1,
|
||||
ProcedureMainCombatEntryBlockReason.NoValidParticipantTower,
|
||||
ProcedureMainCombatEntryValidationService.BuildInvalidParticipantTowerLog(
|
||||
validationResult.ValidationSummary));
|
||||
return;
|
||||
default:
|
||||
Log.Warning(
|
||||
"ProcedureMain blocked combat start. RunId={0}, NodeId={1}, NodeType={2}, SequenceIndex={3}, Reason=Unknown.",
|
||||
_currentRunState?.RunId,
|
||||
currentNode?.NodeId ?? 0,
|
||||
currentNode?.NodeType ?? RunNodeType.None,
|
||||
currentNode?.SequenceIndex ?? -1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleRunAdvanceResult(ProcedureMainRunAdvanceResult result)
|
||||
{
|
||||
switch (result)
|
||||
@@ -375,12 +575,6 @@ namespace GeometryTD.Procedure
|
||||
}
|
||||
}
|
||||
|
||||
private static bool HasAvailableParticipantTower()
|
||||
{
|
||||
return GameEntry.PlayerInventory != null &&
|
||||
GameEntry.PlayerInventory.GetParticipantTowerSnapshot().Count > 0;
|
||||
}
|
||||
|
||||
private void EnterHubFlow()
|
||||
{
|
||||
_flowPhase = ProcedureMainFlowPhase.Hub;
|
||||
|
||||
Reference in New Issue
Block a user