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, 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 = this.getLabelGravite() } 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(duplicate(BASE_TACHE_SOIN_BLESSURE), tache) } static async applyFullBlessure(actor, gravite) { const definition = RdDItemBlessure.getDefinition(gravite) let lostEndurance = 0 let lostVie = 0 if (definition.endurance) { lostEndurance = new Roll(definition.endurance).roll({async: false}).total; actor.santeIncDec("endurance", -Number(lostEndurance)); } if (definition.vie) { lostVie = definition.vie actor.santeIncDec("vie", definition.vie) } await this.createBlessure(actor, gravite) ChatMessage.create({ content: `Blessure ${definition.label} appliquée à ${actor.name}`+ `
Perte d'endurance : ${lostEndurance}`+ `
Perte de Vie : ${lostVie}`, whisper: ChatUtility.getWhisperRecipientsAndGMs(actor.name) }); } static async createBlessure(actor, gravite, localisation = '', attacker) { const definition = RdDItemBlessure.getDefinition(gravite) const blessure = { name: definition.label, type: 'blessure', img: definition.icon, system: { gravite: gravite, difficulte: - gravite, localisation: localisation, origine: attacker?.name ?? "" } } const blessures = await actor.createEmbeddedDocuments('Item', [blessure]) return blessures[0] } 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, difficulte: Math.min(this.system.difficulte, tache.system.difficulte), 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 = this.getLabelGravite(); 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.getDefinition(graviteMoindre).max } async calculerFinPeriodeTemporel(debut) { return await 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` } getLabelGravite() { return RdDItemBlessure.getDefinition(this.system.gravite).label } static getDefinition(gravite) { return definitionsBlessures.sort(Misc.ascending(it => it.gravite)) .find(it => it.gravite >= gravite); } static maxBlessures(gravite) { return RdDItemBlessure.getDefinition(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 } isMort() { return this.system.gravite > 6 } getProprietes() { return [ RdDItem.propertyIfDefined('Causée par', this.system.origine, this.system.origine), `Heure et Date: ${new RdDTimestamp(this.system.temporel.debut).formatDateHeure()}`, RdDItem.propertyIfDefined('Blessé', this.parent?.name, this.parent), `Localisation: ${this.system.localisation}`, `Gravité: ${RdDItemBlessure.getDefinition(this.system.gravite).label}`, `Difficulté des soins: ${this.system.difficulte}`, (this.system.soinscomplets.done ? `Bonus soins complets: ${this.system.soinscomplets.bonus}` : (this.system.premierssoins.done ? `Bonus premiers soins: ${this.system.premierssoins.bonus}` : `Points de tâche: ${this.system.premierssoins.tache}` ) ), ]; } }