Gestion des points de coeur
- Les suivants/compagnons/amoureux sont dans l'onglet description - si acteurs "liés", ils peuvent avoir des points de coeur - les jets de volonté peuvent être ajustés s'ils concernent un compagnon pour lequel on a du coeur - on peut ajouter des points de coeur (entre la gestion de Chateau dormant par le gardien et le jet de repos si ce mode est utilisé) - on peut retirer des points de coeur en perdant du moral (mêmes conditions) - on peut passer de tendres moments si les deux acteurs acceptent - les tendre moments font jouer un jet de moral adapté - on peut perdre un point de coeur suite à un tendre moment qui ne fait pas gagner de moral
This commit is contained in:
		| @@ -16,13 +16,14 @@ import { RdDItem } from "./item.js"; | ||||
| import { RdDItemBlessure } from "./item/blessure.js"; | ||||
| import { RdDEmpoignade } from "./rdd-empoignade.js"; | ||||
| import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js"; | ||||
| import { ChatUtility } from "./chat-utility.js"; | ||||
| import { RdDCoeur } from "./coeur/rdd-coeur.js"; | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| /** | ||||
|  * Extend the basic ActorSheet with some very simple modifications | ||||
|  * @extends {ActorSheet} | ||||
|  */ | ||||
| export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|  | ||||
|   /** @override */ | ||||
|   static get defaultOptions() { | ||||
| @@ -127,9 +128,13 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|     }) | ||||
|  | ||||
|     this.html.find('.subacteur-coeur-toggle a').click(async event => { | ||||
|       const actorId = RdDSheetUtility.getEventItemData(event, 'actor-id') | ||||
|       const clickCoeurNombre = $(event.currentTarget).data("coeur-nombre") | ||||
|       this.toggleSubActeurCoeur(actorId, clickCoeurNombre) | ||||
|       const subActorIdactorId = RdDSheetUtility.getEventItemData(event, 'subactor-id') | ||||
|       const coeurNombre = $(event.currentTarget).data('coeur-nombre') | ||||
|       RdDCoeur.toggleSubActeurCoeur(this.actor.id, subActorIdactorId, coeurNombre) | ||||
|     }) | ||||
|     this.html.find('.subacteur-tendre-moment').click(async event => { | ||||
|       const subActorId = RdDSheetUtility.getEventItemData(event, 'subactor-id') | ||||
|       RdDCoeur.startSubActeurTendreMoment(this.actor.id, subActorId) | ||||
|     }) | ||||
|     this.html.find('.subacteur-open').click(async event => { | ||||
|       const subActorId = RdDSheetUtility.getEventItemData(event, 'subactor-id'); | ||||
| @@ -297,10 +302,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|   } | ||||
|  | ||||
|   openSubActeur(actorId) { | ||||
|     let actor = game.actors.get(actorId); | ||||
|     if (actor) { | ||||
|       actor.sheet.render(true); | ||||
|     } | ||||
|     game.actors.get(actorId)?.sheet.render(true) | ||||
|   } | ||||
|  | ||||
|   deleteSubActeur(actorId, li) { | ||||
| @@ -308,24 +310,12 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|       const subActor = game.actors.get(actorId); | ||||
|       RdDUtility.confirmSubActeurDelete(this, subActor, li, () => { | ||||
|         console.log('Delete : ', subActor.id); | ||||
|         this.actor.removeSubActeur(subActor.id); | ||||
|         this.actor.deleteSubActeur(subActor.id); | ||||
|         RdDUtility.slideOnDelete(this, li); | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   toggleSubActeurCoeur(actorId, toggleCoeur) { | ||||
|     console.log(this.actor, 'toggleSubActeurCoeur', actorId, toggleCoeur) | ||||
|     const coeur = this.actor.getPointsCoeur(actorId) | ||||
|     if (toggleCoeur <= coeur) { | ||||
|       this.actor.jetDeMoral('malheureuse'); | ||||
|       this.actor.setPointsCoeur(actorId, Math.max(0, coeur - 1)) | ||||
|     } | ||||
|     else { | ||||
|       this.actor.setPointsCoeur(actorId, Math.min(4, toggleCoeur)) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async selectTypeOeuvreToCreate() { | ||||
|     let types = RdDItem.getTypesOeuvres(); | ||||
|   | ||||
| @@ -1096,18 +1096,19 @@ export class RdDActor extends RdDBaseActorSang { | ||||
|   /* -------------------------------------------- */ | ||||
|   async moralIncDec(ajustementMoral) { | ||||
|     if (ajustementMoral != 0) { | ||||
|       ajustementMoral = Math.sign(ajustementMoral) | ||||
|       let moral = Misc.toInt(this.system.compteurs.moral.value) + ajustementMoral | ||||
|       if (moral > 3) { // exaltation | ||||
|         const exaltation = Misc.toInt(this.system.compteurs.exaltation.value) + ajustementMoral; | ||||
|         await this.updateCompteurValue('exaltation', exaltation); | ||||
|       const startMoral = parseInt(this.system.compteurs.moral.value) | ||||
|       const moralTheorique = startMoral + ajustementMoral | ||||
|       if (moralTheorique > 3) { // exaltation | ||||
|         const ajoutExaltation = moralTheorique - 3 | ||||
|         const exaltation = parseInt(this.system.compteurs.exaltation.value) + ajoutExaltation | ||||
|         await this.updateCompteurValue('exaltation', exaltation) | ||||
|       } | ||||
|       if (moral < -3) { // dissolution | ||||
|         const dissolution = Misc.toInt(this.system.compteurs.dissolution.value) - ajustementMoral; | ||||
|         await this.updateCompteurValue('dissolution', dissolution); | ||||
|       if (moralTheorique < -3) { // dissolution | ||||
|         const ajoutDissolution = -3 - moralTheorique | ||||
|         const dissolution = parseInt(this.system.compteurs.dissolution.value) + ajoutDissolution | ||||
|         await this.updateCompteurValue('dissolution', dissolution) | ||||
|       } | ||||
|       moral = Math.max(-3, Math.min(moral, 3)); | ||||
|       await this.updateCompteurValue('moral', moral); | ||||
|       await this.updateCompteurValue('moral', Math.max(-3, Math.min(moralTheorique, 3))); | ||||
|     } | ||||
|     return this.system.compteurs.moral.value; | ||||
|   } | ||||
| @@ -2634,6 +2635,7 @@ export class RdDActor extends RdDBaseActorSang { | ||||
|   /* -------------------------------------------- */ | ||||
|   static $transformSubActeurSuivant = (suivant, link) => { | ||||
|     return mergeObject(RdDBaseActor.extractActorMin(suivant), { | ||||
|       ephemere: !suivant.prototypeToken.actorLink, | ||||
|       coeur: link.coeur ?? 0 | ||||
|     }) | ||||
|   }; | ||||
| @@ -2652,6 +2654,19 @@ export class RdDActor extends RdDBaseActorSang { | ||||
|     return undefined | ||||
|   } | ||||
|  | ||||
|   getPointsCoeur(actorId) { | ||||
|     return this.getSuivant(actorId)?.coeur ?? 0; | ||||
|   } | ||||
|  | ||||
|   async setPointsCoeur(actorId, coeur) { | ||||
|     const amoureux = this.getSuivant(actorId); | ||||
|     if (amoureux) { | ||||
|       const suivants = this.system.subacteurs.suivants; | ||||
|       let newSuivants = [...suivants.filter(it => it.id != actorId), { id: actorId, coeur: coeur }] | ||||
|       await this.update({ 'system.subacteurs.suivants': newSuivants }); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static $transformSubActeurVehicule = (vehicle, link) => { | ||||
|     return mergeObject(RdDBaseActor.extractActorMin(vehicle), { | ||||
|   | ||||
| @@ -145,7 +145,6 @@ export class RdDBaseActor extends Actor { | ||||
|     return RdDBaseActor._findCaracByName(this.system.carac, name); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   /* -------------------------------------------- */ | ||||
|   async _preCreate(data, options, user) { | ||||
|     await super._preCreate(data, options, user); | ||||
| @@ -186,7 +185,9 @@ export class RdDBaseActor extends Actor { | ||||
|     } | ||||
|     return undefined; | ||||
|   } | ||||
|  | ||||
|   listeSuivants(filter = suivant => true) { return [] } | ||||
|   listeSuivants(filter = suivant =>true) { return [] } | ||||
|   listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); } | ||||
|   filterItems(filter, type = undefined) { return (type ? this.itemTypes[type] : this.items)?.filter(filter) ?? []; } | ||||
|   findItemLike(idOrName, type) { | ||||
|   | ||||
							
								
								
									
										146
									
								
								module/coeur/rdd-coeur.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								module/coeur/rdd-coeur.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| import { RdDBaseActor } from "../actor/base-actor.js"; | ||||
| import { ChatUtility } from "../chat-utility.js"; | ||||
| import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; | ||||
|  | ||||
| const INFO_COEUR = 'info-coeur'; | ||||
|  | ||||
| export class RdDCoeur { | ||||
|   static registerChatCallbacks(html) { | ||||
|     html.on("click", 'a.accepter-tendre-moment', event => { | ||||
|       RdDCoeur.accepterTendreMoment(RdDCoeur.extractInfoCoeur(event)) | ||||
|     }) | ||||
|     html.on("click", 'a.refuser-tendre-moment', event => { | ||||
|       RdDCoeur.refuserTendreMoment(RdDCoeur.extractInfoCoeur(event)) | ||||
|     }) | ||||
|     html.on("click", 'a.perdre-point-coeur-douceur', event => { | ||||
|       RdDCoeur.perdreEnDouceur( | ||||
|         RdDCoeur.extractInfoCoeur(event), | ||||
|         event.currentTarget.attributes['data-actor-id'].value) | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   static addTagsInfoCoeur(infoCoeur, chatMessage = undefined) { | ||||
|     if (chatMessage) { | ||||
|       infoCoeur.chatMessageId = chatMessage.id | ||||
|     } | ||||
|     else { | ||||
|       chatMessage = game.messages.get(infoCoeur.chatMessageId) | ||||
|     } | ||||
|     ChatUtility.setMessageData(chatMessage, INFO_COEUR, infoCoeur); | ||||
|   } | ||||
|  | ||||
|   static extractInfoCoeur(event) { | ||||
|     return ChatUtility.getMessageData(ChatUtility.getChatMessage(event), INFO_COEUR) | ||||
|   } | ||||
|  | ||||
|   static getInfoCoeur(sourceActorId, targetActorId) { | ||||
|     const sourceActor = game.actors.get(sourceActorId) | ||||
|     const targetActor = game.actors.get(targetActorId) | ||||
|     if (sourceActor && targetActor) { | ||||
|       return { | ||||
|         source: { | ||||
|           actor: RdDBaseActor.extractActorMin(sourceActor), | ||||
|           coeur: sourceActor.getPointsCoeur(targetActorId), | ||||
|         }, | ||||
|         target: { | ||||
|           actor: RdDBaseActor.extractActorMin(targetActor), | ||||
|           coeur: targetActor.getPointsCoeur(sourceActorId), | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     return {} | ||||
|   } | ||||
|  | ||||
|   static async toggleSubActeurCoeur(actorId, subActorId, toggleCoeur) { | ||||
|     const actor = game.actors.get(actorId) | ||||
|     if (ReglesOptionnelles.isUsing("chateau-dormant-gardien") && !actor.system.sommeil.nouveaujour) { | ||||
|       ui.notifications.warn(`Les changements de points de coeur se font juste avant de gérer Château Dormant, juste avant de passer à un nouveau jour`) | ||||
|       return | ||||
|     } | ||||
|     const coeur = actor.getPointsCoeur(subActorId); | ||||
|     if (toggleCoeur <= coeur) { | ||||
|       // TODO: validation? | ||||
|       await actor.moralIncDec(-4); | ||||
|       actor.setPointsCoeur(subActorId, Math.max(0, coeur - 1)); | ||||
|       ChatMessage.create({ | ||||
|         whisper: ChatUtility.getWhisperRecipientsAndGMs(actor.name), | ||||
|         content: `Perte de points de coeur arbitraire: ${actor.name} perd 4 points de moral, pour finir à ${actor.getMoralTotal()}.` | ||||
|       }); | ||||
|     } | ||||
|     else { | ||||
|       actor.setPointsCoeur(subActorId, Math.min(4, toggleCoeur)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static async startSubActeurTendreMoment(actorId, subActeurId) { | ||||
|     const infoCoeur = RdDCoeur.getInfoCoeur(actorId, subActeurId) | ||||
|     if (infoCoeur.target?.actor.id) { | ||||
|       // TODO: passer par une fenêtre pour saisir sa proposition (lieu, heure, ...) | ||||
|       const chatHtml = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/coeur/chat-proposer-tendre-moment.hbs`, infoCoeur) | ||||
|       const chatMessage = await ChatMessage.create({ | ||||
|         whisper: ChatUtility.getWhisperRecipientsAndGMs(infoCoeur.target?.actor.name), | ||||
|         content: chatHtml | ||||
|       }) | ||||
|       RdDCoeur.addTagsInfoCoeur(infoCoeur, chatMessage) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static async accepterTendreMoment(infoCoeur) { | ||||
|     const target = game.actors.get(infoCoeur.target.actor.id) | ||||
|     if (!target.isOwner) { | ||||
|       ui.notifications.warn(`vous ne pouvez pas accepter pour ${infoCoeur.target.actor.name}`) | ||||
|       return | ||||
|     } | ||||
|     ChatUtility.removeChatMessageId(infoCoeur.chatMessageId) | ||||
|  | ||||
|     infoCoeur.target.jetTendre = (await (new Roll('1d6').evaluate({ async: true }))).total | ||||
|     infoCoeur.source.jetTendre = (await (new Roll('1d6').evaluate({ async: true }))).total | ||||
|     const diff = Math.abs(infoCoeur.source.jetTendre - infoCoeur.target.jetTendre) | ||||
|     for (let amoureux of [infoCoeur.source, infoCoeur.target]) { | ||||
|       const actorAmoureux = game.actors.get(amoureux.actor.id); | ||||
|       amoureux.situation = diff <= amoureux.coeur ? 'heureux' : 'neutre' | ||||
|       amoureux.gainMoral = await actorAmoureux.jetDeMoral(amoureux.situation) | ||||
|     } | ||||
|     const chatHtml = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/coeur/chat-accepter-tendre-moment.hbs`, infoCoeur) | ||||
|     const chatMessage = await ChatMessage.create({ | ||||
|       whisper: ChatUtility.getWhisperRecipientsAndGMs(infoCoeur.source?.actor.name, infoCoeur.target?.actor.name), | ||||
|       content: chatHtml | ||||
|     }) | ||||
|     RdDCoeur.addTagsInfoCoeur(infoCoeur, chatMessage) | ||||
|   } | ||||
|  | ||||
|   static async refuserTendreMoment(infoCoeur) { | ||||
|     const target = game.actors.get(infoCoeur.target.actor.id) | ||||
|     if (!target.isOwner) { | ||||
|       ui.notifications.warn(`vous ne pouvez pas refuser pour ${infoCoeur.target.actor.name}`) | ||||
|       return | ||||
|     } | ||||
|     ChatUtility.removeChatMessageId(infoCoeur.chatMessageId) | ||||
|     const chatHtml = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/coeur/chat-refuser-tendre-moment.hbs`, infoCoeur) | ||||
|     await ChatMessage.create({ | ||||
|       whisper: ChatUtility.getWhisperRecipientsAndGMs(infoCoeur.source?.actor.name, infoCoeur.target?.actor.name), | ||||
|       content: chatHtml | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   static async perdreEnDouceur(infoCoeur, actorId) { | ||||
|     const [amoureux, partenaire] = (infoCoeur.source.actor.id == actorId | ||||
|       ? [infoCoeur.source, infoCoeur.target] | ||||
|       : (infoCoeur.target.actor.id == actorId | ||||
|         ? [infoCoeur.target, infoCoeur.source] | ||||
|         : [undefined, undefined])) | ||||
|  | ||||
|     const subActorId = partenaire?.actor.id; | ||||
|     if (amoureux.perteCoeur) { | ||||
|       ui.notifications.warn(`Un point de coeur a déjà été perdu`) | ||||
|     } | ||||
|     else if (amoureux.coeur > 0) { | ||||
|       const actor = game.actors.get(actorId) | ||||
|       if (actor.isOwner) { | ||||
|         await actor.setPointsCoeur(subActorId, amoureux.coeur - 1) | ||||
|         amoureux.perteCoeur = true | ||||
|         RdDCoeur.addTagsInfoCoeur(infoCoeur) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -22,7 +22,7 @@ export class RdDRoll extends Dialog { | ||||
|  | ||||
|     const html = await renderTemplate(dialogConfig.html, rollData); | ||||
|  | ||||
|     let options = { classes: ["rdd-roll-dialog"], width: 650, height: 'fit-content', 'z-index': 99999, close: html => {} }; | ||||
|     let options = { classes: ["rdd-roll-dialog"], width: 650, height: 'fit-content', 'z-index': 99999, close: html => { } }; | ||||
|     if (dialogConfig.close) { | ||||
|       options.close = dialogConfig.close; | ||||
|     } | ||||
| @@ -37,6 +37,7 @@ export class RdDRoll extends Dialog { | ||||
|       difficultesLibres: CONFIG.RDD.difficultesLibres, | ||||
|       etat: actor.getEtatGeneral(), | ||||
|       moral: actor.getMoralTotal(), /* La valeur du moral pour les jets de volonté */ | ||||
|       amoureux: actor.listeSuivants(it => it.coeur > 0), | ||||
|       carac: actor.system.carac, | ||||
|       finalLevel: 0, | ||||
|       diffConditions: 0, | ||||
| @@ -45,6 +46,7 @@ export class RdDRoll extends Dialog { | ||||
|       use: { | ||||
|         moral: false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */ | ||||
|         libre: true, | ||||
|         coeur: undefined, | ||||
|         conditions: true, | ||||
|         surenc: actor.isSurenc(), | ||||
|         encTotal: true | ||||
| @@ -174,6 +176,15 @@ export class RdDRoll extends Dialog { | ||||
|       this.rollData.competence = this.rollData.competences.find(it => it.name == competence); | ||||
|       this.updateRollResult(html); | ||||
|     }); | ||||
|     this.html.find('.select-suivant-coeur').change((event) => { | ||||
|       const selectedActorId = event.currentTarget.value; | ||||
|       this.rollData.use.coeur = this.actor.getSuivant(selectedActorId) | ||||
|       if (this.rollData.use.coeur) { | ||||
|         this.html.find(".utilisation-coeur img.selected-suivant-coeur").attr('src', this.rollData.use.coeur?.img) | ||||
|         this.html.find(".utilisation-coeur img.selected-suivant-coeur").attr('title', this.rollData.use.coeur?.name) | ||||
|       } | ||||
|       this.updateRollResult(html); | ||||
|     }); | ||||
|     this.html.find('.roll-signedraconique').change((event) => { | ||||
|       let sortKey = Misc.toInt(event.currentTarget.value); | ||||
|       this.setSelectedSigneDraconique(this.rollData.signes[sortKey]); | ||||
| @@ -300,17 +311,19 @@ export class RdDRoll extends Dialog { | ||||
|  | ||||
|     const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel)) | ||||
|     const adjustements = await this.buildAjustements(rollData); | ||||
|      | ||||
|  | ||||
|     HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac)); | ||||
|     HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac)); | ||||
|     HtmlUtility.showControlWhen(this.html.find(".utilisation-moral"), rollData.use.appelAuMoral); | ||||
|     HtmlUtility.showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral); | ||||
|     HtmlUtility.showControlWhen(this.html.find(".utilisation-coeur"), rollData.ajustements.coeur.visible); | ||||
|     HtmlUtility.showControlWhen(this.html.find(".utilisation-coeur img.selected-suivant-coeur"), rollData.ajustements.coeur.visible && rollData.use.coeur != undefined) | ||||
|     // HtmlUtility.showControlWhen(this.html.find(".diffMoral"), rollData.ajustements.moral.used); | ||||
|  | ||||
|     // Mise à jour valeurs | ||||
|     this.html.find(".dialog-roll-title").text(this._getTitle(rollData)); | ||||
|     this.html.find("input.check-mortalite").prop('checked', rollData.dmg.mortalite == 'non-mortel'); | ||||
|     this.html.find("label.dmg-arme-actor").text(rollData.dmg.mortalite == 'empoignade'? 'empoignade': Misc.toSignedString(rollData.dmg.total) ); | ||||
|     this.html.find("label.dmg-arme-actor").text(rollData.dmg.mortalite == 'empoignade' ? 'empoignade' : Misc.toSignedString(rollData.dmg.total)); | ||||
|     this.html.find("label.arme-mortalite").text(rollData.dmg.mortalite); | ||||
|     // this.html.find("[name='dmg-arme-actor']").text(rollData.dmg.mortalite == 'empoignade'? 'empoignade': Misc.toSignedString(rollData.dmg.total) ); | ||||
|     // this.html.find("[name='arme-mortalite']").text(rollData.dmg.mortalite); | ||||
|   | ||||
| @@ -17,6 +17,7 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js"; | ||||
| import { RdDRaretes } from "./item/raretes.js"; | ||||
| import { RdDEmpoignade } from "./rdd-empoignade.js"; | ||||
| import { ExperienceLog } from "./actor/experience-log.js"; | ||||
| import { RdDCoeur } from "./coeur/rdd-coeur.js"; | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| // This table starts at 0 -> niveau -10 | ||||
| @@ -75,22 +76,22 @@ const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "C | ||||
| /* -------------------------------------------- */ | ||||
| const definitionsEncaissement = { | ||||
|   "mortel": [ | ||||
|     { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1}, | ||||
|     { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0}, | ||||
|     { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2}, | ||||
|     { minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4}, | ||||
|     { minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6}, | ||||
|     { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 }, | ||||
|     { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 }, | ||||
|     { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 }, | ||||
|     { minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4 }, | ||||
|     { minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6 }, | ||||
|   ], | ||||
|   "non-mortel": [ | ||||
|     { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1}, | ||||
|     { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 }, | ||||
|     { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 }, | ||||
|     { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 }, | ||||
|     { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 }, | ||||
|     { minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 }, | ||||
|   ], | ||||
|   "entiteincarnee": [ | ||||
|     { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1}, | ||||
|     { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0}, | ||||
|     { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 }, | ||||
|     { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 }, | ||||
|     { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 }, | ||||
|     { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 0 }, | ||||
|     { minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 0 }, | ||||
| @@ -203,6 +204,7 @@ export class RdDUtility { | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html', | ||||
|       // Partials | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/coeur/chat-effet-tendre-moment.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/time/horloge.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs', | ||||
| @@ -218,6 +220,7 @@ export class RdDUtility { | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-coeur.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html', | ||||
| @@ -291,7 +294,7 @@ export class RdDUtility { | ||||
|     Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite()); | ||||
|     Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field)); | ||||
|     Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field)); | ||||
|      | ||||
|  | ||||
|     Handlebars.registerHelper('plusMoins', diff => (diff > 0 ? '+' : '') + Math.round(diff)) | ||||
|     Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic)); | ||||
|  | ||||
| @@ -646,6 +649,7 @@ export class RdDUtility { | ||||
|   static async chatListeners(html) { | ||||
|     RdDCombat.registerChatCallbacks(html) | ||||
|     RdDEmpoignade.registerChatCallbacks(html) | ||||
|     RdDCoeur.registerChatCallbacks(html) | ||||
|  | ||||
|     // Gestion spécifique message passeurs | ||||
|     html.on("click", '.tmr-passeur-coord a', event => { | ||||
| @@ -804,7 +808,7 @@ export class RdDUtility { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static confirmSubActeurDelete(sheet, subActor, htmlToDelete, onSuppression = ()=>{}) { | ||||
|   static confirmSubActeurDelete(sheet, subActor, htmlToDelete, onSuppression = () => { }) { | ||||
|     RdDConfirm.confirmer({ | ||||
|       settingConfirmer: "confirmation-supprimer-lien-acteur", | ||||
|       content: `<p>Etes vous certain de vouloir supprimer le lien vers ${subActor.name} ?</p>`, | ||||
|   | ||||
| @@ -80,6 +80,12 @@ export const referenceAjustements = { | ||||
|     getLabel: (rollData, actor) => 'Appel au moral', | ||||
|     getValue: (rollData, actor) => 1 | ||||
|   }, | ||||
|   coeur: { | ||||
|     isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isVolonte(rollData.selectedCarac), | ||||
|     isUsed: (rollData, actor) => rollData.use.coeur != undefined, | ||||
|     getLabel: (rollData, actor) => 'Ajustement de coeur', | ||||
|     getValue: (rollData, actor) => -2 * (rollData.use.coeur?.coeur ?? 0) | ||||
|   }, | ||||
|   moralTotal: { | ||||
|     isUsed: (rollData, actor) => RdDCarac.isVolonte(rollData.selectedCarac), | ||||
|     getLabel: (rollData, actor) => 'Moral', | ||||
|   | ||||
| @@ -1458,6 +1458,9 @@ table.table-nombres-astraux tr:hover { | ||||
|   transition: opacity 0.3s; | ||||
| } | ||||
|  | ||||
| .tendre-moment { | ||||
|   color: hsla(293, 72%, 44%, 0.8); | ||||
| } | ||||
|  | ||||
| /* ======================================== */ | ||||
| /* Fatigue CSS */ | ||||
|   | ||||
| @@ -6,6 +6,22 @@ | ||||
|     <span class="competence-title subacteur-label subacteur-open"> | ||||
|       <a>{{suivant.name}}</a> | ||||
|     </span> | ||||
|     {{#if suivant.ephemere}} | ||||
|       <span></span> | ||||
|       <span></span> | ||||
|     {{else}} | ||||
|       <span class="competence-title subacteur-coeur-toggle"> | ||||
|         <a data-coeur-nombre="1"><i class="{{#if (gte suivant.coeur 1)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i></a> | ||||
|         <a data-coeur-nombre="2"><i class="{{#if (gte suivant.coeur 2)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i></a> | ||||
|         <a data-coeur-nombre="3"><i class="{{#if (gte suivant.coeur 3)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i></a> | ||||
|         <a data-coeur-nombre="4"><i class="{{#if (gte suivant.coeur 4)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i></a> | ||||
|       </span> | ||||
|       <span class="competence-title subacteur-label"> | ||||
|         {{#if (gte suivant.coeur 1)}} | ||||
|           <a class="subacteur-tendre-moment chat-card-button">Tendre moment</a> | ||||
|         {{/if}} | ||||
|       </span> | ||||
|     {{/if}} | ||||
|     <div class="item-controls flex-shrink"> | ||||
|       <a class="subacteur-delete" title="Supprimer"><i class="fas fa-trash"></i></a> | ||||
|     </div> | ||||
|   | ||||
							
								
								
									
										26
									
								
								templates/coeur/chat-accepter-tendre-moment.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								templates/coeur/chat-accepter-tendre-moment.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| <h3> | ||||
|   <div class="flexrow flex-center"> | ||||
|     <img class="chat-icon" src="{{source.actor.img}}" title="{{source.actor.name}}" alt="{{source.actor.name}}" /> | ||||
|     <span class="flexcol tendre-moment"> | ||||
|       <div> | ||||
|       <i class="{{#if (gte source.coeur 1)}}fa-solid{{else}}fa-regular{{/if}} fa-heart "></i> | ||||
|       <i class="{{#if (gte source.coeur 2)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte source.coeur 3)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte source.coeur 4)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       </div> | ||||
|       <div> | ||||
|       <i class="{{#if (gte target.coeur 4)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte target.coeur 3)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte target.coeur 2)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte target.coeur 1)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       </div> | ||||
|     </span> | ||||
|     <img class="chat-icon" src="{{target.actor.img}}" title="{{target.actor.name}}" alt="{{target.actor.name}}" /> | ||||
|   </div> | ||||
| </h3> | ||||
| <p> | ||||
|   {{target.actor.name}} et {{source.actor.name}} passent un tendre moment. | ||||
| </p> | ||||
| <br> | ||||
| {{>'systems/foundryvtt-reve-de-dragon/templates/coeur/chat-effet-tendre-moment.hbs' source}} | ||||
| {{>'systems/foundryvtt-reve-de-dragon/templates/coeur/chat-effet-tendre-moment.hbs' target}} | ||||
							
								
								
									
										11
									
								
								templates/coeur/chat-effet-tendre-moment.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								templates/coeur/chat-effet-tendre-moment.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| <p> | ||||
|   {{actor.name}} obtient {{jetTendre}} sur 1d6 et {{#if (eq situation 'heureux')}}peut{{else}}ne peut pas{{/if}} | ||||
|   ajuster pour atteindre le score de son partenaire. Avec son jet de moral <strong>{{situation}}</strong>, {{actor.name}}  | ||||
|   {{#if (gt gainMoral 0)}}a apprécié ce tendre moment et gagné du moral | ||||
|   {{else}}n'a pas gagné de moral{{#if (gte coeur 1)}} et peut | ||||
|     <span class="chat-card-button-area"> | ||||
|       <a class="perdre-point-coeur-douceur chat-card-button" data-actor-id="{{actor.id}}">perdre un point de coeur</a> | ||||
|     </span> | ||||
|     {{/if}}. | ||||
|   {{/if}} | ||||
| </p> | ||||
							
								
								
									
										32
									
								
								templates/coeur/chat-proposer-tendre-moment.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								templates/coeur/chat-proposer-tendre-moment.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| <h3> | ||||
|   <div class="flexrow flex-center"> | ||||
|     <img class="chat-icon" src="{{source.actor.img}}" title="{{source.actor.name}}" alt="{{source.actor.name}}" /> | ||||
|     <span class="flexcol tendre-moment"> | ||||
|       <div > | ||||
|       <i class="{{#if (gte source.coeur 1)}}fa-solid{{else}}fa-regular{{/if}} fa-heart "></i> | ||||
|       <i class="{{#if (gte source.coeur 2)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte source.coeur 3)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte source.coeur 4)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       </div> | ||||
|       <div> | ||||
|       <i class="{{#if (gte target.coeur 4)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte target.coeur 3)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte target.coeur 2)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte target.coeur 1)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       </div> | ||||
|     </span> | ||||
|     <img class="chat-icon" src="{{target.actor.img}}" title="{{target.actor.name}}" alt="{{target.actor.name}}" /> | ||||
|   </div> | ||||
| </h3> | ||||
| <p> | ||||
|   {{source.actor.name}} propose à {{target.actor.name}} de passer un tendre moment | ||||
| </p> | ||||
| <p> | ||||
|   <span class="chat-card-button-area"> | ||||
|     <a class="accepter-tendre-moment chat-card-button">Accepter</a> | ||||
|   </span> | ||||
|     | ||||
|   <span class="chat-card-button-area"> | ||||
|     <a class="refuser-tendre-moment chat-card-button">Refuser</a> | ||||
|   </span> | ||||
| </p> | ||||
							
								
								
									
										23
									
								
								templates/coeur/chat-refuser-tendre-moment.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								templates/coeur/chat-refuser-tendre-moment.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| <h3> | ||||
|   <div class="flexrow flex-center"> | ||||
|     <img class="chat-icon" src="{{source.actor.img}}" title="{{source.actor.name}}" alt="{{source.actor.name}}" /> | ||||
|     <span class="flexcol"> | ||||
|       <div> | ||||
|       <i class="{{#if (gte source.coeur 1)}}fa-solid{{else}}fa-regular{{/if}} fa-heart "></i> | ||||
|       <i class="{{#if (gte source.coeur 2)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte source.coeur 3)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte source.coeur 4)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       </div> | ||||
|       <div> | ||||
|       <i class="{{#if (gte target.coeur 4)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte target.coeur 3)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte target.coeur 2)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       <i class="{{#if (gte target.coeur 1)}}fa-solid{{else}}fa-regular{{/if}} fa-heart"></i> | ||||
|       </div> | ||||
|     </span> | ||||
|     <img class="chat-icon" src="{{target.actor.img}}" title="{{target.actor.name}}" alt="{{target.actor.name}}" /> | ||||
|   </div> | ||||
| </h3> | ||||
| <p> | ||||
|   {{target.actor.name}} a refusé de passer un tendre moment avec {{source.actor.name}} | ||||
| </p> | ||||
| @@ -8,6 +8,7 @@ | ||||
|       {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.html"}} | ||||
|       {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.html"}} | ||||
|       {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html"}} | ||||
|       {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-coeur.hbs"}} | ||||
|     </div> | ||||
|     <div class="flex-group-left"> | ||||
|       {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.html"}} | ||||
|   | ||||
| @@ -10,6 +10,7 @@ | ||||
|       {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.html"}} | ||||
|       {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.html"}} | ||||
|       {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html"}} | ||||
|       {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-coeur.hbs"}} | ||||
|     </div> | ||||
|     <div class="flex-group-left"> | ||||
|       {{>"systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.html"}} | ||||
|   | ||||
							
								
								
									
										14
									
								
								templates/partial-roll-coeur.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								templates/partial-roll-coeur.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| <div class="flexrow utilisation-coeur"> | ||||
|   <label class="">Ajustement de Coeur</label> | ||||
|   <div class="select-suivant"> | ||||
|     <img class="sheet-competence-img selected-suivant-coeur" src="{{use.coeur.img}}" title="{{use.coeur.name}}" /> | ||||
|     <select name="select-suivant-coeur" class="select-suivant-coeur" data-dtype="String"> | ||||
|       <option value="">Ignorer</option> | ||||
|       {{#each amoureux as |amour id|}} | ||||
|       <option value="{{amour.id}}" style="background-image:url({{amour.img}});"> | ||||
|         {{amour.name}} | ||||
|       </option> | ||||
|       {{/each}} | ||||
|     </select> | ||||
|   </div> | ||||
| </div> | ||||
		Reference in New Issue
	
	Block a user