MECHANIC PROGRAM
STRUCTURED COMBAT LOGIC {rule.clauses.length} {rule.clauses.length === 1 ? 'BRANCH' : 'BRANCHES'}

Events are code-defined. Every branch, condition, state change, and outcome belongs to this item.

{#if aiContext} {/if}
BUILDER CONTROLSSCENARIO ASSUMPTIONS

These controls are retained for the planned advanced build model. Maximum Potential will use the best-case value; Custom Scenario will use the Agent’s saved value.

{#each rule.scenarioInputs as input, index}
updateScenarioInput(index,{kind:values[0] as ScenarioInputDefinition['kind'],defaultValue:values[0] === 'toggle' ? false : Number(input.defaultValue ?? 0),bestCaseValue:values[0] === 'toggle' ? true : Number(input.bestCaseValue ?? 100),min:values[0] === 'toggle' ? undefined : input.min ?? 0,max:values[0] === 'toggle' ? undefined : input.max ?? 100})}/> {#if input.kind === 'toggle'} updateScenarioInput(index,{defaultValue:values[0] === 'true'})}/> updateScenarioInput(index,{bestCaseValue:values[0] === 'true'})}/> {:else} {/if}
{:else}

No source-specific assumptions. This mechanic uses only the shared encounter timeline.

{/each}
RECIPE STARTERSEED AN EDITABLE BRANCH
Recipes copy typed data into this item; they are not shared runtime dependencies.
{#if ['same_target_hits_within_window', 'distinct_enemies_within_window', 'consecutive_same_target_hits'].includes(recipeKey)} {/if} {#if ['same_target_hits_within_window', 'distinct_enemies_within_window', 'continuous_firing_duration'].includes(recipeKey)} {/if} {#if ['target_hit_within_distance', 'within_distance'].includes(recipeKey)} {/if} {#if recipeKey === 'health_threshold_bands'}

Define strict “below Health” bands from strongest to weakest. Exact thresholds enter the next weaker band.

{#each recipeHealthBands as band, index}
{/each}
{/if} {#if rule.clauses.length && recipeKey} {/if}
{#if replaceConfirmation} {/if}
STATEPOOLS
{#each rule.pools as pool, index}
updatePool(index,{scope:values[0] as 'agent'|'target'})}/> {#if pool.expiresAfterSecondsVariants} {#each valueColumns as column} {/each} {:else} {/if}
{:else}

No state pools. Add one for stacks, timers, counters, resources, or target marks.

{/each}
{#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)}
{String(clauseIndex + 1).padStart(2, '0')}
DIRECT EVENT setClauseEvent(clauseIndex,value)}/>
MATCH POLICY{reducerItems.find((item) => item.id === clause.reducer.kind)?.name ?? clause.reducer.kind}
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}
STATE POOL ({id:pool.key,name:pool.label}))} mode="single" compact subjectLabel="STATE POOL" value={statePoolCondition.pool} onvaluechange={(value) => updateStatePoolThreshold(clauseIndex,{pool:value})} />
updateStatePoolThreshold(clauseIndex,{operator:values[0] as PredicateComparisonOperator})} />
{: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}
{/each}
GENERATED MECHANICREAD-ONLY PSEUDO-SCRIPT

The server validates the same typed structure for every configured value variant.