uberwald
eb029e8d66
La confusion entre les Item "objets" et le champ formData.objets rendait les Item "objets" indisponibles (par exemple, les vêtements)
957 lines
43 KiB
JavaScript
957 lines
43 KiB
JavaScript
/* Common useful functions shared between objects */
|
|
import { ChatUtility } from "./chat-utility.js";
|
|
import { RdDCombat } from "./rdd-combat.js";
|
|
import { Misc } from "./misc.js";
|
|
import { Grammar } from "./grammar.js";
|
|
import { TMRUtility } from "./tmr-utility.js";
|
|
import { DialogItemAchat } from "./dialog-item-achat.js";
|
|
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
|
import { RdDDice } from "./rdd-dice.js";
|
|
import { RdDItem } from "./item.js";
|
|
import { RdDPossession } from "./rdd-possession.js";
|
|
import { RdDNameGen } from "./rdd-namegen.js";
|
|
import { RdDConfirm } from "./rdd-confirm.js";
|
|
import { RdDItemCompetence } from "./item-competence.js";
|
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
|
import { RdDRaretes } from "./item/raretes.js";
|
|
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
|
import { ExperienceLog } from "./actor/experience-log.js";
|
|
|
|
/* -------------------------------------------- */
|
|
// This table starts at 0 -> niveau -10
|
|
const carac_array = ["taille", "apparence", "constitution", "force", "agilite", "dexterite", "vue", "ouie", "odoratgout", "volonte", "intellect", "empathie", "reve", "chance", "melee", "tir", "lancer", "derobee"];
|
|
const difficultesLibres = Misc.intArray(0, -11);
|
|
const ajustementsConditions = Misc.intArray(-10, 11);
|
|
const ajustementsEncaissement = Misc.intArray(-10, 26);
|
|
|
|
/* -------------------------------------------- */
|
|
function _buildAllSegmentsFatigue(max) {
|
|
const cycle = [5, 2, 4, 1, 3, 0];
|
|
let fatigue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
|
|
for (let i = 0; i <= max; i++) {
|
|
const ligneFatigue = duplicate(fatigue[i]);
|
|
const caseIncrementee = cycle[i % 6];
|
|
ligneFatigue[caseIncrementee]++;
|
|
ligneFatigue[caseIncrementee + 6]++;
|
|
ligneFatigue.fatigueMax = 2 * (i + 1);
|
|
fatigue[i + 1] = ligneFatigue;
|
|
}
|
|
return fatigue;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
function _cumulSegmentsFatigue(matrix) {
|
|
let cumulMatrix = [];
|
|
for (let line of matrix) {
|
|
let cumul = duplicate(line);
|
|
|
|
for (let i = 1; i < 12; i++) {
|
|
cumul[i] += cumul[i - 1];
|
|
}
|
|
cumulMatrix.push(cumul);
|
|
}
|
|
return cumulMatrix;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
const fatigueMatrix = _buildAllSegmentsFatigue(60);
|
|
const cumulFatigueMatrix = _cumulSegmentsFatigue(fatigueMatrix);
|
|
|
|
const fatigueMalus = [0, 0, 0, -1, -1, -1, -2, -3, -4, -5, -6, -7]; // Provides the malus for each segment of fatigue
|
|
const fatigueLineSize = [3, 6, 7, 8, 9, 10, 11, 12];
|
|
const fatigueLineMalus = [0, -1, -2, -3, -4, -5, -6, -7];
|
|
const fatigueMarche = {
|
|
"aise": { "4": 1, "6": 2, "8": 3, "10": 4, "12": 6 },
|
|
"malaise": { "4": 2, "6": 3, "8": 4, "10": 6 },
|
|
"difficile": { "4": 3, "6": 4, "8": 6 },
|
|
"tresdifficile": { "4": 4, "6": 6 }
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "Complètement fait", "Ivre mort"];
|
|
|
|
/* -------------------------------------------- */
|
|
const definitionsEncaissement = {
|
|
"mortel": [
|
|
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
|
|
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0},
|
|
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2},
|
|
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4},
|
|
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6},
|
|
],
|
|
"non-mortel": [
|
|
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
|
|
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
|
|
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
|
|
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 },
|
|
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 },
|
|
],
|
|
"entiteincarnee": [
|
|
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
|
|
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0},
|
|
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
|
|
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 0 },
|
|
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 0 },
|
|
]
|
|
};
|
|
|
|
/* -------------------------------------------- */
|
|
export class RdDUtility {
|
|
|
|
/* -------------------------------------------- */
|
|
static async init() {
|
|
Hooks.on("renderChatMessage", async (app, html, msg) => RdDUtility.onRenderChatMessage(app, html, msg));
|
|
Hooks.on('renderChatLog', (log, html, chatLog) => RdDUtility.chatListeners(html));
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async preloadHandlebarsTemplates() {
|
|
const templatePaths = [
|
|
//Character Sheets
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html',
|
|
// sous-parties de feuilles de personnages
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-buttons.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-etat.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-hautreve.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/competence.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/combat.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/blessures.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/blessure.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/resonances.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queue.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-signes-draconiques.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-rencontres.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts-reserve.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-meditations.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-casestmr.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-journal.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/editor-notes-mj.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html',
|
|
"systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-monnaie.html",
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-animaux.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html',
|
|
//Items
|
|
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/item/boutons-comestible.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/item/temporel.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
|
|
// partial enums
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-competence.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-periode.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html',
|
|
// Partials
|
|
'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/time/horloge.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffFixe.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffCondition.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/roll/explain.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/resolution-table.html',
|
|
// Dialogs
|
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/sommeil/sommeil-actor-moral.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-gardien.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-joueur.hbs',
|
|
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-theme.hbs',
|
|
// HUD
|
|
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html',
|
|
// messages tchat
|
|
'systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/chat-description.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/chat-potionenchantee-chateaudormant.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/chat-fabriquer-potion-base.html',
|
|
'systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html'
|
|
];
|
|
|
|
Handlebars.registerHelper('either', (a, b) => a ?? b);
|
|
Handlebars.registerHelper('computeResolutionScore', (row, col) => RdDResolutionTable.computePercentage(row, col));
|
|
Handlebars.registerHelper('computeResolutionChances', (row, col) => RdDResolutionTable.computeChances(row, col));
|
|
Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null'));
|
|
Handlebars.registerHelper('lowerFirst', str => Misc.lowerFirst(str ?? 'Null'));
|
|
Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? '');
|
|
Handlebars.registerHelper('lowercase', str => str?.toLowerCase() ?? '');
|
|
Handlebars.registerHelper('le', str => Grammar.articleDetermine(str));
|
|
Handlebars.registerHelper('apostrophe', (article, str) => Grammar.apostrophe(article, str));
|
|
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str));
|
|
Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args));
|
|
Handlebars.registerHelper('buildLigneInventaire', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildLigneInventaire(item, options)); });
|
|
Handlebars.registerHelper('buildInventaireConteneur', (actorId, itemId, options) => { return new Handlebars.SafeString(RdDUtility.buildInventaireConteneur(actorId, itemId, options)); });
|
|
Handlebars.registerHelper('buildContenuConteneur', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildContenuConteneur(item, options)); });
|
|
Handlebars.registerHelper('calculerPrixCommercant', item => item.calculerPrixCommercant());
|
|
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
|
|
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
|
|
Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type));
|
|
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
|
|
|
|
Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) });
|
|
Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) });
|
|
Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier());
|
|
Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree());
|
|
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
|
|
|
|
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
|
|
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
|
|
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
|
|
Handlebars.registerHelper('filtreTriCompetences', competences => RdDItemCompetence.triVisible(competences));
|
|
Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
|
|
Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite());
|
|
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
|
|
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
|
|
|
|
Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
|
|
|
|
return loadTemplates(templatePaths);
|
|
}
|
|
|
|
static getItem(itemId, actorId = undefined) {
|
|
return actorId ? game.actors.get(actorId)?.getItem(itemId) : game.items.get(itemId);
|
|
}
|
|
|
|
static linkCompendium(pack, id, name) {
|
|
return `@Compendium[${pack}.${id}]{${name}}`;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static buildListOptions(min, max) {
|
|
let options = ""
|
|
for (let i = min; i <= max; i++) {
|
|
options += `<option value="${i}">${i}</option>`
|
|
}
|
|
return options;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static arrayOrEmpty(items) {
|
|
if (items?.length) {
|
|
return items;
|
|
}
|
|
return [];
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static getNomEthylisme(niveauEthylisme) {
|
|
let index = -niveauEthylisme;
|
|
return index < 0 ? 'Aucun' : nomEthylisme[index];
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static initAfficheContenu() { // persistent handling of conteneur show/hide
|
|
if (!this.afficheContenu)
|
|
this.afficheContenu = {};
|
|
}
|
|
/* -------------------------------------------- */
|
|
static toggleAfficheContenu(conteneurId) {
|
|
this.afficheContenu[conteneurId] = !this.afficheContenu[conteneurId];
|
|
}
|
|
/* -------------------------------------------- */
|
|
static getAfficheContenu(conteneurId) {
|
|
if (conteneurId)
|
|
return this.afficheContenu[conteneurId];
|
|
return undefined;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static buildArbreDeConteneurs(conteneurs, inventaires) {
|
|
let objetVersConteneur = {};
|
|
// Attribution des objets aux conteneurs
|
|
for (let conteneur of conteneurs) {
|
|
conteneur.subItems = [];
|
|
for (let id of conteneur.system.contenu ?? []) {
|
|
let objet = inventaires.find(objet => (id == objet._id));
|
|
if (objet) {
|
|
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template
|
|
objetVersConteneur[id] = conteneur._id;
|
|
conteneur.subItems.push(objet);
|
|
}
|
|
}
|
|
}
|
|
for (let conteneur of conteneurs) {
|
|
conteneur.system.encTotal = RdDUtility.calculEncContenu(conteneur, inventaires);
|
|
}
|
|
return objetVersConteneur;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static calculEncContenu(conteneur, inventaires) {
|
|
const contenus = (conteneur.system.contenu ?? []).filter(id => id != undefined)
|
|
.map(id => inventaires.find(it => (id == it.id)))
|
|
.filter(it => it);
|
|
let enc = Number(conteneur.system.encombrement ?? 0) * Number(conteneur.system.quantite ?? 1);
|
|
for (let contenu of contenus) {
|
|
if (contenu.type == 'conteneur') {
|
|
enc += RdDUtility.calculEncContenu(contenu, inventaires);
|
|
}
|
|
else {
|
|
enc += Number(contenu.system.encombrement ?? 0) * Number(contenu.system.quantite ?? 1)
|
|
}
|
|
}
|
|
return enc
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
// Construit la liste des conteneurs de niveau 1 (c'est à dire non contenu eux-même dans un conteneur)
|
|
static conteneursRacine(conteneurs) {
|
|
return conteneurs.filter((conteneur, index, arr) => !conteneur.estContenu);
|
|
}
|
|
|
|
static prepareOptionsArbreInventaire(item, optionsArbre) {
|
|
if (!optionsArbre.profondeur) {
|
|
optionsArbre.profondeur = 1
|
|
};
|
|
if (!optionsArbre.templateItem) {
|
|
optionsArbre.templateItem = item.parent?.type == 'commerce'
|
|
? "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html"
|
|
: "systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html";
|
|
}
|
|
item.niveau = optionsArbre.profondeur;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/**
|
|
* Construit la structure récursive des conteneurs, avec imbrication potentielle
|
|
*/
|
|
static buildLigneInventaire(item, options = {}, optionsArbre = { ouvert: false, profondeur: 1 }) {
|
|
RdDUtility.prepareOptionsArbreInventaire(item, optionsArbre);
|
|
|
|
const isConteneur = item.type == 'conteneur';
|
|
const inventaire = {
|
|
item: item,
|
|
vide: isConteneur && item.system.contenu.length == 0,
|
|
ouvert: isConteneur && RdDUtility.getAfficheContenu(item._id),
|
|
options: options
|
|
};
|
|
optionsArbre.ouvert = inventaire.ouvert
|
|
const ligneObjet = Handlebars.partials[optionsArbre.templateItem](inventaire);
|
|
if (isConteneur) {
|
|
return ligneObjet + RdDUtility.buildContenuConteneur(item, options, optionsArbre);
|
|
}
|
|
return ligneObjet;
|
|
}
|
|
|
|
static buildInventaireConteneur(actorId, itemId, options) {
|
|
const actor = game.actors.get(actorId)
|
|
const item = actor?.items.get(itemId)
|
|
if (item) {
|
|
return RdDUtility.buildContenuConteneur(item, options, { ouvert: true, profondeur: 1 });
|
|
}
|
|
return '';
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static buildContenuConteneur(conteneur, options = {}, optionsArbre = {}) {
|
|
RdDUtility.prepareOptionsArbreInventaire(conteneur, optionsArbre);
|
|
const display = optionsArbre.ouvert ? 'item-display-show' : 'item-display-hide';
|
|
const profondeur = optionsArbre.profondeur;
|
|
|
|
optionsArbre.profondeur++;
|
|
const lignesContenu = conteneur.subItems.sort(Misc.ascending(it => it.name))
|
|
.map(contenu => this.buildLigneInventaire(contenu, options, optionsArbre));
|
|
|
|
return `<ul class='item-list alterne-list ${display} list-item-margin${Math.min(profondeur, 6)}'>`
|
|
+ lignesContenu.reduce(Misc.joining(''), '')
|
|
+ "</ul>";
|
|
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static getCaracArray() {
|
|
return carac_array;
|
|
}
|
|
static getDifficultesLibres() {
|
|
return difficultesLibres;
|
|
}
|
|
static getAjustementsConditions() {
|
|
return ajustementsConditions;
|
|
}
|
|
static getAjustementsEncaissement() {
|
|
return ajustementsEncaissement;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static getSegmentsFatigue(maxEnd) {
|
|
maxEnd = Math.max(maxEnd, 1);
|
|
maxEnd = Math.min(maxEnd, fatigueMatrix.length);
|
|
return fatigueMatrix[maxEnd];
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static calculMalusFatigue(fatigue, maxEnd) {
|
|
maxEnd = Math.max(maxEnd, 1);
|
|
maxEnd = Math.min(maxEnd, cumulFatigueMatrix.length);
|
|
let segments = cumulFatigueMatrix[maxEnd];
|
|
for (let i = 0; i < 12; i++) {
|
|
if (fatigue <= segments[i]) {
|
|
return fatigueMalus[i]
|
|
}
|
|
}
|
|
return -7;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static calculFatigueHtml(fatigue, endurance) {
|
|
return ReglesOptionelles.isUsing("appliquer-fatigue") ? {
|
|
malus: RdDUtility.calculMalusFatigue(fatigue, endurance),
|
|
html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(fatigue, endurance).html() + "</table>"
|
|
} : { malus: 0, html: '' };
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
// Build the nice (?) html table used to manage fatigue.
|
|
// max should be the endurance max value
|
|
static makeHTMLfatigueMatrix(fatigue, maxEndurance) {
|
|
let segments = this.getSegmentsFatigue(maxEndurance);
|
|
return this.makeHTMLfatigueMatrixForSegment(fatigue, segments);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static makeHTMLfatigueMatrixForSegment(fatigue, segments) {
|
|
fatigue = Math.max(fatigue, 0);
|
|
fatigue = Math.min(fatigue, segments.fatigueMax);
|
|
|
|
let table = $("<table/>").addClass('table-fatigue');
|
|
let segmentIdx = 0;
|
|
let fatigueCount = 0;
|
|
for (var line = 0; line < fatigueLineSize.length; line++) {
|
|
let row = $("<tr/>");
|
|
let segmentsPerLine = fatigueLineSize[line];
|
|
row.append("<td class='fatigue-malus'>" + fatigueLineMalus[line] + "</td>");
|
|
while (segmentIdx < segmentsPerLine) {
|
|
let freeSize = segments[segmentIdx];
|
|
for (let col = 0; col < 5; col++) {
|
|
if (col < freeSize) {
|
|
if (fatigueCount < fatigue)
|
|
row.append("<td class='fatigue-used'>X</td>");
|
|
|
|
|
|
else
|
|
row.append("<td class='fatigue-free'/>");
|
|
fatigueCount++;
|
|
} else {
|
|
row.append("<td class='fatigue-none'/>");
|
|
}
|
|
}
|
|
row.append("<td class='fatigue-separator'/>");
|
|
segmentIdx = segmentIdx + 1;
|
|
}
|
|
table.append(row);
|
|
}
|
|
return table;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async getLocalisation(type = 'personnage') {
|
|
let result = await RdDDice.rollTotal("1d20");
|
|
let txt = ""
|
|
if (type == 'personnage') {
|
|
if (result <= 3) txt = "Jambe, genou, pied, jarret";
|
|
else if (result <= 7) txt = "Hanche, cuisse, fesse";
|
|
else if (result <= 9) txt = "Ventre, reins";
|
|
else if (result <= 12) txt = "Poitrine, dos";
|
|
else if (result <= 14) txt = "Avant-bras, main, coude";
|
|
else if (result <= 18) txt = "Epaule, bras, omoplate";
|
|
else if (result == 19) txt = "Tête";
|
|
else if (result == 20) txt = "Tête (visage)";
|
|
} else {
|
|
if (result <= 7) txt = "Jambes/Pattes";
|
|
else if (result <= 18) txt = "Corps";
|
|
else if (result <= 20) txt = "Tête";
|
|
}
|
|
|
|
return { result: result, label: txt };
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) {
|
|
let formula = "2d10";
|
|
|
|
// Chaque dé fait au minmum la difficulté libre
|
|
if (ReglesOptionelles.isUsing('degat-minimum-malus-libre')) {
|
|
if (rollData.diffLibre < 0) {
|
|
let valeurMin = Math.abs(rollData.diffLibre);
|
|
formula += "min" + valeurMin;
|
|
}
|
|
}
|
|
// Chaque dé fait au minmum la difficulté libre
|
|
if (ReglesOptionelles.isUsing('degat-ajout-malus-libre')) {
|
|
if (rollData.diffLibre < 0) {
|
|
let valeurMin = Math.abs(rollData.diffLibre);
|
|
formula += "+" + valeurMin;
|
|
}
|
|
}
|
|
|
|
let roll = await RdDDice.roll(formula, options);
|
|
|
|
// 1 dé fait au minmum la difficulté libre
|
|
if (ReglesOptionelles.isUsing('degat-minimum-malus-libre-simple')) {
|
|
if (rollData.diffLibre < 0) {
|
|
let valeurMin = Math.abs(rollData.diffLibre);
|
|
if (roll.terms[0].results[0].result < valeurMin) {
|
|
roll.terms[0].results[0].result = valeurMin;
|
|
} else if (roll.terms[0].results[1].result < valeurMin) {
|
|
roll.terms[0].results[1].result = valeurMin;
|
|
}
|
|
roll._total = roll.terms[0].results[0].result + roll.terms[0].results[1].result;
|
|
}
|
|
}
|
|
|
|
return await RdDUtility.prepareEncaissement(rollData, roll, armure);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async prepareEncaissement(rollData, roll, armure) {
|
|
const jetTotal = roll.total + rollData.dmg.total - armure;
|
|
let encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite);
|
|
let over20 = Math.max(jetTotal - 20, 0);
|
|
encaissement.dmg = rollData.dmg;
|
|
encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type);
|
|
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;';
|
|
encaissement.roll = roll;
|
|
encaissement.armure = armure;
|
|
encaissement.penetration = rollData.arme?.system.penetration ?? 0;
|
|
encaissement.total = jetTotal;
|
|
encaissement.vie = await RdDUtility._evaluatePerte(encaissement.vie, over20);
|
|
encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20);
|
|
return encaissement;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static _selectEncaissement(degats, mortalite) {
|
|
const table = definitionsEncaissement[mortalite] === undefined ? definitionsEncaissement["mortel"] : definitionsEncaissement[mortalite];
|
|
for (let encaissement of table) {
|
|
if ((encaissement.minimum === undefined || encaissement.minimum <= degats)
|
|
&& (encaissement.maximum === undefined || degats <= encaissement.maximum)) {
|
|
return duplicate(encaissement);
|
|
}
|
|
}
|
|
return duplicate(table[0]);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async _evaluatePerte(formula, over20) {
|
|
let perte = new Roll(formula, { over20: over20 });
|
|
await perte.evaluate({ async: true });
|
|
return perte.total;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static currentFatigueMalus(value, max) {
|
|
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
|
max = Math.max(1, Math.min(max, 60));
|
|
value = Math.min(max * 2, Math.max(0, value));
|
|
|
|
let fatigueTab = fatigueMatrix[max];
|
|
let fatigueRem = value;
|
|
for (let idx = 0; idx < fatigueTab.length; idx++) {
|
|
fatigueRem -= fatigueTab[idx];
|
|
if (fatigueRem <= 0) {
|
|
return fatigueMalus[idx];
|
|
}
|
|
}
|
|
return -7; // This is the max !
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async responseNombreAstral(callData) {
|
|
let actor = game.actors.get(callData.id);
|
|
actor.ajouteNombreAstral(callData);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static onSocketMessage(sockmsg) {
|
|
switch (sockmsg.msg) {
|
|
case "msg_gm_chat_message":
|
|
return ChatUtility.handleGMChatMessage(sockmsg.data);
|
|
case "msg_request_nombre_astral":
|
|
return game.system.rdd.calendrier.requestNombreAstral(sockmsg.data);
|
|
case "msg_response_nombre_astral":
|
|
return RdDUtility.responseNombreAstral(sockmsg.data);
|
|
case "msg_tmr_move":
|
|
let actor = game.actors.get(sockmsg.data.actorId);
|
|
if (actor.isOwner || game.user.isGM) {
|
|
actor.refreshTMRView();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async chatListeners(html) {
|
|
RdDCombat.registerChatCallbacks(html);
|
|
|
|
// Gestion spécifique message passeurs
|
|
html.on("click", '.tmr-passeur-coord a', event => {
|
|
let coord = event.currentTarget.attributes['data-tmr-coord'].value;
|
|
let actorId = event.currentTarget.attributes['data-actor-id'].value;
|
|
let actor = game.actors.get(actorId);
|
|
actor.tmrApp.positionnerDemiReve(coord);
|
|
});
|
|
// Gestion spécifique des sorts en réserve multiples (ie têtes)
|
|
html.on("click", '.declencher-sort-reserve', event => {
|
|
let coord = event.currentTarget.attributes['data-tmr-coord'].value;
|
|
let sortId = event.currentTarget.attributes['data-sort-id'].value;
|
|
let actorId = event.currentTarget.attributes['data-actor-id'].value;
|
|
let actor = game.actors.get(actorId);
|
|
actor.tmrApp.lancerSortEnReserve(coord, sortId);
|
|
// TODO: supprimer le message?
|
|
});
|
|
|
|
// gestion bouton tchat Possession
|
|
html.on("click", '.defense-possession', event => {
|
|
let attackerId = event.currentTarget.attributes['data-attackerId'].value
|
|
let defenderId = event.currentTarget.attributes['data-defenderId'].value
|
|
let possessionId = event.currentTarget.attributes['data-possessionId'].value
|
|
RdDPossession.onDefensePossession(attackerId, defenderId, possessionId)
|
|
});
|
|
|
|
html.on("click", '.defense-empoignade-cac', event => {
|
|
const chatMessage = ChatUtility.getChatMessage(event);
|
|
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
|
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
|
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
|
|
});
|
|
html.on("click", '.defense-empoignade-esquive', event => {
|
|
const chatMessage = ChatUtility.getChatMessage(event);
|
|
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
|
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
|
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
|
|
});
|
|
html.on("click", '.empoignade-poursuivre', event => {
|
|
let attackerId = event.currentTarget.attributes['data-attackerId'].value
|
|
let defenderId = event.currentTarget.attributes['data-defenderId'].value
|
|
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId))
|
|
});
|
|
html.on("click", '.empoignade-entrainer-sol', event => {
|
|
const chatMessage = ChatUtility.getChatMessage(event);
|
|
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
|
RdDEmpoignade.entrainerAuSol(rollData)
|
|
ChatUtility.removeChatMessageId(chatMessage.id)
|
|
});
|
|
html.on("click", '.empoignade-projeter-sol', event => {
|
|
const chatMessage = ChatUtility.getChatMessage(event);
|
|
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
|
RdDEmpoignade.projeterAuSol(rollData)
|
|
ChatUtility.removeChatMessageId(chatMessage.id)
|
|
});
|
|
html.on("change", '.empoignade-perte-endurance', event => {
|
|
const chatMessage = ChatUtility.getChatMessage(event);
|
|
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
|
if (event.currentTarget.value && event.currentTarget.value != "none") {
|
|
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
|
|
ChatUtility.removeChatMessageId(chatMessage.id)
|
|
}
|
|
});
|
|
|
|
// gestion bouton tchat Acheter
|
|
html.on("click", '.button-acheter', event => {
|
|
const venteData = DialogItemAchat.preparerAchat(event.currentTarget);
|
|
if (venteData) {
|
|
DialogItemAchat.onAcheter(venteData);
|
|
}
|
|
});
|
|
html.on("click", '.button-creer-acteur', event => RdDNameGen.onCreerActeur(event));
|
|
|
|
// Gestion du bouton payer
|
|
html.on("click", '.payer-button', event => {
|
|
let sommeAPayer = Number(event.currentTarget.attributes['data-somme-a-payer']?.value ?? 0);
|
|
let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:");
|
|
if (actor) {
|
|
actor.payerSols(sommeAPayer);
|
|
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget));
|
|
}
|
|
});
|
|
html.on("click", '.rdd-world-content-link', async event => {
|
|
const htmlElement = html.find(event.currentTarget);
|
|
const id = htmlElement?.data("id");
|
|
const doctype = htmlElement?.data("doctype");
|
|
switch (doctype ?? 'Item') {
|
|
case 'Actor':
|
|
return game.actors.get(id)?.sheet.render(true);
|
|
case 'Item':
|
|
default:
|
|
return game.items.get(id)?.sheet.render(true);
|
|
}
|
|
});
|
|
}
|
|
|
|
static findChatMessageId(current) {
|
|
return RdDUtility.getChatMessageId(RdDUtility.findChatMessage(current));
|
|
}
|
|
|
|
static getChatMessageId(node) {
|
|
return node?.attributes.getNamedItem('data-message-id')?.value;
|
|
}
|
|
|
|
static findChatMessage(current) {
|
|
return RdDUtility.findNodeMatching(current, it => it.classList.contains('chat-message') && it.attributes.getNamedItem('data-message-id'));
|
|
}
|
|
|
|
static findNodeMatching(current, predicate) {
|
|
if (current) {
|
|
if (predicate(current)) {
|
|
return current;
|
|
}
|
|
return RdDUtility.findNodeMatching(current.parentElement, predicate);
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
static getSelectedActor(msgPlayer = undefined) {
|
|
if (canvas.tokens.controlled.length == 1) {
|
|
let token = canvas.tokens.controlled[0];
|
|
if (token.actor) {
|
|
return token.actor;
|
|
}
|
|
if (msgPlayer != undefined) {
|
|
msgPlayer += "<br>le token sélectionné doit être lié à un personnage";
|
|
}
|
|
}
|
|
if (game.user.character) {
|
|
return game.user.character;
|
|
}
|
|
if (msgPlayer != undefined) {
|
|
msgPlayer += "<br>vous pouvez sélectionner un seul token lié à un personnage";
|
|
msgPlayer += "<br>vous devez être connecté comme joueur avec un personnage sélectionné";
|
|
ui.notifications.warn(msgPlayer);
|
|
ChatMessage.create({ content: msgPlayer, whisper: [game.user] });
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static createMonnaie(name, cout, img = "", enc = 0.01) {
|
|
let piece = {
|
|
name: name, type: 'monnaie', img: img, _id: randomID(16),
|
|
dasystemta: {
|
|
quantite: 0,
|
|
cout: cout,
|
|
encombrement: enc,
|
|
description: ""
|
|
}
|
|
}
|
|
return piece;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static afficherDemandePayer(som1, som2) {
|
|
som1 = (som1) ? som1.toLowerCase() : "0d";
|
|
som2 = (som2) ? som2.toLowerCase() : "0d";
|
|
let regExp1 = /(\d+)(\w+)/g;
|
|
let p1 = regExp1.exec(som1);
|
|
let regExp2 = /(\d+)(\w+)/g;
|
|
let p2 = regExp2.exec(som2);
|
|
let deniers = 0;
|
|
let sols = 0;
|
|
if (p1[2] == 'd') deniers += Number(p1[1]);
|
|
if (p1[2] == 's') sols += Number(p1[1]);
|
|
if (p2[2] == 'd') deniers += Number(p2[1]);
|
|
if (p2[2] == 's') sols += Number(p2[1]);
|
|
|
|
let sommeAPayer = sols + deniers / 100;
|
|
let msgPayer = `La somme de ${sols} Sols et ${deniers} Deniers est à payer<br>
|
|
<a class='payer-button chat-card-button' data-somme-a-payer='${sommeAPayer}'>Payer</a>`
|
|
ChatMessage.create({ content: msgPayer });
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static chatDataSetup(content, modeOverride, isRoll = false, forceWhisper) {
|
|
let chatData = {
|
|
user: game.user.id,
|
|
rollMode: modeOverride || game.settings.get("core", "rollMode"),
|
|
content: content
|
|
};
|
|
|
|
if (["gmroll", "blindroll"].includes(chatData.rollMode)) chatData["whisper"] = ChatMessage.getWhisperRecipients("GM").map(u => u.id);
|
|
if (chatData.rollMode === "blindroll") chatData["blind"] = true;
|
|
else if (chatData.rollMode === "selfroll") chatData["whisper"] = [game.user];
|
|
|
|
if (forceWhisper) { // Final force !
|
|
chatData["speaker"] = ChatMessage.getSpeaker();
|
|
chatData["whisper"] = ChatMessage.getWhisperRecipients(forceWhisper);
|
|
}
|
|
|
|
return chatData;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete, onSuppression = ()=>{}) {
|
|
RdDConfirm.confirmer({
|
|
settingConfirmer: "confirmation-supprimer-lien-acteur",
|
|
content: `<p>Etes vous certain de vouloir supprimer le lien vers ${subActor.name} ?</p>`,
|
|
title: 'Confirmer la suppression',
|
|
buttonLabel: 'Supprimer le lien',
|
|
onAction: onSuppression
|
|
})
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async confirmActorItemDelete(sheet, item, htmlToDelete) {
|
|
const itemId = item.id;
|
|
const confirmationSuppression = {
|
|
settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(),
|
|
content: `<p>Etes vous certain de vouloir supprimer: ${item.name}?</p>`,
|
|
title: `Supprimer ${item.name}`,
|
|
buttonLabel: "Supprimer",
|
|
onAction: () => {
|
|
console.log('Delete : ', itemId);
|
|
sheet.actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false });
|
|
RdDUtility.slideOnDelete(sheet, htmlToDelete);
|
|
}
|
|
};
|
|
if (item.isConteneurNonVide()) {
|
|
confirmationSuppression.content += `<p>Ce conteneur n'est pas vide. Que voulez vous supprimer?</p>`;
|
|
confirmationSuppression.settingConfirmer = undefined;
|
|
RdDConfirm.confirmer(confirmationSuppression,
|
|
{
|
|
'deleteall': {
|
|
icon: '<i class="fas fa-check"></i>',
|
|
label: "Supprimer conteneur et contenu",
|
|
callback: () => {
|
|
console.log("Delete : ", itemId);
|
|
sheet.actor.deleteAllConteneur(itemId, { renderSheet: false });
|
|
RdDUtility.slideOnDelete(sheet, htmlToDelete);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
RdDConfirm.confirmer(confirmationSuppression)
|
|
}
|
|
}
|
|
|
|
static slideOnDelete(sheet, htmlToDelete) {
|
|
return htmlToDelete?.slideUp(200, () => sheet.render(false));
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static afficherHeuresChanceMalchance(heureNaissance) {
|
|
if (game.user.isGM) {
|
|
const heure = RdDTimestamp.findHeure(heureNaissance - 1);
|
|
if (heureNaissance && heure) {
|
|
let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance);
|
|
const current = game.system.rdd.calendrier.heureCourante();
|
|
ChatMessage.create({
|
|
content: `A l'heure de <strong>${current.label}</strong>, le modificateur de Chance/Malchance est de <strong>${Misc.toSignedString(ajustement)}</strong> pour l'heure de naissance <strong>${heure.label}</strong>.`,
|
|
whisper: ChatMessage.getWhisperRecipients("GM")
|
|
});
|
|
}
|
|
else if (heureNaissance) {
|
|
ui.notifications.warn(heureNaissance + " ne correspond pas à une heure de naissance");
|
|
}
|
|
else {
|
|
ui.notifications.warn("Pas d'heure de naissance selectionnée");
|
|
}
|
|
} else {
|
|
ui.notifications.warn("Vous n'avez pas accès à cette commande");
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------- */
|
|
static checkThanatosXP(compName) {
|
|
if (compName.includes('Thanatos')) {
|
|
let message = "Vous avez mis des points d'Expérience dans la Voie de Thanatos !<br>Vous devez réduire manuellement d'un même montant d'XP une autre compétence Draconique.";
|
|
ChatMessage.create({
|
|
whisper: ChatMessage.getWhisperRecipients(game.user.name),
|
|
content: message
|
|
});
|
|
}
|
|
}
|
|
|
|
/*-------------------------------------------- */
|
|
static async onRenderChatMessage(app, html, msg) {
|
|
// TODO
|
|
//console.log(app, html, msg);
|
|
}
|
|
|
|
}
|