added partner to npc gen

This commit is contained in:
Vlyan
2022-02-12 18:29:49 +01:00
parent da788d47c7
commit 64b436627f
4 changed files with 110 additions and 48 deletions

View File

@@ -251,6 +251,7 @@
"age": "Age", "age": "Age",
"marital_status": { "marital_status": {
"title": "Marital Status", "title": "Marital Status",
"partner": "Partner",
"married": "Married", "married": "Married",
"betrothed": "Betrothed", "betrothed": "Betrothed",
"unmarried": "Unmarried", "unmarried": "Unmarried",

View File

@@ -251,6 +251,7 @@
"age": "Age", "age": "Age",
"marital_status": { "marital_status": {
"title": "Marital Status", "title": "Marital Status",
"partner": "Partner",
"married": "Married", "married": "Married",
"betrothed": "Betrothed", "betrothed": "Betrothed",
"unmarried": "Unmarried", "unmarried": "Unmarried",

View File

@@ -251,6 +251,7 @@
"age": "Age", "age": "Age",
"marital_status": { "marital_status": {
"title": "État civil", "title": "État civil",
"partner": "Partenaire",
"married": "Marié(e)", "married": "Marié(e)",
"betrothed": "Fiancé(e)", "betrothed": "Fiancé(e)",
"unmarried": "Célibataire", "unmarried": "Célibataire",

View File

@@ -123,7 +123,7 @@ export class CharacterGenerator {
/** /**
* Return a random value for this array * Return a random value for this array
* @param array * @param {String[]} array
* @return {String} * @return {String}
* @private * @private
*/ */
@@ -133,8 +133,8 @@ export class CharacterGenerator {
/** /**
* Return a random value between min and max * Return a random value between min and max
* @param {number} min * @param {number} min
* @param {number} max * @param {number} max
* @return {number} * @return {number}
* @private * @private
*/ */
@@ -144,7 +144,7 @@ export class CharacterGenerator {
/** /**
* Always return a number between 1 and 5 * Always return a number between 1 and 5
* @param {number} number * @param {number} number
* @return {number} * @return {number}
*/ */
static sanitizeMinMax(number) { static sanitizeMinMax(number) {
@@ -153,8 +153,8 @@ export class CharacterGenerator {
/** /**
* Return a Item from this pack (by id if provided, or random otherwise) * Return a Item from this pack (by id if provided, or random otherwise)
* @param {string} packName * @param {string} packName
* @param {string} id * @param {string} id
* @return {Promise<Document|undefined>} * @return {Promise<Document|undefined>}
* @private * @private
*/ */
@@ -175,7 +175,7 @@ export class CharacterGenerator {
/** /**
* Generate and return a family name for this clan * Generate and return a family name for this clan
* @param {string} clanName * @param {string} clanName
* @return {string} * @return {string}
* @private * @private
*/ */
@@ -193,12 +193,12 @@ export class CharacterGenerator {
} }
/** /**
* Generate and return a full name * Generate and return a firstname
* @return {Promise<string>} * @return {Promise<string>}
*/ */
async getRandomizedName() { static async getRandomizedFirstname(isFemale, clan) {
let table = `Japanese names (${this.isFemale ? "Female" : "Male"})`; let table = `Japanese names (${isFemale ? "Female" : "Male"})`;
switch (this.data.clan) { switch (clan) {
case "ivory_kingdoms": case "ivory_kingdoms":
table = "Ivory Kingdoms names"; table = "Ivory Kingdoms names";
break; break;
@@ -212,7 +212,7 @@ export class CharacterGenerator {
const randomNames = await game.l5r5e.HelpersL5r5e.drawManyFromPack("l5r5e.core-name-tables", table, 1, { const randomNames = await game.l5r5e.HelpersL5r5e.drawManyFromPack("l5r5e.core-name-tables", table, 1, {
displayChat: false, displayChat: false,
}); });
return this.data.family + " " + (randomNames?.results[0]?.data.text || ""); return randomNames?.results[0]?.data.text || "";
} }
/** /**
@@ -240,10 +240,39 @@ export class CharacterGenerator {
return rng < 0.8 ? "married" : rng < 0.9 ? "widowed" : "unmarried"; return rng < 0.8 ? "married" : rng < 0.9 ? "widowed" : "unmarried";
} }
/**
* Generate the marital partner
* @param {string} maritalStatus unmarried|betrothed|married|widowed
* @param {number} avgRingsValue
* @param {string} clan
* @param {string} family
* @param {boolean} isFemale
* @return {Promise<{age: number, name: string, clan: string, family: string, female: boolean}>}
*/
static async genMaritalPartner(maritalStatus, avgRingsValue, clan, family, isFemale) {
const alreadyMerged = maritalStatus !== "betrothed";
const partner = {
age: CharacterGenerator.genAge(avgRingsValue),
clan: "",
family: "",
female: Math.random() > 0.9 ? isFemale : !isFemale,
name: "",
};
partner.clan =
alreadyMerged || Math.random() > 0.7
? clan
: CharacterGenerator._getRandomArrayValue(Array.from(CONFIG.l5r5e.families.keys()));
partner.family = alreadyMerged ? family : CharacterGenerator._getRandomFamily(partner.clan);
partner.name = await CharacterGenerator.getRandomizedFirstname(partner.female, partner.clan);
return partner;
}
/** /**
* Generate Honor, Glory and Status values * Generate Honor, Glory and Status values
* @param {number} age * @param {number} age
* @param {string} clan * @param {string} clan
* @return {{honor: number, glory: number, status: number}} * @return {{honor: number, glory: number, status: number}}
*/ */
static genSocialStanding(age, clan) { static genSocialStanding(age, clan) {
@@ -271,16 +300,16 @@ export class CharacterGenerator {
/** /**
* Modify the current actor datas with selected options * Modify the current actor datas with selected options
* *
* @param {ActorL5r5e} actor Actor object * @param {ActorL5r5e} actor Actor object
* @param {Object} generate * @param {Object} generate
* @param {boolean} generate.name If true generate a new name * @param {boolean} generate.name If true generate a new name
* @param {boolean} generate.identity If true generate Clan, Gender, Age, Marital status * @param {boolean} generate.identity If true generate Clan, Gender, Age, Marital status
* @param {boolean} generate.attributes If true generate Rings, attributes, skills and confrontation ranks * @param {boolean} generate.attributes If true generate Rings, attributes, skills and confrontation ranks
* @param {boolean} generate.demeanor If true generate Demeanor and rings affinities * @param {boolean} generate.demeanor If true generate Demeanor and rings affinities
* @param {boolean} generate.peculiarities If true generate Advantage and Disadvantage * @param {boolean} generate.peculiarities If true generate Advantage and Disadvantage
* @param {boolean} generate.items If true generate Armor, Weapons and Items * @param {boolean} generate.items If true generate Armor, Weapons and Items
* @param {boolean} generate.techniques If true generate Shuji, Katas... * @param {boolean} generate.techniques If true generate Shuji, Katas...
* @param {boolean} generate.narrative If true generate Narrative and fluff * @param {boolean} generate.narrative If true generate Narrative and fluff
* @return {Promise<Object>} * @return {Promise<Object>}
*/ */
async toActor( async toActor(
@@ -297,6 +326,7 @@ export class CharacterGenerator {
} }
) { ) {
const actorDatas = actor.data.data; const actorDatas = actor.data.data;
const isNpc = actor.type === "npc";
// Need to set some required values // Need to set some required values
this.data.age = actorDatas.identity.age || CharacterGenerator.genAge(this.data.avgRingsValue); this.data.age = actorDatas.identity.age || CharacterGenerator.genAge(this.data.avgRingsValue);
@@ -308,13 +338,19 @@ export class CharacterGenerator {
actorDatas.identity.female = this.isFemale; actorDatas.identity.female = this.isFemale;
// Name // Name
const newName = generate.name ? await this.getRandomizedName() : actor.data.name; let newName = actor.data.name;
if (generate.name) {
newName =
this.data.family +
" " +
(await CharacterGenerator.getRandomizedFirstname(this.isFemale, this.data.clan));
}
// Identity // Identity
if (generate.identity) { if (generate.identity) {
actorDatas.identity.age = CharacterGenerator.genAge(this.data.avgRingsValue); actorDatas.identity.age = CharacterGenerator.genAge(this.data.avgRingsValue);
actorDatas.identity.marital_status = CharacterGenerator.genMaritalStatus(this.data.age); actorDatas.identity.marital_status = CharacterGenerator.genMaritalStatus(this.data.age);
this._generateNotes(actorDatas); await this._generateNotes(actorDatas);
} }
// Img (only if system defaults) // Img (only if system defaults)
@@ -330,7 +366,7 @@ export class CharacterGenerator {
// Generate attributes & Social Standing // Generate attributes & Social Standing
if (generate.attributes) { if (generate.attributes) {
// Generate attributes (rings, attributes, skills, confrontation ranks) // Generate attributes (rings, attributes, skills, confrontation ranks)
this._generateAttributes(actorDatas); this._generateAttributes(isNpc, actorDatas);
// Social Standing // Social Standing
const social = CharacterGenerator.genSocialStanding(this.data.age, this.data.clan); const social = CharacterGenerator.genSocialStanding(this.data.age, this.data.clan);
@@ -340,7 +376,7 @@ export class CharacterGenerator {
} }
// Demeanor (npc only) // Demeanor (npc only)
if (generate.demeanor && actor.type === "npc") { if (isNpc && generate.demeanor) {
this._generateDemeanor(actorDatas); this._generateDemeanor(actorDatas);
} }
@@ -369,7 +405,7 @@ export class CharacterGenerator {
} }
} }
// TODO Narrative // Narrative
if (generate.narrative) { if (generate.narrative) {
this._generateNarrative(actorDatas); this._generateNarrative(actorDatas);
} }
@@ -381,14 +417,15 @@ export class CharacterGenerator {
data: actorDatas, data: actorDatas,
}; };
} }
//<editor-fold desc="toActor generators">
//<editor-fold desc="toActor generators">
/** /**
* Generate attributes (rings, attributes, skills, confrontation ranks) * Generate attributes (rings, attributes, skills, confrontation ranks)
* @param {boolean} isNpc
* @param {DocumentData.data} actorDatas * @param {DocumentData.data} actorDatas
* @private * @private
*/ */
_generateAttributes(actorDatas) { _generateAttributes(isNpc, actorDatas) {
const stats = { min: 5, max: 1 }; const stats = { min: 5, max: 1 };
// Rings // Rings
@@ -405,12 +442,16 @@ export class CharacterGenerator {
game.l5r5e.ActorL5r5e.computeDerivedAttributes(actorDatas); game.l5r5e.ActorL5r5e.computeDerivedAttributes(actorDatas);
// Skills // Skills
Object.keys(actorDatas.skills).forEach( if (isNpc) {
(skillName) => (actorDatas.skills[skillName] = Math.floor(Math.random() * stats.max)) Object.keys(actorDatas.skills).forEach(
); (skillName) => (actorDatas.skills[skillName] = Math.floor(Math.random() * stats.max))
);
} else {
// TODO PC skills
}
// Confrontation ranks (npc only) // Confrontation ranks (npc only)
if (actorDatas.conflict_rank) { if (isNpc) {
actorDatas.conflict_rank.martial = this.data.avgRingsValue + actorDatas.skills.martial; actorDatas.conflict_rank.martial = this.data.avgRingsValue + actorDatas.skills.martial;
actorDatas.conflict_rank.social = this.data.avgRingsValue + actorDatas.skills.social; actorDatas.conflict_rank.social = this.data.avgRingsValue + actorDatas.skills.social;
} }
@@ -439,8 +480,8 @@ export class CharacterGenerator {
/** /**
* Generate Advantages and Disadvantages * Generate Advantages and Disadvantages
* @param {ActorL5r5e} actor * @param {ActorL5r5e} actor
* @param {DocumentData[]} newItemsData * @param {DocumentData[]} newItemsData
* @return {Promise<void>} * @return {Promise<void>}
* @private * @private
*/ */
@@ -462,8 +503,8 @@ export class CharacterGenerator {
/** /**
* Generate Armor, Weapons, Items * Generate Armor, Weapons, Items
* @param {ActorL5r5e} actor * @param {ActorL5r5e} actor
* @param {DocumentData[]} newItemsData * @param {DocumentData[]} newItemsData
* @return {Promise<void>} * @return {Promise<void>}
* @private * @private
*/ */
@@ -507,8 +548,8 @@ export class CharacterGenerator {
/** /**
* Generate Techniques * Generate Techniques
* @param {ActorL5r5e} actor * @param {ActorL5r5e} actor
* @param {DocumentData[]} newItemsData * @param {DocumentData[]} newItemsData
* @return {Promise<void>} * @return {Promise<void>}
* @private * @private
*/ */
@@ -592,12 +633,9 @@ export class CharacterGenerator {
// Minimum skill required (npc only for now) // Minimum skill required (npc only for now)
if (!!cfg.skill && actor.data.data.skills[cfg.skill.grp_name] < cfg.skill.value_min) { if (!!cfg.skill && actor.data.data.skills[cfg.skill.grp_name] < cfg.skill.value_min) {
console.log("1");
continue; continue;
} }
console.log("2");
// Check probabilities to have more than min qty // Check probabilities to have more than min qty
let qtyMax = cfg.qty?.min ?? 0; let qtyMax = cfg.qty?.min ?? 0;
if (Math.random() < cfg.probability) { if (Math.random() < cfg.probability) {
@@ -612,7 +650,6 @@ export class CharacterGenerator {
} while (item && item.data.data.rank > avgrv); } while (item && item.data.data.rank > avgrv);
if (item) { if (item) {
// console.log('adding', pack, item.data.name);
newItemsData.push(foundry.utils.duplicate(item.data)); newItemsData.push(foundry.utils.duplicate(item.data));
} }
} // fr qty } // fr qty
@@ -621,12 +658,13 @@ export class CharacterGenerator {
/** /**
* Fill notes with some values that don't appear in sheet * Fill notes with some values that don't appear in sheet
* @param {DocumentData.data} actorDatas * @param {DocumentData.data} actorDatas
* @return {Promise<void>}
* @private * @private
*/ */
_generateNotes(actorDatas) { async _generateNotes(actorDatas) {
actorDatas.notes = actorDatas.notes =
`<p>${game.i18n.localize("l5r5e.social.age")}: ${this.data.age}</p>` + `${game.i18n.localize("l5r5e.social.age")}: ${this.data.age}</p>` +
`<p>${game.i18n.localize("l5r5e.social.gender.title")}: ${game.i18n.localize( `<p>${game.i18n.localize("l5r5e.social.gender.title")}: ${game.i18n.localize(
"l5r5e.social.gender." + this.data.gender "l5r5e.social.gender." + this.data.gender
)}</p>` + )}</p>` +
@@ -634,6 +672,26 @@ export class CharacterGenerator {
`<p>${game.i18n.localize("l5r5e.social.marital_status.title")}: ${game.i18n.localize( `<p>${game.i18n.localize("l5r5e.social.marital_status.title")}: ${game.i18n.localize(
"l5r5e.social.marital_status." + this.data.maritalStatus "l5r5e.social.marital_status." + this.data.maritalStatus
)}</p>`; )}</p>`;
// Define partner identity
if (this.data.maritalStatus !== "unmarried") {
const partner = await CharacterGenerator.genMaritalPartner(
this.data.maritalStatus,
this.data.avgRingsValue,
this.data.clan,
this.data.family,
this.isFemale
);
actorDatas.notes +=
"<p>" +
`${game.i18n.localize("l5r5e.social.marital_status.partner")}:` +
` ${partner.family} ${partner.name}` +
` (${partner.age}, ${game.i18n.localize(
"l5r5e.social.gender." + (partner.female ? "female" : "male")
)})` +
"</p>";
}
} }
/** /**
@@ -642,6 +700,7 @@ export class CharacterGenerator {
* @private * @private
*/ */
_generateNarrative(actorDatas) { _generateNarrative(actorDatas) {
// TODO generateNarrative
// actorDatas.description = ''; // actorDatas.description = '';
} }
//</editor-fold> //</editor-fold>