diff --git a/changelog.md b/changelog.md index f1dab016..66c097cf 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,15 @@ # 12.0 +## 12.0.11 - Le scriptorium d'Astrobazzarh +- ajout d'un bouton pour générer les éléments de description d'un personnage +- ajout du logo en background dans la liste des systèmes Foundry +- ajout d'un champ pour le métier +- export scriptarium + - encodage de l'export en windows-1252 + - export de l'esquive avec armure et sans armure + +## 12.0.10 - Le scriptorium d'Astrobazzarh +- corrections de l'export scriptarium + ## 12.0.9 - Le scriptorium d'Astrobazzarh - ajout d'une fonction avancée pour exporter les personnages dans un format csv diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 4ff63dd7..cba5cf81 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -17,6 +17,7 @@ import { RdDItemBlessure } from "./item/blessure.js"; import { RdDEmpoignade } from "./rdd-empoignade.js"; import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js"; +import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js"; /* -------------------------------------------- */ /** @@ -198,6 +199,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { this.html.find('.jeu-label a').click(async event => this.actor.rollJeu(RdDSheetUtility.getItemId(event))) this.html.find('.recettecuisine-label a').click(async event => this.actor.rollRecetteCuisine(RdDSheetUtility.getItemId(event))) + this.html.find('.description-aleatoire').click(async event => new AppPersonnageAleatoire(this.actor).render(true)) if (game.user.isGM) { // experience log this.html.find('.experiencelog-delete').click(async event => { diff --git a/module/actor.js b/module/actor.js index 50666844..ee0569d2 100644 --- a/module/actor.js +++ b/module/actor.js @@ -3067,7 +3067,7 @@ export class RdDActor extends RdDBaseActorSang { incarnation.name = 'Réincarnation de ' + incarnation.name incarnation.system = { carac: foundry.utils.duplicate(this.system.carac), - heure: RdDTimestamp.defHeure(await RdDDice.rollTotal("1dh", { rollMode: "selfroll", showDice: SHOW_DICE })).key, + heure: RdDTimestamp.defHeure(await RdDDice.rollHeure( { rollMode: "selfroll", showDice: SHOW_DICE })).key, age: 18, biographie: '', notes: '', diff --git a/module/actor/export-scriptarium/export-scriptarium.js b/module/actor/export-scriptarium/export-scriptarium.js index 088f693f..42710c70 100644 --- a/module/actor/export-scriptarium/export-scriptarium.js +++ b/module/actor/export-scriptarium/export-scriptarium.js @@ -50,12 +50,12 @@ export class ExportScriptarium { } exportActors(actors, targetName) { - const eol = '\n' + const eol = '\n\r' const header = Misc.join(this.getHeaderLine(), ';') const actorLines = actors.map(actor => Misc.join(this.getActorLine(actor), ';')) const data = Misc.join([header, ...actorLines], eol) const filename = `scriptarium-${targetName?.slugify()}.csv`; - saveDataToFile(data, "text/csv;charset=utf-8", `${filename}`); + saveDataToFile(data, "text/csv;charset=windows-1252", `${filename}`); } getHeaderLine() { @@ -65,7 +65,6 @@ export class ExportScriptarium { getActorLine(actor) { const context = Mapping.prepareContext(actor) return this.mapping.map(it => it.getter(actor, context)) - //.map(it => JSON.stringify(it)) .map(it => this.$escapeQuotes(it)) .map(it => it.replaceAll("\n", " ").replaceAll("\r", "")) } diff --git a/module/actor/export-scriptarium/mapping.js b/module/actor/export-scriptarium/mapping.js index e667d81b..5f8d6237 100644 --- a/module/actor/export-scriptarium/mapping.js +++ b/module/actor/export-scriptarium/mapping.js @@ -53,6 +53,7 @@ const TABLEAU_SORTS = [...Array(NB_SORTS).keys()] const MAPPING_BASE = [ { column: "ID", getter: (actor, context) => actor.id }, { column: "name", getter: (actor, context) => actor.name }, + { column: "metier", getter: (actor, context) => actor.system.metier }, // { column: "biographie", getter: (actor, context) => actor.system.biographie }, { column: "taille", getter: (actor, context) => actor.system.carac.taille.value }, { column: "apparence", getter: (actor, context) => actor.system.carac.apparence.value }, @@ -80,7 +81,8 @@ const MAPPING_BASE = [ { column: "armure", getter: (actor, context) => Mapping.getArmure(actor, context) }, { column: "protection", getter: (actor, context) => Mapping.getProtectionArmure(actor, context) }, { column: "malus-armure", getter: (actor, context) => Mapping.getMalusArmure(actor, context) }, - { column: "esquive", getter: (actor, context) => Mapping.getEsquiveNiveau(context) }, + { column: "esquive", getter: (actor, context) => Mapping.getEsquive(context) }, + { column: "esquive-armure", getter: (actor, context) => Mapping.getEsquiveArmure(context) }, { column: "competences", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_COMPETENCES) }, { column: "draconic", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_DRACONIC) }, ] @@ -181,7 +183,7 @@ export class Mapping { const esquive = esquives[0] return { name: esquive.name, - niveau: Misc.toSignedString(esquive.system.niveau) + niveau: esquive.system.niveau } } return undefined @@ -242,10 +244,16 @@ export class Mapping { return context?.armure?.malus ?? 0 } - static getEsquiveNiveau(context) { + static getEsquive(context) { + if (context.esquive) { + return Misc.toSignedString(context.esquive.niveau) + } + return '' + } + static getEsquiveArmure(context) { if (context.esquive) { const niveau = context.esquive.niveau + context.armure.malus - return niveau > 0 ? ('+' + niveau) : ('' + niveau) + return Misc.toSignedString(niveau) } return '' } diff --git a/module/actor/random/app-personnage-aleatoire.js b/module/actor/random/app-personnage-aleatoire.js new file mode 100644 index 00000000..79d01576 --- /dev/null +++ b/module/actor/random/app-personnage-aleatoire.js @@ -0,0 +1,183 @@ +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 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}` + } + + +} diff --git a/module/dialog-create-signedraconique.js b/module/dialog-create-signedraconique.js index 3d38d29b..48cc1654 100644 --- a/module/dialog-create-signedraconique.js +++ b/module/dialog-create-signedraconique.js @@ -24,7 +24,7 @@ export class DialogCreateSigneDraconique extends Dialog { } constructor(dialogData, html) { - let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 500, height: 650, 'z-index': 99999 }; + let options = { classes: ["DialogCreateSigneDraconiqueActors"], width: 500, height: 650, 'z-index': 99999 }; let conf = { title: "Créer un signe", content: html, diff --git a/module/item-competence.js b/module/item-competence.js index b25ea07f..25c6659d 100644 --- a/module/item-competence.js +++ b/module/item-competence.js @@ -1,4 +1,5 @@ import { Grammar } from "./grammar.js"; +import { RdDItem } from "./item.js"; import { Misc } from "./misc.js"; const competenceTroncs = [["Esquive", "Dague", "Corps à corps"], @@ -23,12 +24,12 @@ const limitesArchetypes = [ ]; /* -------------------------------------------- */ -const categoriesCompetences = { +export const CATEGORIES_COMPETENCES = { "generale": { base: -4, label: "Générales" }, "particuliere": { base: -8, label: "Particulières" }, "specialisee": { base: -11, label: "Spécialisées" }, "connaissance": { base: -11, label: "Connaissances" }, - "draconic": { base: -11, label: "Draconics" }, + "draconic": { base: -11, label: "Draconic" }, "melee": { base: -6, label: "Mêlée" }, "tir": { base: -8, label: "Tir" }, "lancer": { base: -8, label: "Lancer" } @@ -48,16 +49,14 @@ function _buildCumulXP() { const competence_xp_cumul = _buildCumulXP(); export class RdDItemCompetence extends Item { - /* -------------------------------------------- */ - static getCategories() { - return categoriesCompetences; - } /* -------------------------------------------- */ static getLabelCategorie(category) { - return categoriesCompetences[category].label; + return CATEGORIES_COMPETENCES[category].label; } /* -------------------------------------------- */ - static getNiveauBase(category, categories = categoriesCompetences) { + /* -------------------------------------------- */ + static getNiveauBase(category, itemType) { + let categories = RdDItem.getCategories(itemType) return categories[category]?.base ?? 0; } @@ -191,7 +190,7 @@ export class RdDItemCompetence extends Item { /* -------------------------------------------- */ static isNiveauBase(item) { - return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.getCategories()); + return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.type); } /* -------------------------------------------- */ diff --git a/module/item-competencecreature.js b/module/item-competencecreature.js index 19ebf2c7..7e1ab4b5 100644 --- a/module/item-competencecreature.js +++ b/module/item-competencecreature.js @@ -2,7 +2,7 @@ import { ITEM_TYPES } from "./item.js"; import { RdDCombatManager } from "./rdd-combat.js"; -const categories = { +export const CATEGORIES_COMPETENCES_CREATURES = { "generale": { base: 0, label: "Générale" }, "naturelle": { base: 0, label: "Arme naturelle" }, "melee": { base: 0, label: "Mêlée" }, @@ -15,10 +15,6 @@ const categories = { /* -------------------------------------------- */ export class RdDItemCompetenceCreature extends Item { - static getCategories() { - return categories; - } - /* -------------------------------------------- */ static setRollDataCreature(rollData) { rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } } diff --git a/module/item-sheet.js b/module/item-sheet.js index a9292fbb..93e3a6c5 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -12,7 +12,7 @@ import { SystemCompendiums } from "./settings/system-compendiums.js"; import { Misc } from "./misc.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; -import { ITEM_TYPES } from "./item.js"; +import { ITEM_TYPES, RdDItem } from "./item.js"; /** * Extend the basic ItemSheet for RdD specific items @@ -107,7 +107,7 @@ export class RdDItemSheet extends ItemSheet { } const competences = await SystemCompendiums.getCompetences('personnage'); - formData.categories = this.item.getCategories() + formData.categories = RdDItem.getCategories(this.item.type) if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') { formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac) formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve) @@ -258,7 +258,7 @@ export class RdDItemSheet extends ItemSheet { if (this.item.isCompetence()) { const categorie = event.currentTarget.value; - const level = RdDItemCompetence.getNiveauBase(categorie, this.item.getCategories()); + const level = RdDItemCompetence.getNiveauBase(categorie, this.item.type); this.item.system.base = level; this.html.find('[name="system.base"]').val(level); } diff --git a/module/item.js b/module/item.js index fe6d25ad..b45373e2 100644 --- a/module/item.js +++ b/module/item.js @@ -6,8 +6,8 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDUtility } from "./rdd-utility.js"; import { SystemCompendiums } from "./settings/system-compendiums.js"; import { RdDRaretes } from "./item/raretes.js"; -import { RdDItemCompetence } from "./item-competence.js"; -import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; +import { CATEGORIES_COMPETENCES } from "./item-competence.js"; +import { CATEGORIES_COMPETENCES_CREATURES } from "./item-competencecreature.js"; export const ACTOR_TYPES = { personnage: 'personnage', @@ -172,9 +172,11 @@ export class RdDItem extends Item { static getItemTypesInventaire(mode = 'materiel') { return typesInventaire[mode ?? 'materiel'] } + static getItemTypesDraconiques() { return typesObjetsDraconiques; } + static getItemTypesEnvironnement() { return typesEnvironnement; } @@ -183,6 +185,16 @@ export class RdDItem extends Item { return typesObjetsOeuvres } + static getCategories(itemType) { + switch (itemType) { + case ITEM_TYPES.competence: + return CATEGORIES_COMPETENCES + case ITEM_TYPES.competencecreature: + return CATEGORIES_COMPETENCES_CREATURES + } + return {} + } + constructor(docData, context = {}) { if (!context.rdd?.ready) { foundry.utils.mergeObject(context, { rdd: { ready: true } }); @@ -262,13 +274,6 @@ export class RdDItem extends Item { isPresentDansMilieux(milieux) { return this.getEnvironnements(milieux).length > 0 } - getCategories() { - switch (this.type) { - case ITEM_TYPES.competence: return RdDItemCompetence.getCategories() - case ITEM_TYPES.competencecreature: return RdDItemCompetenceCreature.getCategories() - } - return {} - } getEnvironnements(milieux = undefined) { const environnements = this.isInventaire() ? this.system.environnement : undefined; diff --git a/module/rdd-carac.js b/module/rdd-carac.js index 1defe187..8668d9f0 100644 --- a/module/rdd-carac.js +++ b/module/rdd-carac.js @@ -3,38 +3,38 @@ import { Misc } from "./misc.js"; const TABLE_CARACTERISTIQUES_DERIVEES = { // xp: coût pour passer du niveau inférieur à ce niveau - 1: { xp: 3, poids: "moins de 1kg", plusdom: -5, sconst: 0.5, sust: 0.1 }, - 2: { xp: 3, poids: "1-5", plusdom: -4, sconst: 0.5, sust: 0.3 }, - 3: { xp: 4, poids: "6-10", plusdom: -3, sconst: 1, sust: 0.5, beaute: 'hideux' }, - 4: { xp: 4, poids: "11-20", plusdom: -3, sconst: 1, sust: 1, beaute: 'repoussant' }, - 5: { xp: 5, poids: "21-30", plusdom: -2, sconst: 1, sust: 1, beaute: 'franchement très laid' }, - 6: { xp: 5, poids: "31-40", plusdom: -1, sconst: 2, sust: 2, beaute: 'laid' }, - 7: { xp: 6, poids: "41-50", plusdom: -1, sconst: 2, sust: 2, beaute: 'très désavantagé' }, - 8: { xp: 6, poids: "51-60", plusdom: 0, sconst: 2, sust: 2, beaute: 'désavantagé' }, - 9: { xp: 7, poids: "61-65", plusdom: 0, sconst: 3, sust: 2, beaute: 'pas terrible' }, - 10: { xp: 7, poids: "66-70", plusdom: 0, sconst: 3, sust: 3, beaute: 'commun' }, - 11: { xp: 8, poids: "71-75", plusdom: 0, sconst: 3, sust: 3, beaute: 'pas mal' }, - 12: { xp: 8, poids: "76-80", plusdom: +1, sconst: 4, sust: 3, beaute: 'avantagé' }, - 13: { xp: 9, poids: "81-90", plusdom: +1, sconst: 4, sust: 3, beaute: 'mignon' }, - 14: { xp: 9, poids: "91-100", plusdom: +2, sconst: 4, sust: 4, beaute: 'beau' }, - 15: { xp: 10, poids: "101-110", plusdom: +2, sconst: 5, sust: 4, beaute: 'très beau' }, - 16: { xp: 20, poids: "111-120", plusdom: +3, sconst: 5, sust: 4, beaute: 'éblouissant' }, - 17: { xp: 30, poids: "121-131", plusdom: +3, sconst: 5, sust: 5 }, - 18: { xp: 40, poids: "131-141", plusdom: +4, sconst: 6, sust: 5 }, - 19: { xp: 50, poids: "141-150", plusdom: +4, sconst: 6, sust: 5 }, - 20: { xp: 60, poids: "151-160", plusdom: +4, sconst: 6, sust: 6 }, - 21: { xp: 70, poids: "161-180", plusdom: +5, sconst: 7, sust: 6 }, - 22: { xp: 80, poids: "181-200", plusdom: +5, sconst: 7, sust: 7 }, - 23: { xp: 90, poids: "201-300", plusdom: +6, sconst: 7, sust: 8 }, - 24: { xp: 100, poids: "301-400", plusdom: +6, sconst: 8, sust: 9 }, - 25: { xp: 110, poids: "401-500", plusdom: +7, sconst: 8, sust: 10 }, - 26: { xp: 120, poids: "501-600", plusdom: +7, sconst: 8, sust: 11 }, - 27: { xp: 130, poids: "601-700", plusdom: +8, sconst: 9, sust: 12 }, - 28: { xp: 140, poids: "701-800", plusdom: +8, sconst: 9, sust: 13 }, - 29: { xp: 150, poids: "801-900", plusdom: +9, sconst: 9, sust: 14 }, - 30: { xp: 160, poids: "901-1000", plusdom: +9, sconst: 10, sust: 15 }, - 31: { xp: 170, poids: "1001-1500", plusdom: +10, sconst: 10, sust: 16 }, - 32: { xp: 180, poids: "1501-2000", plusdom: +11, sconst: 10, sust: 17 } + 1: { xp: 3, poids: "moins de 1kg", poidsMin: 0, poidsMax: 1, plusdom: -5, sconst: 0.5, sust: 0.1 }, + 2: { xp: 3, poids: "1-5", poidsMin: 1, poidsMax: 5, plusdom: -4, sconst: 0.5, sust: 0.3 }, + 3: { xp: 4, poids: "6-10", poidsMin: 6, poidsMax: 10, plusdom: -3, sconst: 1, sust: 0.5, beaute: 'hideux' }, + 4: { xp: 4, poids: "11-20", poidsMin: 11, poidsMax: 20, plusdom: -3, sconst: 1, sust: 1, beaute: 'repoussant' }, + 5: { xp: 5, poids: "21-30", poidsMin: 21, poidsMax: 30, plusdom: -2, sconst: 1, sust: 1, beaute: 'franchement très laid' }, + 6: { xp: 5, poids: "31-40", poidsMin: 31, poidsMax: 40, plusdom: -1, sconst: 2, sust: 2, beaute: 'laid' }, + 7: { xp: 6, poids: "41-50", poidsMin: 41, poidsMax: 50, plusdom: -1, sconst: 2, sust: 2, beaute: 'très désavantagé' }, + 8: { xp: 6, poids: "51-60", poidsMin: 51, poidsMax: 60, plusdom: 0, sconst: 2, sust: 2, beaute: 'désavantagé' }, + 9: { xp: 7, poids: "61-65", poidsMin: 61, poidsMax: 65, plusdom: 0, sconst: 3, sust: 2, beaute: 'pas terrible' }, + 10: { xp: 7, poids: "66-70", poidsMin: 66, poidsMax: 70, plusdom: 0, sconst: 3, sust: 3, beaute: 'commun' }, + 11: { xp: 8, poids: "71-75", poidsMin: 71, poidsMax: 75, plusdom: 0, sconst: 3, sust: 3, beaute: 'pas mal' }, + 12: { xp: 8, poids: "76-80", poidsMin: 76, poidsMax: 80, plusdom: +1, sconst: 4, sust: 3, beaute: 'avantagé' }, + 13: { xp: 9, poids: "81-90", poidsMin: 81, poidsMax: 90, plusdom: +1, sconst: 4, sust: 3, beaute: 'mignon' }, + 14: { xp: 9, poids: "91-100", poidsMin: 91, poidsMax: 100, plusdom: +2, sconst: 4, sust: 4, beaute: 'beau' }, + 15: { xp: 10, poids: "101-110", poidsMin: 101, poidsMax: 110, plusdom: +2, sconst: 5, sust: 4, beaute: 'très beau' }, + 16: { xp: 20, poids: "111-120", poidsMin: 111, poidsMax: 120, plusdom: +3, sconst: 5, sust: 4, beaute: 'éblouissant' }, + 17: { xp: 30, poids: "121-131", poidsMin: 121, poidsMax: 131, plusdom: +3, sconst: 5, sust: 5 }, + 18: { xp: 40, poids: "131-141", poidsMin: 131, poidsMax: 141, plusdom: +4, sconst: 6, sust: 5 }, + 19: { xp: 50, poids: "141-150", poidsMin: 141, poidsMax: 150, plusdom: +4, sconst: 6, sust: 5 }, + 20: { xp: 60, poids: "151-160", poidsMin: 151, poidsMax: 160, plusdom: +4, sconst: 6, sust: 6 }, + 21: { xp: 70, poids: "161-180", poidsMin: 161, poidsMax: 180, plusdom: +5, sconst: 7, sust: 6 }, + 22: { xp: 80, poids: "181-200", poidsMin: 181, poidsMax: 200, plusdom: +5, sconst: 7, sust: 7 }, + 23: { xp: 90, poids: "201-300", poidsMin: 201, poidsMax: 300, plusdom: +6, sconst: 7, sust: 8 }, + 24: { xp: 100, poids: "301-400", poidsMin: 301, poidsMax: 400, plusdom: +6, sconst: 8, sust: 9 }, + 25: { xp: 110, poids: "401-500", poidsMin: 401, poidsMax: 500, plusdom: +7, sconst: 8, sust: 10 }, + 26: { xp: 120, poids: "501-600", poidsMin: 501, poidsMax: 600, plusdom: +7, sconst: 8, sust: 11 }, + 27: { xp: 130, poids: "601-700", poidsMin: 601, poidsMax: 700, plusdom: +8, sconst: 9, sust: 12 }, + 28: { xp: 140, poids: "701-800", poidsMin: 701, poidsMax: 800, plusdom: +8, sconst: 9, sust: 13 }, + 29: { xp: 150, poids: "801-900", poidsMin: 801, poidsMax: 900, plusdom: +9, sconst: 9, sust: 14 }, + 30: { xp: 160, poids: "901-1000", poidsMin: 901, poidsMax: 1000, plusdom: +9, sconst: 10, sust: 15 }, + 31: { xp: 170, poids: "1001-1500", poidsMin: 1001, poidsMax: 1500, plusdom: +10, sconst: 10, sust: 16 }, + 32: { xp: 180, poids: "1501-2000", poidsMin: 1501, poidsMax: 2000, plusdom: +11, sconst: 10, sust: 17 } }; export class RdDCarac { diff --git a/module/rdd-commands.js b/module/rdd-commands.js index 88b08dc3..03b0ba8e 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -81,7 +81,7 @@ export class RdDCommands { this.registerCommand({ path: ["/sommeil"], func: (content, msg, params) => this.sommeil(msg, params), descr: "Prépare le passage de journée pour chateau dormant" }); this.registerCommand({ path: ["/meteo"], func: (content, msg, params) => this.getMeteo(msg, params), descr: "Propose une météo marine" }); - this.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" }); + this.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.proposeName(msg, params), descr: "Génère un nom aléatoire" }); this.registerCommand({ path: ["/tmr"], func: (content, msg, params) => this.findTMR(msg, params), diff --git a/module/rdd-dice.js b/module/rdd-dice.js index 2f9dc10f..cdc5c74f 100644 --- a/module/rdd-dice.js +++ b/module/rdd-dice.js @@ -132,6 +132,10 @@ export class RdDDice { } } + static async rollHeure(options = { showDice: HIDE_DICE }) { + return await RdDDice.rollTotal("1dh", options) - 1 + } + static async rollTotal(formula, options = { showDice: HIDE_DICE }) { return (await RdDDice.roll(formula, options)).total; } diff --git a/module/rdd-namegen.js b/module/rdd-namegen.js index b27ea5bc..80a47450 100644 --- a/module/rdd-namegen.js +++ b/module/rdd-namegen.js @@ -11,13 +11,17 @@ const words = ['pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', /* -------------------------------------------- */ export class RdDNameGen { - static async getName(msg, params) { + static async proposeName(msg, params) { const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-command-nom.html`, { - nom: Misc.upperFirst(await RdDDice.rollOneOf(words) + await RdDDice.rollOneOf(words)) + nom: await RdDNameGen.generate() }); ChatMessage.create({ content: html, whisper: ChatMessage.getWhisperRecipients("GM") }); } + static async generate() { + return Misc.upperFirst(await RdDDice.rollOneOf(words) + await RdDDice.rollOneOf(words)); + } + static async onCreerActeur(event) { const button = event.currentTarget; await RdDBaseActor.create({ diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 661d9cf8..086c0fff 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -169,6 +169,7 @@ export class RdDUtility { 'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html', + 'systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs', //Items 'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs', 'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs', diff --git a/module/time/rdd-calendrier.js b/module/time/rdd-calendrier.js index a56df1ce..b5b41088 100644 --- a/module/time/rdd-calendrier.js +++ b/module/time/rdd-calendrier.js @@ -227,7 +227,7 @@ export class RdDCalendrier extends Application { /* -------------------------------------------- */ async ajouterNombreAstral(indexDate) { - const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: HIDE_DICE, rollMode: "selfroll" }); + const nombreAstral = await RdDDice.rollHeure( { showDice: HIDE_DICE, rollMode: "selfroll" }); return { nombreAstral: nombreAstral, lectures: [], diff --git a/system.json b/system.json index 57ac8cac..c24b1675 100644 --- a/system.json +++ b/system.json @@ -1,8 +1,8 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "12.0.10", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.10.zip", + "version": "12.0.11", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.11.zip", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", "compatibility": { @@ -534,6 +534,7 @@ }, "primaryTokenAttribute": "sante.vie", "secondaryTokenAttribute": "sante.endurance", + "background": "systems/foundryvtt-reve-de-dragon/styles/img/reve-de-dragon-cover.webp", "media": [ { "type": "icon", diff --git a/template.json b/template.json index c3d58e20..815e9a35 100644 --- a/template.json +++ b/template.json @@ -15,6 +15,7 @@ } }, "background": { + "metier": "", "biographie": "Histoire personnelle...", "notes": "Notes", "notesmj": "Notes du MJ", diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 4f849b8b..58bf0955 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -172,6 +172,10 @@ +