Corrections soins des blessures V2

This commit is contained in:
2025-12-15 01:09:34 +01:00
parent e33727ac8d
commit 67a085f884
11 changed files with 332 additions and 305 deletions
+2
View File
@@ -6,6 +6,8 @@
- lors de la consoimmation suite à un achat, les jets d'appréciation/éthylisme
sont faits par l'acheteur. Du coup, c'est lui qui lance le jet d'appréciation
(pour un service ou un plat de qualité), et ses dés sont utilisés avec dice-so-nice
- Fenêtre de jets V2
- Les soins de blessures sont correctement appliqués
## 13.0.22 - Les reflets d'Illysis
+9 -70
View File
@@ -1936,7 +1936,7 @@ export class RdDActor extends RdDBaseActorSang {
async getTacheBlessure(blesse, blessure) {
const gravite = blessure?.system.gravite ?? 0;
if (gravite > 0) {
const tache = this.itemTypes['tache'].find(it => it.system.itemId == blessure.id)
const tache = this.itemTypes[ITEM_TYPES.tache].find(it => it.system.itemId == blessure.id)
?? await RdDItemBlessure.createTacheSoinBlessure(this, gravite);
await blessure?.updateTacheSoinBlessure(tache);
return tache
@@ -1990,7 +1990,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { tache: { key: tache.id, forced: options.forced } },
type: { allowed: [PART_TACHE], current: PART_TACHE }
}
return await RollDialog.create(rollData)
return await RollDialog.create(rollData, options)
}
const compData = this.getCompetence(tache.system.competence)
@@ -2034,8 +2034,8 @@ export class RdDActor extends RdDBaseActorSang {
await this.santeIncDec("fatigue", rollData.tache.system.fatigue);
await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-tache.hbs');
if (options?.onRollAutomate) {
options.onRollAutomate(rollData);
if (options?.callbacks) {
await Promise.all(callbacks.map(callback => callback(rollData)))
}
}
@@ -2506,77 +2506,16 @@ export class RdDActor extends RdDBaseActorSang {
if (!blessure.system.premierssoins.done) {
const tache = await this.getTacheBlessure(blesse, blessure);
return await this.rollTache(tache.id, {
onRollAutomate: async r => blesse.onRollTachePremiersSoins(blessureId, r),
title: 'Premiers soins',
forced: true
callbacks: [async r => await blesse.onRollTachePremiersSoins(blessureId, r, this.id)],
title: 'Premiers soins', forced: true
});
}
else if (!blessure.system.soinscomplets.done) {
const diff = blessure.system.difficulte + (blessure.system.premierssoins.bonus ?? 0);
return await this.rollCaracCompetence(CARACS.DEXTERITE, "Chirurgie", diff, {
title: "Soins complets",
onRollAutomate: r => blesse.onRollSoinsComplets(blessureId, r),
forced: true
})
}
}
}
async onRollTachePremiersSoins(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollTachePremiersSoins', args: [blessureId, rollData]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && !blessure.system.premierssoins.done) {
const tache = rollData.tache;
if (rollData.rolled.isETotal) {
await blessure.update({
'system.difficulte': blessure.system.difficulte - 1,
'system.premierssoins.tache': Math.max(0, tache.system.points_de_tache_courant)
})
}
else {
const bonus = tache.system.points_de_tache_courant - tache.system.points_de_tache
await blessure.update({
'system.premierssoins': {
done: (bonus >= 0),
bonus: Math.max(0, bonus),
tache: Math.max(0, tache.system.points_de_tache_courant)
}
})
if (bonus >= 0) {
await this.deleteEmbeddedDocuments('Item', [tache.id])
}
}
}
}
async onRollSoinsComplets(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollSoinsComplets', args: [blessureId, rollData]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && blessure.system.premierssoins.done && !blessure.system.soinscomplets.done) {
// TODO: update de la blessure: passer par le MJ!
if (rollData.rolled.isETotal) {
await blessure.setSoinsBlessure({
difficulte: blessure.system.difficulte - 1,
premierssoins: { done: false, bonus: 0 }, soinscomplets: { done: false, bonus: 0 },
})
}
else {
// soins complets finis
await blessure.setSoinsBlessure({
soinscomplets: { done: true, bonus: Math.max(0, rollData.rolled.ptTache) },
callbacks: [async r => await blesse.onRollSoinsComplets(blessureId, r, this.id)],
onRollDone: RollDialog.onRollDoneClose,
title: "Soins complets", forced: true
})
}
}
+6 -3
View File
@@ -26,7 +26,7 @@ import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES } fr
import { RollDataAjustements } from "../rolldata-ajustements-v1.js";
import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs";
import RollDialog from "../roll/roll-dialog.mjs";
import { ATTAQUE_ROLL_TYPES, DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE} from "../roll/roll-constants.mjs";
import { ATTAQUE_ROLL_TYPES, DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE } from "../roll/roll-constants.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js";
import { PART_COMP } from "../roll/roll-part-comp.mjs";
import { RdDInitiative } from "../initiative.mjs";
@@ -208,7 +208,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
.map(async it => await RdDEmpoignade.onImmobilisation(this, it)))
}
async finDeRoundPossession(){
async finDeRoundPossession() {
await Promise.all(this.itemTypes[ITEM_TYPES.possession]
.map(async it => await RdDPossessionV2.onPossession(this, it)))
}
@@ -348,7 +348,10 @@ export class RdDBaseActorReve extends RdDBaseActor {
competence: competence,
show: { title: options?.title ?? '' }
},
callbacks: [async r => this.$onRollCompetence(r, options)]
callbacks: [
async r => this.$onRollCompetence(r, options),
...(options?.callbacks ?? [])
]
});
}
/**
+68 -8
View File
@@ -7,6 +7,7 @@ import { RdDDice } from "../rdd-dice.js";
import { RdDItemBlessure } from "../item/blessure.js";
import { ChatUtility } from "../chat-utility.js";
import { Misc } from "../misc.js";
import { RdDBaseActor } from "./base-actor.js";
/**
* Classe de base pour les acteurs qui peuvent subir des blessures
@@ -120,16 +121,14 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
/* -------------------------------------------- */
async santeIncDec(name, inc, isCritique = false) {
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
return;
return
}
if (!this.system.sante[name]) {
return
}
const sante = foundry.utils.duplicate(this.system.sante)
let compteur = sante[name];
if (!compteur) {
return;
}
let result = {
sonne: false,
};
const compteur = sante[name]
const result = { sonne: false }
let perteEndurance = 0
let minValue = name == "vie" ? -this.getSConst() - 1 : 0;
@@ -171,6 +170,67 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return result
}
async onRollTachePremiersSoins(blessureId, rollData, soigneurId) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollTachePremiersSoins', args: [blessureId, rollData, soigneurId]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && !blessure.system.premierssoins.done) {
const tache = rollData.v2 ? rollData.current.tache.tache : rollData.tache
if (rollData.rolled.isETotal) {
await blessure.update({
'system.difficulte': blessure.system.difficulte - 1,
'system.premierssoins.tache': Math.max(0, tache.system.points_de_tache_courant)
})
}
else {
const bonus = tache.system.points_de_tache_courant - tache.system.points_de_tache
await blessure.update({
'system.premierssoins': {
done: (bonus >= 0),
bonus: Math.max(0, bonus),
tache: Math.max(0, tache.system.points_de_tache_courant)
}
})
if (bonus >= 0 && soigneurId) {
const soigneur = game.actors.get(soigneurId)
await soigneur.deleteEmbeddedDocuments('Item', [tache.id], { render: true })
}
}
}
}
async onRollSoinsComplets(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollSoinsComplets', args: [blessureId, rollData]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && blessure.system.premierssoins.done && !blessure.system.soinscomplets.done) {
// TODO: update de la blessure: passer par le MJ!
if (rollData.rolled.isETotal) {
await blessure.setSoinsBlessure({
difficulte: blessure.system.difficulte - 1,
premierssoins: { done: false, bonus: 0 }, soinscomplets: { done: false, bonus: 0 },
})
}
else {
// soins complets finis
await blessure.setSoinsBlessure({
soinscomplets: { done: true, bonus: Math.max(0, rollData.rolled.ptTache) },
})
}
}
}
/* -------------------------------------------- */
_computeEnduranceMax() {
const diffVie = this.system.sante.vie.max - this.system.sante.vie.value;
+37 -36
View File
@@ -619,22 +619,22 @@ export class RdDBaseActor extends Actor {
await this.setEffect(STATUSES.StatusSurEnc, isSurenc)
}
}
}
}
getEncTotal() {
getEncTotal() {
return Number(this.encTotal?.toFixed(2) ?? 0.00)
}
}
async createItem(type, name = undefined) {
if (!name) {
name = 'Nouveau ' + Misc.typeName('Item', type);
}
await this.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
}
}
canReceive(item) {
canReceive(item) {
return false;
}
}
async processDropItem(params) {
const targetActorId = this.id
@@ -675,22 +675,22 @@ canReceive(item) {
}
await this.computeEncTotal()
return result;
}
}
getContenantOrParent(dest) {
getContenantOrParent(dest) {
if (!dest || dest.isConteneur()) {
return dest;
}
return this.getContenant(dest);
}
}
getContenant(item) {
getContenant(item) {
return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id));
}
}
/* -------------------------------------------- */
conteneurPeutContenir(dest, moved) {
/* -------------------------------------------- */
conteneurPeutContenir(dest, moved) {
if (!dest) {
return true;
}
@@ -715,7 +715,7 @@ conteneurPeutContenir(dest, moved) {
return false;
}
return true;
}
}
/* -------------------------------------------- */
/** Ajoute un item dans un conteneur, sur la base de leurs ID */
@@ -730,7 +730,7 @@ conteneurPeutContenir(dest, moved) {
item.estContenu = false;
await conteneur?.update({ 'system.-=contenu': undefined })
}
}
}
/* -------------------------------------------- */
/** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */
@@ -760,10 +760,10 @@ conteneurPeutContenir(dest, moved) {
}
}
});
}
}
/* -------------------------------------------- */
buildSubConteneurObjetList(conteneurId, deleteList) {
/* -------------------------------------------- */
buildSubConteneurObjetList(conteneurId, deleteList) {
let conteneur = this.getItem(conteneurId);
if (conteneur?.type == 'conteneur') { // Si c'est un conteneur
for (let subId of conteneur.system.contenu) {
@@ -776,7 +776,7 @@ buildSubConteneurObjetList(conteneurId, deleteList) {
}
}
}
}
}
/* -------------------------------------------- */
async deleteAllConteneur(itemId, options) {
@@ -784,7 +784,7 @@ buildSubConteneurObjetList(conteneurId, deleteList) {
list.push({ id: itemId, conteneurId: undefined }); // Init list
this.buildSubConteneurObjetList(itemId, list);
await this.deleteEmbeddedDocuments('Item', list.map(it => it.id), options);
}
}
/* -------------------------------------------- */
/**
@@ -802,7 +802,7 @@ buildSubConteneurObjetList(conteneurId, deleteList) {
}
}
item.estContenu = false;
}
}
/* -------------------------------------------- */
async moveItemsBetweenActors(itemId, sourceActorId, sourceTokenId) {
@@ -831,15 +831,15 @@ buildSubConteneurObjetList(conteneurId, deleteList) {
}
const deletedItemIds = itemsList.map(it => it.id)
await sourceActor.deleteEmbeddedDocuments('Item', deletedItemIds);
}
}
_buildMapOldNewId(itemsList, newItems) {
_buildMapOldNewId(itemsList, newItems) {
let itemMap = {};
for (let i = 0; i < itemsList.length; i++) {
itemMap[itemsList[i].id] = newItems[i].id; // Pour garder le lien ancien / nouveau
}
return itemMap;
}
}
/* -------------------------------------------- */
async postActorToChat(modeOverride) {
@@ -854,32 +854,32 @@ _buildMapOldNewId(itemsList, newItems) {
}
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.hbs', chatData)
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
}
}
actionImpossible(action) {
actionImpossible(action) {
ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`)
}
}
isAlcoolise() { return false }
isAlcoolise() { return false }
async jetEthylisme() { this.actionImpossible("jet d'éthylisme") }
async rollAppelChance() { this.actionImpossible("appel à la chance") }
async jetDeMoral() { this.actionImpossible("jet de moral") }
async resetItemUse() { }
async incDecItemUse(itemId, shouldIncrease = true) { }
getItemUse(itemId) { return 0; }
getItemUse(itemId) { return 0; }
async finDeRound(options = { terminer: false }) { }
isActorCombat() { return false }
getCaracInit(competence) { return 0 }
isActorCombat() { return false }
getCaracInit(competence) { return 0 }
listAttaques() {
listAttaques() {
return this.listActions({ isAttaque: true, isEquipe: false })
}
}
listActions({ isAttaque = false, isEquipe = false }) { return [] }
listActions({ isAttaque = false, isEquipe = false }) { return [] }
listActionsPossessions() {
listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession]
.filter(it => !it.system.possede)
.map(p => {
@@ -889,5 +889,6 @@ listActionsPossessions() {
possessionid: p.system.possessionid,
}
})
}
}
}
+21
View File
@@ -233,4 +233,25 @@ export class ChatUtility {
static async setTimestamp(chatMessage) {
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
}
// TODO: find ChatLog to change the action for data-action flush
// async flush() {
// const question = game.i18n.localize("AreYouSure");
// const warning = game.i18n.localize("CHAT.FlushWarning");
// return foundry.applications.api.DialogV2.confirm({
// window: {title: "CHAT.FlushTitle"},
// content: `<p><strong>${question}</strong> ${warning}</p>`,
// position: {
// top: window.innerHeight - 150,
// left: window.innerWidth - 720
// },
// yes: {
// callback: async () => {
// await this.documentClass.deleteDocuments([], {deleteAll: true});
// const jumpToBottomElement = document.querySelector(".jump-to-bottom");
// jumpToBottomElement.hidden = true;
// }
// }
// });
// }
}
+2 -1
View File
@@ -1378,6 +1378,7 @@ export class RdDCombat {
return
}
const alias = token?.name ?? actor.getAlias();
const blessuresGraves = actor.countBlessures(it => it.isGrave());
const formData = {
combatId: combat._id,
alias: alias,
@@ -1388,7 +1389,7 @@ export class RdDCombat {
actorId: actor.id,
actor: actor,
tokenId: token.id,
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
blessuresGraves: blessuresGraves,
isCritique: actor.countBlessures(it => it.isCritique()) > 0
}
await ChatMessage.create({
+5 -2
View File
@@ -535,12 +535,15 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
roll.result = selectedRollType.getResult(roll, impacts)
console.info('RollDialog.roll:', roll)
const callbacks = [
...this.rollOptions.callbacks,
...selectedRollType.callbacks(this.rollOptions),
...this.rollOptions.callbacks,
]
await Promise.all(callbacks.map(async callback => await callback(roll)))
for (let callback of callbacks) {
await callback(roll)
}
await impacts.applyImpacts()
selectedRollType.onApplyImpacts(roll, impacts)
+6 -10
View File
@@ -1,4 +1,3 @@
import { ITEM_TYPES } from "../constants.js"
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
import { DIFF, ROLL_TYPE_TACHE } from "./roll-constants.mjs"
import { PART_TACHE } from "./roll-part-tache.mjs"
@@ -19,25 +18,22 @@ export class RollTypeTache extends RollType {
this.setDiffType(rollData, DIFF.AUCUN)
}
callbacks(rollOptions) { return [ async r => await RollTypeTache.$onRollTache(r, rollOptions)] }
callbacks(rollOptions) { return [async r => await RollTypeTache.$onRollTache(r)] }
static async $onRollTache(rollData, rollOptions) {
static async $onRollTache(rollData) {
const actor = rollData.active.actor
const tache = rollData.current[PART_TACHE].tache
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
await actor.santeIncDec("fatigue", tache.system.fatigue)
}
rollData.current[PART_TACHE].tache = await tache.update({
'system.points_de_tache_courant': tache.system.points_de_tache_courant + rollData.rolled.ptTache,
'system.nb_jet_succes': tache.system.nb_jet_succes + (rollData.rolled.isSuccess ? 1 : 0),
'system.nb_jet_echec': tache.system.nb_jet_echec + (rollData.rolled.isSuccess ? 0 : 1),
'system.difficulte': tache.system.difficulte - (rollData.rolled.isETotal ? 1 : 0),
}, {render:true})
}, { render: true })
if (rollOptions?.onRollAutomate) {
await rollOptions.onRollAutomate(rollData)
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
await actor.santeIncDec("fatigue", tache.system.fatigue)
}
}
}
+1 -1
View File
@@ -63,5 +63,5 @@ export class RollType {
* @returns undefined ou une structure contenant les informations requise pour afficher
*/
getResult(rollData, impacts) { return { messages: [] } }
onApplyImpacts(roll, impacts) { }
onApplyImpacts(rollData, impacts) { }
}
+4 -3
View File
@@ -3,11 +3,12 @@
</h4>
<p data-combatid="{{combatId}}" data-combatmessage="actor-turn-summary">{{blessuresStatus}}</p>
<p>Son état général est de : {{etatGeneral}} {{#if isSonne}} et est <strong>sonné</strong>{{/if}}</p>
{{#if isGrave}}
<p>{{alias}} souffre de Blessure(s) Grave(s) : n'oubliez pas de faire un Jet de Vie toutes les SC ({{SConst}}) minutes. Un point d'Endurance a été retiré automatiquement.</p>
{{#if blessuresGraves}}
<p>{{alias}} souffre {{#if (eq blessuresGraves 1)}}d'une <strong>blessure grave</strong>{{else}}
de {{blessuresGraves}} <strong>blessures graves</strong>{{/if}} : n'oubliez pas de faire un Jet de Vie toutes les SC ({{SConst}}) minutes. Les pertes d'endurance sont automatiques à la fin du round.</p>
{{/if}}
{{#if isCritique}}
<p>{{alias}} souffre d'une <strong>Blessure Critique</strong> : faites un
<p>{{alias}} souffre d'une <strong>blessure critique</strong> : faites un
<a class="chat-card-button chat-jet-vie"
data-tokenId="{{tokenId}}"
data-actorId="{{actorId}}">Jet de Vie.<a></p>