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 - 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 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 (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 ## 13.0.22 - Les reflets d'Illysis
+9 -70
View File
@@ -1936,7 +1936,7 @@ export class RdDActor extends RdDBaseActorSang {
async getTacheBlessure(blesse, blessure) { async getTacheBlessure(blesse, blessure) {
const gravite = blessure?.system.gravite ?? 0; const gravite = blessure?.system.gravite ?? 0;
if (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 RdDItemBlessure.createTacheSoinBlessure(this, gravite);
await blessure?.updateTacheSoinBlessure(tache); await blessure?.updateTacheSoinBlessure(tache);
return tache return tache
@@ -1990,7 +1990,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { tache: { key: tache.id, forced: options.forced } }, selected: { tache: { key: tache.id, forced: options.forced } },
type: { allowed: [PART_TACHE], current: PART_TACHE } 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) 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 this.santeIncDec("fatigue", rollData.tache.system.fatigue);
await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-tache.hbs'); await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-tache.hbs');
if (options?.onRollAutomate) { if (options?.callbacks) {
options.onRollAutomate(rollData); await Promise.all(callbacks.map(callback => callback(rollData)))
} }
} }
@@ -2506,77 +2506,16 @@ export class RdDActor extends RdDBaseActorSang {
if (!blessure.system.premierssoins.done) { if (!blessure.system.premierssoins.done) {
const tache = await this.getTacheBlessure(blesse, blessure); const tache = await this.getTacheBlessure(blesse, blessure);
return await this.rollTache(tache.id, { return await this.rollTache(tache.id, {
onRollAutomate: async r => blesse.onRollTachePremiersSoins(blessureId, r), callbacks: [async r => await blesse.onRollTachePremiersSoins(blessureId, r, this.id)],
title: 'Premiers soins', title: 'Premiers soins', forced: true
forced: true
}); });
} }
else if (!blessure.system.soinscomplets.done) { else if (!blessure.system.soinscomplets.done) {
const diff = blessure.system.difficulte + (blessure.system.premierssoins.bonus ?? 0); const diff = blessure.system.difficulte + (blessure.system.premierssoins.bonus ?? 0);
return await this.rollCaracCompetence(CARACS.DEXTERITE, "Chirurgie", diff, { return await this.rollCaracCompetence(CARACS.DEXTERITE, "Chirurgie", diff, {
title: "Soins complets", callbacks: [async r => await blesse.onRollSoinsComplets(blessureId, r, this.id)],
onRollAutomate: r => blesse.onRollSoinsComplets(blessureId, r), onRollDone: RollDialog.onRollDoneClose,
forced: true title: "Soins complets", 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) },
}) })
} }
} }
+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 { RollDataAjustements } from "../rolldata-ajustements-v1.js";
import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs"; import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs";
import RollDialog from "../roll/roll-dialog.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 { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js";
import { PART_COMP } from "../roll/roll-part-comp.mjs"; import { PART_COMP } from "../roll/roll-part-comp.mjs";
import { RdDInitiative } from "../initiative.mjs"; import { RdDInitiative } from "../initiative.mjs";
@@ -208,7 +208,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
.map(async it => await RdDEmpoignade.onImmobilisation(this, it))) .map(async it => await RdDEmpoignade.onImmobilisation(this, it)))
} }
async finDeRoundPossession(){ async finDeRoundPossession() {
await Promise.all(this.itemTypes[ITEM_TYPES.possession] await Promise.all(this.itemTypes[ITEM_TYPES.possession]
.map(async it => await RdDPossessionV2.onPossession(this, it))) .map(async it => await RdDPossessionV2.onPossession(this, it)))
} }
@@ -348,7 +348,10 @@ export class RdDBaseActorReve extends RdDBaseActor {
competence: competence, competence: competence,
show: { title: options?.title ?? '' } 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 { RdDItemBlessure } from "../item/blessure.js";
import { ChatUtility } from "../chat-utility.js"; import { ChatUtility } from "../chat-utility.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDBaseActor } from "./base-actor.js";
/** /**
* Classe de base pour les acteurs qui peuvent subir des blessures * 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) { async santeIncDec(name, inc, isCritique = false) {
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) { if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
return; return
}
if (!this.system.sante[name]) {
return
} }
const sante = foundry.utils.duplicate(this.system.sante) const sante = foundry.utils.duplicate(this.system.sante)
let compteur = sante[name]; const compteur = sante[name]
if (!compteur) { const result = { sonne: false }
return;
}
let result = {
sonne: false,
};
let perteEndurance = 0 let perteEndurance = 0
let minValue = name == "vie" ? -this.getSConst() - 1 : 0; let minValue = name == "vie" ? -this.getSConst() - 1 : 0;
@@ -171,6 +170,67 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return result 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() { _computeEnduranceMax() {
const diffVie = this.system.sante.vie.max - this.system.sante.vie.value; const diffVie = this.system.sante.vie.max - this.system.sante.vie.value;
+208 -207
View File
@@ -599,7 +599,7 @@ export class RdDBaseActor extends Actor {
name: item.name, name: item.name,
system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }, { inplace: false }) system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }, { inplace: false })
} }
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem); const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
const items = await this.createEmbeddedDocuments("Item", newItems); const items = await this.createEmbeddedDocuments("Item", newItems);
return newItems.length > 0 ? items[0].id : undefined; return newItems.length > 0 ? items[0].id : undefined;
@@ -607,287 +607,288 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async computeEncTotal() { async computeEncTotal() {
if (this.pack) { if (this.pack) {
this.encTotal = 0 this.encTotal = 0
} }
else { else {
const wasSurenc = this.isSurenc() const wasSurenc = this.isSurenc()
this.encTotal = this.items.filter(it => RdDItem.getItemTypesInventaire().includes(it.type)) this.encTotal = this.items.filter(it => RdDItem.getItemTypesInventaire().includes(it.type))
.map(it => it.getEncTotal()).reduce(Misc.sum(), 0) .map(it => it.getEncTotal()).reduce(Misc.sum(), 0)
const isSurenc = this.isSurenc() const isSurenc = this.isSurenc()
if (isSurenc != wasSurenc) { if (isSurenc != wasSurenc) {
await this.setEffect(STATUSES.StatusSurEnc, isSurenc) await this.setEffect(STATUSES.StatusSurEnc, isSurenc)
}
} }
} }
}
getEncTotal() { getEncTotal() {
return Number(this.encTotal?.toFixed(2) ?? 0.00) return Number(this.encTotal?.toFixed(2) ?? 0.00)
} }
async createItem(type, name = undefined) { async createItem(type, name = undefined) {
if (!name) { if (!name) {
name = 'Nouveau ' + Misc.typeName('Item', type); name = 'Nouveau ' + Misc.typeName('Item', type);
}
await this.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
} }
await this.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
}
canReceive(item) { canReceive(item) {
return false;
}
async processDropItem(params) {
const targetActorId = this.id
const sourceActorId = params.sourceActorId
const sourceTokenId = params.sourceTokenId
const itemId = params.itemId
const destId = params.destId
const srcId = params.srcId
if (sourceActorId && sourceActorId != targetActorId) {
console.log("Moving objects", sourceActorId, sourceTokenId, targetActorId, itemId);
this.moveItemsBetweenActors(itemId, sourceActorId, sourceTokenId);
return false; return false;
} }
let result = true;
const item = this.getItem(itemId); async processDropItem(params) {
if (item?.isInventaire('all') && sourceActorId == targetActorId) { const targetActorId = this.id
// rangement const sourceActorId = params.sourceActorId
if (srcId != destId && itemId != destId) { // déplacement de l'objet const sourceTokenId = params.sourceTokenId
const src = this.getItem(srcId); const itemId = params.itemId
const dest = this.getItem(destId); const destId = params.destId
const cible = this.getContenantOrParent(dest); const srcId = params.srcId
const [empilable, message] = item.isInventaireEmpilable(dest); if (sourceActorId && sourceActorId != targetActorId) {
if (empilable) { console.log("Moving objects", sourceActorId, sourceTokenId, targetActorId, itemId);
await dest.empiler(item) this.moveItemsBetweenActors(itemId, sourceActorId, sourceTokenId);
result = false; return false;
} }
// changer de conteneur let result = true;
else if (!cible || this.conteneurPeutContenir(cible, item)) { const item = this.getItem(itemId);
await this.enleverDeConteneur(item, src, params.onEnleverConteneur); if (item?.isInventaire('all') && sourceActorId == targetActorId) {
await this.ajouterDansConteneur(item, cible, params.onAjouterDansConteneur); // rangement
if (message && !dest.isConteneur()) { if (srcId != destId && itemId != destId) { // déplacement de l'objet
ui.notifications.info(cible const src = this.getItem(srcId);
? `${message}<br>${item.name} a été déplacé dans: ${cible.name}` const dest = this.getItem(destId);
: `${message}<br>${item.name} a été sorti du conteneur`); const cible = this.getContenantOrParent(dest);
const [empilable, message] = item.isInventaireEmpilable(dest);
if (empilable) {
await dest.empiler(item)
result = false;
}
// changer de conteneur
else if (!cible || this.conteneurPeutContenir(cible, item)) {
await this.enleverDeConteneur(item, src, params.onEnleverConteneur);
await this.ajouterDansConteneur(item, cible, params.onAjouterDansConteneur);
if (message && !dest.isConteneur()) {
ui.notifications.info(cible
? `${message}<br>${item.name} a été déplacé dans: ${cible.name}`
: `${message}<br>${item.name} a été sorti du conteneur`);
}
} }
} }
} }
await this.computeEncTotal()
return result;
} }
await this.computeEncTotal()
return result;
}
getContenantOrParent(dest) { getContenantOrParent(dest) {
if (!dest || dest.isConteneur()) { if (!dest || dest.isConteneur()) {
return dest; return dest;
}
return this.getContenant(dest);
} }
return this.getContenant(dest);
}
getContenant(item) { getContenant(item) {
return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id)); return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id));
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
conteneurPeutContenir(dest, moved) { conteneurPeutContenir(dest, moved) {
if (!dest) { if (!dest) {
return true;
}
if (!dest.isConteneur()) {
return false;
}
if (moved.isConteneurContenu(dest)) {
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${moved.name}) dans un de ses contenus ${dest.name} !`);
return false;
}
// Calculer le total actuel des contenus
const encContenu = dest.getEncContenu();
const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet
const placeDisponible = Misc.keepDecimals(dest.system.capacite - encContenu - newEnc, 4)
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
if (placeDisponible < 0) {
ui.notifications.warn(
`Le conteneur ${dest.name} a une capacité de ${dest.system.capacite}, et contient déjà ${encContenu}.
Impossible d'y ranger: ${moved.name} d'encombrement ${newEnc}!`);
return false;
}
return true; return true;
} }
if (!dest.isConteneur()) {
return false;
}
if (moved.isConteneurContenu(dest)) {
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${moved.name}) dans un de ses contenus ${dest.name} !`);
return false;
}
// Calculer le total actuel des contenus
const encContenu = dest.getEncContenu();
const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet
const placeDisponible = Misc.keepDecimals(dest.system.capacite - encContenu - newEnc, 4)
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
if (placeDisponible < 0) {
ui.notifications.warn(
`Le conteneur ${dest.name} a une capacité de ${dest.system.capacite}, et contient déjà ${encContenu}.
Impossible d'y ranger: ${moved.name} d'encombrement ${newEnc}!`);
return false;
}
return true;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/** Ajoute un item dans un conteneur, sur la base de leurs ID */ /** Ajoute un item dans un conteneur, sur la base de leurs ID */
async ajouterDansConteneur(item, conteneur, onAjouterDansConteneur) { async ajouterDansConteneur(item, conteneur, onAjouterDansConteneur) {
if (conteneur?.isConteneur()) { if (conteneur?.isConteneur()) {
item.estContenu = true; item.estContenu = true;
const nouveauContenu = [...conteneur.system.contenu, item.id]; const nouveauContenu = [...conteneur.system.contenu, item.id];
await conteneur.update({ 'system.contenu': nouveauContenu }); await conteneur.update({ 'system.contenu': nouveauContenu });
onAjouterDansConteneur(item.id, conteneur.id) onAjouterDansConteneur(item.id, conteneur.id)
}
else {
item.estContenu = false;
await conteneur?.update({ 'system.-=contenu': undefined })
}
} }
else {
item.estContenu = false;
await conteneur?.update({ 'system.-=contenu': undefined })
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */ /** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */
async nettoyerConteneurs() { async nettoyerConteneurs() {
RdDConfirm.confirmer({ RdDConfirm.confirmer({
settingConfirmer: "confirmation-vider", settingConfirmer: "confirmation-vider",
content: `<p>Etes vous certain de vouloir vider tous les conteneurs ?</p>`, content: `<p>Etes vous certain de vouloir vider tous les conteneurs ?</p>`,
title: 'Vider les conteneurs', title: 'Vider les conteneurs',
buttonLabel: 'Vider', buttonLabel: 'Vider',
onAction: async () => { onAction: async () => {
const corrections = []; const corrections = [];
for (let item of this.items) { for (let item of this.items) {
if (item.estContenu) { if (item.estContenu) {
item.estContenu = undefined; item.estContenu = undefined;
}
if (item.system.contenu != undefined) {
if (item.type == 'conteneur') {
corrections.push({ _id: item.id, 'system.contenu': [] });
} }
else { if (item.system.contenu != undefined) {
corrections.push({ _id: item.id, 'system.-=contenu': undefined }); if (item.type == 'conteneur') {
corrections.push({ _id: item.id, 'system.contenu': [] });
}
else {
corrections.push({ _id: item.id, 'system.-=contenu': undefined });
}
} }
} }
if (corrections.length > 0) {
await this.updateEmbeddedDocuments('Item', corrections);
}
} }
if (corrections.length > 0) { });
await this.updateEmbeddedDocuments('Item', corrections); }
}
}
});
}
/* -------------------------------------------- */ /* -------------------------------------------- */
buildSubConteneurObjetList(conteneurId, deleteList) { buildSubConteneurObjetList(conteneurId, deleteList) {
let conteneur = this.getItem(conteneurId); let conteneur = this.getItem(conteneurId);
if (conteneur?.type == 'conteneur') { // Si c'est un conteneur if (conteneur?.type == 'conteneur') { // Si c'est un conteneur
for (let subId of conteneur.system.contenu) { for (let subId of conteneur.system.contenu) {
let subObj = this.getItem(subId); let subObj = this.getItem(subId);
if (subObj) { if (subObj) {
if (subObj.type == 'conteneur') { if (subObj.type == 'conteneur') {
this.buildSubConteneurObjetList(subId, deleteList); this.buildSubConteneurObjetList(subId, deleteList);
}
deleteList.push({ id: subId, conteneurId: conteneurId });
} }
deleteList.push({ id: subId, conteneurId: conteneurId });
} }
} }
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async deleteAllConteneur(itemId, options) { async deleteAllConteneur(itemId, options) {
let list = []; let list = [];
list.push({ id: itemId, conteneurId: undefined }); // Init list list.push({ id: itemId, conteneurId: undefined }); // Init list
this.buildSubConteneurObjetList(itemId, list); this.buildSubConteneurObjetList(itemId, list);
await this.deleteEmbeddedDocuments('Item', list.map(it => it.id), options); await this.deleteEmbeddedDocuments('Item', list.map(it => it.id), options);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/** /**
* Supprime un item d'un conteneur, sur la base de leurs ID * Supprime un item d'un conteneur, sur la base de leurs ID
*/ */
async enleverDeConteneur(item, conteneur, onEnleverDeConteneur) { async enleverDeConteneur(item, conteneur, onEnleverDeConteneur) {
if (conteneur) { if (conteneur) {
if (conteneur.isConteneur()) { if (conteneur.isConteneur()) {
const contenu = conteneur.system.contenu.filter(id => id != item.id); const contenu = conteneur.system.contenu.filter(id => id != item.id);
await conteneur.update({ 'system.contenu': contenu }); await conteneur.update({ 'system.contenu': contenu });
onEnleverDeConteneur(); onEnleverDeConteneur();
} }
else { else {
await conteneur.update({ 'system.-=contenu': undefined }) await conteneur.update({ 'system.-=contenu': undefined })
}
} }
item.estContenu = false;
} }
item.estContenu = false;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async moveItemsBetweenActors(itemId, sourceActorId, sourceTokenId) { async moveItemsBetweenActors(itemId, sourceActorId, sourceTokenId) {
let sourceActor = RdDBaseActor.getRealActor(sourceActorId, sourceTokenId) let sourceActor = RdDBaseActor.getRealActor(sourceActorId, sourceTokenId)
let itemsList = [{ id: itemId, conteneurId: undefined }] let itemsList = [{ id: itemId, conteneurId: undefined }]
sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list
const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id)) const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id))
.map(it => foundry.utils.duplicate(it)) .map(it => foundry.utils.duplicate(it))
.map(it => { it.system.contenu = []; return it; }); .map(it => { it.system.contenu = []; return it; });
let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate); let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate);
let itemMap = this._buildMapOldNewId(itemsList, newItems); let itemMap = this._buildMapOldNewId(itemsList, newItems);
for (let item of itemsList) { // Second boucle pour traiter la remise en conteneurs for (let item of itemsList) { // Second boucle pour traiter la remise en conteneurs
// gestion conteneur/contenu // gestion conteneur/contenu
if (item.conteneurId) { // l'Objet était dans un conteneur if (item.conteneurId) { // l'Objet était dans un conteneur
const newConteneurId = itemMap[item.conteneurId]; const newConteneurId = itemMap[item.conteneurId];
const newConteneur = this.getItem(newConteneurId); const newConteneur = this.getItem(newConteneurId);
const newItemId = itemMap[item.id]; // Get newItem const newItemId = itemMap[item.id]; // Get newItem
console.log('New conteneur filling!', newConteneur, newItemId, item); console.log('New conteneur filling!', newConteneur, newItemId, item);
const nouveauContenu = [...newConteneur.system.contenu, newItemId] const nouveauContenu = [...newConteneur.system.contenu, newItemId]
await newConteneur.update({ 'system.contenu': nouveauContenu }) await newConteneur.update({ 'system.contenu': nouveauContenu })
}
} }
const deletedItemIds = itemsList.map(it => it.id)
await sourceActor.deleteEmbeddedDocuments('Item', deletedItemIds);
} }
const deletedItemIds = itemsList.map(it => it.id)
await sourceActor.deleteEmbeddedDocuments('Item', deletedItemIds);
}
_buildMapOldNewId(itemsList, newItems) { _buildMapOldNewId(itemsList, newItems) {
let itemMap = {}; let itemMap = {};
for (let i = 0; i < itemsList.length; i++) { for (let i = 0; i < itemsList.length; i++) {
itemMap[itemsList[i].id] = newItems[i].id; // Pour garder le lien ancien / nouveau itemMap[itemsList[i].id] = newItems[i].id; // Pour garder le lien ancien / nouveau
}
return itemMap;
} }
return itemMap;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async postActorToChat(modeOverride) { async postActorToChat(modeOverride) {
let chatData = { let chatData = {
doctype: 'Actor', doctype: 'Actor',
id: this.id, id: this.id,
type: this.type, type: this.type,
img: this.img, img: this.img,
pack: this.pack, pack: this.pack,
name: this.getAlias(), name: this.getAlias(),
system: { description: this.system.description } system: { description: this.system.description }
}
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.hbs', chatData)
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
} }
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}`) 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 jetEthylisme() { this.actionImpossible("jet d'éthylisme") }
async rollAppelChance() { this.actionImpossible("appel à la chance") } async rollAppelChance() { this.actionImpossible("appel à la chance") }
async jetDeMoral() { this.actionImpossible("jet de moral") } async jetDeMoral() { this.actionImpossible("jet de moral") }
async resetItemUse() { } async resetItemUse() { }
async incDecItemUse(itemId, shouldIncrease = true) { } async incDecItemUse(itemId, shouldIncrease = true) { }
getItemUse(itemId) { return 0; } getItemUse(itemId) { return 0; }
async finDeRound(options = { terminer: false }) { } async finDeRound(options = { terminer: false }) { }
isActorCombat() { return false } isActorCombat() { return false }
getCaracInit(competence) { return 0 } getCaracInit(competence) { return 0 }
listAttaques() { listAttaques() {
return this.listActions({ isAttaque: true, isEquipe: false }) return this.listActions({ isAttaque: true, isEquipe: false })
} }
listActions({ isAttaque = false, isEquipe = false }) { return [] } listActions({ isAttaque = false, isEquipe = false }) { return [] }
listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession]
.filter(it => !it.system.possede)
.map(p => {
return {
label: p.name,
action: 'possession',
possessionid: p.system.possessionid,
}
})
}
listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession]
.filter(it => !it.system.possede)
.map(p => {
return {
label: p.name,
action: 'possession',
possessionid: p.system.possessionid,
}
})
}
} }
+21
View File
@@ -233,4 +233,25 @@ export class ChatUtility {
static async setTimestamp(chatMessage) { static async setTimestamp(chatMessage) {
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp()); 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 return
} }
const alias = token?.name ?? actor.getAlias(); const alias = token?.name ?? actor.getAlias();
const blessuresGraves = actor.countBlessures(it => it.isGrave());
const formData = { const formData = {
combatId: combat._id, combatId: combat._id,
alias: alias, alias: alias,
@@ -1388,7 +1389,7 @@ export class RdDCombat {
actorId: actor.id, actorId: actor.id,
actor: actor, actor: actor,
tokenId: token.id, tokenId: token.id,
isGrave: actor.countBlessures(it => it.isGrave()) > 0, blessuresGraves: blessuresGraves,
isCritique: actor.countBlessures(it => it.isCritique()) > 0 isCritique: actor.countBlessures(it => it.isCritique()) > 0
} }
await ChatMessage.create({ await ChatMessage.create({
+5 -2
View File
@@ -535,12 +535,15 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
roll.result = selectedRollType.getResult(roll, impacts) roll.result = selectedRollType.getResult(roll, impacts)
console.info('RollDialog.roll:', roll) console.info('RollDialog.roll:', roll)
const callbacks = [ const callbacks = [
...this.rollOptions.callbacks,
...selectedRollType.callbacks(this.rollOptions), ...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() await impacts.applyImpacts()
selectedRollType.onApplyImpacts(roll, impacts) 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 { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
import { DIFF, ROLL_TYPE_TACHE } from "./roll-constants.mjs" import { DIFF, ROLL_TYPE_TACHE } from "./roll-constants.mjs"
import { PART_TACHE } from "./roll-part-tache.mjs" import { PART_TACHE } from "./roll-part-tache.mjs"
@@ -19,25 +18,22 @@ export class RollTypeTache extends RollType {
this.setDiffType(rollData, DIFF.AUCUN) 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 actor = rollData.active.actor
const tache = rollData.current[PART_TACHE].tache 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({ rollData.current[PART_TACHE].tache = await tache.update({
'system.points_de_tache_courant': tache.system.points_de_tache_courant + rollData.rolled.ptTache, '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_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.nb_jet_echec': tache.system.nb_jet_echec + (rollData.rolled.isSuccess ? 0 : 1),
'system.difficulte': tache.system.difficulte - (rollData.rolled.isETotal ? 1 : 0), 'system.difficulte': tache.system.difficulte - (rollData.rolled.isETotal ? 1 : 0),
}, {render:true}) }, { render: true })
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
if (rollOptions?.onRollAutomate) { await actor.santeIncDec("fatigue", tache.system.fatigue)
await rollOptions.onRollAutomate(rollData)
} }
} }
} }
+1 -1
View File
@@ -63,5 +63,5 @@ export class RollType {
* @returns undefined ou une structure contenant les informations requise pour afficher * @returns undefined ou une structure contenant les informations requise pour afficher
*/ */
getResult(rollData, impacts) { return { messages: [] } } getResult(rollData, impacts) { return { messages: [] } }
onApplyImpacts(roll, impacts) { } onApplyImpacts(rollData, impacts) { }
} }
+4 -3
View File
@@ -3,11 +3,12 @@
</h4> </h4>
<p data-combatid="{{combatId}}" data-combatmessage="actor-turn-summary">{{blessuresStatus}}</p> <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> <p>Son état général est de : {{etatGeneral}} {{#if isSonne}} et est <strong>sonné</strong>{{/if}}</p>
{{#if isGrave}} {{#if blessuresGraves}}
<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> <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}}
{{#if isCritique}} {{#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" <a class="chat-card-button chat-jet-vie"
data-tokenId="{{tokenId}}" data-tokenId="{{tokenId}}"
data-actorId="{{actorId}}">Jet de Vie.<a></p> data-actorId="{{actorId}}">Jet de Vie.<a></p>