diff --git a/module/actor.js b/module/actor.js index acf82344..2fd87cb3 100644 --- a/module/actor.js +++ b/module/actor.js @@ -32,7 +32,7 @@ import { RdDConfirm } from "./rdd-confirm.js"; import { DialogValidationEncaissement } from "./dialog-validation-encaissement.js"; import { RdDRencontre } from "./item/rencontre.js"; import { Targets } from "./targets.js"; -import { DialogRepos } from "./dialog-repos.js"; +import { DialogRepos } from "./sommeil/dialog-repos.js"; import { RdDBaseActor } from "./actor/base-actor.js"; import { RdDTimestamp } from "./rdd-timestamp.js"; import { RdDItemTache } from "./item-tache.js"; @@ -208,6 +208,7 @@ export class RdDActor extends RdDBaseActor { } return etatGeneral } + /* -------------------------------------------- */ getActivePoisons() { return duplicate(this.items.filter(item => item.type == 'poison' && item.system.active)) @@ -359,6 +360,33 @@ export class RdDActor extends RdDBaseActor { dialog.render(true); } + async prepareChateauDormant(finChateauDormant, consignes) { + if (consignes.ignorer) { + return; + } + if (consignes.stress.valeur > 0) { + await this.distribuerStress('stress', consignes.stress.valeur, consignes.stress.motif); + } + if (!consignes.sommeil?.insomnie) { + await this.update({ + "system.sommeil": { + nouveaujour: true, + date: finChateauDormant, + moral: consignes.sommeil?.moral ?? 'neutre', + heures: consignes.sommeil?.heures ?? 4 + } + }) + } + } + + async onTimeChanging(oldTimestamp, newTimestamp) { + await super.onTimeChanging(oldTimestamp, newTimestamp); + const insomnie = EffetsDraconiques.isSujetInsomnie(this); + if (!this.system.sommeil || this.system.sommeil.insomnie || insomnie) { + await this.update({ 'system.sommeil.insomnie': insomnie }); + } + } + async repos() { await DialogRepos.create(this); } @@ -370,7 +398,7 @@ export class RdDActor extends RdDBaseActor { content: `${nGrisReve} jours de gris rêve sont passés. ` }; for (let i = 0; i < nGrisReve; i++) { - await this.dormir(6, { grisReve: true }); + await this.dormir(4, { grisReve: true }); await this._recuperationSante(message); const moralActuel = Misc.toInt(this.system.compteurs.moral.value); @@ -381,6 +409,14 @@ export class RdDActor extends RdDBaseActor { await this.transformerStress(); this.bonusRecuperationPotion = 0; // Reset potion } + await this.update({ + "system.sommeil": { + nouveaujour: false, + moral: "neutre", + heures: 0 + } + }) + ChatMessage.create(message); this.sheet.render(true); } @@ -424,25 +460,35 @@ export class RdDActor extends RdDBaseActor { /* -------------------------------------------- */ async dormirChateauDormant() { - let message = { - whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), - content: "" - }; + if (!ReglesOptionelles.isUsing("chateau-dormant-gardien") || !this.system.sommeil || this.system.sommeil?.nouveaujour) { + const message = { + whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), + content: "" + }; - const blessures = duplicate(this.system.blessures) - await this._recuperationSante(message) - await this._jetDeMoralChateauDormant(message); - await this._recupereChance(); - await this.transformerStress(); - await this.retourSeuilDeReve(message); - this.bonusRecuperationPotion = 0; // Reset potion - await this.retourSust(message); - await this.verifierPotionsEnchantees(); - if (message.content != "") { - message.content = `A la fin Chateau Dormant, ${message.content}
Un nouveau jour se lève`; - ChatMessage.create(message); + await this._recuperationSante(message) + await this._jetDeMoralChateauDormant(message); + await this._recupereChance(); + if (!this.system.sommeil?.insomnie) { + await this.transformerStress(); + } + await this.retourSeuilDeReve(message); + this.bonusRecuperationPotion = 0; // Reset potion + await this.retourSust(message); + await this.verifierPotionsEnchantees(); + if (message.content != "") { + message.content = `A la fin Chateau Dormant, ${message.content}
Un nouveau jour se lève`; + ChatMessage.create(message); + } + await this.update({ + "system.sommeil": { + nouveaujour: false, + moral: "neutre", + heures: 0 + } + }); + this.sheet.render(true); } - this.sheet.render(true); } /* -------------------------------------------- */ @@ -456,9 +502,11 @@ export class RdDActor extends RdDBaseActor { } async _jetDeMoralChateauDormant(message) { - const jetMoral = await this._jetDeMoral('neutre'); - message.content += ' -- le moral ' + this._messageAjustementMoral(jetMoral.ajustement); + const etatMoral = this.system.sommeil?.moral ?? 'neutre'; + const jetMoral = await this._jetDeMoral(etatMoral); + message.content += ` -- le jet de moral est ${etatMoral}, le moral ` + this._messageAjustementMoral(jetMoral.ajustement); } + _messageAjustementMoral(ajustement) { switch (Math.sign(ajustement)) { case 1: @@ -591,59 +639,70 @@ export class RdDActor extends RdDBaseActor { } /* -------------------------------------------- */ - async dormir(heures, options = { grisReve: false }) { - let message = { + async dormir(sommeilHeures, options = { grisReve: false, chateauDormant: false }) { + const sommeil = !this.system.sommeil?.insomnie || options.grisReve; + const message = { whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), content: "" }; await this.recupereEndurance(message); let sep = "" let recuperationReve = ""; - let i = 0; - for (; i < heures; i++) { + let heuresDormies = 0; + for (; heuresDormies < sommeilHeures; heuresDormies++) { await this._recupererEthylisme(message); - await this.recupererFatigue(message); - if (!options.grisReve) { - let r = await this.recuperationReve(message); - if (r >= 0) { - recuperationReve += sep + r; - sep = "+"; - } + if (sommeil) { + await this.recupererFatigue(message); + if (!options.grisReve) { + if (sommeil) { + let r = await this.recuperationReve(message); + if (r >= 0) { + recuperationReve += sep + r; + sep = "+"; + } - if (r >= 0 && EffetsDraconiques.isDonDoubleReve(this)) { - r = await this.recuperationReve(message); - if (r >= 0) { - recuperationReve += sep + r; + if (r >= 0 && EffetsDraconiques.isDonDoubleReve(this)) { + r = await this.recuperationReve(message); + if (r >= 0) { + recuperationReve += sep + r; + } + } + if (r < 0) { + heuresDormies++;// rêve de dragon pendant l'heure en cours + break; + } } } - if (r < 0) { - i++;// rêve de dragon pendant l'heure en cours - break; - } } } if (!options.grisReve) { - message.content = `${this.name}: Vous dormez ${i == 0 ? 'une' : i} heure${i == 1 ? '' : 's'}. ` + const repos = this.system.sommeil?.insomnie ? "vous reposez" : "dormez" + message.content = `${this.name}: Vous ${repos} ${heuresDormies <= 1 ? 'une heure' : (heuresDormies + ' heures')}. ` + (recuperationReve == "" ? "" : `Vous récupérez ${recuperationReve} Points de rêve. `) + message.content; ChatMessage.create(message); } - this.sheet.render(true); - return i; + if (options.chateauDormant && heuresDormies == sommeilHeures) { + await this.dormirChateauDormant(); + } + else { + this.sheet.render(true); + } } /* -------------------------------------------- */ async _recupererEthylisme(message) { - let ethylisme = duplicate(this.system.compteurs.ethylisme); - ethylisme.nb_doses = 0; - ethylisme.jet_moral = false; - if (ethylisme.value < 1) { - ethylisme.value = Math.min(ethylisme.value + 1, 1); - if (ethylisme.value <= 0) { - message.content += `Vous dégrisez un peu (${RdDUtility.getNomEthylisme(ethylisme.value)}). `; - } + let value = Math.min(Number.parseInt(this.system.compteurs.ethylisme.value) + 1, 1); + if (value <= 0) { + message.content += `Vous dégrisez un peu (${RdDUtility.getNomEthylisme(value)}). `; } - await this.update({ "system.compteurs.ethylisme": ethylisme }); + await this.update({ + "system.compteurs.ethylisme": { + nb_doses: 0, + jet_moral: false, + value: value + } + }); } /* -------------------------------------------- */ @@ -651,7 +710,7 @@ export class RdDActor extends RdDBaseActor { const manquant = this._computeEnduranceMax() - this.system.sante.endurance.value; if (manquant > 0) { await this.santeIncDec("endurance", manquant); - message.content += "Vous récuperez " + manquant + " points d'endurance. "; + message.content += `Vous récuperez ${manquant} points d'endurance. `; } } @@ -1012,12 +1071,12 @@ export class RdDActor extends RdDBaseActor { } /* -------------------------------------------- */ - distribuerStress(compteur, stress, motif) { + async distribuerStress(compteur, stress, motif) { if (game.user.isGM && this.hasPlayerOwner && this.isPersonnage()) { switch (compteur) { case 'stress': case 'experience': + await this.addCompteurValue(compteur, stress, motif); const message = `${this.name} a reçu ${stress} points ${compteur == 'stress' ? "de stress" : "d'expérience"} (raison : ${motif})`; - this.addCompteurValue(compteur, stress, motif); ui.notifications.info(message); game.users.players.filter(player => player.active && player.character?.id == this.id) .forEach(player => ChatUtility.notifyUser(player.id, 'info', message)); @@ -1612,7 +1671,7 @@ export class RdDActor extends RdDBaseActor { case 'heureux': case 'heureuse': return succes ? 1 : 0; case 'malheureuse': case 'malheureux': return succes ? 0 : -1; case 'neutre': - if (succes && moral <= 0) return 1; + if (succes && moral < 0) return 1; if (!succes && moral > 0) return -1; } return 0; @@ -3779,9 +3838,10 @@ export class RdDActor extends RdDBaseActor { if (Misc.isUniqueConnectedGM()) { let draconique = Draconique.all().find(it => it.match(item)); if (draconique) { - draconique.onActorCreateOwned(this, item) + await draconique.onActorCreateOwned(this, item) this.notifyGestionTeteSouffleQueue(item, draconique.manualMessage()); } + await this.update({ 'system.sommeil.insomnie': EffetsDraconiques.isSujetInsomnie(this) }); } } @@ -3790,7 +3850,7 @@ export class RdDActor extends RdDBaseActor { if (Misc.isUniqueConnectedGM()) { let draconique = Draconique.all().find(it => it.match(item)); if (draconique) { - draconique.onActorDeleteOwned(this, item) + await draconique.onActorDeleteOwned(this, item) } } } @@ -3800,7 +3860,7 @@ export class RdDActor extends RdDBaseActor { if (Misc.isUniqueConnectedGM()) { let draconique = Draconique.all().find(it => it.isCase(item)); if (draconique) { - draconique.onActorDeleteCaseTmr(this, item) + await draconique.onActorDeleteCaseTmr(this, item) } } } diff --git a/module/dialog-repos.js b/module/dialog-repos.js deleted file mode 100644 index ec43ecc6..00000000 --- a/module/dialog-repos.js +++ /dev/null @@ -1,57 +0,0 @@ - -export class DialogRepos extends Dialog { - - static async create(actor) { - const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-repos.html", actor); - const dialog = new DialogRepos(html, actor); - dialog.render(true); - } - - constructor(html, actor) { - let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 400, height: 'fit-content', 'z-index': 99999 }; - let conf = { - title: "Se reposer", - content: html, - default: "repos", - buttons: { - "repos": { label: "Se reposer", callback: async it => { this.repos(); } } - } - }; - super(conf, options); - this.actor = actor; - } - activateListeners(html) { - super.activateListeners(html); - this.html = html; - } - /* -------------------------------------------- */ - - async repos() { - await this.html.find("[name='nb-heures']").change(); - await this.html.find("[name='nb-jours']").change(); - const selection = await this.html.find("[name='repos']:checked").val(); - const nbHeures = Number.parseInt(await this.html.find("[name='nb-heures']").val()); - const nbJours = Number.parseInt(await this.html.find("[name='nb-jours']").val()); - console.log("ACTOR", this.actor) - switch (selection) { - case "sieste": { - await this.actor.dormir(nbHeures); - return; - } - case "nuit": { - let heuresDormies = await this.actor.dormir(nbHeures); - if (heuresDormies == nbHeures) { - await this.actor.dormirChateauDormant(); - } - return; - } - case "chateau-dormant": - await this.actor.dormirChateauDormant(); - return; - case "gris-reve": { - await this.actor.grisReve(nbJours); - return; - } - } - } -} \ No newline at end of file diff --git a/module/rdd-calendrier.js b/module/rdd-calendrier.js index 0b1f65af..8730f7ee 100644 --- a/module/rdd-calendrier.js +++ b/module/rdd-calendrier.js @@ -7,6 +7,8 @@ import { Misc } from "./misc.js"; import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; import { DialogChronologie } from "./dialog-chronologie.js"; import { RdDTimestamp, WORLD_TIMESTAMP_SETTING } from "./rdd-timestamp.js"; +import { DialogChateauDormant } from "./sommeil/dialog-chateau-dormant.js"; +import { ReglesOptionelles } from "./settings/regles-optionelles.js"; const RDD_JOUR_PAR_MOIS = 28; const RDD_HEURES_PAR_JOUR = 12; @@ -67,17 +69,17 @@ export class RdDCalendrier extends Application { this.html.find('.calendar-btn').click(ev => this.onCalendarButton(ev)); - this.html.find('.calendar-btn-edit').click(ev => { + this.html.find('.calendar-set-datetime').click(ev => { ev.preventDefault(); this.showCalendarEditor(); }); - this.html.find('.astrologie-btn-edit').click(ev => { + this.html.find('.calendar-astrologie').click(ev => { ev.preventDefault(); this.showAstrologieEditor(); }); - this.html.find('#calendar-move-handle').mousedown(ev => { + this.html.find('.calendar-title').mousedown(ev => { ev.preventDefault(); ev = ev || window.event; let isRightMB = false; @@ -169,7 +171,7 @@ export class RdDCalendrier extends Application { getCurrentMinute() { return this.timestamp.indexMinute; } getTimestampFinChateauDormant(nbJours = 0) { - return this.timestamp.nouveauJour().addJour(nbJours); + return this.timestamp.nouveauJour().addJours(nbJours); } getTimestampFinHeure(nbHeures = 0) { @@ -257,8 +259,12 @@ export class RdDCalendrier extends Application { /* -------------------------------------------- */ async setNewTimestamp(newTimestamp) { - game.actors.forEach(actor => actor.onTimeChanging(this.timestamp, newTimestamp)); + const oldTimestamp = this.timestamp; + game.actors.forEach(actor => actor.onTimeChanging(oldTimestamp, newTimestamp)); RdDTimestamp.setWorldTime(newTimestamp); + if (oldTimestamp.indexDate + 1 == newTimestamp.indexDate && ReglesOptionelles.isUsing("chateau-dormant-gardien")) { + await DialogChateauDormant.create(); + } this.timestamp = newTimestamp; await this.rebuildListeNombreAstral(); this.updateDisplay(); @@ -292,10 +298,8 @@ export class RdDCalendrier extends Application { async positionnerHeure(heure) { const indexDate = this.timestamp.indexDate; const addDay = this.timestamp.heure < heure ? 0 : 1; - await this.setNewTimestamp(new RdDTimestamp({ - indexDate: indexDate + addDay, indexHeure: 0 - }) - .addHeures(heure)) + const newTimestamp = new RdDTimestamp({ indexDate: indexDate + addDay}).addHeures(heure); + await this.setNewTimestamp(newTimestamp) } /* -------------------------------------------- */ @@ -428,13 +432,13 @@ export class RdDCalendrier extends Application { if (game.user.isGM) { dateHTML = dateHTML + "
Nombre Astral: " + (this.getNombreAstral() ?? "?"); } - for (let handle of document.getElementsByClassName("calendar-date-rdd")) { + for (let handle of document.getElementsByClassName("calendar-title")) { handle.innerHTML = dateHTML; } for (let heure of document.getElementsByClassName("calendar-heure-texte")) { heure.innerHTML = calendrier.heure.label; } - for (const minute of document.getElementsByClassName("calendar-time-disp")) { + for (const minute of document.getElementsByClassName("calendar-minute-texte")) { minute.innerHTML = `${calendrier.minute} minutes`; } for (const heureImg of document.getElementsByClassName("calendar-heure-img")) { diff --git a/module/rdd-commands.js b/module/rdd-commands.js index 49ac180a..ebab970a 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -2,7 +2,8 @@ import { DialogChronologie } from "./dialog-chronologie.js"; import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js"; -import { DialogStress } from "./dialog-stress.js"; +import { DialogChateauDormant } from "./sommeil/dialog-chateau-dormant.js"; +import { DialogStress } from "./sommeil/dialog-stress.js"; import { RdDItemCompetence } from "./item-competence.js"; import { Misc } from "./misc.js"; import { RdDCarac } from "./rdd-carac.js"; @@ -13,7 +14,6 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js"; import { RdDRollTables } from "./rdd-rolltables.js"; import { RdDUtility } from "./rdd-utility.js"; -import { CompendiumTableHelpers } from "./settings/system-compendiums.js"; import { FenetreRechercheTirage } from "./tirage/fenetre-recherche-tirage.js"; import { TMRUtility } from "./tmr-utility.js"; @@ -77,6 +77,7 @@ export class RdDCommands { this.registerCommand({ path: ["/tirer", "rencontre"], func: (content, msg, params) => this.getRencontreTMR(params), descr: `Détermine une rencontre dans les TMR (synonyme de "/tmrr")` }); this.registerCommand({ path: ["/tirage"], func: (content, msg, params) => this.tirage(), descr: "Ouvre la fenêtre de recherche et tirage" }); + 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" }); @@ -462,13 +463,14 @@ export class RdDCommands { let name = params[params.length - 1]; if (name == undefined) { for (let actor of game.actors) { - actor.distribuerStress('stress', stress, motif); + // TODO: ne plus stresser les entités de cauchemar! + await actor.distribuerStress('stress', stress, motif); } } else { //console.log(stressValue, nomJoueur); let actor = Misc.findActor(name, game.actors.filter(it => it.hasPlayerOwner)) ?? Misc.findPlayer(name)?.character if (actor) { - actor.distribuerStress('stress', stress, motif); + await actor.distribuerStress('stress', stress, motif); } else { ui.notifications.warn(`Pas de personnage ou de joueur correspondant à ${name}!`); @@ -485,5 +487,8 @@ export class RdDCommands { async tirage() { FenetreRechercheTirage.create(); } + async sommeil() { + DialogChateauDormant.create(); + } } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 6c73014b..e69a57b0 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -235,6 +235,7 @@ export class RdDUtility { 'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', + 'systems/foundryvtt-reve-de-dragon/templates/sommeil/sommeil-actor-moral.hbs', // Calendrier 'systems/foundryvtt-reve-de-dragon/templates/calendar-template.html', 'systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', diff --git a/module/settings/regles-optionelles.js b/module/settings/regles-optionelles.js index 6253b238..04157cb5 100644 --- a/module/settings/regles-optionelles.js +++ b/module/settings/regles-optionelles.js @@ -17,6 +17,7 @@ const listeReglesOptionelles = [ { group: 'Règles générales', name: 'afficher-prix-joueurs', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true}, { group: 'Règles générales', name: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"}, { group: 'Règles générales', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false }, + { group: 'Règles générales', name: 'chateau-dormant-gardien', descr: "Saisie des heures de sommeil/jets de moral par le gardien des rêves", default: true }, { group: 'Confirmations', name: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"}, { group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"}, diff --git a/module/sommeil/dialog-chateau-dormant.js b/module/sommeil/dialog-chateau-dormant.js new file mode 100644 index 00000000..bc1f8584 --- /dev/null +++ b/module/sommeil/dialog-chateau-dormant.js @@ -0,0 +1,108 @@ +export class DialogChateauDormant extends Dialog { + + static async create() { + const date = game.system.rdd.calendrier.dateCourante(); + const actorsSettings = game.actors.filter(actor => actor.hasPlayerOwner && actor.isPersonnage()) + .map(actor => ({ + actor: actor, + insomnie: actor.system.sommeil?.insomnie, + moral: 'neutre' + })); + + const dialogData = { + actorsSettings, + date: date, + motifStress: `Nuit du ${date}`, + finChateauDormant: game.system.rdd.calendrier.getTimestampFinChateauDormant() + }; + const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-chateau-dormant.hbs", + dialogData); + + new DialogChateauDormant(dialogData, html) + .render(true); + } + + constructor(dialogData, html) { + const options = { + classes: ["rdd-dialog-chateau-dormant"], + width: 600, + height: 'fit-content', + 'z-index': 99999 + }; + const conf = { + title: "De Chateau dormant à Vaisseau", + content: html, + buttons: { + chateauDormant: { label: "Passer à Vaisseau!", callback: it => { this.onChateauDormant(); } } + } + }; + super(conf, options); + this.dialogData = dialogData; + } + + activateListeners(html) { + super.activateListeners(html); + this.html = html; + this.html.find('input.sommeil-insomnie').change(event => this.onInsomnie(event)); + this._activateListenerOnActorMoral(this.html); + } + + _activateListenerOnActorMoral(html) { + html.find(`span.sommeil-actor-moral a`).click(event => this.onActorMoral(event)); + } + + onInsomnie(event) { + const sommeilInsomnie = this.html.find(event.currentTarget); + const isInsomnie = sommeilInsomnie.is(':checked'); + const sommeilHeures = sommeilInsomnie.parents('.set-sommeil-actor').find('input.sommeil-heures'); + sommeilHeures.prop('disabled', isInsomnie); + if (isInsomnie) { + sommeilHeures.val('0'); + } + } + + async onActorMoral(event) { + const selected = this.html.find(event.currentTarget); + const actorRow = selected.parents('.set-sommeil-actor'); + const actorId = actorRow.data('actor-id'); + const actorSetting = this.getActorSetting(actorId); + if (actorSetting) { + actorSetting.moral = selected.data('moral'); + const htmlMoral = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/sommeil/sommeil-actor-moral.hbs', actorSetting) + actorRow.find('.sommeil-actor-moral').html(htmlMoral); + // re-attach listeners for actor row + this._activateListenerOnActorMoral(actorRow); + } + } + + getActorSetting(actorId) { + return this.dialogData.actorsSettings.find(it => it.actor.id == actorId); + } + + async onChateauDormant() { + const motifStress = this.html.find("form input[name='motifStress']").val(); + const sommeilActors = jQuery.map(this.html.find('li.set-sommeil-actor'), it => { + const actorRow = this.html.find(it); + const actorId = actorRow.data('actor-id'); + const actorSetting = this.getActorSetting(actorId); + return { + actorId, + ignorer: actorRow.find('input.sommeil-ignorer').is(':checked'), + stress: { + motif: motifStress, + valeur: Number.parseInt(actorRow.find('input.sommeil-stress').val()), + }, + sommeil: { + insomnie: actorRow.find('input.sommeil-insomnie').is(':checked'), + heures: Number.parseInt(actorRow.find('input.sommeil-heures').val()), + moral: actorSetting.moral, + } + } + }); + await Promise.all( + sommeilActors.filter(it => !it.ignorer) + .map(async it => await game.actors.get(it.actorId)?.prepareChateauDormant(this.dialogData.finChateauDormant, it)) + ) + } + +} \ No newline at end of file diff --git a/module/sommeil/dialog-repos.js b/module/sommeil/dialog-repos.js new file mode 100644 index 00000000..4e4c80b1 --- /dev/null +++ b/module/sommeil/dialog-repos.js @@ -0,0 +1,82 @@ +import { ReglesOptionelles } from "../settings/regles-optionelles.js"; + +export class DialogRepos extends Dialog { + + static async create(actor) { + if (!ReglesOptionelles.isUsing("chateau-dormant-gardien")) { + actor.system.sommeil = { + "nouveaujour": true, + "insomnie": false, + "moral": "neutre", + "heures": 4 + } + } + const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-repos.html", actor); + const dialog = new DialogRepos(html, actor); + dialog.render(true); + } + + constructor(html, actor) { + let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 400, height: 'fit-content', 'z-index': 99999 }; + let conf = { + title: "Se reposer", + content: html, + default: "repos", + buttons: { + "repos": { label: "Se reposer", callback: async it => { this.repos(); } } + } + }; + super(conf, options); + this.actor = actor; + } + activateListeners(html) { + super.activateListeners(html); + this.html = html; + this.html.find(`.sommeil-actor-moral a`).click(event => this.onActorMoral(event)); + } + /* -------------------------------------------- */ + + async repos() { + const selection = await this.html.find("[name='repos']:checked").val(); + switch (selection) { + case "sieste": return await this.sieste(); + case "nuit": return await this.nuit(); + case "chateau-dormant": return await this.chateauDormant(); + case "gris-reve": return await this.grisReve(); + } + } + + async grisReve() { + await this.html.find("[name='nb-jours']").change(); + const nbJours = Number.parseInt(await this.html.find("[name='nb-jours']").val()); + await this.actor.grisReve(nbJours); + } + + async chateauDormant() { + await this.actor.dormirChateauDormant(); + } + + async nuit() { + await this.html.find("[name='sommeil.heures']").change(); + const sommeilHeures = Number.parseInt(await this.html.find("[name='sommeil.heures']").val()); + await this.actor.dormir(sommeilHeures, { chateauDormant: true }); + } + + async sieste() { + await this.html.find("[name='sieste.heures']").change(); + const siesteHeures = Number.parseInt(await this.html.find("[name='sieste.heures']").val()); + await this.actor.dormir(siesteHeures); + } + + async onActorMoral(event) { + const selected = this.html.find(event.currentTarget); + const parentDiv = selected.parents().find('.sommeil-actor-moral'); + const situationMoral = selected.data('moral'); + await this.actor.update({"system.sommeil.moral": situationMoral}); + const htmlMoral = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/sommeil/sommeil-actor-moral.hbs', { + moral: situationMoral + }); + parentDiv.html(htmlMoral); + this.html.find(`.sommeil-actor-moral a`).click(event => this.onActorMoral(event)); + } +} diff --git a/module/dialog-stress.js b/module/sommeil/dialog-stress.js similarity index 92% rename from module/dialog-stress.js rename to module/sommeil/dialog-stress.js index f0b9b8e6..fd413798 100644 --- a/module/dialog-stress.js +++ b/module/sommeil/dialog-stress.js @@ -15,7 +15,7 @@ export class DialogStress extends Dialog { ) }; - const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-stress.html", dialogData); + const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-stress.html", dialogData); new DialogStress(dialogData, html) .render(true); } @@ -50,7 +50,7 @@ export class DialogStress extends Dialog { this.dialogData.actors.filter(it => it.selected) .map(it => game.actors.get(it.id)) - .forEach(actor => actor.distribuerStress(compteur, stress, motif)); + .forEach(async actor => await actor.distribuerStress(compteur, stress, motif)); } async onSelectActor(event) { diff --git a/module/tirage/fenetre-recherche-tirage.js b/module/tirage/fenetre-recherche-tirage.js index 9d4bbc8f..0f3da395 100644 --- a/module/tirage/fenetre-recherche-tirage.js +++ b/module/tirage/fenetre-recherche-tirage.js @@ -189,30 +189,6 @@ export class FenetreRechercheTirage extends Application { const row = await CompendiumTableHelpers.getRandom(table, 'Item') await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item'); }) - - // this.html.find('.recherche') - // .each((index, field) => { - // if (this.options.recherche) { - // field.focus(); - // field.setSelectionRange(this.options.recherche.start, this.options.recherche.end); - // } - // }) - // .keyup(async event => { - // const nouvelleRecherche = this._optionRecherche(event.currentTarget); - // if (this.options.recherche?.text != nouvelleRecherche?.text) { - // this.options.recherche = nouvelleRecherche; - // if (this.timerRecherche) { - // clearTimeout(this.timerRecherche); - // } - // this.timerRecherche = setTimeout(() => { - // this.timerRecherche = undefined; - // this.render(true); - // }, 500); - // } - // }) - // .change(async event => - // this.options.recherche = this._optionRecherche(event.currentTarget) - // ); } showFilterGroup(groupDiv, show) { diff --git a/module/tmr/effets-draconiques.js b/module/tmr/effets-draconiques.js index f1674a31..06c9939a 100644 --- a/module/tmr/effets-draconiques.js +++ b/module/tmr/effets-draconiques.js @@ -164,6 +164,10 @@ export class EffetsDraconiques { return actor.items.find(it => EffetsDraconiques.urgenceDraconique.match(it)); } + static isSujetInsomnie(actor) { + return actor.items.find(it => ['queue', 'ombre'].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, 'Insomnie')) ? true : false; + } + static isPeage(actor) { return EffetsDraconiques.filterItems(actor, Draconique.isSouffleDragon, 'péage').length > 0; } diff --git a/styles/simple.css b/styles/simple.css index e5999b92..9b8eb556 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -80,7 +80,8 @@ --background-custom-button: linear-gradient(to bottom, rgba(33, 55, 74, 0.988) 5%, rgba(21, 40, 51, 0.671) 100%); --background-custom-button-hover: linear-gradient(to bottom, rgb(128, 0, 0) 5%, rgb(62, 1, 1) 100%); - --background-tooltip: rgba(220,220,210,0.95); + --background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%); + --background-tooltip: hsla(60, 12%, 85%, 0.95); --background-error:hsla(16, 100%, 50%, 0.8); } @@ -250,7 +251,10 @@ nav.sheet-tabs .item:after { /* =================== Autres ============ */ -.tabs .item.active, .blessures-list li ul li:first-child:hover, a:hover { +.tabs .item.active, +.blessures-list li ul li:first-child:hover, +i.moral-radio-checkmark-off:hover, +a:hover { text-shadow: 1px 0px 0px #ff6600; } @@ -514,7 +518,7 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) { border: 0; vertical-align: bottom; } -:is(.button-img,.button-effect-img:hover,.small-button-direction):hover { +:is(.button-img,.button-effect-img,.small-button-direction):hover { color: var(--color-controls-hover); border: 1px solid var(--color-control-border-hover); text-shadow: 1px 0px 0px #ff6600; @@ -602,13 +606,13 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) { margin-right: 0.2rem; margin-left: 0.2rem; } -.rdd.sheet .window-content .sheet-body .carac-list .caracteristique .flex-grow-1 { +.flex-grow-1 { flex-grow: 1; } -.rdd.sheet .window-content .sheet-body .carac-list .caracteristique .flex-grow-2 { +.flex-grow-2 { flex-grow: 2; } -.rdd.sheet .window-content .sheet-body .carac-list .caracteristique .flex-grow-3 { +.flex-grow-3 { flex-grow: 3; } @@ -1560,213 +1564,176 @@ table.table-nombres-astraux tr:hover { position: absolute; display: block; } -.calendar{ - min-width: 150px; - grid-row: 1; - grid-column: 1; + +.calendar { + min-width: 250px; width: fit-content; - height: 6rem; + + display: grid; + grid-row: 2; + grid-column: 9; + + min-height: 5rem; + height: fit-content; margin: 0; padding: 0; border: 1px solid #000; - border-radius: 3%; - background: rgba(0, 0, 0, 0.5); + border-radius: 0.3rem; + background: hsla(0, 0%, 0%, 0.5); font-family: "GoudyAcc"; z-index: 100; } -.calendar-hdr{ - display: grid; - font-size: 1rem; - margin: 0.1rem; - padding: 0.2rem; - height: fit-content; - width: fit-content; - min-width: 200px; - border-bottom: 1px solid #111; - color: #CCC; - float: left; -} -.calendar-date-rdd { - font-family: "GoudyAcc"; + +.calendar-title { + grid-column: 1 / span 7; + grid-row: 1; + color: #CCC; opacity: 90; font-size: 0.9rem; text-align: center; - padding: 0; - margin: 0; - border: none; - flex: 1; } -.calendar-date{ - grid-row: 1; - grid-column: 2; - float: left; - text-align: center; - padding-top: 0px; - padding-bottom: 0px; - margin-bottom: 5px; - color: #CCC; - cursor: pointer; +.calendar-options { + grid-column: 8 / span 2; } -.calendar-date, -.calendar-date-num { - transition: 0.2s; +.calendar-title,.calendar-options{ + border-bottom: 1px solid hsla(0, 0%, 80%, 0.5); } -.calendar-date-num { - grid-row: 1; - grid-column: 2; - float: left; - text-align: center; - padding-top: 0px; - padding-bottom: 0px; - margin-bottom: 5px; - color: #CCC; - opacity: 0; - cursor: pointer; + +.calendar-avance-heure { + grid-column: 1 / span 3; } -.calendar-heure-img{ - width: 24px; - height: 24px; - flex-grow: 0; - border-width: 0; - opacity: 90; - color: rgba(255, 255, 255, 0.5); + +.calendar-change-heure { + grid-column: 9 / span 1; } -.calendar-hdr:hover .calendar-date { - opacity: 0; + +.calendar-change-heure .calendar-change-heure-grid { + display: grid; + grid-column: 1; + grid-row: 2; + + margin: 2px; + grid-row-gap: 3px; + color: hsla(0, 0%, 80%, 0.5); } -.calendar-hdr:hover .calendar-date-num{ - opacity: 1; -} -.calendar-container{ - min-width: 250px; - padding-top: 3px; - padding-bottom: 20px; -} -.calendar-btn-container-left{ - width: 25%; + +.calendar-avance-heure .calendar-avance-heure-grid { display: grid; - float: left; + grid-column: 3; + grid-row: 2; + margin: 2px; grid-row-gap: 3px; - color: rgba(0, 0, 0, 0.5); + color: hsla(0, 0%, 80%, 0.5); } -.calendar-btn-container-right{ - width: 15%; + +.calendar-avance-heure .calendar-avance-heure-grid:hover { + color: #FFF; + cursor: pointer; +} + +.calendar-affiche-heure { + grid-column: 4 / span 4; + grid-row: 2; +} + +.calendar-affiche-heure .calendar-horloge { display: grid; - float: right; - margin: 2px; - grid-row-gap: 3px; + max-width: 100px; + float: left; + padding-top: 0px; + padding-bottom: 0px; + margin: 0 0.3rem 0 0.3rem; + color: #CCC; + text-align: center; } -.astrologie-btn-edit, -.calendar-btn-edit{ + +.calendar-affiche-heure .calendar-horloge .calendar-heure-texte { + font-size: 1.1rem; +} +.calendar-affiche-heure .calendar-horloge .calendar-minute-texte { + margin: 0; +} + +.calendar-affiche-heure .calendar-horloge .calendar-heure-img{ + width: 2rem; + height: 2rem; + float: left; + flex-grow: 0; + padding: 0.1rem; + border: 0; + opacity: 0.9; + color: hsla(0, 0%, 100%, 0.5); +} + +.calendar :is(.calendar-astrologie,.calendar-set-datetime) { grid-row: 1; grid-column: 1; } -:is(.astrologie-btn-edit,.calendar-btn-edit,.calendar-btn){ - margin: auto; +.calendar :is(.calendar-astrologie,.calendar-set-datetime,.calendar-btn) { + color: hsla(0, 0%, 100%, 0.5); border: 1px solid rgba(0, 0, 0, 0); - color: rgba(255, 255, 255, 0.5); } -:is(.astrologie-btn-edit,.calendar-btn-edit,.calendar-btn):hover { - color: var(--color-controls-hover); +.calendar :is(.calendar-astrologie,.calendar-set-datetime,.calendar-btn):hover { + color: var(--color-controls-hover); border: 1px solid var(--color-control-border-hover); cursor: pointer; } +.calendar .calendar-affiche-heure .calendar-horloge a { + border: 1px solid rgba(0, 0, 0, 0); +} +.calendar .calendar-affiche-heure .calendar-horloge a:hover { + color: var(--color-controls-hover); + border: 1px solid var(--color-control-border-hover); + cursor: pointer; +} -.calendar-1min{ +.calendar-avance-heure .calendar-1min { grid-row: 1; grid-column: 1; - margin-left: 0.2rem; } -.calendar-5min{ +.calendar-avance-heure .calendar-5min { grid-row: 1; grid-column: 2; } -.calendar-15min{ +.calendar-avance-heure .calendar-15min { grid-row: 1; grid-column: 3; - margin-right: 0.2rem; } - -.calendar-30min{ +.calendar-avance-heure .calendar-30min { grid-row: 2; grid-column: 1; - margin-left: 0.2rem; } - -.calendar-60min{ +.calendar-avance-heure .calendar-60min { grid-row: 2; grid-column: 2; } -.calendar-1heure{ +.calendar-avance-heure .calendar-1heure { grid-row: 2; grid-column: 3; - margin-right: 0.2rem; } .calendar-lyre{ grid-row: 1; grid-column: 1; - margin-left: 0.2rem; - margin-right: 0.2rem; } -.calendar-vaisseau{ +.calendar-vaisseau { grid-row: 2; grid-column: 1; - margin-left: 0.2rem; - margin-right: 0.2rem; } -.img-calendar-forward{ - color: rgba(255, 255, 255, 0.5); + +.calendar-change-heure .calendar-btn:is(.calendar-lyre,.calendar-vaisseau) img { + color: hsla(0, 0%, 100%, 0.5); vertical-align: bottom; max-width: 1.2em; max-height: 1.2em; border-width: 0; } -.calendar-btn-container-left:hover{ - color: #FFF; - border: 0px solid #000; - cursor: pointer; -} -.calendar-weekday-time{ - display: grid; - float: left; - width: 55%; - padding-top: 0px; - padding-bottom: 0px; - margin: auto; - color: #CCC; -} -.calendar-weekday { - grid-column: 1; - grid-row: 1; - text-align: center; - font-size: 1.1rem; - margin: auto; -} -.calendar-time{ - grid-column: 1; - grid-row: 2; - text-align: center; - margin: auto; - cursor: pointer; - display: inline-flex; -} -.calendar-nombre-astral{ -grid-column: 2; -grid-row: 2; -font-size: 1.1rem; -text-align: right; -margin: auto; -cursor: pointer; -display: inline-flex; -} -.calendar-time-disp{ - position: relative; - bottom: 6px; +div.calendar-timestamp-edit select.calendar-signe-heure { + width: max-content; } /* Tooltip container */ diff --git a/system.json b/system.json index 1b2908d1..8a593495 100644 --- a/system.json +++ b/system.json @@ -1,8 +1,8 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "10.6.13", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.6.13.zip", + "version": "10.6.14", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.6.14.zip", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json", "compatibility": { "minimum": "10", diff --git a/template.json b/template.json index 2a49c793..52543e5f 100644 --- a/template.json +++ b/template.json @@ -528,6 +528,16 @@ "label": "Experience", "isInput": true } + }, + "sommeil": { + "nouveaujour": false, + "date":{ + "indexDate": -1, + "indexMinute": 0 + }, + "insomnie": false, + "moral": "", + "heures": 0 } } }, diff --git a/templates/calendar-template.html b/templates/calendar-template.html index d08c4750..4c77d5e8 100644 --- a/templates/calendar-template.html +++ b/templates/calendar-template.html @@ -1,47 +1,47 @@
-
-
-

{{jourDuMois}} {{mois.label}} ({{mois.saison}})

-
+
{{jourDuMois}} {{mois.label}} ({{mois.saison}})
+
{{#if isGM}} - - + + {{/if}}
-
- {{#if isGM}} -
+
+
+ {{#if isGM}} +1 +5 +15 +30 +60 +1h + {{else}} + {{/if}}
- {{else}} -
-
- {{/if}} - +
+
+ + {{nomHeure}} {{heure.label}} {{#if isGM}} -

{{minute}} minutes

+

{{minute}} minutes

{{/if}}
- {{#if isGM}} -
- - Avancer à Lyre - - - Avancer au Vaisseau - +
+
+
+ {{#if isGM}} + + Avancer à Lyre + + + Avancer au Vaisseau + + {{/if}}
- {{/if}}
diff --git a/templates/common/timestamp.hbs b/templates/common/timestamp.hbs index 3295e4c3..0b2e2dfd 100644 --- a/templates/common/timestamp.hbs +++ b/templates/common/timestamp.hbs @@ -1,11 +1,11 @@ -
+
- {{#select mois.key}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-heures.html"}} {{/select}} @@ -16,7 +16,7 @@
- {{#select heure.key}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-heures.html"}} {{/select}} diff --git a/templates/dialog-repos.html b/templates/dialog-repos.html deleted file mode 100644 index f3a0c6d3..00000000 --- a/templates/dialog-repos.html +++ /dev/null @@ -1,34 +0,0 @@ -
- {{name}} -
-
-

{{name}} se repose

-
-
- - -
-

-
- - -
-
- - -
-
- - -
-

-
- - -
-
- - -
-
-
\ No newline at end of file diff --git a/templates/sommeil/dialog-chateau-dormant.hbs b/templates/sommeil/dialog-chateau-dormant.hbs new file mode 100644 index 00000000..98f708b2 --- /dev/null +++ b/templates/sommeil/dialog-chateau-dormant.hbs @@ -0,0 +1,48 @@ +
+
+
+ + +
+
+
    +
  • + Personnage + Insomnie + Sommeil + Stress + Moral + Ignorer +
  • + {{#each actorsSettings as |actorSetting|}} +
  • + + + + + + + + + h + + + + + + {{> "systems/foundryvtt-reve-de-dragon/templates/sommeil/sommeil-actor-moral.hbs" actorSetting}} + + + + +
  • + {{/each}} +
+
+
diff --git a/templates/sommeil/dialog-repos.html b/templates/sommeil/dialog-repos.html new file mode 100644 index 00000000..ffc71c2c --- /dev/null +++ b/templates/sommeil/dialog-repos.html @@ -0,0 +1,53 @@ +
+ {{name}} +
+
+

{{name}} se repose

+
+ {{#if system.sommeil.insomnie}} +
+ Insomnie, impossible de dormir +
+ {{else}} +
+ + +
+

+ {{#if system.sommeil.nouveaujour}} +
+ + +
+
+ + +
+
+ +
+ {{> "systems/foundryvtt-reve-de-dragon/templates/sommeil/sommeil-actor-moral.hbs" system.sommeil}} +
+
+ {{else}} +
+ Le gardien des rêves doit faire passer Chateau Dormant +
+ {{/if}} + {{/if}} +

+
+ + +
+
+ + +
+
+
\ No newline at end of file diff --git a/templates/dialog-stress.html b/templates/sommeil/dialog-stress.html similarity index 100% rename from templates/dialog-stress.html rename to templates/sommeil/dialog-stress.html diff --git a/templates/sommeil/sommeil-actor-moral.hbs b/templates/sommeil/sommeil-actor-moral.hbs new file mode 100644 index 00000000..2198883b --- /dev/null +++ b/templates/sommeil/sommeil-actor-moral.hbs @@ -0,0 +1,11 @@ + + + + + + + + + + +