Add event id validation

This commit is contained in:
2026-06-18 12:20:04 +09:00
parent 47754b5d45
commit c3a09d6577
2 changed files with 31 additions and 7 deletions

View File

@@ -462,7 +462,7 @@ Conditions may include `after_event` to stay inactive until a one-shot event has
`post_battle_choices` are shown on the victory result panel after first-time scenario rewards are applied. Each choice needs a unique stable lowercase `id`, a non-empty `label`, and a `set_flags` object whose keys are stable lowercase flag ids. Choices may also grant positive `gold`, known `items`, `join_officers`, and `leave_officers`. When rewards are saved but the player has not selected a choice yet, `CampaignState.pending_post_battle_choice_scenario_id` records that scenario id so reloading the game returns to the victory choice panel instead of skipping the branch. The selected choice is saved to `CampaignState.flags`, `CampaignState.applied_post_battle_choices`, and campaign membership only when the player presses its result-panel button; completed-scenario replays do not show choices again. Save-load migration for older saves uses flags as a conservative choice signal, so avoid designing multiple choices in one scenario that can all match the same saved flag state.
Scenario `events` support `battle_start`, `battle_begin`, `turn_start`, and movement-triggered `unit_reaches_tile` triggers. `battle_begin` runs after the briefing is closed. `unit_reaches_tile` events run when a moved unit enters the zero-based `pos` cell; use `team`, `unit_ids`, or `officer_ids` to limit who can trigger the event. Actions currently include `log`, `dialogue`, `set_objective`, `grant_item`, `grant_items`, `spawn_deployment`, and `spawn_deployments`. Event `dialogue` actions use the same dialogue line format, portrait default rules, and optional `side` placement as `post_battle_dialogue`. Event item grants add to the battle inventory immediately; they persist to the campaign save only when the battle is won.
Scenario `events` support `battle_start`, `battle_begin`, `turn_start`, and movement-triggered `unit_reaches_tile` triggers. Each event needs a stable lowercase `id` that is unique within the scenario; `after_event` conditions can only reference those explicit ids. `battle_begin` runs after the briefing is closed. `unit_reaches_tile` events run when a moved unit enters the zero-based `pos` cell; use `team`, `unit_ids`, or `officer_ids` to limit who can trigger the event. Actions currently include `log`, `dialogue`, `set_objective`, `grant_item`, `grant_items`, `spawn_deployment`, and `spawn_deployments`. Event `dialogue` actions use the same dialogue line format, portrait default rules, and optional `side` placement as `post_battle_dialogue`. Event item grants add to the battle inventory immediately; they persist to the campaign save only when the battle is won.
```json
{

View File

@@ -1408,6 +1408,35 @@ function Check-Post-Battle-Choices($Choices, [string]$ScenarioId) {
}
}
function Check-Event-Ids($Events, [string]$ScenarioId) {
$eventIds = New-Object System.Collections.Generic.HashSet[string]
if ($null -eq $Events) {
return ,$eventIds
}
if (-not ($Events -is [System.Array])) {
Fail "Scenario $ScenarioId events must be an array."
}
foreach ($event in @($Events)) {
if ($event -is [string] -or $event -is [System.Array]) {
Fail "Scenario $ScenarioId has malformed event."
}
if (-not (Has-Prop $event "id")) {
Fail "Scenario $ScenarioId event has empty id."
}
$eventId = [string](Get-Prop $event "id" "")
if ([string]::IsNullOrWhiteSpace($eventId)) {
Fail "Scenario $ScenarioId event has empty id."
}
if (-not ($eventId -match "^[a-z0-9_]+$")) {
Fail "Scenario $ScenarioId event has unstable id: $eventId"
}
if (-not $eventIds.Add($eventId)) {
Fail "Scenario $ScenarioId has duplicate event id: $eventId"
}
}
return ,$eventIds
}
function Check-Required-Flags($RequiredFlags, [string]$ScenarioId, [string]$Context) {
if ($null -eq $RequiredFlags) {
return
@@ -1602,12 +1631,7 @@ foreach ($scenario in $campaign.scenarios) {
}
}
$eventIds = New-Object System.Collections.Generic.HashSet[string]
foreach ($event in (Get-Prop $scenarioData "events" @())) {
if (Has-Prop $event "id") {
$eventIds.Add([string]$event.id) | Out-Null
}
}
$eventIds = Check-Event-Ids (Get-Prop $scenarioData "events" $null) $scenarioId
$knownUnitIds = Collect-Scenario-Unit-Ids $scenarioData
if (Has-Prop $scenarioData "conditions") {