189 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			189 lines
		
	
	
		
			6.0 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";
 | |
| 
 | |
| 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, 'ambidextre': 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}`
 | |
|   }
 | |
| 
 | |
| 
 | |
| }
 |