diff --git a/changelog.md b/changelog.md index f830ae20..f1dab016 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,7 @@ # 12.0 +## 12.0.9 - Le scriptorium d'Astrobazzarh +- ajout d'une fonction avancée pour exporter les personnages dans un format csv + ## 12.0.8 - La quincaillerie d'Astrobazzarh - le propriétaire est indiqué dans les feuilles d'équipements/compétences/... - Ecaille d'efficacité diff --git a/module/actor.js b/module/actor.js index e8c87a07..50666844 100644 --- a/module/actor.js +++ b/module/actor.js @@ -32,7 +32,7 @@ import { RdDItemBlessure } from "./item/blessure.js"; import { AppAstrologie } from "./sommeil/app-astrologie.js"; import { RdDEmpoignade } from "./rdd-empoignade.js"; import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js"; -import { TYPES } from "./item.js"; +import { ITEM_TYPES } from "./item.js"; import { RdDBaseActorSang } from "./actor/base-actor-sang.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js"; @@ -92,7 +92,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ canReceive(item) { - return ![TYPES.competencecreature, TYPES.tarot, TYPES.service].includes(item.type) + return ![ITEM_TYPES.competencecreature, ITEM_TYPES.tarot, ITEM_TYPES.service].includes(item.type) } isPersonnageJoueur() { @@ -125,7 +125,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ getMalusArmure() { - return this.itemTypes[TYPES.armure].filter(it => it.system.equipe) + return this.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe) .map(it => it.system.malus) .reduce(Misc.sum(), 0); } @@ -142,7 +142,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ getDemiReve() { return this.system.reve.tmrpos.coord } - getDraconicList() { return this.itemTypes[TYPES.competence].filter(it => it.system.categorie == 'draconic') } + getDraconicList() { return this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == 'draconic') } getBestDraconic() { return foundry.utils.duplicate(this.getDraconicList().sort(Misc.descending(it => it.system.niveau)).find(it => true)) } getDraconicOuPossession() { return [...this.getDraconicList().filter(it => it.system.niveau >= 0), @@ -153,7 +153,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async $perteRevePotionsEnchantees() { - let potions = this.itemTypes[TYPES.potion] + let potions = this.itemTypes[ITEM_TYPES.potion] .filter(it => Grammar.includesLowerCaseNoAccent(it.system.categorie, 'enchanté') && !it.system.prpermanent) const potionUpdates = await Promise.all(potions.map(async it => { @@ -345,7 +345,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async _recupererBlessures(message, isMaladeEmpoisonne) { const timestamp = game.system.rdd.calendrier.getTimestamp() - const blessures = this.filterItems(it => it.system.gravite > 0, TYPES.blessure).sort(Misc.ascending(it => it.system.gravite)) + const blessures = this.filterItems(it => it.system.gravite > 0, ITEM_TYPES.blessure).sort(Misc.ascending(it => it.system.gravite)) await Promise.all(blessures.map(async b => b.recuperationBlessure({ actor: this, @@ -361,7 +361,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async _recupererVie(message, isMaladeEmpoisonne) { const tData = this.system - let blessures = this.filterItems(it => it.system.gravite > 0, TYPES.blessure); + let blessures = this.filterItems(it => it.system.gravite > 0, ITEM_TYPES.blessure); if (blessures.length > 0) { return } @@ -636,7 +636,7 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async sortMisEnReserve(sort, draconic, coord, ptreve) { await this.createEmbeddedDocuments("Item", [{ - type: TYPES.sortreserve, + type: ITEM_TYPES.sortreserve, name: sort.name, img: sort.img, system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' } @@ -991,24 +991,24 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ buildTMRInnaccessible() { - return this.items.filter(it => it.type == TYPES.casetmr).filter(it => EffetsDraconiques.isInnaccessible(it)).map(it => it.system.coord) + return this.items.filter(it => it.type == ITEM_TYPES.casetmr).filter(it => EffetsDraconiques.isInnaccessible(it)).map(it => it.system.coord) } /* -------------------------------------------- */ getRencontresTMR() { - return this.itemTypes[TYPES.rencontre]; + return this.itemTypes[ITEM_TYPES.rencontre]; } /* -------------------------------------------- */ async deleteRencontreTMRAtPosition() { - const rencontreIds = this.itemTypes[TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id) + const rencontreIds = this.itemTypes[ITEM_TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id) if (rencontreIds.length > 0) { await this.deleteEmbeddedDocuments('Item', rencontreIds) } } getRencontreTMREnAttente() { - return this.itemTypes[TYPES.rencontre].find(this.filterRencontreTMRDemiReve()) + return this.itemTypes[ITEM_TYPES.rencontre].find(this.filterRencontreTMRDemiReve()) } filterRencontreTMRDemiReve() { @@ -1160,11 +1160,11 @@ export class RdDActor extends RdDBaseActorSang { if (result) { return result } switch (item.type) { - case TYPES.potion: return await this.consommerPotion(item, onActionItem); - case TYPES.livre: return await this.actionLire(item); - case TYPES.conteneur: return await item.sheet.render(true); - case TYPES.herbe: return await this.actionHerbe(item, onActionItem); - case TYPES.queue: case TYPES.ombre: return await this.actionRefoulement(item); + case ITEM_TYPES.potion: return await this.consommerPotion(item, onActionItem); + case ITEM_TYPES.livre: return await this.actionLire(item); + case ITEM_TYPES.conteneur: return await item.sheet.render(true); + case ITEM_TYPES.herbe: return await this.actionHerbe(item, onActionItem); + case ITEM_TYPES.queue: case ITEM_TYPES.ombre: return await this.actionRefoulement(item); } return undefined } @@ -1559,7 +1559,7 @@ export class RdDActor extends RdDBaseActorSang { xpData }) if (hideChatMessage) { - ChatUtility.blindMessageToGM({ content: content }); + ChatUtility.blindMessageToGM({ content: content }) } else { ChatMessage.create({ @@ -1602,7 +1602,7 @@ export class RdDActor extends RdDBaseActorSang { computeDraconicAndSortIndex(sortList) { let draconicList = this.getDraconicList(); for (let sort of sortList) { - let draconicsSort = this.getDraconicsSort(draconicList, sort).map(it => it.name); + let draconicsSort = RdDItemSort.getDraconicsSort(draconicList, sort).map(it => it.name); for (let index = 0; index < draconicList.length && sort.system.listIndex == undefined; index++) { if (draconicsSort.includes(draconicList[index].name)) { sort.system.listIndex = index; @@ -1612,19 +1612,6 @@ export class RdDActor extends RdDBaseActorSang { return draconicList; } - /* -------------------------------------------- */ - getDraconicsSort(draconicList, sort) { - //console.log(draconicList, bestDraconic, draconic, voie); - switch (Grammar.toLowerCaseNoAccent(sort.name)) { - case "lecture d'aura": - case "detection d'aura": - return draconicList; - case "annulation de magie": - return draconicList.filter(it => !RdDItemCompetence.isThanatos(it)); - } - return [RdDItemCompetence.getVoieDraconic(draconicList, sort.system.draconic)]; - } - /* -------------------------------------------- */ async rollUnSort(coord) { RdDEmpoignade.checkEmpoignadeEnCours(this) @@ -1826,7 +1813,7 @@ export class RdDActor extends RdDBaseActorSang { } blessuresASoigner() { - return (this.itemTypes[TYPES.blessure]) + return (this.itemTypes[ITEM_TYPES.blessure]) .filter(it => it.system.gravite > 0 && it.system.gravite <= 6) .filter(it => !(it.system.premierssoins.done && it.system.soinscomplets.done)) .sort(Misc.descending(b => (b.system.premierssoins.done ? "A" : "B") + b.system.gravite)) @@ -3065,7 +3052,7 @@ export class RdDActor extends RdDBaseActorSang { async nouvelleIncarnation() { let incarnation = this.toObject(); - incarnation.items = Array.from(this.items.filter(it => it.type == TYPES.competence), + incarnation.items = Array.from(this.items.filter(it => it.type == ITEM_TYPES.competence), it => { it = it.toObject(); it.id = undefined; diff --git a/module/actor/base-actor-reve.js b/module/actor/base-actor-reve.js index 7938e58a..60ebb6f1 100644 --- a/module/actor/base-actor-reve.js +++ b/module/actor/base-actor-reve.js @@ -12,7 +12,7 @@ import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; import { RdDBaseActor } from "./base-actor.js"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; import { StatusEffects } from "../settings/status-effects.js"; -import { TYPES } from "../item.js"; +import { ITEM_TYPES } from "../item.js"; import { Targets } from "../targets.js"; import { RdDPossession } from "../rdd-possession.js"; import { RdDCombat } from "../rdd-combat.js"; @@ -108,14 +108,14 @@ export class RdDBaseActorReve extends RdDBaseActor { async $finDeRoundSupprimerObsoletes() { const obsoletes = [] - .concat(this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp <= 0)) - .concat(this.itemTypes[TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2)) + .concat(this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp <= 0)) + .concat(this.itemTypes[ITEM_TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2)) .map(it => it.id); await this.deleteEmbeddedDocuments('Item', obsoletes); } async $finDeRoundEmpoignade() { - const immobilisations = this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id); + const immobilisations = this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id); immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this, game.actors.get(emp.system.empoigneid), emp @@ -151,13 +151,13 @@ export class RdDBaseActorReve extends RdDBaseActor { } getPossession(possessionId) { - return this.itemTypes[TYPES.possession].find(it => it.system.possessionid == possessionId); + return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId); } getPossessions() { - return this.itemTypes[TYPES.possession]; + return this.itemTypes[ITEM_TYPES.possession]; } getEmpoignades() { - return this.itemTypes[TYPES.empoignade]; + return this.itemTypes[ITEM_TYPES.empoignade]; } /* -------------------------------------------- */ @@ -322,7 +322,7 @@ export class RdDBaseActorReve extends RdDBaseActor { RdDEmpoignade.checkEmpoignadeEnCours(this) const competence = this.getCompetence(idOrName); let rollData = { carac: this.system.carac, competence: competence, arme: options.arme } - if (competence.type == TYPES.competencecreature) { + if (competence.type == ITEM_TYPES.competencecreature) { const arme = RdDItemCompetenceCreature.armeCreature(competence) if (arme && options.tryTarget && Targets.hasTargets()) { Targets.selectOneToken(target => { @@ -396,19 +396,7 @@ export class RdDBaseActorReve extends RdDBaseActor { } $getCompetenceArme(arme, competenceName) { - switch (arme.type) { - case TYPES.competencecreature: - return arme.name - case TYPES.arme: - switch (competenceName) { - case 'competence': return arme.system.competence; - case 'unemain': return RdDItemArme.competence1Mains(arme); - case 'deuxmains': return RdDItemArme.competence2Mains(arme); - case 'tir': return arme.system.tir; - case 'lancer': return arme.system.lancer; - } - } - return undefined + return RdDItemArme.getCompetenceArme(arme, competenceName) } verifierForceMin(item) { diff --git a/module/actor/base-actor-sang.js b/module/actor/base-actor-sang.js index 2131666f..1a4ad1e5 100644 --- a/module/actor/base-actor-sang.js +++ b/module/actor/base-actor-sang.js @@ -1,7 +1,7 @@ import { MAX_ENDURANCE_FATIGUE, RdDUtility } from "../rdd-utility.js"; import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; import { STATUSES } from "../settings/status-effects.js"; -import { TYPES } from "../item.js"; +import { ITEM_TYPES } from "../item.js"; import { RdDBaseActorReve } from "./base-actor-reve.js"; import { RdDDice } from "../rdd-dice.js"; import { RdDItemBlessure } from "../item/blessure.js"; @@ -50,9 +50,9 @@ export class RdDBaseActorSang extends RdDBaseActorReve { isDead() { return this.system.sante.vie.value < -this.getSConst() } - nbBlessuresLegeres() { return this.itemTypes[TYPES.blessure].filter(it => it.isLegere()).length } - nbBlessuresGraves() { return this.itemTypes[TYPES.blessure].filter(it => it.isGrave()).length } - nbBlessuresCritiques() { return this.itemTypes[TYPES.blessure].filter(it => it.isCritique()).length } + nbBlessuresLegeres() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isLegere()).length } + nbBlessuresGraves() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isGrave()).length } + nbBlessuresCritiques() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isCritique()).length } /* -------------------------------------------- */ computeResumeBlessure() { @@ -197,7 +197,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve { } async supprimerBlessures(filterToDelete) { - const toDelete = this.filterItems(filterToDelete, TYPES.blessure) + const toDelete = this.filterItems(filterToDelete, ITEM_TYPES.blessure) .map(it => it.id); await this.deleteEmbeddedDocuments('Item', toDelete); } diff --git a/module/actor/base-actor-sheet.js b/module/actor/base-actor-sheet.js index 8af1c89e..c83106b7 100644 --- a/module/actor/base-actor-sheet.js +++ b/module/actor/base-actor-sheet.js @@ -3,7 +3,7 @@ import { Misc } from "../misc.js"; import { DialogSplitItem } from "../dialog-split-item.js"; import { RdDSheetUtility } from "../rdd-sheet-utility.js"; import { Monnaie } from "../item-monnaie.js"; -import { RdDItem, TYPES } from "../item.js"; +import { RdDItem, ITEM_TYPES } from "../item.js"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; /* -------------------------------------------- */ @@ -51,7 +51,7 @@ export class RdDBaseActorSheet extends ActorSheet { this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires); this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires); formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs); - formData.competences.filter(it => it.type == TYPES.competencecreature) + formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature) .forEach(it => it.isdommages = RdDItemCompetenceCreature.isDommages(it)) return formData; } diff --git a/module/actor/base-actor.js b/module/actor/base-actor.js index 4b35d754..228181ad 100644 --- a/module/actor/base-actor.js +++ b/module/actor/base-actor.js @@ -3,7 +3,7 @@ import { ChatUtility } from "../chat-utility.js"; import { SYSTEM_SOCKET_ID } from "../constants.js"; import { Grammar } from "../grammar.js"; import { Monnaie } from "../item-monnaie.js"; -import { TYPES } from "../item.js"; +import { ITEM_TYPES } from "../item.js"; import { Misc } from "../misc.js"; import { RdDAudio } from "../rdd-audio.js"; import { RdDConfirm } from "../rdd-confirm.js"; @@ -542,7 +542,7 @@ export class RdDBaseActor extends Actor { // Calculer le total actuel des contenus const encContenu = dest.getEncContenu(); const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet - const placeDisponible = Math.roundDecimals(dest.system.capacite - encContenu - newEnc, 4) + 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) { @@ -704,7 +704,7 @@ export class RdDBaseActor extends Actor { async actionPrincipale(item, onActionItem = async () => { }) { switch (item.type) { - case TYPES.conteneur: return await item.sheet.render(true); + case ITEM_TYPES.conteneur: return await item.sheet.render(true); } return undefined } diff --git a/module/actor/creature.js b/module/actor/creature.js index 67b36168..d0307e66 100644 --- a/module/actor/creature.js +++ b/module/actor/creature.js @@ -1,5 +1,5 @@ import { ENTITE_INCARNE } from "../constants.js"; -import { TYPES } from "../item.js"; +import { ITEM_TYPES } from "../item.js"; import { STATUSES } from "../settings/status-effects.js"; import { RdDBaseActorSang } from "./base-actor-sang.js"; @@ -12,7 +12,7 @@ export class RdDCreature extends RdDBaseActorSang { isCreature() { return true } canReceive(item) { - return item.type == TYPES.competencecreature || item.isInventaire(); + return item.type == ITEM_TYPES.competencecreature || item.isInventaire(); } async remiseANeuf() { diff --git a/module/actor/entite.js b/module/actor/entite.js index ca63f334..70bc0577 100644 --- a/module/actor/entite.js +++ b/module/actor/entite.js @@ -1,5 +1,5 @@ import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js"; -import { TYPES } from "../item.js"; +import { ITEM_TYPES } from "../item.js"; import { Misc } from "../misc.js"; import { RdDEncaisser } from "../rdd-roll-encaisser.js"; import { STATUSES } from "../settings/status-effects.js"; @@ -12,7 +12,7 @@ export class RdDEntite extends RdDBaseActorReve { } canReceive(item) { - return item.type == TYPES.competencecreature + return item.type == ITEM_TYPES.competencecreature } isEntite(typeentite = []) { @@ -29,7 +29,7 @@ export class RdDEntite extends RdDBaseActorReve { getChance() { return this.getReve() } getDraconicOuPossession() { - return this.itemTypes[TYPES.competencecreature] + return this.itemTypes[ITEM_TYPES.competencecreature] .filter(it => it.system.categorie == 'possession') .sort(Misc.descending(it => it.system.niveau)) .find(it => true); diff --git a/module/actor/export-scriptarium/export-scriptarium.js b/module/actor/export-scriptarium/export-scriptarium.js new file mode 100644 index 00000000..e6cd20ce --- /dev/null +++ b/module/actor/export-scriptarium/export-scriptarium.js @@ -0,0 +1,80 @@ +import { ACTOR_TYPES } from "../../item.js" +import { Misc } from "../../misc.js" +import { EXPORT_CSV_SCRIPTARIUM, OptionsAvancees } from "../../settings/options-avancees.js" +import { Mapping } from "./mapping.js" + +const IMG_SCRIPTARIUM = '' + +export class ExportScriptarium { + + static init() { + ExportScriptarium.INSTANCE = new ExportScriptarium() + } + + constructor() { + this.mapping = Mapping.getMapping() + Hooks.on("getActorDirectoryFolderContext", (actorDirectory, menus) => { ExportScriptarium.INSTANCE.onActorDirectoryMenu(actorDirectory, menus) }) + Hooks.on("getActorDirectoryEntryContext", (actorDirectory, menus) => { ExportScriptarium.INSTANCE.onActorDirectoryMenu(actorDirectory, menus) }) + } + + onActorDirectoryMenu(actorDirectory, menus) { + menus.push({ + name: 'Export Personnages', + icon: IMG_SCRIPTARIUM, + condition: (target) => game.user.isGM && + OptionsAvancees.isUsing(EXPORT_CSV_SCRIPTARIUM) && + this.$getActors(actorDirectory, target).length > 0, + callback: target => this.exportActors(this.$getActors(actorDirectory, target), this.$getTargetName(actorDirectory, target)) + }) + } + + $getTargetName(actorDirectory, target) { + const li = target.closest(".directory-item") + const folderId = li.data("folderId") + const actorId = li.data("documentId") + return actorId + ? game.actors.get(actorId).name + : actorDirectory.folders.find(it => it.id == folderId).name + } + + $getActors(actorDirectory, target) { + const li = target.closest(".directory-item") + const folderId = li.data("folderId") + const actorId = li.data("documentId") + const actors = actorId + ? [game.actors.get(actorId)] + : folderId + ? actorDirectory.folders.find(it => it.id == folderId).contents + : [] + return actors.filter(it => it.type == ACTOR_TYPES.personnage) + } + + exportActors(actors, targetName) { + const eol = '\n' + const header = Misc.join(this.getHeaderLine(), ';') + const actorLines = actors.map(actor => Misc.join(this.getActorLine(actor), ';')) + const data = Misc.join([header, ...actorLines], eol) + const filename = `scriptatium-${targetName?.slugify()}.csv`; + saveDataToFile(data, "text/csv", `${filename}`); + } + + getHeaderLine() { + return this.mapping.map(it => it.column) + } + + getActorLine(actor) { + const context = Mapping.prepareContext(actor) + return this.mapping.map(it => it.getter(actor, context)) + //.map(it => JSON.stringify(it)) + .map(it => this.$escapeQuotes(it)) + .map(it => it.replaceAll("\n", " ").replaceAll("\r", "")) + } + + $escapeQuotes(it) { + it = '' + it + if (it.includes('"') || it.includes(';')) { + return `"${it.replaceAll('"', '\\"')}"` + } + return it + } +} diff --git a/module/actor/export-scriptarium/mapping.js b/module/actor/export-scriptarium/mapping.js new file mode 100644 index 00000000..e667d81b --- /dev/null +++ b/module/actor/export-scriptarium/mapping.js @@ -0,0 +1,308 @@ +import { Grammar } from "../../grammar.js" +import { RdDItemArme } from "../../item-arme.js" +import { RdDItemCompetence } from "../../item-competence.js" +import { RdDItemSort } from "../../item-sort.js" +import { ITEM_TYPES } from "../../item.js" +import { Misc } from "../../misc.js" +import { RdDTimestamp } from "../../time/rdd-timestamp.js" +import { RdDBonus } from "../../rdd-bonus.js" + + +const CATEGORIES_COMPETENCES = [ + "generale", + "particuliere", + "specialisee", + "connaissance", +] +const CATEGORIES_DRACONIC = [ + "draconic", +] + +const CATEGORIES_COMBAT = [ + "melee", + "tir", + "lancer" +] + +const NIVEAU_BASE = { + "generale": -4, + "particuliere": -8, + "specialisee": -11, + "connaissance": -11, + "draconic": -11, + "melee": -6, + "tir": -8, + "lancer": -8, +} + +class ColumnMappingFactory { + static createMappingArme(part, i) { + return { column: `arme-${part}-${i}`, getter: (actor, context) => Mapping.getArme(actor, context, part, i) } + } + + static createMappingSort(part, i) { + return { column: `sort-${part}-${i}`, getter: (actor, context) => Mapping.getSort(actor, context, part, i) } + } +} + +const NB_ARMES = 10 +const NB_SORTS = 20 +const TABLEAU_ARMES = [...Array(NB_ARMES).keys()] +const TABLEAU_SORTS = [...Array(NB_SORTS).keys()] + +const MAPPING_BASE = [ + { column: "ID", getter: (actor, context) => actor.id }, + { column: "name", getter: (actor, context) => actor.name }, + // { column: "biographie", getter: (actor, context) => actor.system.biographie }, + { column: "taille", getter: (actor, context) => actor.system.carac.taille.value }, + { column: "apparence", getter: (actor, context) => actor.system.carac.apparence.value }, + { column: "constitution", getter: (actor, context) => actor.system.carac.constitution.value }, + { column: "force", getter: (actor, context) => actor.system.carac.force.value }, + { column: "agilite", getter: (actor, context) => actor.system.carac.agilite.value }, + { column: "dexterite", getter: (actor, context) => actor.system.carac.dexterite.value }, + { column: "vue", getter: (actor, context) => actor.system.carac.vue.value }, + { column: "ouie", getter: (actor, context) => actor.system.carac.ouie.value }, + { column: "odoratgout", getter: (actor, context) => actor.system.carac.odoratgout.value }, + { column: "volonte", getter: (actor, context) => actor.system.carac.volonte.value }, + { column: "intellect", getter: (actor, context) => actor.system.carac.intellect.value }, + { column: "empathie", getter: (actor, context) => actor.system.carac.empathie.value }, + { column: "reve", getter: (actor, context) => actor.system.carac.reve.value }, + { column: "chance", getter: (actor, context) => actor.system.carac.chance.value }, + { column: "melee", getter: (actor, context) => actor.system.carac.melee.value }, + { column: "tir", getter: (actor, context) => actor.system.carac.tir.value }, + { column: "lancer", getter: (actor, context) => actor.system.carac.lancer.value }, + { column: "derobee", getter: (actor, context) => actor.system.carac.derobee.value }, + { column: "vie", getter: (actor, context) => actor.system.sante.vie.max }, + { column: "plusdom", getter: (actor, context) => actor.system.attributs.plusdom.value }, + { column: "protectionnaturelle", getter: (actor, context) => actor.system.attributs.protection.value }, + { column: "endurance", getter: (actor, context) => actor.system.sante.endurance.max }, + { column: "description", getter: (actor, context) => Mapping.getDescription(actor) }, + { column: "armure", getter: (actor, context) => Mapping.getArmure(actor, context) }, + { column: "protection", getter: (actor, context) => Mapping.getProtectionArmure(actor, context) }, + { column: "malus-armure", getter: (actor, context) => Mapping.getMalusArmure(actor, context) }, + { column: "esquive", getter: (actor, context) => Mapping.getEsquiveNiveau(context) }, + { column: "competences", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_COMPETENCES) }, + { column: "draconic", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_DRACONIC) }, +] + +const MAPPING_ARMES = TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('name', i)) + .concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('niveau', i))) + .concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('init', i))) + .concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('dommages', i))) +const MAPPING_SORTS = TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('voie', i)) + .concat(TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('description', i))) + .concat(TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('bonus', i))) +const MAPPING = MAPPING_BASE + .concat(MAPPING_ARMES) + .concat(MAPPING_SORTS) + +export class Mapping { + + static getMapping() { + return MAPPING + } + + static prepareContext(actor) { + return { + armes: Mapping.prepareArmes(actor), + armure: Mapping.prepareArmure(actor), + esquive: Mapping.prepareEsquive(actor), + sorts: Mapping.prepareSorts(actor) + } + } + + static prepareArmes(actor) { + const armes = actor.items.filter(it => it.type == ITEM_TYPES.arme) + return armes.map(arme => + [ + arme.system.tir != "" ? Mapping.prepareArme(actor, arme, 'tir') : undefined, + arme.system.lancer = "" ? Mapping.prepareArme(actor, arme, 'lancer') : undefined, + arme.system.unemain ? Mapping.prepareArme(actor, arme, 'unemain') : undefined, + arme.system.deuxmains ? Mapping.prepareArme(actor, arme, 'deuxmains') : undefined, + !(arme.system.unemain || arme.system.deuxmains) ? Mapping.prepareArme(actor, arme, 'competence') : undefined + ] + .filter(it => it != undefined) + ).reduce((a, b) => a.concat(b), []) + } + + static prepareArme(actor, arme, maniement) { + const nameCompArme = RdDItemArme.getCompetenceArme(arme, maniement) + const competence = actor.getCompetence(nameCompArme) + if (RdDItemCompetence.isNiveauBase(competence)) { + return undefined + } + const dmgArme = RdDItemArme.dommagesReels(arme, maniement) + const dommages = dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme) + return { + name: arme.name, + niveau: Misc.toSignedString(competence.system.niveau), + init: Mapping.calculBaseInit(actor, competence.system.categorie) + competence.system.niveau, + dommages: Misc.toSignedString(dommages) + } + } + + static calculBaseInit(actor, categorie) { + const mapping = MAPPING_BASE.find(it => it.column == categorie) + if (mapping) { + switch (categorie) { + case 'melee': + case 'tir': + case 'lancer': + const caracteristique = Number(actor.system.carac[categorie].value) + return Math.floor(caracteristique / 2) + } + } + return 0 + } + + static prepareArmure(actor) { + const armures = actor.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe) + if (armures.length > 1) { + console.warn(`${actor.name} a équipé ${armures.length} armures, seule la première sera considérée`) + } + if (armures.length > 0) { + const armure = armures[0] + return { + name: armure.name, + protection: armure.system.protection, + malus: armure.system.malus ?? 0 + } + } + return { + name: '', + protection: actor.system.attributs.protection.value, + malus: 0 + } + } + + static prepareEsquive(actor) { + const esquives = actor.getCompetences("Esquive") + if (esquives.length > 0) { + const esquive = esquives[0] + return { + name: esquive.name, + niveau: Misc.toSignedString(esquive.system.niveau) + } + } + return undefined + } + + static prepareSorts(actor) { + return actor.itemTypes[ITEM_TYPES.sort].map(it => Mapping.prepareSort(it)) + } + + static prepareSort(sort) { + return { + voie: RdDItemSort.getCodeDraconic(sort), + description: Mapping.descriptionSort(sort), + bonus: Mapping.bonusCase(sort) + } + } + + static descriptionSort(sort) { + const ptSeuil = Array(sort.system.coutseuil).map(it => '*') + const caseTMR = sort.system.caseTMRspeciale.length > 0 ? sort.system.caseTMRspeciale : sort.system.caseTMR + return `${sort.name}${ptSeuil} (${caseTMR}) R${sort.system.difficulte} r${sort.system.ptreve}` + } + + static bonusCase(sort) { + const list = RdDItemSort.bonuscaseStringToList(sort.system.bonuscase).sort(Misc.descending(it => it.bonus)) + if (list.length > 0) { + const bonus = list[0] + return `+${bonus.bonus}% en ${bonus.case}` + } + return '' + } + + static getDescription(actor) { + const sexe = actor.system.sexe + const sexeFeminin = sexe.length > 0 && sexe.charAt(0).toLowerCase() == 'f' ? 'Née' : 'Né' + const race = ['', 'humain'].includes(Grammar.toLowerCaseNoAccent(actor.system.race)) ? '' : (actor.system.race + ' ') + const heure = actor.system.heure + const hn = `${sexeFeminin} à l'heure ${RdDTimestamp.definition(heure).avecArticle}` + const age = actor.system.age ? `${actor.system.age} ans` : undefined + const taille = actor.system.taille + const poids = actor.system.poids + const cheveux = actor.system.cheveux ? `cheveux ${actor.system.cheveux}` : undefined + const yeux = actor.system.yeux ? `yeux ${actor.system.yeux}` : undefined + const beaute = actor.system.beaute ? `Beauté ${actor.system.beaute}` : undefined + const list = [race, hn, age, taille, poids, cheveux, yeux, beaute] + return Misc.join(list.filter(it => it), ', ') + } + + static getArmure(actor, context) { + return context.armure?.name ?? '' + } + + static getProtectionArmure(actor, context) { + return Number(context?.armure?.protection ?? 0) + Number(actor.system.attributs.protection.value) + } + + static getMalusArmure(actor, context) { + return context?.armure?.malus ?? 0 + } + + static getEsquiveNiveau(context) { + if (context.esquive) { + const niveau = context.esquive.niveau + context.armure.malus + return niveau > 0 ? ('+' + niveau) : ('' + niveau) + } + return '' + } + + static getCompetences(actor, categories) { + const competences = Mapping.getCompetencesCategorie(actor, categories) + if (competences.length == 0) { + return '' + } + const byCartegories = Mapping.competencesByCategoriesByNiveau(competences, categories) + const txtByCategories = Object.values(byCartegories) + .map(it => it.competencesParNiveau) + .map(byNiveau => { + const niveaux = Object.keys(byNiveau).map(it => Number(it)).sort(Misc.ascending()) + if (niveaux.length == 0) { + return '' + } + const txtCategorieByNiveau = niveaux.map(niveau => { + const names = Misc.join(byNiveau[niveau].map(it => it.name).sort(Misc.ascending()), ', ') + return names + ' ' + Misc.toSignedString(niveau) + }) + const txtCategorie = Misc.join(txtCategorieByNiveau, ' / ') + return txtCategorie + }).filter(it => it != '') + + return Misc.join(txtByCategories, ' / ') + } + + static competencesByCategoriesByNiveau(competences, categories) { + return categories.map(c => { + return { + categorie: c, + competencesParNiveau: Misc.classify( + competences.filter(comp => comp.system.categorie == c), + comp => comp.system.niveau) + } + }) + } + + static getArme(actor, context, part, numero) { + if (numero < context.armes.length) { + return context.armes[numero][part] ?? '' + } + return '' + } + + static getCompetencesCategorie(actor, categories) { + return actor.itemTypes[ITEM_TYPES.competence] + .filter(it => categories.includes(it.system.categorie)) + .filter(it => !RdDItemCompetence.isNiveauBase(it)) + } + + static getSort(actor, context, part, numero) { + if (numero < context.sorts.length) { + return context.sorts[numero][part] + } + return '' + } +} + diff --git a/module/item-arme.js b/module/item-arme.js index 695a2bde..25cb4dd4 100644 --- a/module/item-arme.js +++ b/module/item-arme.js @@ -1,5 +1,5 @@ import { RdDItemCompetenceCreature } from "./item-competencecreature.js" -import { TYPES } from "./item.js"; +import { ITEM_TYPES } from "./item.js"; import { RdDCombatManager } from "./rdd-combat.js"; const nomCategorieParade = { @@ -20,19 +20,35 @@ const nomCategorieParade = { export class RdDItemArme extends Item { static isArme(item) { - return item.type == TYPES.arme || RdDItemCompetenceCreature.getCategorieAttaque(item); + return item.type == ITEM_TYPES.arme || RdDItemCompetenceCreature.getCategorieAttaque(item); } /* -------------------------------------------- */ static getArme(arme) { switch (arme ? arme.type : '') { - case TYPES.arme: return arme; - case TYPES.competencecreature: + case ITEM_TYPES.arme: return arme; + case ITEM_TYPES.competencecreature: return RdDItemCompetenceCreature.armeCreature(arme); } return RdDItemArme.mainsNues(); } + static getCompetenceArme(arme, maniement) { + switch (arme.type) { + case ITEM_TYPES.competencecreature: + return arme.name + case ITEM_TYPES.arme: + switch (maniement) { + case 'competence': return arme.system.competence; + case 'unemain': return RdDItemArme.competence1Mains(arme); + case 'deuxmains': return RdDItemArme.competence2Mains(arme); + case 'tir': return arme.system.tir; + case 'lancer': return arme.system.lancer; + } + } + return undefined + } + static computeNiveauArmes(armes, competences) { for (const arme of armes) { arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences); @@ -68,14 +84,14 @@ export class RdDItemArme extends Item { return armeData.system.categorie_parade; } // pour compatibilité avec des personnages existants - if (armeData.type == TYPES.competencecreature || armeData.system.categorie == 'creature') { + if (armeData.type == ITEM_TYPES.competencecreature || armeData.system.categorie == 'creature') { return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : ''); } if (!armeData.type.match(/arme|competencecreature/)) { return ''; } if (armeData.system.competence == undefined) { - return TYPES.competencecreature; + return ITEM_TYPES.competencecreature; } let compname = armeData.system.competence.toLowerCase(); if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return ''; @@ -132,43 +148,46 @@ export class RdDItemArme extends Item { return true; } - /* -------------------------------------------- */ - static armeUneOuDeuxMains(armeData, aUneMain) { - if (armeData && !armeData.system.cac) { - armeData.system.unemain = armeData.system.unemain || !armeData.system.deuxmains; - const uneOuDeuxMains = armeData.system.unemain && armeData.system.deuxmains; - const containsSlash = !Number.isInteger(armeData.system.dommages) && armeData.system.dommages.includes("/"); - if (containsSlash) { // Sanity check - armeData = foundry.utils.duplicate(armeData); - - const tableauDegats = armeData.system.dommages.split("/"); - if (aUneMain) - armeData.system.dommagesReels = Number(tableauDegats[0]); - else // 2 mains - armeData.system.dommagesReels = Number(tableauDegats[1]); - } - else { - armeData.system.dommagesReels = Number(armeData.system.dommages); - } - - if (uneOuDeuxMains != containsSlash) { - ui.notifications.info("Les dommages de l'arme à 1/2 mains " + armeData.name + " ne sont pas corrects (ie sous la forme X/Y)"); - } + static dommagesReels(arme, maniement) { + switch (maniement) { + case 'tir': + case 'lancer': + case 'competence': + return Number(arme.system.dommages) } - return armeData; + if (arme.system.unemain && arme.system.deuxmains) { + const containsSlash = !Number.isInteger(arme.system.dommages) && arme.system.dommages.includes("/") + if (!containsSlash) { + ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)"); + return Number(arme.system.dommages) + } + const tableauDegats = arme.system.dommages.split("/"); + return Number(tableauDegats[maniement == 'unemain' ? 0 : 1]) + } + return Number(arme.system.dommages); } - static competence2Mains(arme) { - return arme.system.competence.replace(" 1 main", " 2 mains"); + + /* -------------------------------------------- */ + static armeUneOuDeuxMains(arme, aUneMain) { + if (arme && !arme.system.cac) { + arme = foundry.utils.duplicate(arme); + arme.system.dommagesReels = RdDItemArme.dommagesReels(arme, aUneMain ? 'unemain' : 'deuxmains') + } + return arme; } static competence1Mains(arme) { return arme.system.competence.replace(" 2 mains", " 1 main"); } + static competence2Mains(arme) { + return arme.system.competence.replace(" 1 main", " 2 mains"); + } + static isArmeUtilisable(arme) { switch (arme.type) { - case TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0) - case TYPES.competencecreature: return true + case ITEM_TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0) + case ITEM_TYPES.competencecreature: return true } return false } @@ -180,11 +199,11 @@ export class RdDItemArme extends Item { static corpsACorps(actor) { let competence = actor?.getCompetenceCorpsACorps() ?? { system: { niveau: -6 } }; - let melee = actor? actor.system.carac['melee'].value : 0 + let melee = actor ? actor.system.carac['melee'].value : 0 return { _id: competence?.id, name: 'Corps à corps', - type: TYPES.arme, + type: ITEM_TYPES.arme, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp', system: { initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee), diff --git a/module/item-competencecreature.js b/module/item-competencecreature.js index d16f8aba..19ebf2c7 100644 --- a/module/item-competencecreature.js +++ b/module/item-competencecreature.js @@ -1,5 +1,5 @@ -import { TYPES } from "./item.js"; +import { ITEM_TYPES } from "./item.js"; import { RdDCombatManager } from "./rdd-combat.js"; const categories = { @@ -54,7 +54,7 @@ export class RdDItemCompetenceCreature extends Item { /* -------------------------------------------- */ static isCompetenceAttaque(item) { - if (item.type == TYPES.competencecreature) { + if (item.type == ITEM_TYPES.competencecreature) { switch (item.system.categorie) { case "melee": case "tir": @@ -68,7 +68,7 @@ export class RdDItemCompetenceCreature extends Item { } static getCategorieAttaque(item) { - if (item.type == TYPES.competencecreature) { + if (item.type == ITEM_TYPES.competencecreature) { switch (item.system.categorie) { case "melee": case "tir": @@ -82,7 +82,7 @@ export class RdDItemCompetenceCreature extends Item { return undefined } static isDommages(item) { - if (item.type == TYPES.competencecreature) { + if (item.type == ITEM_TYPES.competencecreature) { switch (item.system.categorie) { case "melee": case "tir": @@ -94,7 +94,7 @@ export class RdDItemCompetenceCreature extends Item { return false } static isParade(item) { - if (item.type == TYPES.competencecreature) { + if (item.type == ITEM_TYPES.competencecreature) { switch (item.system.categorie) { case "melee": case "naturelle": diff --git a/module/item-sheet.js b/module/item-sheet.js index fd8b90e3..a9292fbb 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -12,7 +12,7 @@ import { SystemCompendiums } from "./settings/system-compendiums.js"; import { Misc } from "./misc.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; -import { TYPES } from "./item.js"; +import { ITEM_TYPES } from "./item.js"; /** * Extend the basic ItemSheet for RdD specific items @@ -101,7 +101,7 @@ export class RdDItemSheet extends ItemSheet { isComestible: this.item.getUtilisationCuisine(), options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable), } - if (this.item.type == TYPES.competencecreature) { + if (this.item.type == ITEM_TYPES.competencecreature) { formData.isparade = RdDItemCompetenceCreature.isParade(this.item) formData.isdommages = RdDItemCompetenceCreature.isDommages(this.item) } diff --git a/module/item-sort.js b/module/item-sort.js index 09f9be37..be1a2f66 100644 --- a/module/item-sort.js +++ b/module/item-sort.js @@ -1,9 +1,43 @@ +import { Grammar } from "./grammar.js"; +import { RdDItemCompetence } from "./item-competence.js"; +import { ITEM_TYPES } from "./item.js"; import { Misc } from "./misc.js"; import { TMRUtility } from "./tmr-utility.js"; +const VOIES_DRACONIC = [ + { code: 'O', label: "Voie d'Oniros", short: 'Oniros' }, + { code: 'H', label: "Voie d'Hypnos", short: 'Hypnos' }, + { code: 'N', label: "Voie de Narcos", short: 'Narcos' }, + { code: 'T', label: "Voie de Thanatos", short: 'Thanatos' }, + { code: 'O/H/N/T', label: "Oniros/Hypnos/Narcos/Thanatos", short: 'Oniros/Hypnos/Narcos/Thanatos' }, + { code: 'O/H/N', label: "Oniros/Hypnos/Narcos" } +] + /* -------------------------------------------- */ export class RdDItemSort extends Item { + static getDraconicsSort(draconicList, sort) { + switch (Grammar.toLowerCaseNoAccent(sort.name)) { + case "lecture d'aura": + case "detection d'aura": + return draconicList; + case "annulation de magie": + return draconicList.filter(it => !RdDItemCompetence.isThanatos(it)); + } + return [RdDItemCompetence.getVoieDraconic(draconicList, sort.system.draconic)]; + } + + static getCodeDraconic(sort) { + switch (Grammar.toLowerCaseNoAccent(sort.name)) { + case "lecture d'aura": + case "detection d'aura": + return 'O/H/N/T' + case "annulation de magie": + return 'O/H/N' + } + const voie = VOIES_DRACONIC.find(it => it.label.includes(sort.system.draconic)) + return voie?.code ?? sort.system.draconic + } /* -------------------------------------------- */ static isDifficulteVariable(sort) { return sort && (sort.system.difficulte.toLowerCase() == "variable"); @@ -31,9 +65,9 @@ export class RdDItemSort extends Item { /* -------------------------------------------- */ static buildBonusCaseList(bonuscase, newCase) { - const list = RdDItemSort._bonuscaseStringToList(bonuscase) + const list = RdDItemSort.bonuscaseStringToList(bonuscase) if (newCase) { - return list.concat({ case: "Nouvelle", bonus: 0 }); + list.push({ case: "Nouvelle", bonus: 0 }) } return list; } @@ -44,7 +78,7 @@ export class RdDItemSort extends Item { */ static getBonusCaseList(item, newCase = false) { // Gestion spéciale case bonus - if (item.type == 'sort') { + if (item.type == ITEM_TYPES.sort) { return RdDItemSort.buildBonusCaseList(item.system.bonuscase, newCase); } return undefined; @@ -104,8 +138,11 @@ export class RdDItemSort extends Item { .sort(Misc.ascending()) .join(','); } - static _bonuscaseStringToList(bonuscase) { - return (bonuscase ?? '').split(',').map(it => { + static bonuscaseStringToList(bonuscase) { + if (bonuscase == undefined || bonuscase == '') { + return [] + } + return bonuscase.split(',').map(it => { const b = it.split(':'); return { case: b[0], bonus: b[1] }; }); diff --git a/module/item.js b/module/item.js index 8569d3b9..fe6d25ad 100644 --- a/module/item.js +++ b/module/item.js @@ -9,7 +9,15 @@ import { RdDRaretes } from "./item/raretes.js"; import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; -export const TYPES = { +export const ACTOR_TYPES = { + personnage: 'personnage', + creature: 'creature', + entite: 'entite', + commerce: 'commerce', + vehicule: 'vehicule' +} + +export const ITEM_TYPES = { competence: 'competence', competencecreature: 'competencecreature', empoignade: 'empoignade', @@ -56,33 +64,33 @@ export const TYPES = { } const typesInventaireMateriel = [ - 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, + ITEM_TYPES.arme, + ITEM_TYPES.armure, + ITEM_TYPES.conteneur, + ITEM_TYPES.faune, + ITEM_TYPES.gemme, + ITEM_TYPES.herbe, + ITEM_TYPES.plante, + ITEM_TYPES.ingredient, + ITEM_TYPES.livre, + ITEM_TYPES.monnaie, + ITEM_TYPES.munition, + ITEM_TYPES.nourritureboisson, + ITEM_TYPES.objet, + ITEM_TYPES.potion, ] const typesInventaire = { materiel: typesInventaireMateriel, all: ['service'].concat(typesInventaireMateriel), } -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 typesObjetsOeuvres = [ITEM_TYPES.oeuvre, ITEM_TYPES.recettecuisine, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.jeu] +const typesObjetsDraconiques = [ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.tete, ITEM_TYPES.signedraconique, ITEM_TYPES.sortreserve, ITEM_TYPES.rencontre] +const typesObjetsConnaissance = [ITEM_TYPES.meditation, ITEM_TYPES.recettealchimique, ITEM_TYPES.sort] +const typesObjetsEffet = [ITEM_TYPES.possession, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.blessure] +const typesObjetsCompetence = [ITEM_TYPES.competence, ITEM_TYPES.competencecreature] +const typesObjetsTemporels = [ITEM_TYPES.blessure, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.signedraconique, ITEM_TYPES.rencontre] +const typesObjetsEquipable = [ITEM_TYPES.arme, ITEM_TYPES.armure, ITEM_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 @@ -141,12 +149,12 @@ export class RdDItem extends Item { static isFieldInventaireModifiable(type, field) { switch (field) { case 'quantite': - if ([TYPES.conteneur].includes(type)) { + if ([ITEM_TYPES.conteneur].includes(type)) { return false; } break; case 'cout': - if ([TYPES.monnaie].includes(type)) { + if ([ITEM_TYPES.monnaie].includes(type)) { return game.user.isGM; } break; @@ -195,15 +203,15 @@ export class RdDItem extends Item { getUniteQuantite() { switch (this.type) { - case TYPES.monnaie: return "(Pièces)" - case TYPES.herbe: + case ITEM_TYPES.monnaie: return "(Pièces)" + case ITEM_TYPES.herbe: switch (this.system.categorie) { case 'Alchimie': case 'Repos': case 'Soin': return "(Brins)" case 'Cuisine': return ''; } return ''; - case TYPES.ingredient: return "(Pépins ou Brins)" + case ITEM_TYPES.ingredient: return "(Pépins ou Brins)" } return ''; } @@ -212,13 +220,13 @@ export class RdDItem extends Item { return typesObjetsEquipable.includes(this.type) } - 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; } + isCompetencePersonnage() { return this.type == ITEM_TYPES.competence } + isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature } + isConteneur() { return this.type == ITEM_TYPES.conteneur; } + isMonnaie() { return this.type == ITEM_TYPES.monnaie; } + isPotion() { return this.type == ITEM_TYPES.potion; } + isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; } + isService() { return this.type == ITEM_TYPES.service; } isCompetence() { return typesObjetsCompetence.includes(this.type) } isEsquive() { @@ -237,27 +245,27 @@ export class RdDItem extends Item { return this.isCompetence() && ['melee', 'tir', 'lancer'].includes(this.system.categorie) } - isCompetencePossession() { return TYPES.competencecreature == this.type && this.system.categorie == "possession" } + isCompetencePossession() { return ITEM_TYPES.competencecreature == this.type && this.system.categorie == "possession" } 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) } + isQueueDragon() { return [ITEM_TYPES.queue, ITEM_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 == TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); } - isBlessure() { return this.type == TYPES.blessure } + isHerbeAPotion() { return this.type == ITEM_TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); } + isBlessure() { return this.type == ITEM_TYPES.blessure } isPresentDansMilieux(milieux) { return this.getEnvironnements(milieux).length > 0 } getCategories() { switch (this.type) { - case TYPES.competence: return RdDItemCompetence.getCategories() - case TYPES.competencecreature: return RdDItemCompetenceCreature.getCategories() + case ITEM_TYPES.competence: return RdDItemCompetence.getCategories() + case ITEM_TYPES.competencecreature: return RdDItemCompetenceCreature.getCategories() } return {} } @@ -341,15 +349,15 @@ export class RdDItem extends Item { getUtilisation() { switch (this.type) { - case TYPES.potion: + case ITEM_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 TYPES.nourritureboisson: return 'cuisine'; - case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante: + case ITEM_TYPES.nourritureboisson: return 'cuisine'; + case ITEM_TYPES.herbe: case ITEM_TYPES.faune: case ITEM_TYPES.ingredient: case ITEM_TYPES.plante: switch (this.system.categorie) { case 'Cuisine': return 'cuisine'; case 'Toxique': case 'Poison': return 'poison'; @@ -364,9 +372,9 @@ export class RdDItem extends Item { getUtilisationCuisine() { if (this.getUtilisation() == 'cuisine') { switch (this.type) { - case TYPES.nourritureboisson: + case ITEM_TYPES.nourritureboisson: return 'pret'; - case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante: + case ITEM_TYPES.herbe: case ITEM_TYPES.faune: case ITEM_TYPES.ingredient: case ITEM_TYPES.plante: return 'brut'; } } @@ -374,7 +382,7 @@ export class RdDItem extends Item { } isCristalAlchimique() { - return this.type == TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0; + return this.type == ITEM_TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0; } isMagique() { @@ -402,11 +410,11 @@ export class RdDItem extends Item { getEnc() { switch (this.type) { - case TYPES.service: + case ITEM_TYPES.service: return 0; - case TYPES.herbe: + case ITEM_TYPES.herbe: return this.getEncHerbe(); - case TYPES.gemme: + case ITEM_TYPES.gemme: return encPepin * this.system.taille; } return Math.max(this.system.encombrement ?? 0, 0); @@ -484,7 +492,7 @@ export class RdDItem extends Item { getActionPrincipale(options = { warnIfNot: true }) { switch (this.type) { - case TYPES.conteneur: return 'Ouvrir'; + case ITEM_TYPES.conteneur: return 'Ouvrir'; } if (this.actor?.isPersonnage()) { const warn = options.warnIfNot; @@ -492,11 +500,11 @@ export class RdDItem extends Item { return 'Cuisiner'; } switch (this.type) { - case TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn); - case TYPES.potion: return this._actionOrWarnQuantiteZero('Consommer', 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; + case ITEM_TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn); + case ITEM_TYPES.potion: return this._actionOrWarnQuantiteZero('Consommer', warn); + case ITEM_TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn); + case ITEM_TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined; + case ITEM_TYPES.queue: case ITEM_TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined; } } return undefined; diff --git a/module/migrations.js b/module/migrations.js index 675e2088..c608d08a 100644 --- a/module/migrations.js +++ b/module/migrations.js @@ -2,7 +2,7 @@ import { RdDBaseActor } from "./actor/base-actor.js"; import { LOG_HEAD, SYSTEM_RDD } from "./constants.js"; import { Grammar } from "./grammar.js"; import { Monnaie } from "./item-monnaie.js"; -import { RdDItem, TYPES } from "./item.js"; +import { RdDItem, ITEM_TYPES } from "./item.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDRaretes } from "./item/raretes.js"; import { RdDCalendrier } from "./time/rdd-calendrier.js"; @@ -465,7 +465,7 @@ class _10_7_19_CategorieCompetenceCreature extends Migration { async migrate() { await this.applyItemsUpdates(items => items - .filter(it => TYPES.competencecreature == it.type) + .filter(it => ITEM_TYPES.competencecreature == it.type) .map(it => this.migrateCompetenceCreature(it)) ); } @@ -502,7 +502,7 @@ class _10_7_19_PossessionsEntiteVictime extends Migration { async migrate() { await this.applyItemsUpdates(items => items - .filter(it => TYPES.possession == it.type) + .filter(it => ITEM_TYPES.possession == it.type) .map(it => this.migratePossession(it)) ); } diff --git a/module/rdd-bonus.js b/module/rdd-bonus.js index 93c1d36e..1d69e3ea 100644 --- a/module/rdd-bonus.js +++ b/module/rdd-bonus.js @@ -31,8 +31,8 @@ export class RdDBonus { } /* -------------------------------------------- */ - static dmg(rollData, dmgActor, isEntiteIncarnee = false) { - const dmgArme = RdDBonus._dmgArme(rollData) + static dmg(rollData, actor, isEntiteIncarnee = false) { + const dmgArme = RdDBonus.dmgArme(rollData.arme) let dmg = { total: 0, dmgArme: dmgArme, @@ -41,7 +41,7 @@ export class RdDBonus { dmgParticuliere: RdDBonus._dmgParticuliere(rollData), dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used), mortalite: RdDBonus._calculMortalite(rollData, isEntiteIncarnee), - dmgActor: RdDBonus._dmgPerso(dmgActor, rollData.selectedCarac?.label, dmgArme) + dmgActor: RdDBonus.bonusDmg(actor, rollData.selectedCarac?.label.toLowerCase(), dmgArme) } dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere; return dmg; @@ -71,11 +71,11 @@ export class RdDBonus { } /* -------------------------------------------- */ - static _dmgArme(rollData) { - if (rollData.arme) { - let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0); + static dmgArme(arme) { + if (arme) { + let dmgBase = arme.system.dommagesReels ?? Number(arme.system.dommages ?? 0); //Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278) - return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0); + return dmgBase + Math.min(dmgBase, arme.system.magique ? arme.system.ecaille_efficacite : 0); } return 0; } @@ -86,13 +86,14 @@ export class RdDBonus { } /* -------------------------------------------- */ - static _dmgPerso(dmgActor, categorie, dmgArme) { + static bonusDmg(actor, categorie, dmgArme) { + const dmgActor = actor.getBonusDegat() if (categorie == undefined) { return 0 } switch (categorie) { - case "Tir": return 0; - case "Lancer": return Math.max(0, Math.min(dmgArme, dmgActor)); + case "tir": return 0; + case "lancer": return Math.max(0, Math.min(dmgArme, dmgActor)); } return dmgActor; } diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 66cbe453..be55bc5a 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -864,7 +864,7 @@ export class RdDCombat { async _onAttaqueNormale(attackerRoll) { console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll); - attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntite()); + attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite()); let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} } attackerRoll.show = { cible: this.target ? this.defender.name : 'la cible', diff --git a/module/rdd-empoignade.js b/module/rdd-empoignade.js index 49778fd2..81c3b965 100644 --- a/module/rdd-empoignade.js +++ b/module/rdd-empoignade.js @@ -5,7 +5,7 @@ import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { ChatUtility } from "./chat-utility.js"; import { STATUSES } from "./settings/status-effects.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; -import { TYPES } from "./item.js"; +import { ITEM_TYPES } from "./item.js"; /* -------------------------------------------- */ @@ -92,18 +92,18 @@ export class RdDEmpoignade { /* -------------------------------------------- */ static isEmpoignadeEnCours(actor) { - return actor.itemTypes[TYPES.empoignade].find(it => it.system.pointsemp > 0) + return actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.pointsemp > 0) } /* -------------------------------------------- */ static getEmpoignadeById(actor, id) { - let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id) + let emp = actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id) return emp && foundry.utils.duplicate(emp) || undefined; } /* -------------------------------------------- */ static getEmpoignade(attacker, defender) { - let emp = attacker.itemTypes[TYPES.empoignade].find(it => + let emp = attacker.itemTypes[ITEM_TYPES.empoignade].find(it => (it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) || (it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id) ) diff --git a/module/rdd-herbes.js b/module/rdd-herbes.js index edcd3513..4d650e27 100644 --- a/module/rdd-herbes.js +++ b/module/rdd-herbes.js @@ -6,7 +6,7 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js"; export class RdDHerbes extends Item { /* -------------------------------------------- */ - static async initializeHerbes() { + static async onReady() { this.herbesSoins = await RdDHerbes.listCategorieHerbes('Soin'); this.herbesRepos = await RdDHerbes.listCategorieHerbes('Repos'); } diff --git a/module/rdd-hotbar-drop.js b/module/rdd-hotbar-drop.js index edb8ae1e..7bb6db05 100644 --- a/module/rdd-hotbar-drop.js +++ b/module/rdd-hotbar-drop.js @@ -1,6 +1,6 @@ import { RdDItemArme } from "./item-arme.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; -import { TYPES } from "./item.js"; +import { ITEM_TYPES } from "./item.js"; export class RdDHotbar { @@ -35,7 +35,7 @@ export class RdDHotbar { static async addToHotbar(item, slot) { switch (item?.type ?? '') { - case TYPES.arme: + case ITEM_TYPES.arme: { // Les armes peuvent avoir plusieurs usages if (item.system.competence != '') { @@ -54,12 +54,12 @@ export class RdDHotbar { } } return - case TYPES.competencecreature: + case ITEM_TYPES.competencecreature: const categorie = RdDItemCompetenceCreature.getCategorieAttaque(item) ?? 'competence'; await this.createItemMacro(item, slot, categorie) return default: - case TYPES.competence: + case ITEM_TYPES.competence: await this.createItemMacro(item, slot++, 'competence') if (item.isCorpsACorps()) { await this.createItemMacro(item, slot++, 'pugilat') @@ -79,7 +79,7 @@ export class RdDHotbar { * Actor - open actor sheet * Journal - open journal sheet */ - static initDropbar() { + static init() { Hooks.on('hotbarDrop', (bar, documentData, slot) => { @@ -88,9 +88,9 @@ export class RdDHotbar { const item = fromUuidSync(documentData.uuid) ?? this.actor.items.get(documentData.uuid) console.log('DROP', documentData, item) switch (item?.type) { - case TYPES.arme: - case TYPES.competence: - case TYPES.competencecreature: + case ITEM_TYPES.arme: + case ITEM_TYPES.competence: + case ITEM_TYPES.competencecreature: this.addToHotbar(item, slot) return false } @@ -116,9 +116,9 @@ export class RdDHotbar { // Trigger the item roll switch (item.type) { - case TYPES.arme: + case ITEM_TYPES.arme: return actor.rollArme(item, categorieArme); - case TYPES.competence: + case ITEM_TYPES.competence: if (item.isCorpsACorps()) { switch (categorieArme) { case 'pugilat': @@ -128,7 +128,7 @@ export class RdDHotbar { } } return actor.rollCompetence(item); - case TYPES.competencecreature: + case ITEM_TYPES.competencecreature: return item.system.iscombat && !item.system.isparade ? actor.rollArme(item, categorieArme) : actor.rollCompetence(item); diff --git a/module/rdd-main.js b/module/rdd-main.js index d51f3351..ffcf00e8 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -1,69 +1,72 @@ -import { SYSTEM_RDD, SYSTEM_SOCKET_ID, RDD_CONFIG } from "./constants.js"; -import { Migrations } from './migrations.js'; +import { SYSTEM_RDD, SYSTEM_SOCKET_ID, RDD_CONFIG } from "./constants.js" +import { Migrations } from './migrations.js' -import { RdDUtility } from "./rdd-utility.js"; -import { TMRUtility } from "./tmr-utility.js"; -import { TMRRencontres } from "./tmr-rencontres.js"; -import { RdDCalendrier } from "./time/rdd-calendrier.js"; -import { RdDTimestamp } from "./time/rdd-timestamp.js"; -import { DialogChronologie } from "./dialog-chronologie.js"; +import { RdDUtility } from "./rdd-utility.js" +import { TMRUtility } from "./tmr-utility.js" +import { TMRRencontres } from "./tmr-rencontres.js" +import { RdDCalendrier } from "./time/rdd-calendrier.js" +import { RdDTimestamp } from "./time/rdd-timestamp.js" +import { DialogChronologie } from "./dialog-chronologie.js" -import { RdDResolutionTable } from "./rdd-resolution-table.js"; -import { RdDTokenHud } from "./rdd-token-hud.js"; -import { RdDCommands } from "./rdd-commands.js"; -import { RdDCombatManager, RdDCombat } from "./rdd-combat.js"; -import { ChatUtility } from "./chat-utility.js"; -import { StatusEffects } from "./settings/status-effects.js"; -import { RdDCompendiumOrganiser } from "./rdd-compendium-organiser.js"; -import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; +import { RdDResolutionTable } from "./rdd-resolution-table.js" +import { RdDTokenHud } from "./rdd-token-hud.js" +import { RdDCommands } from "./rdd-commands.js" +import { RdDCombatManager, RdDCombat } from "./rdd-combat.js" +import { ChatUtility } from "./chat-utility.js" +import { StatusEffects } from "./settings/status-effects.js" +import { RdDCompendiumOrganiser } from "./rdd-compendium-organiser.js" +import { ReglesOptionnelles } from "./settings/regles-optionnelles.js" import { RdDHotbar } from "./rdd-hotbar-drop.js" -import { EffetsDraconiques } from "./tmr/effets-draconiques.js"; -import { RdDHerbes } from "./rdd-herbes.js"; -import { RdDDice } from "./rdd-dice.js"; -import { RdDPossession } from "./rdd-possession.js"; -import { Misc } from "./misc.js"; +import { EffetsDraconiques } from "./tmr/effets-draconiques.js" +import { RdDHerbes } from "./rdd-herbes.js" +import { RdDDice } from "./rdd-dice.js" +import { RdDPossession } from "./rdd-possession.js" +import { Misc } from "./misc.js" -import { SystemCompendiums } from "./settings/system-compendiums.js"; -import { Environnement } from "./environnement.js"; +import { SystemCompendiums } from "./settings/system-compendiums.js" +import { Environnement } from "./environnement.js" -import { RdDActor } from "./actor.js"; -import { RdDBaseActor } from "./actor/base-actor.js"; -import { RdDCommerce } from "./actor/commerce.js"; -import { RdDEntite } from "./actor/entite.js"; -import { RdDVehicule } from "./actor/vehicule.js"; -import { RdDActorSheet } from "./actor-sheet.js"; -import { RdDCommerceSheet } from "./actor/commerce-sheet.js"; -import { RdDCreatureSheet } from "./actor/creature-sheet.js"; -import { RdDActorEntiteSheet } from "./actor/entite-sheet.js"; -import { RdDActorVehiculeSheet } from "./actor/vehicule-sheet.js"; +import { RdDActor } from "./actor.js" +import { RdDBaseActor } from "./actor/base-actor.js" +import { RdDCommerce } from "./actor/commerce.js" +import { RdDEntite } from "./actor/entite.js" +import { RdDVehicule } from "./actor/vehicule.js" +import { RdDActorSheet } from "./actor-sheet.js" +import { RdDCommerceSheet } from "./actor/commerce-sheet.js" +import { RdDCreatureSheet } from "./actor/creature-sheet.js" +import { RdDActorEntiteSheet } from "./actor/entite-sheet.js" +import { RdDActorVehiculeSheet } from "./actor/vehicule-sheet.js" -import { RdDItem } from "./item.js"; -import { RdDItemBlessure } from "./item/blessure.js"; -import { RdDItemService } from "./item/service.js"; -import { RdDItemMaladie } from "./item/maladie.js"; -import { RdDItemPoison } from "./item/poison.js"; -import { RdDItemSigneDraconique } from "./item/signedraconique.js"; -import { RdDItemQueue } from "./item/queue.js"; -import { RdDItemOmbre } from "./item/ombre.js"; -import { RdDItemSouffle } from "./item/souffle.js"; -import { RdDRencontre } from "./item/rencontre.js"; +import { RdDItem } from "./item.js" +import { RdDItemBlessure } from "./item/blessure.js" +import { RdDItemService } from "./item/service.js" +import { RdDItemMaladie } from "./item/maladie.js" +import { RdDItemPoison } from "./item/poison.js" +import { RdDItemSigneDraconique } from "./item/signedraconique.js" +import { RdDItemQueue } from "./item/queue.js" +import { RdDItemOmbre } from "./item/ombre.js" +import { RdDItemSouffle } from "./item/souffle.js" +import { RdDRencontre } from "./item/rencontre.js" -import { RdDItemSheet } from "./item-sheet.js"; -import { RdDBlessureItemSheet } from "./item/sheet-blessure.js"; -import { RdDServiceItemSheet } from "./item/sheet-service.js"; -import { RdDRencontreItemSheet } from "./item/sheet-rencontre.js"; -import { RdDHerbeItemSheet } from "./item/sheet-herbe.js"; -import { RdDPlanteItemSheet } from "./item/sheet-plante.js"; -import { RdDIngredientItemSheet } from "./item/sheet-ingredient.js"; -import { RdDFauneItemSheet } from "./item/sheet-faune.js"; -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"; -import { AutoAdjustDarkness as AutoAdjustDarkness } from "./time/auto-adjust-darkness.js"; -import { RdDCreature } from "./actor/creature.js"; -import { RdDTMRDialog } from "./rdd-tmr-dialog.js"; +import { RdDItemSheet } from "./item-sheet.js" +import { RdDBlessureItemSheet } from "./item/sheet-blessure.js" +import { RdDServiceItemSheet } from "./item/sheet-service.js" +import { RdDRencontreItemSheet } from "./item/sheet-rencontre.js" +import { RdDHerbeItemSheet } from "./item/sheet-herbe.js" +import { RdDPlanteItemSheet } from "./item/sheet-plante.js" +import { RdDIngredientItemSheet } from "./item/sheet-ingredient.js" +import { RdDFauneItemSheet } from "./item/sheet-faune.js" +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" +import { AutoAdjustDarkness as AutoAdjustDarkness } from "./time/auto-adjust-darkness.js" +import { RdDCreature } from "./actor/creature.js" +import { RdDTMRDialog } from "./rdd-tmr-dialog.js" +import { RdDActorExportSheet } from "./actor/actor-export-sheet.js" +import { OptionsAvancees } from "./settings/options-avancees.js" +import { ExportScriptarium } from "./actor/export-scriptarium/export-scriptarium.js" /** * RdD system @@ -71,18 +74,18 @@ import { RdDTMRDialog } from "./rdd-tmr-dialog.js"; * Software License: GNU GPLv3 */ export class SystemReveDeDragon { - + static start() { const system = new SystemReveDeDragon() Hooks.once('init', async () => await system.onInit()) Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d)) Hooks.once('ready', () => system.onReady()) } - + constructor() { - this.config = RDD_CONFIG; - this.RdDUtility = RdDUtility; - this.RdDHotbar = RdDHotbar; + this.config = RDD_CONFIG + this.RdDUtility = RdDUtility + this.RdDHotbar = RdDHotbar this.itemClasses = { armure: RdDItemArmure, blessure: RdDItemBlessure, @@ -108,42 +111,42 @@ export class SystemReveDeDragon { /* Foundry VTT Initialization */ /* -------------------------------------------- */ async onInit() { - game.system.rdd = this; - this.AppAstrologie = AppAstrologie; + game.system.rdd = this + this.AppAstrologie = AppAstrologie - console.log(`Initializing Reve de Dragon System`); + console.log(`Initializing Reve de Dragon System`) // preload handlebars templates - RdDUtility.preloadHandlebarsTemplates(); + RdDUtility.preloadHandlebarsTemplates() /* -------------------------------------------- */ - this.initSystemSettings(); + this.initSystemSettings() /* -------------------------------------------- */ // Set an initiative formula for the system CONFIG.Combat.initiative = { formula: "1+(1d6/10)", decimals: 2 - }; + } /* -------------------------------------------- */ game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => { - console.log(">>>>> MSG RECV", sockmsg); + console.log(">>>>> MSG RECV", sockmsg) try { - RdDUtility.onSocketMessage(sockmsg); - RdDCombat.onSocketMessage(sockmsg); - ChatUtility.onSocketMessage(sockmsg); - RdDBaseActor.onSocketMessage(sockmsg); + RdDUtility.onSocketMessage(sockmsg) + RdDCombat.onSocketMessage(sockmsg) + ChatUtility.onSocketMessage(sockmsg) + RdDBaseActor.onSocketMessage(sockmsg) } catch (e) { console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg, ' => ', e) } - }); + }) /* -------------------------------------------- */ // Define custom Entity classes - CONFIG.Actor.documentClass = RdDBaseActor; - CONFIG.Item.documentClass = RdDItem; + CONFIG.Actor.documentClass = RdDBaseActor + CONFIG.Item.documentClass = RdDItem CONFIG.RDD = { resolutionTable: RdDResolutionTable.resolutionTable, carac_array: RdDUtility.getCaracArray(), @@ -153,30 +156,31 @@ export class SystemReveDeDragon { /* -------------------------------------------- */ // Register sheet application classes - Actors.unregisterSheet("core", ActorSheet); - Actors.registerSheet(SYSTEM_RDD, RdDCommerceSheet, { types: ["commerce"], makeDefault: true }); - Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true }); - Actors.registerSheet(SYSTEM_RDD, RdDCreatureSheet, { types: ["creature"], makeDefault: true }); - Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true }); - Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true }); - Items.unregisterSheet("core", ItemSheet); + Actors.unregisterSheet("core", ActorSheet) + Actors.registerSheet(SYSTEM_RDD, RdDCommerceSheet, { types: ["commerce"], makeDefault: true }) + Actors.registerSheet(SYSTEM_RDD, RdDActorExportSheet, { types: ["personnage"], makeDefault: false }) + Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true }) + Actors.registerSheet(SYSTEM_RDD, RdDCreatureSheet, { types: ["creature"], makeDefault: true }) + Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true }) + Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true }) + Items.unregisterSheet("core", ItemSheet) - RdDItemSheet.register(RdDSigneDraconiqueItemSheet); - RdDItemSheet.register(RdDRencontreItemSheet); - RdDItemSheet.register(RdDConteneurItemSheet); - RdDItemSheet.register(RdDHerbeItemSheet); - RdDItemSheet.register(RdDFauneItemSheet); - RdDItemSheet.register(RdDPlanteItemSheet); - RdDItemSheet.register(RdDIngredientItemSheet); - RdDItemSheet.register(RdDServiceItemSheet); - RdDItemSheet.register(RdDBlessureItemSheet); + RdDItemSheet.register(RdDSigneDraconiqueItemSheet) + RdDItemSheet.register(RdDRencontreItemSheet) + RdDItemSheet.register(RdDConteneurItemSheet) + RdDItemSheet.register(RdDHerbeItemSheet) + RdDItemSheet.register(RdDFauneItemSheet) + RdDItemSheet.register(RdDPlanteItemSheet) + RdDItemSheet.register(RdDIngredientItemSheet) + RdDItemSheet.register(RdDServiceItemSheet) + RdDItemSheet.register(RdDBlessureItemSheet) Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, { types: [ "objet", "arme", "armure", "livre", "potion", "munition", "monnaie", "nourritureboisson", "gemme", ], makeDefault: true - }); + }) Items.registerSheet(SYSTEM_RDD, RdDItemSheet, { types: [ "competence", "competencecreature", @@ -185,31 +189,32 @@ export class SystemReveDeDragon { "nombreastral", "tache", "maladie", "poison", "possession", "tarot", "extraitpoetique", "empoignade" ], makeDefault: true - }); - CONFIG.Combat.documentClass = RdDCombatManager; + }) + CONFIG.Combat.documentClass = RdDCombatManager // préparation des différents modules - AutoAdjustDarkness.init(); - RdDTimestamp.init(); - RdDCalendrier.init(); - SystemCompendiums.init(); - DialogChronologie.init(); - ReglesOptionnelles.init(); - RdDUtility.init(); - RdDDice.init(); - RdDCommands.init(); - RdDCombatManager.init(); - RdDTokenHud.init(); - RdDBaseActor.init(); - RdDCompendiumOrganiser.init(); + AutoAdjustDarkness.init() + RdDTimestamp.init() + RdDCalendrier.init() + SystemCompendiums.init() + DialogChronologie.init() + ReglesOptionnelles.init() + OptionsAvancees.init() + RdDUtility.init() + RdDDice.init() + RdDCommands.init() + RdDCombatManager.init() + RdDTokenHud.init() + RdDBaseActor.init() + RdDCompendiumOrganiser.init() EffetsDraconiques.init() - TMRUtility.init(); + TMRUtility.init() await RdDTMRDialog.init() - RdDHotbar.initDropbar(); - RdDPossession.init(); - TMRRencontres.init(); - Environnement.init(); - + RdDHotbar.init() + RdDPossession.init() + TMRRencontres.init() + Environnement.init() + ExportScriptarium.init() } initSystemSettings() { @@ -225,7 +230,7 @@ export class SystemReveDeDragon { "avant-encaissement": "Avant l'encaissement", }, default: "avant-encaissement" - }); + }) /* -------------------------------------------- */ game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", { @@ -235,7 +240,7 @@ export class SystemReveDeDragon { config: true, default: true, type: Boolean - }); + }) /* -------------------------------------------- */ game.settings.register(SYSTEM_RDD, "activer-sons-audio", { @@ -245,7 +250,8 @@ export class SystemReveDeDragon { config: true, default: true, type: Boolean - }); + }) + /* -------------------------------------------- */ game.settings.register(SYSTEM_RDD, "appliquer-famine-soif", { name: "Notifier de la famine et la soif pour", @@ -259,7 +265,7 @@ export class SystemReveDeDragon { "famine-soif": "la famine et la soif", }, default: "aucun" - }); + }) } async onReady() { @@ -267,47 +273,47 @@ export class SystemReveDeDragon { /* -------------------------------------------- */ /* Foundry VTT Initialization */ /* -------------------------------------------- */ - game.system.rdd.calendrier = new RdDCalendrier(); + game.system.rdd.calendrier = new RdDCalendrier() if (Misc.isUniqueConnectedGM()) { - new Migrations().migrate(); - this.messageDeBienvenue(); - import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter=>{ + new Migrations().migrate() + this.messageDeBienvenue() + import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => { console.log("ClassCounter loaded", moduleCounter) moduleCounter.ClassCounter.registerUsageCount() - }).catch(err=> + }).catch(err => console.log("No stats available, giving up.") - ) + ) } - StatusEffects.onReady(); - RdDHerbes.initializeHerbes(); - RdDDice.onReady(); + StatusEffects.onReady() + RdDHerbes.onReady() + RdDDice.onReady() /* -------------------------------------------- */ /* Affiche/Init le calendrier */ - game.system.rdd.calendrier.display(); + game.system.rdd.calendrier.display() // Avertissement si joueur sans personnage if (!game.user.isGM && game.user.character == undefined) { - ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !"); + ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !") ChatMessage.create({ content: "ATTENTION Le joueur " + game.user.name + " n'est connecté à aucun personnage !", user: game.user.id - }); + }) } } /* -------------------------------------------- */ messageDeBienvenue() { if (game.user.isGM) { - ChatUtility.removeChatMessageContaining('
'); + ChatUtility.removeChatMessageContaining('
') ChatMessage.create({ user: game.user.id, content: `
Bienvenue dans le Rêve des Dragons !
Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs}
La commande /aide dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.
- ` }); + ` }) } } } -SystemReveDeDragon.start(); +SystemReveDeDragon.start() diff --git a/module/rdd-possession.js b/module/rdd-possession.js index 93409689..57c3a142 100644 --- a/module/rdd-possession.js +++ b/module/rdd-possession.js @@ -3,7 +3,7 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDRoll } from "./rdd-roll.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { Targets } from "./targets.js"; -import { TYPES } from "./item.js"; +import { ITEM_TYPES } from "./item.js"; /* -------------------------------------------- */ /* On part du principe qu'une entité démarre tjs @@ -20,9 +20,9 @@ export class RdDPossession { /* -------------------------------------------- */ static searchPossessionFromEntite(attacker, defender) { - let poss = attacker.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id); + let poss = attacker.items.find(poss => poss.type == ITEM_TYPES.possession && poss.system.victime.actorid == defender.id); if (!poss) { - poss = defender.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id); + poss = defender.items.find(poss => poss.type == ITEM_TYPES.possession && poss.system.victime.actorid == defender.id); } return poss && foundry.utils.duplicate(poss) || undefined; } diff --git a/module/rdd-roll.js b/module/rdd-roll.js index 791029cc..5613e322 100644 --- a/module/rdd-roll.js +++ b/module/rdd-roll.js @@ -307,7 +307,7 @@ export class RdDRoll extends Dialog { async updateRollResult(html) { const rollData = this.rollData; - rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat()) + rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor) rollData.caracValue = parseInt(rollData.selectedCarac.value) rollData.dmg.mortalite = rollData.dmg.mortalite ?? 'mortel'; rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac); diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index 7eb633ab..5b388e2b 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -16,7 +16,7 @@ import { RdDDice } from "./rdd-dice.js"; import { STATUSES } from "./settings/status-effects.js"; import { RdDRencontre } from "./item/rencontre.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js"; -import { TYPES } from "./item.js"; +import { ITEM_TYPES } from "./item.js"; import { Misc } from "./misc.js"; const TMR_DISPLAY_SIZE = { @@ -208,11 +208,11 @@ export class RdDTMRDialog extends Dialog { } get sortsReserve() { - return this.actor.itemTypes[TYPES.sortreserve]; + return this.actor.itemTypes[ITEM_TYPES.sortreserve]; } getSortsReserve(coord) { - return this.actor.itemTypes[TYPES.sortreserve].filter(// Reserve sur une case fleuve ou normale + return this.actor.itemTypes[ITEM_TYPES.sortreserve].filter(// Reserve sur une case fleuve ou normale TMRUtility.getTMR(coord).type == 'fleuve' ? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve' : it => it.system.coord == coord @@ -270,7 +270,7 @@ export class RdDTMRDialog extends Dialog { } _getTokensSortsReserve() { - const sortsReserve = this.actor.itemTypes[TYPES.sortreserve]; + const sortsReserve = this.actor.itemTypes[ITEM_TYPES.sortreserve]; return Misc.concat(sortsReserve.map(sortReserve => EffetsDraconiques.sortReserve.tokens(this.pixiTMR, sortReserve, () => sortReserve.system.coord))) } diff --git a/module/settings/options-avancees.js b/module/settings/options-avancees.js new file mode 100644 index 00000000..1e4cad4e --- /dev/null +++ b/module/settings/options-avancees.js @@ -0,0 +1,91 @@ +import { SYSTEM_RDD } from "../constants.js" +import { Misc } from "../misc.js" + +export const EXPORT_CSV_SCRIPTARIUM = 'export-csv-scriptarium' + +const OPTIONS_AVANCEES = [ + { group: 'Menus', name: EXPORT_CSV_SCRIPTARIUM, descr: "Proposer le menu d'export csv Scriptarium (raffraichissement requis)" }, +] + +export class OptionsAvancees extends FormApplication { + static init() { + for (const regle of OPTIONS_AVANCEES) { + const name = regle.name + const id = OptionsAvancees._getId(name) + game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean }) + } + + game.settings.registerMenu(SYSTEM_RDD, "rdd-options-avancees", { + name: "Configurer les options avancées", + label: "Options avancées", + hint: "Ouvre la fenêtre de configuration des options avancées", + icon: "fas fa-bars", + type: OptionsAvancees + }) + } + + constructor(...args) { + super(...args) + } + + static _getId(name) { + return `rdd-advanced-${name}` + } + + static get defaultOptions() { + return foundry.utils.mergeObject(super.defaultOptions, { + id: "options-avancees", + template: "systems/foundryvtt-reve-de-dragon/templates/settings/options-avancees.hbs", + height: 650, + width: 550, + minimizable: false, + closeOnSubmit: true, + title: "Options avancées" + }, { inplace: false }) + } + + getData() { + let formData = super.getData() + const regles = OPTIONS_AVANCEES.filter(it => game.user.isGM || it.scope == "client") + .map(it => { + it = foundry.utils.duplicate(it) + it.id = OptionsAvancees._getId(it.name) + it.active = OptionsAvancees.isSet(it.name) + return it + }) + formData.regles = regles + formData.groups = Misc.classify(regles, it => it.group) + return formData + } + + static getSettingKey(name){ + return `${SYSTEM_RDD}.${this._getId(name)}` + } + + static isUsing(name) { + return OptionsAvancees.isSet(name) + } + + static isSet(name) { + return game.settings.get(SYSTEM_RDD, OptionsAvancees._getId(name)) + } + + static set(name, value) { + return game.settings.set(SYSTEM_RDD, OptionsAvancees._getId(name), value ? true : false) + } + + activateListeners(html) { + html.find(".select-option").click((event) => { + if (event.currentTarget.attributes.name) { + let id = event.currentTarget.attributes.name.value + let isChecked = event.currentTarget.checked + game.settings.set(SYSTEM_RDD, id, isChecked) + } + }) + } + + async _updateObject(event, formData) { + this.close() + } +} + diff --git a/module/settings/regles-optionnelles.js b/module/settings/regles-optionnelles.js index 95ca2a2c..bbb53638 100644 --- a/module/settings/regles-optionnelles.js +++ b/module/settings/regles-optionnelles.js @@ -73,7 +73,7 @@ export class ReglesOptionnelles extends FormApplication { static get defaultOptions() { return foundry.utils.mergeObject(super.defaultOptions, { id: "regles-optionnelles", - template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.html", + template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.hbs", height: 650, width: 550, minimizable: false, diff --git a/module/time/rdd-calendrier.js b/module/time/rdd-calendrier.js index 5e7e88a5..a56df1ce 100644 --- a/module/time/rdd-calendrier.js +++ b/module/time/rdd-calendrier.js @@ -1,7 +1,6 @@ import { MAX_NOMBRE_ASTRAL, RdDTimestamp, WORLD_TIMESTAMP_SETTING } from "./rdd-timestamp.js"; import { RdDCalendrierEditor } from "./rdd-calendrier-editor.js"; import { RdDResolutionTable } from "../rdd-resolution-table.js"; -import { RdDUtility } from "../rdd-utility.js"; import { RdDDice } from "../rdd-dice.js"; import { Misc } from "../misc.js"; import { DialogChronologie } from "../dialog-chronologie.js"; diff --git a/module/time/rdd-timestamp.js b/module/time/rdd-timestamp.js index 2f12d5c3..c10d55f6 100644 --- a/module/time/rdd-timestamp.js +++ b/module/time/rdd-timestamp.js @@ -15,18 +15,18 @@ export const RDD_MINUTES_PAR_JOUR = 1440; //RDD_HEURES_PAR_JOUR * RDD_MINUTES_PA const ROUNDS_PAR_MINUTE = 10; const DEFINITION_HEURES = [ - { key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "Printemps", darkness: 0.9 }, - { key: "sirene", label: "Sirène", lettreFont: 'i', saison: "Printemps", darkness: 0.1 }, - { key: "faucon", label: "Faucon", lettreFont: 'f', saison: "Printemps", darkness: 0 }, - { key: "couronne", label: "Couronne", lettreFont: '', saison: "Eté", darkness: 0 }, - { key: "dragon", label: "Dragon", lettreFont: 'd', saison: "Eté", darkness: 0 }, - { key: "epees", label: "Epées", lettreFont: 'e', saison: "Eté", darkness: 0 }, - { key: "lyre", label: "Lyre", lettreFont: 'l', saison: "Automne", darkness: 0.1 }, - { key: "serpent", label: "Serpent", lettreFont: 's', saison: "Automne", darkness: 0.9 }, - { key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne", darkness: 1 }, - { key: "araignee", label: "Araignée", lettreFont: 'a', saison: "Hiver", darkness: 1 }, - { key: "roseau", label: "Roseau", lettreFont: 'r', saison: "Hiver", darkness: 1 }, - { key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "Hiver", darkness: 1 }, + { key: "vaisseau", article: "du ", label: "Vaisseau", lettreFont: 'v', saison: "Printemps", darkness: 0.9 }, + { key: "sirene", article: "de la ", label: "Sirène", lettreFont: 'i', saison: "Printemps", darkness: 0.1 }, + { key: "faucon", article: "du ", label: "Faucon", lettreFont: 'f', saison: "Printemps", darkness: 0 }, + { key: "couronne", article: "de la ", label: "Couronne", lettreFont: '', saison: "Eté", darkness: 0 }, + { key: "dragon", article: "du ", label: "Dragon", lettreFont: 'd', saison: "Eté", darkness: 0 }, + { key: "epees", article: "des ", label: "Epées", lettreFont: 'e', saison: "Eté", darkness: 0 }, + { key: "lyre", article: "de la ", label: "Lyre", lettreFont: 'l', saison: "Automne", darkness: 0.1 }, + { key: "serpent", article: "du ", label: "Serpent", lettreFont: 's', saison: "Automne", darkness: 0.9 }, + { key: "poissonacrobate", article: "du ", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne", darkness: 1 }, + { key: "araignee", article: "de l'", label: "Araignée", lettreFont: 'a', saison: "Hiver", darkness: 1 }, + { key: "roseau", article: "du ", label: "Roseau", lettreFont: 'r', saison: "Hiver", darkness: 1 }, + { key: "chateaudormant", article: "du ", label: "Château Dormant", lettreFont: 'c', saison: "Hiver", darkness: 1 }, ] const FORMULES_DUREE = [ @@ -64,6 +64,7 @@ export class RdDTimestamp { DEFINITION_HEURES[i].hh = RdDTimestamp.hh(i); DEFINITION_HEURES[i].icon = RdDTimestamp.iconeHeure(i); DEFINITION_HEURES[i].webp = DEFINITION_HEURES[i].icon.replace(".svg", ".webp"); + DEFINITION_HEURES[i].avecArticle = DEFINITION_HEURES[i].article + DEFINITION_HEURES[i].label } } @@ -241,7 +242,7 @@ export class RdDTimestamp { get darkness() { const darknessDebut = 100 * RdDTimestamp.definition(this.heure).darkness - const darknessFin = 100 * RdDTimestamp.definition(this.heure + 1).darkness + const darknessFin = 100 * RdDTimestamp.definition(this.heure + 1).darkness const darknessMinute = Math.round((darknessFin - darknessDebut) * this.minute / RDD_MINUTES_PAR_HEURES); return (darknessDebut + darknessMinute) / 100 } diff --git a/module/tmr/draconique.js b/module/tmr/draconique.js index 90b58092..fb12145e 100644 --- a/module/tmr/draconique.js +++ b/module/tmr/draconique.js @@ -1,4 +1,4 @@ -import { TYPES } from "../item.js"; +import { ITEM_TYPES } from "../item.js"; import { TMRUtility } from "../tmr-utility.js"; import { PixiTMR } from "./pixi-tmr.js"; @@ -12,10 +12,10 @@ export class Draconique { static init() { } - static isCaseTMR(item) { return item.type == TYPES.casetmr; } + static isCaseTMR(item) { return item.type == ITEM_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 isSouffleDragon(item) { return item.type == ITEM_TYPES.souffle; } + static isTeteDragon(item) { return item.type == ITEM_TYPES.tete; } static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); } static register(draconique, code = undefined) { diff --git a/module/tmr/effets-draconiques.js b/module/tmr/effets-draconiques.js index 1b0753d1..80ed02ca 100644 --- a/module/tmr/effets-draconiques.js +++ b/module/tmr/effets-draconiques.js @@ -18,7 +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"; +import { ITEM_TYPES } from "../item.js"; export class EffetsDraconiques { static carteTmr = new CarteTmr(); @@ -122,11 +122,11 @@ export class EffetsDraconiques { } static tetesDragon(actor, name) { - return actor.itemTypes[TYPES.tete].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name)); + return actor.itemTypes[ITEM_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)); + return actor.itemTypes[ITEM_TYPES.souffle].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name)); } static queuesDragon(actor, name) { @@ -134,7 +134,7 @@ export class EffetsDraconiques { } static queuesSoufflesDragon(actor, name) { - return actor.filterItems(it => [TYPES.queue, TYPES.ombre, TYPES.souffle].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, name)); + return actor.filterItems(it => [ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, name)); } static countAugmentationSeuil(actor) { diff --git a/module/tmr/urgence-draconique.js b/module/tmr/urgence-draconique.js index 03a6f94b..f3c00769 100644 --- a/module/tmr/urgence-draconique.js +++ b/module/tmr/urgence-draconique.js @@ -5,7 +5,7 @@ import { RdDRollTables } from "../rdd-rolltables.js"; import { TMRUtility } from "../tmr-utility.js"; import { tmrTokenZIndex } from "../tmr-constants.js"; import { Draconique } from "./draconique.js"; -import { TYPES } from "../item.js"; +import { ITEM_TYPES } from "../item.js"; import { TMRAnimations } from "./animation.js"; export class UrgenceDraconique extends Draconique { @@ -14,7 +14,7 @@ export class UrgenceDraconique extends Draconique { match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); } manualMessage() { return false } async onActorCreateOwned(actor, queue) { - const coordSortsReserve = actor.itemTypes[TYPES.sortreserve].map(it => it.system.coord) ?? []; + const coordSortsReserve = actor.itemTypes[ITEM_TYPES.sortreserve].map(it => it.system.coord) ?? []; if (coordSortsReserve.length == 0) { // La queue se transforme en idée fixe const ideeFixe = await RdDRollTables.getIdeeFixe(); diff --git a/module/voyage/dialog-fatigue-voyage.js b/module/voyage/dialog-fatigue-voyage.js index 1ae7bef6..591c1942 100644 --- a/module/voyage/dialog-fatigue-voyage.js +++ b/module/voyage/dialog-fatigue-voyage.js @@ -1,4 +1,4 @@ -import { TYPES } from "../item.js" +import { ITEM_TYPES } from "../item.js" import { RdDItemCompetence } from "../item-competence.js" import { ChatUtility } from "../chat-utility.js" import { Misc } from "../misc.js" @@ -69,7 +69,7 @@ export class DialogFatigueVoyage extends Dialog { } const competencesVoyage = {} CODES_COMPETENCES_VOYAGE.forEach(codeSurvie => { - competencesVoyage[codeSurvie] = RdDItemCompetence.findCompetence(actor.itemTypes[TYPES.competence], codeSurvie, { onMessage: () => { } }) + competencesVoyage[codeSurvie] = RdDItemCompetence.findCompetence(actor.itemTypes[ITEM_TYPES.competence], codeSurvie, { onMessage: () => { } }) }) TABLEAU_FATIGUE_MARCHE.forEach(terrain => { actorParameters.survies[terrain.code] = Misc.join( diff --git a/styles/img/ui/scriptarium.svg b/styles/img/ui/scriptarium.svg new file mode 100644 index 00000000..9d066697 --- /dev/null +++ b/styles/img/ui/scriptarium.svg @@ -0,0 +1,65 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/styles/simple.css b/styles/simple.css index da09b65a..77a3b277 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -572,6 +572,15 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) { border: none; padding: 0.1rem; } +.context-menu-img { + max-width: 2rem; + max-height: 1rem; + flex-grow: 0; + margin: 0.2rem 0.3rem 0 0; + vertical-align: middle; + border: none; + padding: 0rem; +} .button-img { vertical-align: baseline; diff --git a/system.json b/system.json index 0d611bc6..72df40e3 100644 --- a/system.json +++ b/system.json @@ -1,8 +1,8 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "12.0.8", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.8.zip", + "version": "12.0.9", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.9.zip", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", "compatibility": { diff --git a/template.json b/template.json index 791118ab..c3d58e20 100644 --- a/template.json +++ b/template.json @@ -21,6 +21,7 @@ "race": "Humain", "yeux": "", "cheveux": "", + "taille": "", "poids": "", "heure": "", "sexe": "", diff --git a/templates/chat-compendium-table-roll.html b/templates/chat-compendium-table-roll.html index 40c368e6..2981d9af 100644 --- a/templates/chat-compendium-table-roll.html +++ b/templates/chat-compendium-table-roll.html @@ -1,5 +1,5 @@ -

Tirage aléatoire: {{typeName}}

-
{{document.pack}}
+

Tirage aléatoire: {{document.name}}

+
Tirage de {{typeName}} aléatoire depuis {{document.pack}}
Jet {{roll.formula}} : {{roll.total}}{{percentages}}

@@ -15,4 +15,4 @@ {{{document.system.description}}}
{{/if}} -
\ No newline at end of file +
diff --git a/templates/enum-draconic.html b/templates/enum-draconic.html index 340c669b..b86b8839 100644 --- a/templates/enum-draconic.html +++ b/templates/enum-draconic.html @@ -3,3 +3,5 @@ {{/if}} {{/each}} + + diff --git a/templates/settings/regles-optionnelles.html b/templates/settings/options-avancees.hbs similarity index 100% rename from templates/settings/regles-optionnelles.html rename to templates/settings/options-avancees.hbs diff --git a/templates/settings/regles-optionnelles.hbs b/templates/settings/regles-optionnelles.hbs new file mode 100644 index 00000000..6ea970cd --- /dev/null +++ b/templates/settings/regles-optionnelles.hbs @@ -0,0 +1,13 @@ +
+ {{#each groups as |group key|}} +

{{key}}

+ + {{/each}} +
\ No newline at end of file