Tirer dans les compendiums selon les fréquences

This commit is contained in:
Vincent Vandemeulebrouck
2022-11-26 03:13:45 +01:00
parent 970be67537
commit 0dacbefd6b
15 changed files with 370 additions and 165 deletions

View File

@@ -21,7 +21,6 @@ import { STATUSES, StatusEffects } from "./settings/status-effects.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { TMRRencontres } from "./tmr-rencontres.js";
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { Draconique } from "./tmr/draconique.js";
import { RdDCarac } from "./rdd-carac.js";
@@ -771,7 +770,7 @@ export class RdDActor extends Actor {
actor: this,
competence: duplicate(this.getDraconicOuPossession()),
canClose: false,
rencontre: await TMRRencontres.getReveDeDragon(force),
rencontre: await game.system.rencontresTMR.getReveDeDragon(force),
tmr: true,
use: { libre: false, conditions: false },
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.getReveActuel() } }

View File

@@ -59,17 +59,23 @@ export const defaultItemImg = {
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
}
/* -------------------------------------------- */
export class RdDItem extends Item {
static getDefaultImg(itemType) {
return defaultItemImg[itemType];
}
constructor(itemData, context) {
if (!itemData.img) {
itemData.img = defaultItemImg[itemData.type];
}
itemData.img = RdDItem.getDefaultImg(itemData.type);
}
super(itemData, context);
}
}
static getTypesObjetsEquipement() {
return typesObjetsEquipement

View File

@@ -3,7 +3,6 @@
import { DialogChronologie } from "./dialog-chronologie.js";
import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js";
import { DialogStress } from "./dialog-stress.js";
import { Grammar } from "./grammar.js";
import { RdDItemCompetence } from "./item-competence.js";
import { Misc } from "./misc.js";
import { RdDCarac } from "./rdd-carac.js";
@@ -14,7 +13,6 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
import { RdDRollTables } from "./rdd-rolltables.js";
import { RdDUtility } from "./rdd-utility.js";
import { TMRRencontres } from "./tmr-rencontres.js";
import { TMRUtility } from "./tmr-utility.js";
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
@@ -27,15 +25,34 @@ export class RdDCommands {
const rddCommands = new RdDCommands();
rddCommands.registerCommand({ path: ["/aide"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
rddCommands.registerCommand({ path: ["/help"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
rddCommands.registerCommand({ path: ["/table", "queues"], func: (content, msg, params) => RdDRollTables.getQueue(true), descr: "Tire une Queue de Dragon" });
rddCommands.registerCommand({ path: ["/table", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe(true), descr: "Tire une Idée fixe" });
rddCommands.registerCommand({ path: ["/table", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant(true), descr: "Tire un Désir Lancinant" });
rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre(true), descr: "Tire une Ombre de Dragon" });
rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR(true), descr: "Tire une Tête de Dragon pour Hauts Revants" });
rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete(true), descr: "Tire une Tête de Dragon" });
rddCommands.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle(true), descr: " Tire un Souffle de Dragon" });
rddCommands.registerCommand({ path: ["/table", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence(true), descr: "Tire une compétence au hasard" });
rddCommands.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot(true), descr: "Tire une carte du Tarot Draconique" });
rddCommands.registerCommand({ path: ["/liste", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('liste'), descr: "Affiche la liste des compétences" });
rddCommands.registerCommand({ path: ["/table", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('liste'), descr: "Affiche la table des Queues de Dragon" });
rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre('liste'), descr: "Affiche la table des Ombres de Thanatos" });
rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR('liste'), descr: "Affiche la table des Têtes de Dragon pour Hauts Revants" });
rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete('liste'), descr: "Affiche la table des Tête de Dragon pour tous" });
rddCommands.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle('liste'), descr: "Affiche la table des Souffles de Dragon" });
rddCommands.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot('liste'), descr: "Affiche la table les cartes du Tarot Draconique" });
rddCommands.registerCommand({ path: ["/table", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe('liste'), descr: "Affiche la table des Idées fixes" });
rddCommands.registerCommand({ path: ["/table", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('liste'), descr: "Affiche la table des Désirs Lancinants" });
rddCommands.registerCommand({
path: ["/table", "rencontre"], func: (content, msg, params) => rddCommands.tableRencontres(msg, params),
descr: `Affiche la table des Rencontres
<br><strong>/table rencontre deso</strong> affiche la table des rencontres en Désolation
<br><strong>/table rencontre mauvaise</strong> affiche la table des mauvaises rencontres` });
rddCommands.registerCommand({ path: ["/tirer", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('chat'), descr: "Tire une compétence au hasard" });
rddCommands.registerCommand({ path: ["/tirer", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('chat'), descr: "Tire une Queue de Dragon" });
rddCommands.registerCommand({ path: ["/tirer", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre('chat'), descr: "Tire une Ombre de Thanatos" });
rddCommands.registerCommand({ path: ["/tirer", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR('chat'), descr: "Tire une Tête de Dragon pour Hauts Revants" });
rddCommands.registerCommand({ path: ["/tirer", "tete"], func: (content, msg, params) => RdDRollTables.getTete('chat'), descr: "Tire une Tête de Dragon" });
rddCommands.registerCommand({ path: ["/tirer", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle('chat'), descr: "Tire un Souffle de Dragon" });
rddCommands.registerCommand({ path: ["/tirer", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot('chat'), descr: "Tire une carte du Tarot Draconique" });
rddCommands.registerCommand({ path: ["/tirer", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe('chat'), descr: "Tire une Idée fixe" });
rddCommands.registerCommand({ path: ["/tirer", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('chat'), descr: "Tire un Désir Lancinant" });
rddCommands.registerCommand({ path: ["/tirer", "rencontre"], func: (content, msg, params) => rddCommands.getRencontreTMR(params), descr: `Détermine une rencontre dans les TMR (synonyme de "/tmrr")` });
rddCommands.registerCommand({ path: ["/meteo"], func: (content, msg, params) => rddCommands.getMeteo(msg, params), descr: "Propose une météo marine" });
rddCommands.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
@@ -51,11 +68,10 @@ export class RdDCommands {
<br><strong>/tmra</strong> détermine une case aléatoire dans toutes les TMR` });
rddCommands.registerCommand({
path: ["/tmrr"], func: (content, msg, params) => rddCommands.getRencontreTMR(params),
descr: `Détermine une rencontre dans un type de case
descr: `Détermine une rencontre dans les TMR
<br><strong>/tmrr forêt</strong> détermine une rencontre aléatoire en 'forêt'
<br><strong>/tmrr mauvaise</strong> détermine une mauvaise rencontre aléatoire
<br><strong>/tmrr for 47</strong> détermine la rencontre en 'forêt' pour un jet de dé de 47`
});
<br><strong>/tmrr for 47</strong> détermine la rencontre en 'forêt' pour un jet de dé de 47` });
rddCommands.registerCommand({
path: ["/xp", "comp"], func: (content, msg, params) => rddCommands.getCoutXpComp(msg, params),
@@ -208,10 +224,10 @@ export class RdDCommands {
this.help(msg, undefined);
}
async help(msg, table) {
let list = []
this._buildSubTableHelp(list, table || this.commandsTable);
let commands = []
this._buildSubTableHelp(commands, table || this.commandsTable);
let html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/settings/dialog-aide-commands.html", { commands: list });
let html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/settings/dialog-aide-commands.html", { commands: commands });
let d = new Dialog(
{
title: "Commandes disponibles dans le tchat",
@@ -249,7 +265,7 @@ export class RdDCommands {
/* -------------------------------------------- */
async getRencontreTMR(params) {
if (params.length == 1 || params.length == 2) {
return TMRRencontres.rollRencontre(params[0], params[1])
return game.system.rencontresTMR.rollRencontre(params[0], params[1])
}
return false;
}
@@ -335,6 +351,17 @@ export class RdDCommands {
}
return false;
}
async tableRencontres(msg, params) {
if (params && params.length > 0) {
const search = Misc.join(params, ' ');
const solvedTerrain = TMRUtility.findTMRLike(search);
if (solvedTerrain == undefined) {
return RdDCommands._chatAnswer(msg, 'Aucune TMR correspondant à ' + search);
}
return game.system.rencontresTMR.chatTable(solvedTerrain);
}
return false;
}
/* -------------------------------------------- */
getCoutXpComp(msg, params) {

View File

@@ -39,6 +39,7 @@ import { Migrations } from './migrations.js';
import { DialogChronologie } from "./dialog-chronologie.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
import { RdDRencontreItemSheet } from "./item-rencontre-sheet.js";
import { TMRRencontres } from "./tmr-rencontres.js";
/* -------------------------------------------- */
/* Foundry VTT Initialization */
@@ -223,6 +224,7 @@ Hooks.once("init", async function () {
TMRUtility.init();
RdDHotbar.initDropbar();
RdDPossession.init();
TMRRencontres.init();
});
/* -------------------------------------------- */

View File

@@ -1,3 +1,4 @@
import { Grammar } from "./grammar.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
export class RdDRollTables {
@@ -5,10 +6,8 @@ export class RdDRollTables {
/* -------------------------------------------- */
static async genericGetTableResult(tableName, toChat) {
let table = RdDRollTables.getWorldTable(tableName) ?? (await RdDRollTables.getSystemTable(tableName));
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll"});
//console.log("RdDRollTables", tableName, toChat, ":", draw);
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll" });
return draw.results.length > 0 ? draw.results[0] : undefined;
}
static getWorldTable(tableName) {
@@ -28,7 +27,7 @@ export class RdDRollTables {
const pack = game.packs.get(drawResult.documentCollection)
return await pack.getDocument(drawResult.documentId)
}
/* -------------------------------------------- */
static async drawTextFromRollTable(tableName, toChat) {
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
@@ -37,58 +36,67 @@ export class RdDRollTables {
/* -------------------------------------------- */
static async getCompetence(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat);
if (toChat == 'liste') {
return await SystemCompendiums.chatTableItems('competences', 'Item', 'competence', it => 1);
}
else {
return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat);
}
}
/* -------------------------------------------- */
static async getSouffle(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Souffles de Dragon", toChat);
return await RdDRollTables.listOrRoll('souffles-de-dragon', 'Item', 'souffle', toChat);
}
/* -------------------------------------------- */
static async getQueue(toChat = false) {
let queue = await RdDRollTables.drawItemFromRollTable("Queues de dragon", toChat);
if (queue.name.toLowerCase().includes('lancinant') ) {
return await RdDRollTables.getDesirLancinant(toChat);
}
if (queue.name.toLowerCase().includes('fixe') ) {
return await RdDRollTables.getIdeeFixe(toChat);
}
return queue;
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', 'queue', toChat);
}
static async getDesirLancinant(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Désirs lancinants", toChat);
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', 'queue', toChat, it => it.system.frequence,
it => Grammar.toLowerCaseNoAccent(it.name).includes('desir lancinant') /* it.system.lancinant */);
}
static async getIdeeFixe(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Idées fixes", toChat);
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', 'queue', toChat, it => it.system.frequence,
it => Grammar.toLowerCaseNoAccent(it.name).includes('idee fixe') /* it.system.ideefixe */);
}
/* -------------------------------------------- */
static async getTeteHR(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour haut-rêvants", toChat);
return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-haut-revants', 'Item', 'tete', toChat);
}
/* -------------------------------------------- */
static async getTete(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour tous personnages", toChat);
return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-tous-personnages', 'Item', 'tete', toChat);
}
/* -------------------------------------------- */
static async getOmbre(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Ombre de Thanatos", toChat);
return await RdDRollTables.listOrRoll('ombres-de-thanatos', 'Item', 'ombre', toChat);
}
/* -------------------------------------------- */
static async getTarot(toChat = true) {
return await RdDRollTables.drawItemFromRollTable("Tarot Draconique", toChat);
return await RdDRollTables.listOrRoll('tarot-draconique', 'Item', 'tarot', toChat);
}
/* -------------------------------------------- */
static async getMaladresse(options = {toChat: false, arme: false}) {
static async listOrRoll(compendium, type, subType, toChat, itemFrequence = it => it.system.frequence, filter = it => true) {
if (toChat == 'liste') {
return await SystemCompendiums.chatTableItems(compendium, type, subType, itemFrequence, filter);
}
return await SystemCompendiums.getRandom(compendium, type, subType, toChat, itemFrequence, filter);
}
/* -------------------------------------------- */
static async getMaladresse(options = { toChat: false, arme: false }) {
return await RdDRollTables.drawTextFromRollTable(
options.arme ? "Maladresse armé" : "Maladresses non armé",
options.toChat);
}
}

View File

@@ -575,7 +575,7 @@ export class RdDTMRDialog extends Dialog {
async _jetDeRencontre(tmr) {
let rencontre = this.lookupRencontreExistente(tmr);
if (rencontre) {
return TMRRencontres.calculRencontre(rencontre, tmr);
return game.system.rencontresTMR.calculRencontre(rencontre, tmr);
}
let locTMR = (this.isDemiReveCache()
? TMRUtility.getTMRType(tmr.coord) + " ??"
@@ -584,7 +584,7 @@ export class RdDTMRDialog extends Dialog {
let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
if (myRoll == 7) {
this._tellToUser(myRoll + ": Rencontre en " + locTMR);
return await TMRRencontres.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
return await game.system.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
} else {
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
}

View File

@@ -283,14 +283,14 @@ export class RdDUtility {
Handlebars.registerHelper('buildContenu', (objet) => { return new Handlebars.SafeString(RdDUtility.buildContenu(objet, 1, true)); });
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
Handlebars.registerHelper('typeTmr-name', coord => TMRUtility.typeTmrName(coord));
Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type));
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
Handlebars.registerHelper('signeHeure', (key, heure) => RdDCalendrier.getSigneAs(key, heure));
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 => competences.filter(it => it.system.isVisible)
.sort((a, b) => {
.sort((a, b) => {
if (a.name.startsWith("Survie") && b.name.startsWith("Survie")) {
if (a.name.includes("Cité")) return -1;
if (b.name.includes("Cité")) return 1;
@@ -320,7 +320,8 @@ export class RdDUtility {
}
return a.name.localeCompare(b.name);
})
);
);
Handlebars.registerHelper('linkCompendium', (compendium, id, name) => `@Compendium[${compendium}.${id}]{${name}}`);
return loadTemplates(templatePaths);
}

View File

@@ -69,13 +69,13 @@ export const referenceAjustements = {
},
surenc: {
isVisible: (rollData, actor) => actor.isSurenc(),
isUsed: (rollData, actor) => rollData.use.surenc,
isUsed: (rollData, actor) => rollData.use?.surenc,
getLabel: (rollData, actor) => 'Sur-encombrement',
getValue: (rollData, actor) => actor.computeMalusSurEncombrement()
},
moral: {
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac) && rollData.use.moral,
isUsed: (rollData, actor) => rollData.use.moral,
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac) && rollData.use?.moral,
isUsed: (rollData, actor) => rollData.use?.moral,
getLabel: (rollData, actor) => 'Appel au moral',
getValue: (rollData, actor) => 1
},

View File

@@ -1,4 +1,7 @@
import { SYSTEM_RDD } from "../constants.js";
import { HIDE_DICE, SYSTEM_RDD } from "../constants.js";
import { RdDItem } from "../item.js";
import { Misc } from "../misc.js";
import { RdDDice } from "../rdd-dice.js";
const COMPENDIUM_SETTING_PREFIX = 'compendium-';
@@ -63,6 +66,7 @@ export class SystemCompendiums extends FormApplication {
case 'vehicule': return [];
}
}
/* -------------------------------------------- */
static async getWorldOrCompendiumItems(itemType, compendium) {
let items = game.items.filter(it => it.type == itemType);
@@ -80,7 +84,34 @@ export class SystemCompendiums extends FormApplication {
static async getItems(compendium, itemType = undefined) {
const items = await SystemCompendiums.getContent(compendium, 'Item');
return itemType ? items.filter(it => it.type == itemType) : items;
return (itemType ? items.filter(it => it.type == itemType) : items);
}
static async buildTable(compendium, itemFrequence, filter, type = 'Item', sorting = undefined) {
let elements = await SystemCompendiums.getContent(compendium, type);
elements = elements.filter(filter).filter(it => itemFrequence(it) > 0)
if (sorting) {
elements = elements.sort(sorting);
}
let max = 0;
const table = elements
.map(it => {
const frequence = itemFrequence(it)
let row = { document: it, frequence: frequence, min: max + 1, max: max + frequence }
max += frequence;
return row;
});
table.forEach(it => it.total = max);
return table;
}
static async getRandom(compendium, type, subType, toChat = true, itemFrequence = it => it.system.frequence, filter = it => true) {
const table = new SystemCompendiumTable(compendium, type, subType);
return await table.getRandom(toChat, itemFrequence, filter);
}
static async chatTableItems(compendium, type, subType, itemFrequence = it => it.system.frequence, filter = it => true) {
const table = new SystemCompendiumTable(compendium, type, subType, itemFrequence);
await table.chatTable(itemFrequence, filter);
}
static async getDefaultItems(compendium) {
@@ -125,11 +156,13 @@ export class SystemCompendiums extends FormApplication {
getData() {
const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS)
.map(it => mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) }));
const availableCompendiums = game.packs.map(pack => { return {
name: pack.collection,
path: pack.collection.replace('.', " / "),
type: pack.metadata.type
} });
const availableCompendiums = game.packs.map(pack => {
return {
name: pack.collection,
path: pack.collection.replace('.', " / "),
type: pack.metadata.type
}
});
return mergeObject(super.getData(), {
systemCompendiums: systemCompendiums,
availableCompendiums: availableCompendiums
@@ -145,5 +178,102 @@ export class SystemCompendiums extends FormApplication {
game.settings.set(SYSTEM_RDD, systemCompendium.setting, value);
});
}
}
}
export class SystemCompendiumTable {
constructor(compendium, type, subType, sorting = undefined) {
this.compendium = compendium;
this.type = type;
this.subType = subType;
this.compendium = compendium;
this.sourceCompendium = SystemCompendiums.getCompendium(compendium);
this.sorting = sorting
}
typeName() {
return game.i18n.localize(`${this.type.toUpperCase()}.Type${Misc.upperFirst(this.subType)}`);
}
applyType(filter) {
return it => it.type == this.subType && filter(it);
}
async getRandom(toChat = true, itemFrequence = it => it.system.frequence, filter = it => true, forcedRoll = undefined) {
const table = await this.$buildTable(itemFrequence, filter);
if (table.length == 0) {
ui.notifications.warn(`Aucun ${this.typeName()} dans ${this.sourceCompendium}`);
return undefined;
}
const row = await this.$selectRow(table, forcedRoll);
if (row && toChat) {
await this.$chatRolledResult(row);
}
return row;
}
async chatTable(itemFrequence = it => it.system.frequence, filter = it => true, typeName = undefined) {
const table = await this.$buildTable(itemFrequence, filter);
await this.$chatSystemCompendiumTable(table, typeName);
}
async $buildTable(itemFrequence, filter) {
return await SystemCompendiums.buildTable(this.compendium, itemFrequence, this.applyType(filter), this.type, this.sorting);
}
/* -------------------------------------------- */
async $selectRow(table, forcedRoll = undefined) {
if (table.length == 0) {
return undefined
}
const total = table[0].total;
const formula = `1d${total}`;
if (forcedRoll == undefined && (forcedRoll > total || forcedRoll <= 0)) {
ui.notifications.warn(`Jet de rencontre ${forcedRoll} en dehors de la table [1..${total}], le jet est relancé`);
forcedRoll = undefined;
}
const roll = forcedRoll ? { total: forcedRoll, formula } : await RdDDice.roll(formula, { showDice: HIDE_DICE });
const row = table.find(it => it.min <= roll.total && roll.total <= it.max);
row.roll = roll;
return row;
}
/* -------------------------------------------- */
async $chatRolledResult(row) {
const percentages = (row.total == 100) ? '%' : ''
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table-roll.html', {
roll: row.roll,
document: row?.document,
percentages,
typeName: this.typeName(),
sourceCompendium: this.sourceCompendium,
isGM: game.user.isGM,
});
const messageData = {
// flavor: flavorContent,
user: game.user.id,
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
roll: row.roll,
sound: CONFIG.sounds.dice,
content: flavorContent
};
ChatMessage.create(messageData, { rollMode: "gmroll" });
}
/* -------------------------------------------- */
async $chatSystemCompendiumTable(table, typeName) {
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table.html', {
img: RdDItem.getDefaultImg(this.subType),
typeName: typeName ?? this.typeName(),
sourceCompendium: this.sourceCompendium,
table,
isGM: game.user.isGM,
});
ChatMessage.create({
user: game.user.id,
whisper: game.user.id,
content: flavorContent
}, { rollMode: "gmroll" });
}
}

View File

@@ -1,88 +1,73 @@
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
import { SystemCompendiums, SystemCompendiumTable } from "./settings/system-compendiums.js";
import { TMRUtility } from "./tmr-utility.js";
/* -------------------------------------------- */
export class TMRRencontres {
static init() {
const tmrRencontre = new TMRRencontres();
game.system.rencontresTMR = tmrRencontre;
}
constructor(){
this.table = new SystemCompendiumTable('rencontres', 'Item', 'rencontre', Misc.ascending(it => it.system.ordreTri));
}
/* -------------------------------------------- */
/**
* Retourne une recontre en fonction de la case et du tirage
* @param {*} terrain
* @param {*} forcedRoll
*/
static async rollRencontre(terrain, forcedRoll) {
async rollRencontre(terrain, forcedRoll) {
terrain = TMRUtility.findTMRLike(terrain);
if (terrain == undefined) {
return undefined;
}
if (forcedRoll && (forcedRoll <= 0 || forcedRoll > 100)) {
forcedRoll = undefined;
}
const codeTerrain = Grammar.toLowerCaseNoAccent(terrain)
const table = await TMRRencontres.$buildTableRencontre(codeTerrain);
const [selected, roll] = await TMRRencontres.$selectRencontre(codeTerrain, table, forcedRoll);
const rencontre = await TMRRencontres.createRencontre(selected.rencontre);
TMRRencontres.$chatRolledRencontre(rencontre, terrain, table, roll, true);
return false;
}
/* -------------------------------------------- */
static async $buildTableRencontre(codeTerrain) {
let max = 0;
const items = await SystemCompendiums.getItems('rencontres', 'rencontre');
const filtreMauvaise = codeTerrain == 'mauvaise' ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
const rencontres = items.filter(it => it.type == 'rencontre')
.filter(filtreMauvaise)
.filter(it => it.system.frequence[codeTerrain] > 0)
.sort(Misc.ascending(it => it.system.ordreTri))
.map(it => {
const frequence = it.system.frequence[codeTerrain];
max += frequence;
return { rencontre: it, min: max - frequence + 1, max: max,frequence: frequence };
});
return rencontres;
const frequence = it => it.system.frequence[codeTerrain];
const random = await this.table.getRandom(true, frequence, filtreMauvaise, forcedRoll);
return random?.document;
}
/* -------------------------------------------- */
static async $selectRencontre(terrain, table, roll = undefined) {
const total = table.map(it => it.frequence).reduce(Misc.sum(), 0);
if (total == 0){
ui.notifications.warn(`Pas de rencontres définies pour ${terrain}`);
return undefined;
}
if (roll != undefined && (roll > total || roll <= 0)) {
ui.notifications.warn(`Jet de rencontre ${roll} en dehors de la table [1..${total}], le jet est relancé`);
roll = undefined;
}
if (!roll) {
roll = await RdDDice.rollTotal(`1d${total}`);
}
return [table.find(it => it.min <= roll && roll <= it.max), roll];
async chatTable(terrain) {
const codeTerrain = Grammar.toLowerCaseNoAccent(terrain)
const isMauvaise = codeTerrain == 'mauvaise';
const filtreMauvaise = isMauvaise ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
const frequence = it => it.system.frequence[codeTerrain];
const typeName = isMauvaise ? 'Mauvaises rencontres' : `Rencontres en ${Misc.upperFirst(terrain)}`;
await this.table.chatTable(frequence, filtreMauvaise, typeName);
return true
}
/* -------------------------------------------- */
static async createRencontre(rencontre, tmr = undefined) {
async createRencontre(rencontre, tmr = undefined) {
return rencontre.clone({
'system.force': await RdDDice.rollTotal(rencontre.system.formule),
'system.coord': tmr?.coord,
'system.date': game.system.rdd.calendrier.getDateFromIndex(),
'system.heure': game.system.rdd.calendrier.getCurrentHeure()
}, {save: false});
}, { save: false });
}
static async calculRencontre(rencontre, tmr = undefined) {
if (rencontre.system.coord == ""){
async calculRencontre(rencontre, tmr = undefined) {
if (rencontre.system.coord == "") {
rencontre.system.coord = tmr?.coord;
}
if (rencontre.system.force == 0){
if (rencontre.system.force == 0) {
rencontre.system.force = await RdDDice.rollTotal(rencontre.system.formule);
}
if (rencontre.system.date == "" ) {
if (rencontre.system.date == "") {
rencontre.system.date = game.system.rdd.calendrier.getDateFromIndex();
}
if (rencontre.system.heure == "") {
@@ -91,46 +76,51 @@ export class TMRRencontres {
return rencontre;
}
/* -------------------------------------------- */
static $chatRolledRencontre(rencontre, terrain, table, roll = 0, displayTable=false){
const total = table.map(it => it.frequence).reduce(Misc.sum(), 0);
const namesPercent = displayTable ?
table.map(it => `<br>${it.rencontre.name} : ${it.frequence}${total == 100 ? '%' : ''} (${it.min} - ${it.max})`).reduce((a, b) => a + b, '<hr>')
: '';
const chances = game.user.isGM
? (roll ? `Jet: ${roll} / ${total}` : `Valeurs: [1..${total}]`)
: (roll ? `Jet: ${Math.ceil(roll*100/total)} / 100` : '');
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: `Compendium: ${SystemCompendiums.getCompendium('rencontres')}
<br>Rencontre en ${terrain}:
${namesPercent}<hr>
<br>${chances}
<br>Rencontre: ${rencontre.name} ${rencontre.system.force} (${rencontre.system.formule})`
});
}
static async getPresentsCite() {
async getPresentsCite() {
const rencontres = await SystemCompendiums.getDefaultItems('rencontres');
return rencontres.filter(it => !it.system.mauvaiseRencontre && it.system.presentCite).map(it =>
it.clone({ 'system.formule': "2d6" }, {save: false}));
return rencontres.filter(it => !it.system.mauvaiseRencontre && it.system.presentCite).map(it =>
it.clone({ 'system.formule': "2d6" }, { save: false }));
}
static async getReveDeDragon(force) {
async getReveDeDragon(force) {
const rencontres = await SystemCompendiums.getDefaultItems('rencontres');
const reveDeDragon = rencontres.find(it => Grammar.equalsInsensitive(it.name, 'Rêve de Dragon'));
return reveDeDragon?.clone({ 'system.force': force }, {save: false});
return reveDeDragon?.clone({ 'system.force': force }, { save: false });
}
/* -------------------------------------------- */
static async getRencontreAleatoire(tmr, mauvaise) {
async getRencontreAleatoire(tmr, mauvaise) {
const codeTerrain = mauvaise ? 'mauvaise' : tmr.type;
const table = await TMRRencontres.$buildTableRencontre(codeTerrain);
const [selected, roll] = await TMRRencontres.$selectRencontre(codeTerrain, table);
const rencontre = await TMRRencontres.createRencontre(selected.rencontre, tmr);
TMRRencontres.$chatRolledRencontre(rencontre, TMRUtility.getTMRType(tmr.coord), table, roll);
return rencontre;
const filtreMauvaise = codeTerrain == 'mauvaise' ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
const frequence = it => it.system.frequence[codeTerrain];
const row = await this.table.getRandom(false, frequence, filtreMauvaise);
if (row) {
row.document = this.createRencontre(row.document, tmr);
await this.$chatRolledRencontre(row, tmr);
}
return row?.document;
}
/* -------------------------------------------- */
async $chatRolledRencontre(row, tmr) {
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table-roll-rencontre.html',
{
roll: row.roll,
rencontre: row?.document,
percentages: (row.total == 100) ? '%' : '',
tmr,
isGM: game.user.isGM,
});
const messageData = {
user: game.user.id,
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
roll: row.roll,
sound: CONFIG.sounds.dice,
content: flavorContent
};
ChatMessage.create(messageData, { rollMode: "gmroll" });
}
}

View File

@@ -3,7 +3,6 @@ import { Grammar } from "../grammar.js";
import { TMRUtility } from "../tmr-utility.js";
import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js";
import { Draconique } from "./draconique.js";
import { TMRRencontres } from "../tmr-rencontres.js";
export class PresentCites extends Draconique {
@@ -47,7 +46,7 @@ export class PresentCites extends Draconique {
}
async choisirUnPresent(casetmr, onChoixPresent) {
const presents = await TMRRencontres.getPresentsCite()
const presents = await game.system.rencontresTMR.getPresentsCite()
const buttons = {};
presents.forEach(r => buttons['present'+r.id] = { icon: '<i class="fas fa-check"></i>', label: r.name, callback: async () => onChoixPresent(r) });
let d = new Dialog({