{#each rule.clauses as clause, clauseIndex}
{@const conditionBand = readCurrentHealthPercentBand(clause.if)}
{@const eventFieldCondition = readEventFieldComparison(clause.if)}
{@const registeredPredicateField = selectedEventPredicateField(clause)}
{@const registeredPredicateFields = eventPredicateFields(clause)}
{@const statePoolCondition = readStatePoolThreshold(clause.if)}
setConditionModel(clauseIndex,values[0])}
/>
{#if conditionBand}
{:else if eventFieldCondition}
{#if registeredPredicateFields.length && registeredPredicateField}
({value:field.path,label:field.label.toUpperCase()}))}
value={registeredPredicateField.path}
onchange={(values) => setRegisteredEventField(clauseIndex,values[0])}
/>
{:else}
{/if}
updateEventFieldComparison(clauseIndex,{operator:values[0] as PredicateComparisonOperator})}
/>
{#if !registeredPredicateField}
setEventFieldScalarType(clauseIndex,values[0])}
/>
{/if}
{#if typeof eventFieldCondition.value === 'number'}
{:else if typeof eventFieldCondition.value === 'boolean'}
updateEventFieldComparison(clauseIndex,{value:values[0] === 'true'})}
/>
{:else}
{/if}
{:else if statePoolCondition}
{:else if conditionModel(clause) === 'advanced'}
This saved condition remains active and is preserved unchanged. Use the generated mechanic preview to inspect it.
{/if}
({value:item.id,label:item.name.replace(' matches','').replace(' within a time window',' window').toUpperCase()}))}
value={clause.reducer.kind}
columns={4}
onchange={(values) => reducerKind(clauseIndex,values[0])}
/>
{#if ['count','distinct_count','consecutive_count','sliding_count'].includes(clause.reducer.kind)}
{/if}
{#if ['distinct_count','sliding_count'].includes(clause.reducer.kind)}
{/if}
{#if clause.reducer.kind === 'duration'}
{:else if clause.reducer.kind === 'periodic'}
{:else if clause.reducer.kind === 'derived_scalar'}
{/if}
STATE CHANGES{clause.mutations.length}
{#each clause.mutations as mutation, mutationIndex}
updateMutation(clauseIndex,mutationIndex,values[0] as 'add'|'set'|'consume'|'clear')}
/>
({value:pool.key,label:pool.label.toUpperCase()}))}
value={'pool' in mutation ? mutation.pool : rule.pools[0]?.key ?? ''}
columns={Math.min(4,Math.max(1,rule.pools.length))}
onchange={(values) => updateMutation(clauseIndex,mutationIndex,mutation.kind === 'clear' ? 'clear' : mutation.kind === 'set' || mutation.kind === 'consume' ? mutation.kind : 'add',values[0])}
/>
{#if mutation.kind !== 'clear'}
{/if}
{#if 'pool' in mutation && rule.pools.find((pool) => pool.key === mutation.pool)?.scope === 'target'}
updateMutationEntity(clauseIndex,mutationIndex,values[0] as 'event_target'|'event_actor')}
/>
{/if}
{:else}
This branch emits outcomes without changing shared state.
{/each}
OUTCOMES{clause.outcomes.length}
{#each clause.outcomes as outcome, outcomeIndex}
updateOutcome(clauseIndex,outcomeIndex,{kind:values[0] as ConditionalMechanicOutcomeDraft['kind'],resource:values[0] === 'restoration' || values[0] === 'resource_cost' ? outcome.resource ?? 'health' : undefined,attributeId:values[0] === 'attribute_modifier' ? outcome.attributeId ?? '' : undefined,delivery:values[0] === 'restoration' ? outcome.delivery : undefined,durationSeconds:values[0] === 'restoration' ? outcome.durationSeconds : undefined})}/>
4 ? 4 : scopeOptions.length} onchange={(values) => updateOutcome(clauseIndex,outcomeIndex,{scope:values[0] as MechanicOutcomeScope})}/>
{#if outcome.scope === 'allies' || outcome.scope === 'self_and_allies' || outcome.scope === 'target'}
updateOutcome(clauseIndex,outcomeIndex,{
targeting: values[0] === 'none'
? undefined
: {kind:'within_radius',population:values[0] as 'allies'|'enemies',radiusMeters:outcome.targeting?.radiusMeters ?? 20}
})}
/>
{#if outcome.targeting}
{/if}
{/if}
{#if outcome.kind === 'attribute_modifier'}
{:else if outcome.kind === 'restoration' || outcome.kind === 'resource_cost'}
updateOutcome(clauseIndex,outcomeIndex,{resource:values[0] as 'health'|'armor'|'ammo'|'signature_ability_charge'})}/>
{/if}
{#if outcome.kind === 'restoration'}
updateOutcome(clauseIndex,outcomeIndex,{
delivery: values[0] === 'continuous' ? 'continuous' : undefined,
durationSeconds: values[0] === 'continuous' ? outcome.durationSeconds ?? 3 : undefined
})}
/>
{#if outcome.delivery === 'continuous'}
{/if}
{/if}
{#if outcome.kind === 'direct_damage' || outcome.kind === 'restoration' || outcome.kind === 'resource_cost'}
updateOutcome(clauseIndex,outcomeIndex,{basis:values[0] as OutcomeBasis})}/>
{/if}
setOutcomeValueModel(clauseIndex,outcomeIndex,values[0] as OutcomeValueModel,values[0] === 'event' ? 'values.enemyCount' : values[0] === 'scenario' ? rule.scenarioInputs[0]?.key ?? '' : '')}
/>
{#if outcomeValueModel(outcome) === 'event'}
setOutcomeValueModel(clauseIndex,outcomeIndex,'event',values[0])}
/>
{:else if outcomeValueModel(outcome) === 'scenario' && rule.scenarioInputs.length}
({value:input.key,label:input.label.toUpperCase()}))}
value={outcomeReference(outcome,'scenario')}
columns={Math.min(4,rule.scenarioInputs.length)}
onchange={(values) => setOutcomeValueModel(clauseIndex,outcomeIndex,'scenario',values[0])}
/>
{:else if outcomeValueModel(outcome) === 'attribute' || outcomeValueModel(outcome) === 'attribute_value'}
setOutcomeValueModel(clauseIndex,outcomeIndex,outcomeValueModel(outcome),value)}
/>
{/if}
{#if rule.pools.length}
({value:pool.key,label:pool.label.toUpperCase()}))]}
value={outcome.statePool ?? ''}
columns={Math.min(4,rule.pools.length + 1)}
onchange={(values) => updateOutcome(clauseIndex,outcomeIndex,{statePool:values[0] || undefined,perStack:values[0] ? outcome.perStack ?? true : false,minStacks:values[0] ? outcome.minStacks : undefined,maxStacks:values[0] ? outcome.maxStacks : undefined})}
/>
{#if outcome.statePool}
updateOutcome(clauseIndex,outcomeIndex,{perStack:values[0] === 'true'})}/>
{/if}
{/if}
{#each valueColumns as column}
{/each}
{:else}
This branch has no outcomes yet.
{/each}