From 7b1fa009bba1987e99e9379868001a51fa4c153e Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Fri, 12 May 2023 22:56:45 +0200 Subject: [PATCH 1/3] Utilisation de constantes pour les types (sans effet) --- module/item.js | 148 +++++++++++++++++++------------ module/tmr/draconique.js | 10 +-- module/tmr/effets-draconiques.js | 42 +++++---- 3 files changed, 125 insertions(+), 75 deletions(-) diff --git a/module/item.js b/module/item.js index 679dd9da..67c2df5d 100644 --- a/module/item.js +++ b/module/item.js @@ -7,34 +7,71 @@ import { RdDUtility } from "./rdd-utility.js"; import { SystemCompendiums } from "./settings/system-compendiums.js"; import { RdDRaretes } from "./item/raretes.js"; +export const TYPES = { + competence: 'competence', + competencecreature: 'competencecreature', + arme: 'arme', + armure: 'armure', + conteneur: 'conteneur', + sort: 'sort', + herbe: 'herbe', + faune: 'faune', + ingredient: 'ingredient', + livre: 'livre', + potion: 'potion', + rencontre: 'rencontre', + queue: 'queue', + ombre: 'ombre', + souffle: 'souffle', + tete: 'tete', + meditation: 'meditation', + recettealchimique: 'recettealchimique', + chant: 'chant', + danse: 'danse', + jeu: 'jeu', + recettecuisine: 'recettecuisine', + musique: 'musique', + maladie: 'maladie', + poison: 'poison', + oeuvre: 'oeuvre', + nourritureboisson: 'nourritureboisson', + service: 'service', + signedraconique: 'signedraconique', + gemme: 'gemme', + possession: 'possession', + sortreserve: 'sortreserve', + extraitpoetique: 'extraitpoetique', + tarot: 'tarot', + empoignade: 'empoignade' +} const typesInventaireMateriel = [ - "arme", - "armure", - "conteneur", - "faune", - "gemme", - "herbe", - "plante", - "ingredient", - "livre", - "monnaie", - "munition", - "nourritureboisson", - "objet", - "potion", + TYPES.arme, + TYPES.armure, + TYPES.conteneur, + TYPES.faune, + TYPES.gemme, + TYPES.herbe, + TYPES.plante, + TYPES.ingredient, + TYPES.livre, + TYPES.monnaie, + TYPES.munition, + TYPES.nourritureboisson, + TYPES.objet, + TYPES.potion, ] const typesInventaire = { materiel: typesInventaireMateriel, all: ['service'].concat(typesInventaireMateriel), } -const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"] -const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"] -const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"] -const typesObjetsEffet = ["possession", "poison", "maladie", "blessure"] -const typesObjetsCompetence = ["competence", "competencecreature"] -const typesObjetsTemporels = ["blessure", "poison", "maladie", "queue", "ombre", "souffle", "signedraconique", "rencontre"] -const typesObjetsEquipable = ['arme', 'armure', 'objet']; +const typesObjetsOeuvres = [TYPES.oeuvre, TYPES.recettecuisine, TYPES.musique, TYPES.chant, TYPES.danse, TYPES.jeu] +const typesObjetsDraconiques = [TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.tete, TYPES.signedraconique, TYPES.sortreserve, TYPES.rencontre] +const typesObjetsConnaissance = [TYPES.meditation, TYPES.recettealchimique, TYPES.sort] +const typesObjetsEffet = [TYPES.possession, TYPES.poison, TYPES.maladie, TYPES.blessure] +const typesObjetsCompetence = [TYPES.competence, TYPES.competencecreature] +const typesObjetsTemporels = [TYPES.blessure, TYPES.poison, TYPES.maladie, TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.signedraconique, TYPES.rencontre] +const typesObjetsEquipable = [TYPES.arme, TYPES.armure, TYPES.objet]; const typesEnvironnement = typesInventaireMateriel; const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc @@ -93,12 +130,12 @@ export class RdDItem extends Item { static isFieldInventaireModifiable(type, field) { switch (field) { case 'quantite': - if (['conteneur'].includes(type)) { + if ([TYPES.conteneur].includes(type)) { return false; } break; case 'cout': - if (['monnaie'].includes(type)) { + if ([TYPES.monnaie].includes(type)) { return game.user.isGM; } break; @@ -146,15 +183,15 @@ export class RdDItem extends Item { getUniteQuantite() { switch (this.type) { - case "monnaie": return "(Pièces)" - case "herbe": + case TYPES.monnaie: return "(Pièces)" + case TYPES.herbe: switch (this.system.categorie) { case 'Alchimie': case 'Repos': case 'Soin': return "(Brins)" case 'Cuisine': return ''; } return ''; - case "ingredient": return "(Pépins ou Brins)" + case TYPES.ingredient: return "(Pépins ou Brins)" } return ''; } @@ -163,26 +200,27 @@ export class RdDItem extends Item { return typesObjetsEquipable.includes(this.type) } - isCompetencePersonnage() { return this.type == 'competence' } - isCompetenceCreature() { return this.type == 'competencecreature' } - isConteneur() { return this.type == 'conteneur'; } - isMonnaie() { return this.type == 'monnaie'; } - isPotion() { return this.type == 'potion'; } - isNourritureBoisson() { return this.type == 'nourritureboisson'; } - isService() { return this.type == 'service'; } + isCompetencePersonnage() { return this.type == TYPES.competence } + isCompetenceCreature() { return this.type == TYPES.competencecreature } + isConteneur() { return this.type == TYPES.conteneur; } + isMonnaie() { return this.type == TYPES.monnaie; } + isPotion() { return this.type == TYPES.potion; } + isNourritureBoisson() { return this.type == TYPES.nourritureboisson; } + isService() { return this.type == TYPES.service; } isCompetence() { return typesObjetsCompetence.includes(this.type) } isTemporel() { return typesObjetsTemporels.includes(this.type) } isOeuvre() { return typesObjetsOeuvres.includes(this.type) } isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) } + isQueueDragon() { return [TYPES.queue, TYPES.ombre].includes(this.type) } isEffet() { return typesObjetsEffet.includes(this.type) } isConnaissance() { return typesObjetsConnaissance.includes(this.type) } isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); } isBoisson() { return this.isNourritureBoisson() && this.system.boisson; } isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; } - isHerbeAPotion() { return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); } - isBlessure() { return this.type == 'blessure' } + isHerbeAPotion() { return this.type == TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); } + isBlessure() { return this.type == TYPES.blessure } isPresentDansMilieux(milieux) { return this.getEnvironnements(milieux).length > 0 @@ -267,15 +305,15 @@ export class RdDItem extends Item { getUtilisation() { switch (this.type) { - case 'potion': + case TYPES.potion: switch (this.system.categorie) { case 'Alchimie': case 'AlchimieEnchante': case 'AlchimieAutre': return 'alchimie' case 'Cuisine': return 'cuisine' case 'Remede': case 'Repos': case 'ReposEnchante': case 'Soin': case 'SoinEnchante': return 'soins' } return ''; - case 'nourritureboisson': return 'cuisine'; - case 'herbe': case 'faune': case 'ingredient': case 'plante': + case TYPES.nourritureboisson: return 'cuisine'; + case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante: switch (this.system.categorie) { case 'Cuisine': return 'cuisine'; case 'Toxique': case 'Poison': return 'poison'; @@ -290,9 +328,9 @@ export class RdDItem extends Item { getUtilisationCuisine() { if (this.getUtilisation() == 'cuisine') { switch (this.type) { - case 'nourritureboisson': + case TYPES.nourritureboisson: return 'pret'; - case 'herbe': case 'faune': case 'ingredient': case 'plante': + case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante: return 'brut'; } } @@ -300,7 +338,7 @@ export class RdDItem extends Item { } isCristalAlchimique() { - return this.type == 'objet' && Grammar.toLowerCaseNoAccent(this.name) == 'cristal alchimique' && this.system.quantite > 0; + return this.type == TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0; } isMagique() { @@ -328,11 +366,11 @@ export class RdDItem extends Item { getEnc() { switch (this.type) { - case 'service': + case TYPES.service: return 0; - case 'herbe': + case TYPES.herbe: return this.getEncHerbe(); - case 'gemme': + case TYPES.gemme: return encPepin * this.system.taille; } return Math.max(this.system.encombrement ?? 0, 0); @@ -388,7 +426,7 @@ export class RdDItem extends Item { getActionPrincipale(options = { warnIfNot: true }) { switch (this.type) { - case 'conteneur': return 'Ouvrir'; + case TYPES.conteneur: return 'Ouvrir'; } if (this.actor?.isPersonnage()) { const warn = options.warnIfNot; @@ -396,11 +434,11 @@ export class RdDItem extends Item { return 'Utiliser'; } switch (this.type) { - case 'nourritureboisson': return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn); - case 'potion': return this._actionOrWarnQuantiteZero('Boire', warn); - case 'livre': return this._actionOrWarnQuantiteZero('Lire', warn); - case 'herbe': return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined; - case 'queue': case 'ombre': return this.system.refoulement > 0 ? 'Refouler' : undefined; + case TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn); + case TYPES.potion: return this._actionOrWarnQuantiteZero('Boire', warn); + case TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn); + case TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined; + case TYPES.queue: case TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined; } } return undefined; @@ -415,11 +453,11 @@ export class RdDItem extends Item { return; } switch (this.type) { - case 'potion': return await actor.consommerPotion(this, onActionItem); - case 'livre': return await actor.actionLire(this); - case 'conteneur': return await this.sheet.render(true); - case 'herbe': return await actor.actionHerbe(this, onActionItem); - case 'queue': case 'ombre': return await actor.actionRefoulement(this); + case TYPES.potion: return await actor.consommerPotion(this, onActionItem); + case TYPES.livre: return await actor.actionLire(this); + case TYPES.conteneur: return await this.sheet.render(true); + case TYPES.herbe: return await actor.actionHerbe(this, onActionItem); + case TYPES.queue: case TYPES.ombre: return await actor.actionRefoulement(this); } } diff --git a/module/tmr/draconique.js b/module/tmr/draconique.js index 460ea74d..c5a78fa7 100644 --- a/module/tmr/draconique.js +++ b/module/tmr/draconique.js @@ -1,4 +1,4 @@ -import { Misc } from "../misc.js"; +import { TYPES } from "../item.js"; import { TMRUtility } from "../tmr-utility.js"; import { PixiTMR } from "./pixi-tmr.js"; @@ -9,10 +9,10 @@ const registeredEffects = [ * Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR */ export class Draconique { - static isCaseTMR(item) { return item.type == 'casetmr'; } - static isQueueDragon(item) { return item.type == 'queue' || item.type == 'ombre'; } - static isSouffleDragon(item) { return item.type == 'souffle'; } - static isTeteDragon(item) { return item.type == 'tete'; } + static isCaseTMR(item) { return item.type == TYPES.casetmr; } + static isQueueDragon(item) { return item.isQueueDragon(); } + static isSouffleDragon(item) {return item.type == TYPES.souffle; } + static isTeteDragon(item) { return item.type == TYPES.tete; } static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); } tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.system.coord); } diff --git a/module/tmr/effets-draconiques.js b/module/tmr/effets-draconiques.js index 06c9939a..3bc8cfc6 100644 --- a/module/tmr/effets-draconiques.js +++ b/module/tmr/effets-draconiques.js @@ -18,6 +18,7 @@ import { Periple } from "./periple.js"; import { UrgenceDraconique } from "./urgence-draconique.js"; import { Grammar } from "../grammar.js"; import { AugmentationSeuil } from "./augmentation-seuil.js"; +import { TYPES } from "../item.js"; export class EffetsDraconiques { @@ -114,46 +115,57 @@ export class EffetsDraconiques { ); } - static filterItems(actor, filter, name) { - return actor.filterItems(filter) - .filter(it => Grammar.includesLowerCaseNoAccent(it.name, name)); + static tetesDragon(actor, name) { + return actor.itemTypes[TYPES.tete].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name)); + } + + static soufflesDragon(actor, name) { + return actor.itemTypes[TYPES.souffle].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name)); + } + + static queuesDragon(actor, name) { + return actor.filterItems(it => it.isQueueDragon() && Grammar.includesLowerCaseNoAccent(it.name, name)); + } + + static queuesSoufflesDragon(actor, name) { + return actor.filterItems(it => [TYPES.queue, TYPES.ombre, TYPES.souffle].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, name)); } static countAugmentationSeuil(actor) { - return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Augmentation du seuil de rêve').length; + return EffetsDraconiques.tetesDragon(actor, 'Augmentation du seuil de rêve').length; } static isDonDoubleReve(actor) { - return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Don de double-rêve').length>0; + return EffetsDraconiques.tetesDragon(actor, 'Don de double-rêve').length > 0; } static isConnaissanceFleuve(actor) { - return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'connaissance du fleuve').length>0; + return EffetsDraconiques.tetesDragon(actor, 'connaissance du fleuve').length > 0; } static isReserveEnSecurite(actor) { - return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'réserve en sécurité').length>0; + return EffetsDraconiques.tetesDragon(actor, 'réserve en sécurité').length > 0; } static isDeplacementAccelere(actor) { - return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, ' déplacement accéléré').length>0; + return EffetsDraconiques.tetesDragon(actor, 'déplacement accéléré').length > 0; } static isDoubleResistanceFleuve(actor) { - return EffetsDraconiques.filterItems(actor, Draconique.isSouffleDragon, 'résistance du fleuve').length>0; + return EffetsDraconiques.soufflesDragon(actor, 'résistance du fleuve').length > 0; } static countInertieDraconique(actor) { - return EffetsDraconiques.filterItems(actor, Draconique.isQueueDragon, 'inertie draconique').length; + return EffetsDraconiques.queuesDragon(actor, 'inertie draconique').length; } static countMonteeLaborieuse(actor) { - return EffetsDraconiques.filterItems(actor, Draconique.isQueueSouffle, 'montée laborieuse').length; + return EffetsDraconiques.queuesSoufflesDragon(actor, 'montée laborieuse').length; } static mauvaiseRencontre(actor) { - const mauvaisesRencontres = EffetsDraconiques.filterItems(actor, Draconique.isQueueSouffle, 'mauvaise rencontre'); - return mauvaisesRencontres.length>0 ? mauvaisesRencontres[0] : undefined; + const mauvaisesRencontres = EffetsDraconiques.queuesSoufflesDragon(actor, 'mauvaise rencontre'); + return mauvaisesRencontres.length > 0 ? mauvaisesRencontres[0] : undefined; } static isPontImpraticable(actor) { @@ -165,11 +177,11 @@ export class EffetsDraconiques { } static isSujetInsomnie(actor) { - return actor.items.find(it => ['queue', 'ombre'].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, 'Insomnie')) ? true : false; + return EffetsDraconiques.queuesDragon(actor, 'Insomnie').length > 0 ? true : false; } static isPeage(actor) { - return EffetsDraconiques.filterItems(actor, Draconique.isSouffleDragon, 'péage').length > 0; + return EffetsDraconiques.soufflesDragon(actor, 'péage').length > 0; } From 4d7317b96468af87ff6b6c2f392b3a37803d2cc1 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 24 May 2023 21:59:17 +0200 Subject: [PATCH 2/3] Gestion de l'armure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correction de la détérioration d'une armure variable Séparation du code d'armure dans l'Item RdDArmureItem --- module/actor.js | 33 ++-------------------------- module/item/armure.js | 51 +++++++++++++++++++++++++++++++++++++++++++ module/rdd-main.js | 2 ++ 3 files changed, 55 insertions(+), 31 deletions(-) create mode 100644 module/item/armure.js diff --git a/module/actor.js b/module/actor.js index abcfb45b..ed20d6ab 100644 --- a/module/actor.js +++ b/module/actor.js @@ -3149,8 +3149,8 @@ export class RdDActor extends RdDBaseActor { const armures = this.items.filter(it => it.type == "armure" && it.system.equipe); for (const armure of armures) { protection += await RdDDice.rollTotal(armure.system.protection.toString()); - if (dmg > 0) { - this._deteriorerArmure(armure, dmg); + if (dmg > 0 && attackerRoll.dmg.encaisserSpecial != "noarmure") { + armure.deteriorerArmure(dmg); dmg = 0; } } @@ -3168,35 +3168,6 @@ export class RdDActor extends RdDBaseActor { return protection; } - /* -------------------------------------------- */ - _deteriorerArmure(armure, dmg) { - armure = duplicate(armure); - if (!ReglesOptionelles.isUsing('deteriorationArmure') || armure.system.protection == '0') { - return; - } - armure.system.deterioration = (armure.system.deterioration ?? 0) + dmg; - if (armure.system.deterioration >= 10) { - armure.system.deterioration -= 10; - let res = /(\d+)?d(\d+)(\-\d+)?/.exec(armure.system.protection); - if (res) { - let malus = Misc.toInt(res[3]) - 1; - let armure = Misc.toInt(res[2]); - if (armure + malus <= 0) { - armure.system.protection = 0; - } else { - armure.system.protection = '' + (res[1] ?? '1') + 'd' + armure + malus; - } - } - else if (/\d+/.exec(armure.system.protection)) { - armure.system.protection = "1d" + armure.system.protection; - } - else { - ui.notifications.warn(`La valeur d'armure de votre ${armure.name} est incorrecte`); - } - ChatMessage.create({ content: "Votre armure s'est détériorée, elle protège maintenant de " + armure.system.protection }); - } - this.updateEmbeddedDocuments('Item', [armure]); - } /* -------------------------------------------- */ async encaisser() { diff --git a/module/item/armure.js b/module/item/armure.js new file mode 100644 index 00000000..101977a5 --- /dev/null +++ b/module/item/armure.js @@ -0,0 +1,51 @@ +import { RdDItem } from "../item.js"; +import { Misc } from "../misc.js"; +import { ReglesOptionelles } from "../settings/regles-optionelles.js"; + +export class RdDItemArmure extends RdDItem { + + static get defaultIcon() { + return "systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp"; + } + + deteriorerArmure(dmg) { + if (!ReglesOptionelles.isUsing('deteriorationArmure') || this.system.protection == '0') { + return; + } + let deterioration = (this.system.deterioration ?? 0) + dmg; + let protection = this.system.protection; + + if (deterioration >= 10) { + deterioration -= 10; + protection = this.calculProtectionDeterioree(); + ChatMessage.create({ content: `Votre armure ${this.name} s'est détériorée, elle protège maintenant de ${protection}` }); + } + this.update({ + system: { + deterioration: deterioration, + protection: protection + } + }); + } + + calculProtectionDeterioree() { + const protectionCourante = this.system.protection; + let res = /(\d+)?d(\d+)(\-\d+)?/.exec(protectionCourante); + if (res) { + let protection = Misc.toInt(res[2]); + let malus = Misc.toInt(res[3]) - 1; + if (protection + malus <= 0) { + return 0; + } else { + return `1d${protection}${malus}`; + } + } + else if (/\d+/.exec(protectionCourante)) { + return `1d${protectionCourante}`; + } + else { + ui.notifications.warn(`La valeur d'armure de votre ${this.name} est incorrecte`); + return undefined; + } + } +} \ No newline at end of file diff --git a/module/rdd-main.js b/module/rdd-main.js index a45f2a9f..65d4b106 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -58,6 +58,7 @@ import { RdDConteneurItemSheet } from "./item/sheet-conteneur.js"; import { RdDSigneDraconiqueItemSheet } from "./item/sheet-signedraconique.js"; import { RdDItemInventaireSheet } from "./item/sheet-base-inventaire.js"; import { AppAstrologie } from "./sommeil/app-astrologie.js"; +import { RdDItemArmure } from "./item/armure.js"; /** * RdD system @@ -76,6 +77,7 @@ export class SystemReveDeDragon { this.RdDUtility = RdDUtility; this.RdDHotbar = RdDHotbar; this.itemClasses = { + armure: RdDItemArmure, blessure: RdDItemBlessure, maladie: RdDItemMaladie, ombre: RdDItemOmbre, From c10195f75318d1a725b2e2983e261e3ab989305d Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 24 May 2023 21:59:30 +0200 Subject: [PATCH 3/3] Version 10.7.13 --- changelog.md | 3 +++ system.json | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index 85877124..178fa015 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,9 @@ --- # v10.7 - L'os de Semolosse +## v10.7.13 - l'armure de Semolosse +- Fix: en cas d'armure variable, la détérioration diminue le dé d'armure + ## v10.7.12 - Fix: si le MJ gère les changements de jours, l'option "sieste" de la fenêtre de repos est prise par défaut si chateau dormant n'est pas passé diff --git a/system.json b/system.json index 830bd800..642ddf03 100644 --- a/system.json +++ b/system.json @@ -1,8 +1,8 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "10.7.12", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.7.12.zip", + "version": "10.7.13", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.7.13.zip", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json", "compatibility": { "minimum": "10",