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:
Vincent Vandemeulebrouck 2023-11-21 21:07:37 +01:00
parent 135546467d
commit 4a03c222d5
16 changed files with 347 additions and 45 deletions

View File

@ -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();

View File

@ -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), {

View File

@ -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
View 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)
}
}
}
}

View File

@ -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);

View File

@ -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>`,

View File

@ -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',

View File

@ -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 */

View File

@ -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>

View 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}}

View 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>

View 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>
&nbsp;
<span class="chat-card-button-area">
<a class="refuser-tendre-moment chat-card-button">Refuser</a>
</span>
</p>

View 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>

View File

@ -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"}}

View File

@ -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"}}

View 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>