206 lines
7.4 KiB
JavaScript
206 lines
7.4 KiB
JavaScript
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";
|
|
|
|
async function randomFrom(values) {
|
|
const max = Object.values(values).reduce(Misc.sum(), 0)
|
|
const total = await RdDDice.rollTotal(`1d${max}`)
|
|
let sum = 0
|
|
for (let entry of Object.entries(values)) {
|
|
sum = sum + entry[1]
|
|
if (sum >= total) {
|
|
return entry[0]
|
|
}
|
|
}
|
|
return Object.keys(values)[0]
|
|
}
|
|
|
|
async function randomTailleCm(taille) {
|
|
const infoTaille = RdDCarac.getCaracDerivee(taille)
|
|
const infoTailleSup = RdDCarac.getCaracDerivee(taille + 1)
|
|
const variation = (infoTailleSup.taille - infoTaille.taille) + Math.floor((infoTaille.poidsMax - infoTaille.poidsMin) / 2)
|
|
const base = infoTaille.taille
|
|
const total = await RdDDice.rollTotal(`1d${variation} -1d ${variation} + ${base}`)
|
|
const cm = total % 100
|
|
const dm = cm < 10 ? '0' : ''
|
|
const m = (total - cm) / 100
|
|
return `${m}m${dm}${cm}`
|
|
}
|
|
|
|
async function randomPoidsKg(taille) {
|
|
const infoTaille = RdDCarac.getCaracDerivee(taille)
|
|
const range = infoTaille.poidsMax - infoTaille.poidsMin + 1
|
|
const total = await RdDDice.rollTotal(`1d${range} + ${infoTaille.poidsMin}`)
|
|
return total + ' kg'
|
|
}
|
|
|
|
async function randomHeure() {
|
|
return RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key
|
|
}
|
|
|
|
const CONTROL_UNKNOWN = { name: 'unknown', path: '', getter: (act) => { undefined }, random: async act => undefined }
|
|
const TABLE_SEXES = { 'masculin': 1, 'féminin': 1 };
|
|
const TABLE_MAINS = { 'droitier': 51, 'gaucher': 15, 'ambidextre': 6 };
|
|
const TABLE_COULEURS_CHEVEUX = {
|
|
'noirs': 2,
|
|
'bruns': 5,
|
|
'châtains': 3,
|
|
'châtain clair': 5,
|
|
'blonds': 4,
|
|
'blond platine': 1,
|
|
'roux carotte': 1,
|
|
'roux cuivré': 3,
|
|
'chauve': 1
|
|
};
|
|
const TABLE_COULEURS_YEUX = {
|
|
'noirs': 2,
|
|
'noisette': 3,
|
|
'brun-vert': 4,
|
|
'verts': 3,
|
|
'bleu clair': 3,
|
|
'bleu gris': 2,
|
|
'gris': 1,
|
|
'mauves': 1,
|
|
'indigos': 1
|
|
};
|
|
|
|
const CONTROLS = [
|
|
{ name: 'name', path: 'name', getter: (act) => act.name, random: async act => await RdDNameGen.generate() },
|
|
{ name: 'sexe', path: 'system.sexe', getter: act => act.system.sexe, random: async act => await randomFrom(TABLE_SEXES) },
|
|
{ name: 'age', path: 'system.age', getter: act => act.system.age, random: async act => await RdDDice.rollTotal('(2d4kl)*10 + 1d7xo + 2d20kl') },
|
|
{ name: 'taille', path: 'system.taille', getter: act => act.system.taille, random: async act => await randomTailleCm(act.system.carac.taille.value) },
|
|
{ name: 'poids', path: 'system.poids', getter: act => act.system.poids, random: async act => await randomPoidsKg(act.system.carac.taille.value) },
|
|
{ name: 'main', path: 'system.main', getter: act => act.system.main, random: async act => await randomFrom(TABLE_MAINS) },
|
|
{ name: 'heure', path: 'system.heure', getter: act => act.system.heure, random: async act => await randomHeure() },
|
|
{ name: 'cheveux', path: 'system.cheveux', getter: act => act.system.cheveux, random: async act => await randomFrom(TABLE_COULEURS_CHEVEUX) },
|
|
{ name: 'yeux', path: 'system.yeux', getter: act => act.system.yeux, random: async act => await randomFrom(TABLE_COULEURS_YEUX) },
|
|
]
|
|
|
|
export class AppPersonnageAleatoire extends FormApplication {
|
|
static preloadHandlebars() {
|
|
foundry.applications.handlebars.loadTemplates([
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/random/sexe-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 = AppPersonnageAleatoire.getActorValues()
|
|
this.checked = Object.fromEntries(CONTROLS.map(it => [it.name, [0, '', undefined].includes(it.getter(this.current))]))
|
|
}
|
|
|
|
static getActorValues() {
|
|
return Object.fromEntries(CONTROLS.map(it => [it.name, it.getter(this.actor)]));
|
|
}
|
|
|
|
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("input.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))
|
|
|
|
this.html.find("div.random-field[data-field-name='heure'] select.current-value").change(async event => await this.onChange(event))
|
|
this.html.find('a[data-action="sexe-masculin"]').click(async event => await this.onSexe('masculin'))
|
|
this.html.find('a[data-action="sexe-feminin"]').click(async event => await this.onSexe('féminin'))
|
|
|
|
this.html.find("button.button-cancel").click(async event => await this.close())
|
|
this.html.find("button.button-apply").click(async event => await this.onApply())
|
|
}
|
|
|
|
async _updateObject(event, formData) { }
|
|
|
|
async onApply() {
|
|
const updates = Object.fromEntries(
|
|
CONTROLS.filter(control => game.user.isGM || control.name != 'name')
|
|
.map(control => [control.path, control.getter(this.current)])
|
|
)
|
|
await this.actor.update(updates)
|
|
await this.close()
|
|
}
|
|
|
|
getName(selector) {
|
|
const fields = this.html.find(selector).parents("div.random-field:first")
|
|
return fields[0].attributes['data-field-name'].value
|
|
}
|
|
|
|
getControl(name) {
|
|
return CONTROLS.find(it => it.name == name) ?? CONTROL_UNKNOWN
|
|
}
|
|
|
|
async onSexe(sexe) {
|
|
this.current['sexe'] = sexe
|
|
this.render()
|
|
}
|
|
|
|
async onChange(event) {
|
|
const name = this.getName(event.currentTarget)
|
|
const control = this.getControl(name)
|
|
this.current[control.name] = event.currentTarget.value
|
|
this.render()
|
|
}
|
|
|
|
|
|
async onRandom(event) {
|
|
const name = this.getName(event.currentTarget)
|
|
const control = this.getControl(name)
|
|
await this.randomControl(control)
|
|
this.render()
|
|
}
|
|
|
|
async onReset(event) {
|
|
const name = this.getName(event.currentTarget)
|
|
const control = this.getControl(name)
|
|
this.current[control.name] = control.getter(this.actor)
|
|
await this.render()
|
|
}
|
|
|
|
async onCheckForRandom(event) {
|
|
const name = this.getName(event.currentTarget)
|
|
this.checked[name] = event.currentTarget.checked
|
|
this.render()
|
|
}
|
|
|
|
async onRandomizeSelected() {
|
|
const controls = this.html.find("input.check-for-random:checked")
|
|
.parents("div.random-field")
|
|
.toArray()
|
|
.map(it => this.getControl(it.attributes['data-field-name'].value))
|
|
await Promise.all(controls.map(it => this.randomControl(it)))
|
|
this.render()
|
|
}
|
|
|
|
async randomControl(control) {
|
|
this.current[control.name] = await control.random(this.current)
|
|
}
|
|
}
|
|
|