Added damaged veteran dialog

This commit is contained in:
Aaron Lutomski
2026-06-21 13:44:55 -07:00
parent f6ab3fbe09
commit baa4dfc8b5
34 changed files with 1946 additions and 383 deletions
@@ -0,0 +1,134 @@
import { applyDamagedVeteranModifications } from "./damaged-veteran-modifiers.js";
import { finalizeAgentStartingResources } from "../data/derived/actor-derived.js";
/**
* @typedef {object} CharacterCreationBond
* @property {string} name
* @property {string} relationship
*/
/**
* @typedef {object} CharacterCreationPayload
* @property {Record<string, number>} fixedValues
* @property {Record<string, { group: string, label: string, value: number }>} typedValues
* @property {string} professionName
* @property {CharacterCreationBond[]} bonds
*/
/**
* @param {ReturnType<import("./compute.js").default>} computed
* @param {Item} professionItem
* @param {{ bondNames: string[], bondRelationships: string[] }} formState
* @returns {CharacterCreationPayload}
*/
export function buildCharacterCreationPayload(
computed,
professionItem,
formState,
) {
const bonds = [];
const bondCount = Math.max(
1,
Math.trunc(Number(professionItem.system.bonds) || 1),
);
for (let i = 0; i < bondCount; i++) {
bonds.push({
name: formState.bondNames?.[i]?.trim() ?? "",
relationship: formState.bondRelationships?.[i]?.trim() ?? "",
});
}
return {
fixedValues: { ...computed.fixedValues },
typedValues: foundry.utils.deepClone(computed.typedValues),
professionName: professionItem.name,
bonds,
};
}
/**
* @param {Actor} actor
* @param {CharacterCreationPayload} payload
* @param {{ skipBondIndices?: number[] }} [options]
*/
export async function applyCharacterCreationPayload(
actor,
payload,
{ skipBondIndices = [] } = {},
) {
const skipSet = new Set(skipBondIndices);
const updateData = {};
for (const [key, value] of Object.entries(payload.fixedValues)) {
updateData[`system.skills.${key}.proficiency`] = value;
updateData[`system.skills.${key}.failure`] = false;
}
const typedSkills = { ...(actor.system.typedSkills ?? {}) };
for (const [, data] of Object.entries(payload.typedValues)) {
const id = foundry.utils.randomID();
typedSkills[id] = {
label: data.label,
group: data.group,
proficiency: data.value,
failure: false,
};
}
updateData["system.typedSkills"] = typedSkills;
updateData["system.biography.profession"] = payload.professionName;
await actor.update(updateData);
const chaScore =
actor.system.statistics.cha.effectiveValue ??
actor.system.statistics.cha.value;
/** @type {object[]} */
const bondDocs = [];
payload.bonds.forEach((bond, index) => {
if (skipSet.has(index)) return;
bondDocs.push({
name: bond.name,
type: "bond",
system: {
score: chaScore,
relationship: bond.relationship,
},
});
});
if (bondDocs.length) {
await actor.createEmbeddedDocuments("Item", bondDocs);
}
}
/**
* @param {Item} professionStub
* @param {Actor} actor
* @param {CharacterCreationPayload} payload
* @param {object} veteranResult
*/
export async function commitProfessionSetup(
actor,
professionStub,
payload,
veteranResult,
) {
const skipBondIndices =
veteranResult.path === "hardExperience" &&
Number.isInteger(veteranResult.removedBondIndex)
? [veteranResult.removedBondIndex]
: [];
await applyCharacterCreationPayload(actor, payload, { skipBondIndices });
await applyDamagedVeteranModifications(actor, veteranResult, payload);
await finalizeAgentStartingResources(actor, veteranResult.path);
const createData = professionStub.toObject();
delete createData._id;
const created = await actor.createEmbeddedDocuments("Item", [createData]);
return created[0] ?? null;
}