import { SHOW_DICE } from "../../constants.js"; import { Misc } from "../../misc.js"; import { RdDCarac } from "../../rdd-carac.js"; import { RdDDice } from "../../rdd-dice.js"; import { RdDNameGen } from "../../rdd-namegen.js"; import { RdDTimestamp } from "../../time/rdd-timestamp.js"; const PATHS = [ 'name', 'system.sexe', 'system.age', 'system.taille', 'system.poids', 'system.main', 'system.heure', 'system.cheveux', 'system.yeux' ] const RANDOM_VALUES = { 'system.sexe': { 'masculin': 1, 'féminin': 1 }, 'system.main': { 'droitier': 51, 'gaucher': 15, 'ambidectre': 6 }, 'system.cheveux': { 'noirs': 2, 'bruns': 5, 'châtains clair': 5, 'blonds': 4, 'blonds très clair': 1, 'roux carotte': 1, 'roux cuivré': 3 }, 'system.yeux': { 'noirs': 2, 'noisettes': 3, 'bruns vert': 4, 'verts': 3, 'bleus clair': 3, 'bleus gris': 2, 'gris': 1, 'mauves': 1, 'indigos': 1 }, } export class AppPersonnageAleatoire extends FormApplication { static preloadHandlebars() { loadTemplates([ 'systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs', ]) } static get defaultOptions() { return foundry.utils.mergeObject(super.defaultOptions, { template: "systems/foundryvtt-reve-de-dragon/templates/actor/random/app-personnage-aleatoire.hbs", title: "Génération aléatoire", width: 'fit-content', height: 'fit-content', classes: ['app-personnage-aleatoire'], popOut: true, resizable: true }, { inplace: false }) } constructor(actor) { super({}) this.actor = actor this.current = foundry.utils.duplicate(actor) this.checked = { 'name': false, 'system.sexe': true, 'system.age': true, 'system.taille': true, 'system.poids': true, 'system.main': true, 'system.heure': true, 'system.cheveux': true, 'system.yeux': true } } async getData(options) { return foundry.utils.mergeObject(await super.getData(options), { actor: this.actor, current: this.current, checked: this.checked, options: { isGM: game.user.isGM } }) } activateListeners(html) { super.activateListeners(html) this.html = html this.html.find("button.button-cancel").click(async event => await this.close()) this.html.find("button.button-apply").click(async event => await this.onApply()) this.html.find("input.current-value").change(async event => await this.onChange(event)) this.html.find("div.random-field[data-path='system.heure'] select.current-value").change(async event => await this.onChange(event)) this.html.find("a.random").click(async event => await this.onRandom(event)) this.html.find("a.reset").click(async event => await this.onReset(event)) this.html.find("a.randomize-selected").click(async event => await this.onRandomizeSelected()) this.html.find("input.check-for-random").click(async event => await this.onCheckForRandom(event)) } async _updateObject(event, formData) { } async onApply() { const updates = Object.fromEntries( PATHS.filter(path => game.user.isGM || path != 'name') .map(path => [path, this.current[path]]) ) await this.actor.update(updates) await this.close() } getPath(selector) { const fields = this.html.find(selector).parents("div.random-field:first") return fields[0].attributes['data-path'].value } async onChange(event) { const path = this.getPath(event.currentTarget) this.current[path] = event.currentTarget.value } async onRandom(event) { const path = this.getPath(event.currentTarget) await this.setRandom(path); this.render() } async onReset(event) { const path = this.getPath(event.currentTarget) this.current[path] = this.actor[path] await this.render() } async onCheckForRandom(event) { const path = this.getPath(event.currentTarget) this.checked[path] = event.currentTarget.checked this.render() } async onRandomizeSelected() { const paths = this.html.find("input.check-for-random:checked") .parents("div.random-field") .toArray() .map(it => it.attributes['data-path'].value) await Promise.all(paths.map(path => this.setRandom(path))) this.render() } async setRandom(path) { this.current[path] = await this.random(path); } async random(path) { switch (path) { case 'name': return await RdDNameGen.generate() case 'system.sexe': case 'system.main': case 'system.cheveux': case 'system.yeux': return await this.randomFromMap(RANDOM_VALUES[path]) case 'system.poids': return await this.randomPoids() case 'system.taille': return await this.randomTaille() case 'system.age': return await RdDDice.rollTotal('(2d4kl)*10 + 1d7xo + 2d20kl') case 'system.heure': return RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key } return 'unknown' } async randomFromMap(valuesMap) { const max = Object.values(valuesMap).reduce(Misc.sum(), 0) const total = await RdDDice.rollTotal(`1d${max}`) let sum = 0 for (let entry of Object.entries(valuesMap)) { sum = sum + entry[1] if (sum >= total) { return entry[0] } } return Object.keys(valuesMap)[0] } async randomPoids() { const caracTaille = RdDCarac.getCaracDerivee(this.current.system.carac.taille.value) const range = caracTaille.poidsMax - caracTaille.poidsMin + 1 const total = await RdDDice.rollTotal(`1d${range} + ${caracTaille.poidsMin}`) return total + ' kg' } async randomTaille() { const caracTaille = RdDCarac.getCaracDerivee(this.current.system.carac.taille.value) const base = this.current.system.carac.taille.value * 2 + 60 + caracTaille.poidsMin const variation = Math.floor((caracTaille.poidsMax - caracTaille.poidsMin + base / 5) / 2) const total = await RdDDice.rollTotal(`2d${variation} + ${base}`) const cm = total % 100 const m = (total - cm) / 100 return `${m}m${cm}` } }