Files
foundryvtt-reve-de-dragon/module/item/blessure.js
Vincent Vandemeulebrouck 7fb0ee1659 await ChatMessage.create
ChatMessage.create est async, il faut donc de préférence
l'appeler avec un await.

Des effets secondaires avaient lieu (ordre de messages, updates
ultérieurs parfois pas pris en compte)
2026-05-02 00:42:45 +02:00

241 lines
8.5 KiB
JavaScript

import { RdDItem } from "../item.js";
import { Misc } from "../misc.js";
import { RdDTimestamp } from "../time/rdd-timestamp.js";
import { ChatUtility } from "../chat-utility.js";
const BASE_TACHE_SOIN_BLESSURE = {
type: "tache",
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_chirurgie.webp',
system: { carac: "dexterite", competence: "Chirurgie", periodicite: "1 round", fatigue: 0, }
}
const TACHES_SOIN_BLESSURE = {
6: { name: 'Blessure critique', system: { difficulte: -6, points_de_tache: 6 } },
4: { name: 'Blessure grave', system: { difficulte: -4, points_de_tache: 4 } },
2: { name: 'Blessure légère', system: { difficulte: -2, points_de_tache: 2 } },
}
const definitionsBlessures = [
{ type: "contusion", gravite: 0, endurance: "1d4", vie: 0, label: 'Contusion/éraflure', max: 100, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/eraflure.webp" },
{ type: "legere", gravite: 2, endurance: "1d6", vie: 0, label: 'Légère', max: 5, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
{ type: "grave", gravite: 4, endurance: "2d6", vie: -2, label: 'Grave', max: 2, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
{ type: "critique", gravite: 6, endurance: "-100", vie: -4, label: 'Critique', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
{ type: "mort", gravite: 8, endurance: "-100", vie: 0, label: 'Mort', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/mort.webp" }
]
export class RdDItemBlessure extends RdDItem {
static get defaultIcon() {
return "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp";
}
prepareDerivedData() {
super.prepareDerivedData();
this.system.label = RdDItemBlessure.getLabelGravite(this.system.gravite)
}
static prepareTacheSoin(gravite) {
const tache = TACHES_SOIN_BLESSURE[gravite]
if (!tache) {
ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`)
return undefined;
}
return foundry.utils.mergeObject(BASE_TACHE_SOIN_BLESSURE, tache, { inplace: false })
}
static async applyFullBlessure(actor, gravite) {
const definition = foundry.utils.duplicate(RdDItemBlessure.getDefinition(gravite))
if (definition.vie) {
await actor.santeIncDec("vie", definition.vie)
}
const lostEndurance = await RdDItemBlessure.rollLostEndurance(definition.endurance)
if (lostEndurance) {
await actor.santeIncDec("endurance", -Number(lostEndurance));
}
await this.createBlessure(actor, gravite)
await ChatMessage.create({
//TODO: hbs
content: `Blessure ${definition.label} appliquée à ${actor.name}<br>Perte d'endurance : ${lostEndurance} (${definition.endurance})<br>Perte de Vie : ${definition.vie}`,
whisper: ChatUtility.getOwners(actor)
});
actor.sheet?.render()
}
static async rollLostEndurance(formula) {
if (formula) {
const roll = new Roll(formula)
await roll.evaluate()
return roll.total
}
return 0
}
static async createBlessure(actor, gravite, options = { localisation: '', origine: '', render: true }) {
const blessure = RdDItemBlessure.prepareBlessure(gravite, options);
const blessures = await actor.createEmbeddedDocuments('Item', [blessure], options)
return blessures[0]
}
static prepareBlessure(gravite, options = { localisation: '', origine: '' }) {
const definition = RdDItemBlessure.getDefinition(gravite);
return {
name: definition.label,
type: 'blessure',
img: definition.icon,
system: {
gravite: gravite,
vie: definition.vie,
endurance: definition.endurance,
difficulte: -gravite,
localisation: options.localisation,
origine: options.origine
}
}
}
static async createTacheSoinBlessure(actor, gravite) {
const tache = RdDItemBlessure.prepareTacheSoin(gravite)
if (tache) {
const taches = await actor.createEmbeddedDocuments('Item', [tache], { renderSheet: false });
return taches[0];
}
return undefined
}
async updateTacheSoinBlessure(tache) {
if (tache) {
await tache.update({
'system.itemId': this.id,
'system.difficulte': Math.min(this.system.difficulte, tache.system.difficulte),
'system.points_de_tache_courant': Math.max(0, this.system.premierssoins.tache)
});
}
}
async setSoinsBlessure(systemUpdate = {}) {
systemUpdate = foundry.utils.mergeObject(systemUpdate, this.system, { overwrite: false })
systemUpdate.soinscomplets.done = systemUpdate.premierssoins.done && systemUpdate.soinscomplets.done
await this.update({
img: this.getImgSoins(systemUpdate.gravite, systemUpdate.soinscomplets.done),
system: systemUpdate
})
}
async recuperationBlessure({ actor, timestamp, message, isMaladeEmpoisonne, blessures }) {
if (this.parent != actor || actor == undefined) {
return
}
if (new RdDTimestamp(this.system.temporel.fin).compare(timestamp) > 0) {
// attente periode
return
}
if (this.system.gravite > 0) {
const update = { system: { premierssoins: { bonus: 0 }, soinscomplets: { bonus: 0 } } }
const gravite = this.system.gravite
const graviteMoindre = gravite - 2
const moindres = blessures.filter(it => it.system.gravite == graviteMoindre, 'blessures').length
const label = RdDItemBlessure.getLabelGravite(this.system.gravite)
let rolled = await actor.jetRecuperationConstitution(this.system.soinscomplets.bonus, message);
if (rolled.isETotal) {
message.content += ` -- une blessure ${label} s'infecte (temps de guérison augmenté de ${gravite} jours, perte de vie)`;
await actor.santeIncDec("vie", -1);
foundry.utils.mergeObject(update, {
system: { fin: { indexDate: timestamp.addJours(gravite).indexDate } }
});
}
else {
if (!isMaladeEmpoisonne && rolled.isSuccess && this.peutRetrograder(graviteMoindre, moindres)) {
message.content += ` -- une blessure ${label} cicatrise`;
foundry.utils.mergeObject(update, {
system: {
gravite: graviteMoindre,
temporel: { fin: { indexDate: timestamp.addJours(graviteMoindre).indexDate } }
}
});
}
else {
message.content += ` -- une blessure ${label} reste stable`;
}
}
await this.update(update)
}
}
peutRetrograder(graviteMoindre, moindres) {
return moindres < RdDItemBlessure.maxBlessures(graviteMoindre)
}
async calculerFinPeriodeTemporel(debut) {
return debut.nouveauJour().addJours(this.system.gravite);
}
async onFinPeriode(oldTimestamp, newTimestamp) {
if (this.system.gravite <= 0) {
await super.onFinPeriode(oldTimestamp, newTimestamp)
}
}
getImgSoins(gravite, soins) {
let img = 'blessure'
if (gravite > 6) {
img = 'mort'
}
if (gravite <= 0) {
img = 'eraflure'
}
return `systems/foundryvtt-reve-de-dragon/icons/sante/${soins ? 'blessure-soins' : img}.webp`
}
static getLabelGravite(gravite) {
return definitionsBlessures.find(it => it.gravite >= gravite).label
}
static getDefinition(gravite) {
return definitionsBlessures.find(it => it.gravite >= gravite)
}
static maxBlessures(gravite) {
return definitionsBlessures.find(it => it.gravite >= gravite).max
}
isContusion() {
return this.system.gravite <= 0
}
isLegere() {
return this.system.gravite > 0 && this.system.gravite <= 2
}
isGrave() {
return this.system.gravite > 2 && this.system.gravite <= 4
}
isCritique() {
return this.system.gravite > 4 && this.system.gravite <= 6
}
isBleeding() {
return this.system.gravite > 2 && !this.system.premierssoins.done
}
isMort() {
return this.system.gravite > 6
}
getProprietes() {
return [
RdDItem.propertyIfDefined('Causée par', this.system.origine, this.system.origine),
`<b>Heure et Date</b>: ${new RdDTimestamp(this.system.temporel.debut).formatDateHeure()}`,
RdDItem.propertyIfDefined('Blessé', this.parent?.name, this.parent),
`<b>Localisation</b>: ${this.system.localisation}`,
`<b>Gravité</b>: ${this.system.label}`,
`<b>Difficulté des soins</b>: ${this.system.difficulte}`,
(this.system.soinscomplets.done ?
`<b>Bonus soins complets</b>: ${this.system.soinscomplets.bonus}` :
(this.system.premierssoins.done ?
`<b>Bonus premiers soins</b>: ${this.system.premierssoins.bonus}` :
`<b>Points de tâche</b>: ${this.system.premierssoins.tache}`
)
),
];
}
}