From d77f046a6acc37bbd8da6b10df0a146cea12dd9c Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Sat, 5 Nov 2022 18:19:53 +0100 Subject: [PATCH] Ajout d'Item rencontre MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pour l'instant, pas utilisée. Une rencontre permettra de définir les différents effets de la rencontre. Un compendium dédié donnera les rencontres possibles. --- lang/fr.json | 3 +- module/item-rencontre-sheet.js | 109 +++++++++++++ module/item-rencontre.js | 60 +++++++ module/item-signedraconique-sheet.js | 3 +- module/item.js | 17 +- module/rdd-main.js | 18 ++- module/rdd-utility.js | 2 + module/tmr-rencontres.js | 2 +- styles/simple.css | 35 ++++ template.json | 55 ++++++- templates/item-rencontre-sheet.html | 232 +++++++++++++++++++++++++++ 11 files changed, 524 insertions(+), 12 deletions(-) create mode 100644 module/item-rencontre-sheet.js create mode 100644 module/item-rencontre.js create mode 100644 templates/item-rencontre-sheet.html diff --git a/lang/fr.json b/lang/fr.json index 3201992b..465f180a 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -15,7 +15,8 @@ "TypeNombreastral": "Nombre astral", "TypeTarot": "Carte de tarot", "TypeCasetmr": "TMR spéciale", - "TypeRencontrestmr": "Rencontre TMR", + "TypeRencontre": "Rencontre TMR", + "TypeRencontrestmr": "Rencontre TMR (ancien)", "TypeMunition": "Munition", "TypeMonnaie": "Monnaie", "TypeHerbe": "Herbe ou plante", diff --git a/module/item-rencontre-sheet.js b/module/item-rencontre-sheet.js new file mode 100644 index 00000000..46b2b54b --- /dev/null +++ b/module/item-rencontre-sheet.js @@ -0,0 +1,109 @@ +import { SYSTEM_RDD } from "./constants.js"; +import { RdDRencontre } from "./item-rencontre.js"; + +/** + * Item sheet pour configurer les rencontres + * @extends {ItemSheet} + */ +export class RdDRencontreItemSheet extends ItemSheet { + + /** @override */ + static get defaultOptions() { + return mergeObject(super.defaultOptions, { + classes: ["rdd", "sheet", "item"], + template: "systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html", + width: 500, + height: 500, + tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }] + }); + } + + /* -------------------------------------------- */ + _getHeaderButtons() { + let buttons = super._getHeaderButtons(); + buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => this.item.postItem() }); + return buttons; + } + + /* -------------------------------------------- */ + /** @override */ + setPosition(options = {}) { + const position = super.setPosition(options); + const sheetHeader = this.element.find(".sheet-header"); + const sheetBody = this.element.find(".sheet-body"); + sheetBody.css("height", position.height - sheetHeader[0].clientHeight) + return position; + } + + + /* -------------------------------------------- */ + async getData() { + const formData = duplicate(this.item); + mergeObject(formData, { + title: formData.name, + isGM: game.user.isGM, + owner: this.actor?.isOwner, + isOwned: this.actor ? true : false, + actorId: this.actor?.id, + editable: this.isEditable, + cssClass: this.isEditable ? "editable" : "locked", + effets: { + succes: { + liste: RdDRencontre.getEffetsSucces(), + select: RdDRencontre.mapEffets(this.item.system.succes.effets) + }, + echec: { + liste: RdDRencontre.getEffetsEchec(), + select: RdDRencontre.mapEffets(this.item.system.echec.effets) + } + } + }); + return formData; + } + + /* -------------------------------------------- */ + /** @override */ + activateListeners(html) { + super.activateListeners(html); + if (!this.options.editable) return; + html.find("a.effet-add").click(event => this.onAddEffet(event)); + html.find("a.effet-delete").click(event => this.onDeleteEffet(event)); + } + + async onAddEffet(event) { + const resultat = $(event.currentTarget)?.data("effet-resultat"); + const keyEffets = `system.${resultat}.effets`; + + const code = $(event.currentTarget)?.data("effet-code"); + const liste = RdDRencontre.getListeEffets(this.item, resultat); + liste.push(code); + + await this._updateEffetsRencontre(keyEffets, liste); + } + + async onDeleteEffet(event) { + const resultat = $(event.currentTarget)?.data("effet-resultat"); + const keyEffets = `system.${resultat}.effets`; + + const pos = $(event.currentTarget)?.data("effet-pos"); + const liste = RdDRencontre.getListeEffets(this.item, resultat); + liste.splice(pos, 1); + + await this._updateEffetsRencontre(keyEffets, liste); + } + + async _updateEffetsRencontre(key, liste) { + const updates = {}; + updates[key] = liste; + this.item.update(updates); + } + + get template() { + /* -------------------------------------------- */ + return `systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html`; + } + + get title() { + return `Rencontre: ${this.object.name}`; + } +} diff --git a/module/item-rencontre.js b/module/item-rencontre.js new file mode 100644 index 00000000..66454b34 --- /dev/null +++ b/module/item-rencontre.js @@ -0,0 +1,60 @@ +import { RdDRollTables } from "./rdd-rolltables.js"; + +const tableEffets = [ + { code: "messager", resultat: "succes", description: "Envoie un message à (force) cases" }, + { code: "passeur", resultat: "succes", description: "Déplacer le demi-rêve à (force) cases" }, + { code: "reve+f", resultat: "succes", description: "Gain de (force) points de rêve" }, + { code: "teleport", resultat: "succes", description: "Déplacer le demi-rêve (même type de case)" }, + { code: "part+tete", resultat: "succes", description: "Tête de dragon sur réussite particulière" }, + { code: "part+xp", resultat: "succes", description: "Expérience sur réussite particulière" }, + + { code: "reve-1", resultat: "echec", description: "Perte de 1 point de rêve" }, + { code: "reve-f", resultat: "echec", description: "Perte de (force) points de rêve" }, + { code: "vie-1", resultat: "echec", description: "Perte de 1 point de vie" }, + { code: "reinsere", resultat: "echec", description: "Réinsertion aléatoire" }, + { code: "declenhe", resultat: "echec", description: "Déclenche un sort aléatoire" }, + { code: "persistant", resultat: "echec", description: "Bloque le demi-rêve" }, + { code: "teleport-aleatoire", resultat: "echec", description: "Déplacement aléatoire (même type de case)" }, + { code: "aleatoire", resultat: "echec", description: "Déplacement aléatoire" }, + { code: "sort-aleatoire", resultat: "echec", description: "Déplacement pour déclencher un sort en réserve aléatoire" }, + { code: "rompu", resultat: "echec", description: "Demi-rêve interrompu" }, + { code: "echec-queue", resultat: "echec", description: "Queue de dragon sur échec" }, + { code: "etotal-queue", resultat: "echec", description: "Queue de dragon sur échec total" }, + + { code: "moral+1", resultat: "succes", description: "Gain de 1 point de moral" }, + { code: "reve+1", resultat: "succes", description: "Gain de 1 point de rêve" }, + { code: "vie-f", resultat: "echec", description: "Perte de (force) point de vie" }, + { code: "endurance-1", resultat: "echec", description: "Perte de 1 point d'endurance" }, + { code: "endurance-f", resultat: "echec", description: "Perte de (force) point d'endurance" }, + { code: "fatigue-1", resultat: "echec", description: "Perte de 1 point de fatigue" }, + { code: "fatigue-f", resultat: "echec", description: "Perte de (force) point de fatigue" }, + { code: "moral-1", resultat: "echec", description: "Perte de 1 point de moral" }, + { code: "chance-1", resultat: "echec", description: "Perte de 1 point de chance actuelle" }, + { code: "chance-f", resultat: "echec", description: "Perte de (force) point de chance" }, + { code: "epart-queue", resultat: "echec", description: "Queue de dragon sur échec particulier" }, + { code: "etotal-souffle", resultat: "echec", description: "Souffle de dragon sur échec total" }, + { code: "epart-souffle", resultat: "echec", description: "Souffle de dragon sur échec particulier" }, +]; + +export class RdDRencontre { + static getEffets(resultat) { + return tableEffets.filter(e => resultat == e.resultat); + } + static getEffetsSucces() { return RdDRencontre.getEffets("succes"); } + static getEffetsEchec() { return RdDRencontre.getEffets("echec"); } + + static mapEffets(liste) { + return liste.map(it => tableEffets.find(e => it == e.code)); + } + + static getListeEffets(item, reussite) { + if (reussite == 'echec') { + return [...item.system.echec.effets]; + } + if (reussite == 'succes') { + return [...item.system.succes.effets]; + } + return []; + } + +} diff --git a/module/item-signedraconique-sheet.js b/module/item-signedraconique-sheet.js index 3e013f4b..f3c33fdd 100644 --- a/module/item-signedraconique-sheet.js +++ b/module/item-signedraconique-sheet.js @@ -1,7 +1,6 @@ import { SYSTEM_RDD } from "./constants.js"; import { RdDItemSigneDraconique } from "./item-signedraconique.js"; -import { Misc } from "./misc.js"; -import { TMRType, TMRUtility } from "./tmr-utility.js"; +import { TMRUtility } from "./tmr-utility.js"; /** * Item sheet pour signes draconiques diff --git a/module/item.js b/module/item.js index e3ab374b..9f2396fe 100644 --- a/module/item.js +++ b/module/item.js @@ -18,7 +18,7 @@ const typesObjetsEquipement = [ "potion", ] const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"] -const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve"] +const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"] const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"] const typesObjetsEffet = ["possession", "poison", "maladie"] const typesObjetsCompetence = ["competence", "competencecreature"] @@ -38,6 +38,7 @@ export const defaultItemImg = { ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp", livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp", potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp", + rencontre: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp", queue: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp", ombre: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp", souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp", @@ -504,6 +505,20 @@ export class RdDItem extends Item { ] } /* -------------------------------------------- */ + _rencontreChatData() { + if (this.system.coord) { + return [ + `Force: ${this.system.force}`, + `Coordonnées: ${this.system.coord}`, + ] + } + return [ + `Force: ${this.system.force}`, + `Refoulement: ${this.system.refoulement}`, + `Présent de cités: ${this.system.presentCite}`, + ] + } + /* -------------------------------------------- */ _casetmrChatData() { return [ `Coordonnée: ${this.system.coord}`, diff --git a/module/rdd-main.js b/module/rdd-main.js index 0b1146c9..81a80311 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -38,6 +38,7 @@ import { Misc } from "./misc.js"; import { Migrations } from './migrations.js'; import { DialogChronologie } from "./dialog-chronologie.js"; import { SystemCompendiums } from "./settings/system-compendiums.js"; +import { RdDRencontreItemSheet } from "./item-rencontre-sheet.js"; /* -------------------------------------------- */ /* Foundry VTT Initialization */ @@ -188,10 +189,21 @@ Hooks.once("init", async function () { types: ["signedraconique"], makeDefault: true }); + Items.registerSheet(SYSTEM_RDD, RdDRencontreItemSheet, { + label: "Rencontre", + types: ["rencontre"], + makeDefault: true + }); Items.registerSheet(SYSTEM_RDD, RdDItemSheet, { - types: ["arme", "armure", "objet", "arme", "armure", "conteneur", "competence", "sort", "herbe", "ingredient", "livre", "potion", "munition", "rencontresTMR", "queue", "ombre", "souffle", - "tete", "competencecreature", "tarot", "monnaie", "nombreastral", "tache", "meditation", "casetmr", "recettealchimique", "gemme", - "musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre", "nourritureboisson", "possession", "sortreserve"], makeDefault: true + types: [ + "competence", "competencecreature", + "recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre", + "objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", + "monnaie", "nourritureboisson", "gemme", + "meditation", "rencontresTMR", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve", + "nombreastral", "tache", "maladie", "poison", "possession", + "tarot" + ], makeDefault: true }); CONFIG.Combat.documentClass = RdDCombatManager; diff --git a/module/rdd-utility.js b/module/rdd-utility.js index e23d3377..16fd06fd 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -181,6 +181,7 @@ export class RdDUtility { 'systems/foundryvtt-reve-de-dragon/templates/item-livre-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-tache-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-potion-sheet.html', + 'systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-rencontresTMR-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-souffle-sheet.html', @@ -279,6 +280,7 @@ export class RdDUtility { Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord)); Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord)); Handlebars.registerHelper('typeTmr-name', coord => TMRUtility.typeTmrName(coord)); + Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord)); Handlebars.registerHelper('signeHeure', (key, heure) => RdDCalendrier.getSigneAs(key, heure)); Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1))); Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option)); diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js index d10ea9be..a7b543ae 100644 --- a/module/tmr-rencontres.js +++ b/module/tmr-rencontres.js @@ -11,7 +11,7 @@ const typeRencontres = { if (rencData.actor.isTMRCache()){ return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort, mais vous ne savez pas où vous êtes.`; } - return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`; + return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases de ${rencData.tmr.label}.`; }, msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`, postSucces: async (tmrDialog, rencData) => { diff --git a/styles/simple.css b/styles/simple.css index 7256ae59..5915b626 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -1657,6 +1657,41 @@ display: inline-flex; position:relative; top:1px; } +/* Dropdown Content (Hidden by Default) */ +.button-dropdown-content { + display: none; + position: absolute; + width: max-content; + box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2); + background: var(--background-tooltip) ; + overflow-y: scroll; + max-height: 14rem; + z-index: 10; +} + +.button-dropdown { + position: relative; + display: inline-block; +} +/* Change the background color of the dropdown button when the dropdown content is shown */ +.button-dropdown:hover .button-dropbutton { + text-shadow: 1px 0px 0px #ff6600; +} +/* Show the dropdown menu on hover */ +.button-dropdown:hover .button-dropdown-content {display: block;} + +/* Links inside the dropdown */ +.button-dropdown-content a { + color: black; + padding: 0.2rem 0.4rem; + text-decoration: none; + display: block; +} + +/* Change color of dropdown links on hover */ +.button-dropdown-content a:hover {background-color: #ddd;} + + /*************************************************************/ #pause diff --git a/template.json b/template.json index 63d46cba..525206b4 100644 --- a/template.json +++ b/template.json @@ -587,10 +587,15 @@ } }, "Item": { - "types": ["objet", "arme", "armure", "conteneur", "competence", "sort", "herbe", "ingredient", "livre", "potion", "munition", "rencontresTMR", "queue", "ombre", "souffle", - "tete", "competencecreature", "tarot", "monnaie", "nombreastral", "tache", "meditation", "casetmr", "recettealchimique", - "musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre", "nourritureboisson", "signedraconique", "gemme", - "possession", "sortreserve" ], + "types": [ + "competence", "competencecreature", + "recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre", + "objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", + "monnaie", "nourritureboisson", "gemme", + "meditation", "rencontre", "rencontresTMR", "queue", "ombre", "souffle", "tete", "casetmr", "signedraconique", "sort", "sortreserve", + "nombreastral", "tache", "maladie", "poison", "possession", + "tarot" + ], "possession": { "typepossession": "", "possede": false, @@ -786,6 +791,48 @@ "prdate": 0, "cout": 0 }, + "rencontre": { + "genre": "f", + "formule": "2d4", + "refoulement": 1, + "presentCite": false, + "mauvaiseRencontre": false, + "ordreTri": 0, + "force": 0, + "coord": "", + "date": "", + "heure": "", + "succes": { + "effets": [], + "message": "", + "poesie": "", + "reference":"" + }, + "echec": { + "effets": [], + "message": "", + "poesie": "", + "reference": "" + }, + "frequence": { + "cite": 0, + "sanctuaire": 0, + "plaines": 0, + "pont": 0, + "collines": 0, + "foret": 0, + "monts": 0, + "desert": 0, + "fleuve": 0, + "lac": 0, + "marais": 0, + "gouffre": 0, + "necropole": 0, + "desolation": 0, + "mauvaise": 0 + }, + "description": "" + }, "rencontresTMR": { "description": "", "descriptionmj": "" diff --git a/templates/item-rencontre-sheet.html b/templates/item-rencontre-sheet.html new file mode 100644 index 00000000..42ba135b --- /dev/null +++ b/templates/item-rencontre-sheet.html @@ -0,0 +1,232 @@ +
+ {{>"systems/foundryvtt-reve-de-dragon/templates/header-item.html"}} + {{!-- Sheet Body --}} + + +
+ +
+ {{#if isOwned}} +
+ + +
+
+ + +
+
+ +
+ + +
+
+ {{else}} +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ {{/if}} +
+ + +
+ {{#unless isOwned}} + {{#if system.mauvaiseRencontre}} +
+ + +
+ {{/if}} + {{/unless}} +
+ +
+ {{editor description target="system.description" button=true owner=owner editable=editable}} +
+
+
+ +
+
+ + +
+
+
+ {{#if isGM}} + +
+ {{#each effets.succes.liste as |effet|}} + {{effet.description}} + {{/each}} +
+ {{else}} + + {{/if}} +
+
+
+ +
+ {{#each effets.succes.select as |effet pos|}} + + {{/each}} +
+
+
+
+ + +
+
+ +
+ {{editor system.succes.poesie target="system.succes.poesie" button=true owner=owner editable=editable}} +
+
+
+ +
+
+ + +
+
+
+ {{#if isGM}} + +
+ {{#each effets.echec.liste as |effet|}} + {{effet.description}} + {{/each}} +
+ {{else}} + + {{/if}} +
+
+
+ +
+ {{#each effets.echec.select as |effet pos|}} + + {{/each}} +
+
+
+
+ + +
+
+ +
+ {{editor system.echec.poesie target="system.echec.poesie" button=true owner=owner editable=editable}} +
+
+
+ + {{#unless system.mauvaiseRencontre}} +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ {{/unless}} +
+