forked from public/foundryvtt-reve-de-dragon
		
	
		
			
				
	
	
		
			237 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
		
			8.3 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, 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)
 | |
| 
 | |
|     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, localisation = '', attackerToken) {
 | |
|     const definition = RdDItemBlessure.getDefinition(gravite)
 | |
|     const blessure = {
 | |
|       name: definition.label,
 | |
|       type: 'blessure',
 | |
|       img: definition.icon,
 | |
|       system: {
 | |
|         gravite: gravite,
 | |
|         difficulte: - gravite,
 | |
|         localisation: localisation,
 | |
|         origine: attackerToken?.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 = 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}`
 | |
|         )
 | |
|       ),
 | |
|     ];
 | |
|   }
 | |
| }
 |