Adding skills & isac talent updates

This commit is contained in:
jb
2026-07-29 20:56:22 -04:00
parent f1b473ffa8
commit 65a4987cad
68 changed files with 5486 additions and 569 deletions
+44 -15
View File
@@ -37,9 +37,11 @@ const applicationKind = (outcome: ConditionalMechanicOutcomeDraft) => {
if (outcome.kind === 'attribute_modifier') return 'active_modifier';
if (outcome.kind === 'direct_damage') return 'direct_damage';
if (outcome.kind === 'resource_cost') return 'resource_cost';
if (outcome.kind === 'weapon_reload') return 'weapon_reload';
if (outcome.kind === 'marker') return 'marker';
if (outcome.resource === 'armor') return 'restore_armor';
if (outcome.resource === 'ammo') return 'restore_ammo';
if (outcome.resource === 'signature_ability_charge') return 'restore_signature_ability_charge';
return 'restore_health';
};
@@ -47,17 +49,24 @@ const outcomeKind = (row: OutcomeRow): MechanicOutcome['kind'] => {
if (row.application_kind === 'active_modifier') return 'attribute_modifier';
if (row.application_kind === 'direct_damage') return 'direct_damage';
if (row.application_kind === 'resource_cost') return 'resource_cost';
if (row.application_kind === 'weapon_reload') return 'weapon_reload';
if (row.application_kind === 'marker') return 'marker';
return 'restoration';
};
const outcomeResource = (row: OutcomeRow): MechanicResource | undefined => {
if (row.resource_kind === 'health' || row.resource_kind === 'armor' || row.resource_kind === 'ammo') {
if (
row.resource_kind === 'health'
|| row.resource_kind === 'armor'
|| row.resource_kind === 'ammo'
|| row.resource_kind === 'signature_ability_charge'
) {
return row.resource_kind;
}
if (row.application_kind === 'restore_health') return 'health';
if (row.application_kind === 'restore_armor') return 'armor';
if (row.application_kind === 'restore_ammo') return 'ammo';
if (row.application_kind === 'restore_signature_ability_charge') return 'signature_ability_charge';
return undefined;
};
@@ -74,6 +83,7 @@ const outcomeMetadataColumns = [
'resource_kind',
'delivery_mode',
'delivery_duration_seconds',
'targeting_json',
'state_pool_id',
'min_state_value',
'max_state_value',
@@ -131,17 +141,25 @@ export function conditionalRuleDraftFromRows(
const pools = poolRows
.filter((row) => row.rule_id === rule.id)
.sort((left, right) => Number(left.sort_order) - Number(right.sort_order))
.map((row): ConditionalMechanicPoolDraft => ({
key: String(row.state_key),
label: String(row.label),
stateKind: String(row.state_kind) as ConditionalMechanicPoolDraft['stateKind'],
scope: String(row.state_scope) as ConditionalMechanicPoolDraft['scope'],
initial: Number(row.initial_value),
...(row.minimum_value === null || row.minimum_value === undefined ? {} : { min: Number(row.minimum_value) }),
...(row.maximum_value === null || row.maximum_value === undefined ? {} : { max: Number(row.maximum_value) }),
...(row.best_case_value === null || row.best_case_value === undefined ? {} : { bestCaseValue: Number(row.best_case_value) }),
...(row.duration_seconds === null || row.duration_seconds === undefined ? {} : { expiresAfterSeconds: Number(row.duration_seconds) })
}));
.map((row): ConditionalMechanicPoolDraft => {
const parameters = parseJson<Record<string, unknown>>(row.parameters_json, {});
const expiresAfterSecondsVariants = parameters.expiresAfterSecondsVariants;
return {
key: String(row.state_key),
label: String(row.label),
stateKind: String(row.state_kind) as ConditionalMechanicPoolDraft['stateKind'],
scope: String(row.state_scope) as ConditionalMechanicPoolDraft['scope'],
initial: Number(row.initial_value),
...(row.minimum_value === null || row.minimum_value === undefined ? {} : { min: Number(row.minimum_value) }),
...(row.maximum_value === null || row.maximum_value === undefined ? {} : { max: Number(row.maximum_value) }),
...(row.best_case_value === null || row.best_case_value === undefined ? {} : { bestCaseValue: Number(row.best_case_value) }),
...(row.duration_seconds === null || row.duration_seconds === undefined ? {} : { expiresAfterSeconds: Number(row.duration_seconds) }),
...(expiresAfterSecondsVariants && typeof expiresAfterSecondsVariants === 'object'
&& !Array.isArray(expiresAfterSecondsVariants)
? { expiresAfterSecondsVariants: expiresAfterSecondsVariants as Record<string, number> }
: {})
};
});
const poolKeyById = new Map(poolRows.map((row) => [String(row.id), String(row.state_key)]));
const rowsByClause = new Map<string, OutcomeRow[]>();
for (const row of outcomeRows.filter((item) => item.rule_id === rule.id)) {
@@ -189,6 +207,9 @@ export function conditionalRuleDraftFromRows(
...(delivery === 'continuous'
? { delivery, durationSeconds: durationSeconds as number }
: {}),
...(first.targeting_json
? { targeting: parseJson(first.targeting_json, undefined) }
: {}),
...(first.stat_attribute_id ? { attributeId: String(first.stat_attribute_id) } : {}),
...(first.state_pool_id && poolKeyById.has(String(first.state_pool_id))
? { statePool: poolKeyById.get(String(first.state_pool_id)) }
@@ -293,6 +314,11 @@ export async function saveConditionalRuleInTransaction(
const poolIds = new Map<string, string>();
for (const [index, pool] of draft.pools.entries()) {
const expiresAfterSecondsVariants = (
pool as ConditionalMechanicPoolDraft & {
expiresAfterSecondsVariants?: Record<string, number>;
}
).expiresAfterSecondsVariants;
const poolId = randomUUID();
poolIds.set(pool.key, poolId);
await (await database.prepare(`INSERT INTO conditional_effect_state_pools
@@ -313,7 +339,9 @@ export async function saveConditionalRuleInTransaction(
pool.expiresAfterSeconds ?? null,
'clear_all',
'refresh',
'{}',
JSON.stringify(expiresAfterSecondsVariants
? { expiresAfterSecondsVariants }
: {}),
index + 1,
now,
now
@@ -356,9 +384,9 @@ export async function saveConditionalRuleInTransaction(
application_kind,effect_scope,stat_attribute_id,value,value_expression_json,
value_basis,value_scaling,unit,damage_basis,application_phase,combat_timing,
resource_kind,delivery_mode,delivery_duration_seconds,
min_state_value,max_state_value,description_slot,sort_order,
targeting_json,min_state_value,max_state_value,description_slot,sort_order,
created_at,updated_at)
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`)).run(
VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`)).run(
randomUUID(),
ruleId,
clauseId,
@@ -382,6 +410,7 @@ export async function saveConditionalRuleInTransaction(
outcome.resource ?? null,
outcome.delivery ?? 'instant',
outcome.durationSeconds ?? null,
outcome.targeting === undefined ? null : JSON.stringify(outcome.targeting),
outcome.minStacks ?? null,
outcome.maxStacks ?? null,
outcome.descriptionSlot ?? null,