Fréquences par milieu pour l'environnement
Les herbes et les ingrédients peuvent être cherchées/tirées
This commit is contained in:
parent
b7a8b0c08d
commit
b7a0e5d034
222
module/environnement.js
Normal file
222
module/environnement.js
Normal file
@ -0,0 +1,222 @@
|
||||
import { SYSTEM_RDD } from "./constants.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { CompendiumTableHelpers, SystemCompendiums, CompendiumTable } from "./settings/system-compendiums.js";
|
||||
|
||||
const RARETES = [
|
||||
{ name: 'Commune', frequence: 54, min: 27, max: 108 },
|
||||
{ name: 'Frequente', frequence: 18, min: 9, max: 36 },
|
||||
{ name: 'Rare', frequence: 6, min: 3, max: 12 },
|
||||
{ name: 'Rarissime', frequence: 2, min: 1, max: 4 }]
|
||||
|
||||
const SETTINGS_LISTE_MILIEUX = "liste-milieux";
|
||||
const MILIEUX = [
|
||||
"Collines",
|
||||
"Déserts",
|
||||
"Désolations",
|
||||
"Forêts",
|
||||
"Forêts Tropicales",
|
||||
"Marais",
|
||||
"Milieux Aquatiques",
|
||||
"Milieux Maritimes",
|
||||
"Montagnes",
|
||||
"Plaines",
|
||||
"Sous-Sols",
|
||||
]
|
||||
const ITEM_ENVIRONNEMENT_TYPES = [
|
||||
'herbe', 'ingredient'
|
||||
]
|
||||
const COMPENDIUMS_ENVIRONNEMENT = [
|
||||
{ type: 'Item', subType: 'herbe', compendium: 'botanique' },
|
||||
{ type: 'Item', subType: 'ingredient', compendium: 'botanique' },
|
||||
{ type: 'Item', subType: 'ingredient', compendium: 'equipement' },
|
||||
]
|
||||
|
||||
export class Environnement {
|
||||
|
||||
static init() {
|
||||
game.settings.register(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX, {
|
||||
name: "Liste des milieux proposés",
|
||||
hint: "Liste des noms de milieux proposés, séparés par des virgules",
|
||||
scope: "world",
|
||||
config: true,
|
||||
default: MILIEUX.reduce(Misc.joining(',')),
|
||||
type: String
|
||||
});
|
||||
game.system.rdd.environnement = new Environnement();
|
||||
}
|
||||
|
||||
constructor() {
|
||||
this.table = new CompendiumTable('faune-flore-mineraux', 'Item', ITEM_ENVIRONNEMENT_TYPES)
|
||||
}
|
||||
|
||||
static getRarete(name = undefined) {
|
||||
return RARETES.find(it => it.name == name) ?? RARETES[0];
|
||||
}
|
||||
|
||||
static getFrequenceRarete(rarete, field = undefined) {
|
||||
const selected = this.getRarete(rarete);
|
||||
return selected[field];
|
||||
}
|
||||
|
||||
async milieux() {
|
||||
const milieux = new Set(this.getMilieuxSettings());
|
||||
const elements = await this.getElements(it => 1, it => ITEM_ENVIRONNEMENT_TYPES.includes(it.type));
|
||||
elements.forEach(it => it.system.environnement.forEach(env => milieux.add(env.milieu)))
|
||||
return [...milieux];
|
||||
}
|
||||
|
||||
getMilieuxSettings() {
|
||||
return game.settings.get(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX).split(',');
|
||||
}
|
||||
|
||||
async findEnvironnementsLike(search) {
|
||||
return (await this.milieux()).filter(it => Grammar.includesLowerCaseNoAccent(it, search));
|
||||
}
|
||||
|
||||
async searchToChatMessage(search) {
|
||||
const table = await this.buildEnvironnementTable(search);
|
||||
await CompendiumTableHelpers.tableToChatMessage(table, 'Item', 'herbe', 'Ressource naturelle');
|
||||
return true
|
||||
}
|
||||
|
||||
async getRandom(search) {
|
||||
const table = await this.buildEnvironnementTable(search);
|
||||
const row = await CompendiumTableHelpers.getRandom(table, 'Item', 'herbe', undefined, 'Ressource naturelle');
|
||||
return row
|
||||
}
|
||||
|
||||
async buildEnvironnementTable(search) {
|
||||
const itemRareteEnMilieu = item => item.system?.environnement.find(env => Grammar.includesLowerCaseNoAccent(env.milieu, search));
|
||||
const itemFrequenceEnMilieu = item => itemRareteEnMilieu(item)?.frequence ?? 0;
|
||||
const isPresentEnMilieu = item => itemFrequenceEnMilieu(item) > 0;
|
||||
let elements = await this.getElements(itemFrequenceEnMilieu, isPresentEnMilieu);
|
||||
return CompendiumTableHelpers.buildTable(elements, itemFrequenceEnMilieu);
|
||||
}
|
||||
|
||||
|
||||
async getElements(itemFrequence, filter) {
|
||||
let elements = [];
|
||||
for (let c of COMPENDIUMS_ENVIRONNEMENT) {
|
||||
const fromCompendium = await c.table.getContent(itemFrequence, filter);
|
||||
elements = elements.concat(fromCompendium);
|
||||
}
|
||||
return elements;
|
||||
}
|
||||
}
|
||||
|
||||
export class EnvironmentSheetHelper {
|
||||
|
||||
static defaultOptions(defaultOptions, type) {
|
||||
return mergeObject(defaultOptions, {
|
||||
classes: ["rdd", "sheet", "item"],
|
||||
template: `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`,
|
||||
width: 500,
|
||||
height: 600,
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getHeaderButtons(sheet, buttons) {
|
||||
buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => sheet.item.postItem() });
|
||||
return buttons;
|
||||
}
|
||||
|
||||
static setPosition(sheet, superPosition) {
|
||||
const position = superPosition;
|
||||
const sheetHeader = sheet.element.find(".sheet-header");
|
||||
const sheetBody = sheet.element.find(".sheet-body");
|
||||
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
|
||||
return position;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async getData(sheet) {
|
||||
const formData = duplicate(sheet.item);
|
||||
const milieux = await game.system.rdd.environnement.milieux();
|
||||
const milieuxDisponibles = milieux.filter(it => !sheet.item.system.environnement.find(e => e.milieu == it));
|
||||
mergeObject(formData, {
|
||||
title: formData.name,
|
||||
isGM: game.user.isGM,
|
||||
owner: sheet.actor?.isOwner,
|
||||
isOwned: sheet.actor ? true : false,
|
||||
actorId: sheet.actor?.id,
|
||||
editable: sheet.isEditable,
|
||||
cssClass: sheet.isEditable ? "editable" : "locked",
|
||||
milieux: milieuxDisponibles
|
||||
});
|
||||
return formData;
|
||||
}
|
||||
|
||||
static activateListeners(sheet, html) {
|
||||
if (!sheet.options.editable) return;
|
||||
html.find("a.milieu-add").click(event => EnvironmentSheetHelper.onAddMilieu(sheet, event));
|
||||
html.find("div.environnement-milieu a.milieu-delete").click(event => EnvironmentSheetHelper.onDeleteMilieu(sheet, event));
|
||||
html.find("div.environnement-milieu select.environnement-rarete").change(event => EnvironmentSheetHelper.onChange(sheet, event,
|
||||
(updated) => {
|
||||
const name = $(event.currentTarget).val();
|
||||
const rarete = Environnement.getRarete(name);
|
||||
updated.rarete = rarete.name;
|
||||
updated.frequence = Math.min(
|
||||
Math.max(rarete.min, updated.frequence ?? rarete.frequence),
|
||||
rarete.max);
|
||||
}));
|
||||
html.find("div.environnement-milieu input[name='environnement-frequence']").change(event => EnvironmentSheetHelper.onChange(sheet, event,
|
||||
(updated) => {
|
||||
updated.frequence = Number($(event.currentTarget).val())
|
||||
}));
|
||||
}
|
||||
|
||||
static async onAddMilieu(sheet, event) {
|
||||
const milieu = $("input.input-selection-milieu").val();
|
||||
if (!milieu) {
|
||||
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${sheet.item.name}`);
|
||||
return
|
||||
}
|
||||
const list = sheet.item.system.environnement;
|
||||
const exists = list.find(it => it.milieu == milieu);
|
||||
if (exists) {
|
||||
ui.notifications.warn(`${sheet.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`);
|
||||
return
|
||||
}
|
||||
const rarete = Environnement.getRarete();
|
||||
const newList = [...list, { milieu, rarete: rarete.name, frequence: rarete.frequence }].sort(Misc.ascending(it => it.milieu))
|
||||
await sheet.item.update({ 'system.environnement': newList })
|
||||
}
|
||||
|
||||
static async onDeleteMilieu(sheet, event) {
|
||||
const milieu = EnvironmentSheetHelper.$getEventMilieu(event);
|
||||
if (milieu) {
|
||||
const newList = sheet.item.system.environnement.filter(it => it.milieu != milieu)
|
||||
.sort(Misc.ascending(it => it.milieu));
|
||||
await sheet.item.update({ 'system.environnement': newList });
|
||||
}
|
||||
}
|
||||
|
||||
static async onChange(sheet, event, doMutation) {
|
||||
const list = sheet.item.system.environnement;
|
||||
const milieu = EnvironmentSheetHelper.$getEventMilieu(event);
|
||||
const updated = list.find(it => it.milieu == milieu);
|
||||
if (updated) {
|
||||
doMutation(updated);
|
||||
const newList = [...list.filter(it => it.milieu != milieu), updated]
|
||||
.sort(Misc.ascending(it => it.milieu));
|
||||
await sheet.item.update({ 'system.environnement': newList });
|
||||
}
|
||||
}
|
||||
|
||||
static $getEventMilieu(event) {
|
||||
return $(event.currentTarget)?.parents("div.environnement-milieu").data("milieu");
|
||||
}
|
||||
|
||||
static template(itemType) {
|
||||
/* -------------------------------------------- */
|
||||
return `systems/foundryvtt-reve-de-dragon/templates/item-${itemType}-sheet.html`;
|
||||
}
|
||||
|
||||
static title(item) {
|
||||
return Misc.typeName('Item', item.type) + ': ' + item.name;
|
||||
}
|
||||
|
||||
}
|
45
module/item-herbe-sheet.js
Normal file
45
module/item-herbe-sheet.js
Normal file
@ -0,0 +1,45 @@
|
||||
import { SYSTEM_RDD } from "./constants.js";
|
||||
import { EnvironmentSheetHelper as EnvironmentItemSheet } from "./environnement.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
const ITEM_TYPE = 'herbe';
|
||||
|
||||
export class RdDHerbeItemSheet extends ItemSheet {
|
||||
|
||||
static register() {
|
||||
Items.registerSheet(SYSTEM_RDD, RdDHerbeItemSheet, {
|
||||
label: Misc.typeName('Item', ITEM_TYPE),
|
||||
types: [ITEM_TYPE],
|
||||
makeDefault: true
|
||||
});
|
||||
}
|
||||
|
||||
static get defaultOptions() {
|
||||
return EnvironmentItemSheet.defaultOptions(super.defaultOptions, ITEM_TYPE);
|
||||
}
|
||||
|
||||
_getHeaderButtons() {
|
||||
return EnvironmentItemSheet.getHeaderButtons(this, super._getHeaderButtons());
|
||||
}
|
||||
|
||||
setPosition(options = {}) {
|
||||
return EnvironmentItemSheet.setPosition(this, super.setPosition(options));
|
||||
}
|
||||
|
||||
async getData() {
|
||||
return await EnvironmentItemSheet.getData(this);
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
EnvironmentItemSheet.activateListeners(this, html);
|
||||
}
|
||||
|
||||
get template() {
|
||||
return EnvironmentItemSheet.template(this.item.type);
|
||||
}
|
||||
|
||||
get title() {
|
||||
return EnvironmentItemSheet.title(this.item);
|
||||
}
|
||||
}
|
44
module/item-ingredient-sheet.js
Normal file
44
module/item-ingredient-sheet.js
Normal file
@ -0,0 +1,44 @@
|
||||
import { SYSTEM_RDD } from "./constants.js";
|
||||
import { EnvironmentSheetHelper } from "./environnement.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
const ITEM_TYPE = 'ingredient';
|
||||
export class RdDIngredientItemSheet extends ItemSheet {
|
||||
|
||||
static register() {
|
||||
Items.registerSheet(SYSTEM_RDD, RdDIngredientItemSheet, {
|
||||
label: Misc.typeName('Item', ITEM_TYPE),
|
||||
types: [ITEM_TYPE],
|
||||
makeDefault: true
|
||||
});
|
||||
}
|
||||
|
||||
static get defaultOptions() {
|
||||
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions, ITEM_TYPE);
|
||||
}
|
||||
|
||||
_getHeaderButtons() {
|
||||
return EnvironmentSheetHelper.getHeaderButtons(this, super._getHeaderButtons());
|
||||
}
|
||||
|
||||
setPosition(options = {}) {
|
||||
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
||||
}
|
||||
|
||||
async getData() {
|
||||
return await EnvironmentSheetHelper.getData(this);
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
EnvironmentSheetHelper.activateListeners(this, html);
|
||||
}
|
||||
|
||||
get template() {
|
||||
return EnvironmentSheetHelper.template(this.item.type);
|
||||
}
|
||||
|
||||
get title() {
|
||||
return EnvironmentSheetHelper.title(this.item);
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
||||
import { Environnement } from "./environnement.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
class Migration {
|
||||
get code() { return "sample"; }
|
||||
@ -179,6 +179,7 @@ class _10_2_5_ArmesTirLancer extends Migration {
|
||||
return Grammar.toLowerCaseNoAccent(it.system.competence);
|
||||
}
|
||||
}
|
||||
|
||||
class _10_2_10_DesirLancinant_IdeeFixe extends Migration {
|
||||
get code() { return "desir-lancinat-idee-fixe"; }
|
||||
get version() { return "10.2.10"; }
|
||||
@ -240,6 +241,24 @@ class _10_3_0_Inventaire extends Migration {
|
||||
}
|
||||
}
|
||||
|
||||
class _10_3_0_FrequenceEnvironnement extends Migration {
|
||||
get code() { return "migration-frequence-resources"; }
|
||||
get version() { return "10.3.0"; }
|
||||
|
||||
async migrate() {
|
||||
await this.applyItemsUpdates(items => items.filter(it => ['herbe', 'ingredient'].includes(it.type))
|
||||
.map(it => this._updatesFrequences(it)));
|
||||
}
|
||||
|
||||
_updatesFrequences(it) {
|
||||
return {
|
||||
_id: it.id,
|
||||
'system.rarete': undefined,
|
||||
'system.environnement': [{ milieu: it.system.milieu, rarete: it.system.rarete, frequence: Environnement.getFrequenceRarete(it.system.rarete, 'frequence') }]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Migrations {
|
||||
static getMigrations() {
|
||||
return [
|
||||
@ -249,7 +268,8 @@ export class Migrations {
|
||||
new _10_0_33_MigrationNomsDraconic(),
|
||||
new _10_2_5_ArmesTirLancer(),
|
||||
new _10_2_10_DesirLancinant_IdeeFixe(),
|
||||
new _10_3_0_Inventaire()
|
||||
new _10_3_0_Inventaire(),
|
||||
new _10_3_0_FrequenceEnvironnement()
|
||||
];
|
||||
}
|
||||
|
||||
@ -264,11 +284,9 @@ export class Migrations {
|
||||
}
|
||||
|
||||
migrate() {
|
||||
const currentVersion = game.settings.get(
|
||||
SYSTEM_RDD,
|
||||
"systemMigrationVersion"
|
||||
);
|
||||
if (isNewerVersion(game.system.version, currentVersion)) {
|
||||
const currentVersion = game.settings.get(SYSTEM_RDD,"systemMigrationVersion");
|
||||
//if (isNewerVersion(game.system.version, currentVersion)) {
|
||||
if (true) { /* comment previous and uncomment here to test before upgrade */
|
||||
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
|
||||
if (migrations.length > 0) {
|
||||
migrations.sort((a, b) =>
|
||||
|
@ -13,6 +13,7 @@ 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 { CompendiumTableHelpers } from "./settings/system-compendiums.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
|
||||
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
|
||||
@ -49,7 +50,9 @@ export class RdDCommands {
|
||||
<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`
|
||||
});
|
||||
|
||||
this.registerCommand({ path: ["/table", "milieu"], func: (content, msg, params) => this.tableMilieu(msg, params,'liste'), descr: "Affiche la table des trouvailles dans un milieu donné" });
|
||||
this.registerCommand({ path: ["/tirer", "milieu"], func: (content, msg, params) => this.tableMilieu(msg, params, 'chat'), descr: "Affiche la table des trouvailles dans un milieu donné" });
|
||||
|
||||
this.registerCommand({ path: ["/tirer", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('chat'), descr: "Tire une compétence au hasard" });
|
||||
this.registerCommand({ path: ["/tirer", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('chat'), descr: "Tire une Queue de Dragon" });
|
||||
this.registerCommand({ path: ["/tirer", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre('chat'), descr: "Tire une Ombre de Thanatos" });
|
||||
@ -363,6 +366,7 @@ export class RdDCommands {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async tableRencontres(msg, params) {
|
||||
if (params && params.length > 0) {
|
||||
const search = Misc.join(params, ' ');
|
||||
@ -370,11 +374,29 @@ export class RdDCommands {
|
||||
if (solvedTerrain == undefined) {
|
||||
return RdDCommands._chatAnswer(msg, 'Aucune TMR correspondant à ' + search);
|
||||
}
|
||||
return game.system.rdd.rencontresTMR.chatTable(solvedTerrain);
|
||||
return await game.system.rdd.rencontresTMR.chatTable(solvedTerrain);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async tableMilieu(msg, params, toChat) {
|
||||
if (params && params.length > 0) {
|
||||
const search = Misc.join(params, ' ');
|
||||
const searches = game.system.rdd.environnement.findEnvironnementsLike(search);
|
||||
if (searches.length == 0) {
|
||||
return RdDCommands._chatAnswer(msg, 'Aucun milieu correspondant à ' + search);
|
||||
}
|
||||
if (toChat == 'liste') {
|
||||
return await game.system.rdd.environnement.searchToChatMessage(search);
|
||||
}
|
||||
else {
|
||||
const row = await game.system.rdd.environnement.getRandom(search);
|
||||
await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
getCoutXpComp(msg, params) {
|
||||
if (params && (params.length == 1 || params.length == 2)) {
|
||||
|
@ -39,6 +39,9 @@ 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";
|
||||
import { RdDHerbeItemSheet } from "./item-herbe-sheet.js";
|
||||
import { Environnement } from "./environnement.js";
|
||||
import { RdDIngredientItemSheet } from "./item-ingredient-sheet.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
@ -194,11 +197,13 @@ Hooks.once("init", async function () {
|
||||
types: ["rencontre"],
|
||||
makeDefault: true
|
||||
});
|
||||
RdDHerbeItemSheet.register();
|
||||
RdDIngredientItemSheet.register();
|
||||
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
|
||||
types: [
|
||||
"competence", "competencecreature",
|
||||
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
|
||||
"objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition",
|
||||
"objet", "arme", "armure", "conteneur", "livre", "potion", "munition",
|
||||
"monnaie", "nourritureboisson", "gemme",
|
||||
"meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
|
||||
"nombreastral", "tache", "maladie", "poison", "possession",
|
||||
@ -224,6 +229,7 @@ Hooks.once("init", async function () {
|
||||
RdDHotbar.initDropbar();
|
||||
RdDPossession.init();
|
||||
TMRRencontres.init();
|
||||
Environnement.init();
|
||||
});
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||
import { CompendiumTable, CompendiumTableHelpers, SystemCompendiums } from "./settings/system-compendiums.js";
|
||||
|
||||
export class RdDRollTables {
|
||||
|
||||
@ -37,7 +37,7 @@ export class RdDRollTables {
|
||||
/* -------------------------------------------- */
|
||||
static async getCompetence(toChat = false) {
|
||||
if (toChat == 'liste') {
|
||||
return await SystemCompendiums.chatTableItems('competences', 'Item', 'competence', it => 1);
|
||||
return await RdDRollTables.listOrRoll('competences', 'Item', 'competence', toChat, it => 1);
|
||||
}
|
||||
else {
|
||||
return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat);
|
||||
@ -55,13 +55,15 @@ export class RdDRollTables {
|
||||
}
|
||||
|
||||
static async getDesirLancinant(toChat = false) {
|
||||
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', 'queue', toChat, it => it.system.frequence,
|
||||
it => it.system.categorie == 'lancinant' );
|
||||
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', 'queue', toChat,
|
||||
it => it.system.frequence,
|
||||
it => it.system.categorie == 'lancinant');
|
||||
}
|
||||
|
||||
static async getIdeeFixe(toChat = false) {
|
||||
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', 'queue', toChat, it => it.system.frequence,
|
||||
it => it.system.categorie == 'ideefixe' );
|
||||
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', 'queue', toChat,
|
||||
it => it.system.frequence,
|
||||
it => it.system.categorie == 'ideefixe');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -86,10 +88,15 @@ export class RdDRollTables {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async listOrRoll(compendium, type, subType, toChat, itemFrequence = it => it.system.frequence, filter = it => true) {
|
||||
const table = new CompendiumTable(compendium, type, subType);
|
||||
if (toChat == 'liste') {
|
||||
return await SystemCompendiums.chatTableItems(compendium, type, subType, itemFrequence, filter);
|
||||
return await table.toChatMessage(itemFrequence, filter);
|
||||
}
|
||||
return await SystemCompendiums.getRandom(compendium, type, subType, toChat, itemFrequence, filter);
|
||||
const row = await table.getRandom(itemFrequence, filter);
|
||||
if (row) {
|
||||
await CompendiumTableHelpers.tableRowToChatMessage(row, type);
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -15,6 +15,7 @@ import { RdDNameGen } from "./rdd-namegen.js";
|
||||
import { RdDConfirm } from "./rdd-confirm.js";
|
||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { Environnement } from "./environnement.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// This table starts at 0 -> niveau -10
|
||||
@ -169,7 +170,11 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.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/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/header-item.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html',
|
||||
@ -326,7 +331,8 @@ export class RdDUtility {
|
||||
Handlebars.registerHelper('linkCompendium', (compendium, id, name) => `@Compendium[${compendium}.${id}]{${name}}`);
|
||||
Handlebars.registerHelper('uniteQuantite', (type) => RdDItem.getUniteQuantite(type));
|
||||
Handlebars.registerHelper('isEquipementFieldEditable', (type, field) => RdDItem.isEquipementFieldEditable(type, field));
|
||||
|
||||
Handlebars.registerHelper('getFrequenceRarete', (rarete, field) => Environnement.getFrequenceRarete(rarete, field));
|
||||
Handlebars.registerHelper('either', (a, b) => a ?? b);
|
||||
return loadTemplates(templatePaths);
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,13 @@ const CONFIGURABLE_COMPENDIUMS = {
|
||||
'rencontres': { label: "Rencontres dans les TMR", type: "Item" },
|
||||
'tetes-de-dragon-pour-haut-revants': { label: "Têtes de dragons (haut-rêvant)", type: "Item" },
|
||||
'tetes-de-dragon-pour-tous-personnages': { label: "Têtes de dragons (tous)", type: "Item" },
|
||||
'botanique': { label: "Herbes & plantes", type: "Item" },
|
||||
'equipement': { label: "Equipements", type: "Item" },
|
||||
}
|
||||
|
||||
/**
|
||||
* ======= Gestion des accès aux compendiums systèmes (ou surchargés) =======
|
||||
*/
|
||||
export class SystemCompendiums extends FormApplication {
|
||||
static init() {
|
||||
Object.keys(CONFIGURABLE_COMPENDIUMS).forEach(compendium => {
|
||||
@ -50,7 +55,7 @@ export class SystemCompendiums extends FormApplication {
|
||||
return game.packs.get(SystemCompendiums.getCompendium(compendium));
|
||||
}
|
||||
|
||||
static async getContent(compendium, docType) {
|
||||
static async getPackContent(compendium, docType) {
|
||||
const pack = SystemCompendiums.getPack(compendium);
|
||||
if (pack.metadata.type == docType) {
|
||||
return await pack.getDocuments();
|
||||
@ -83,35 +88,17 @@ export class SystemCompendiums extends FormApplication {
|
||||
}
|
||||
|
||||
static async getItems(compendium, itemType = undefined) {
|
||||
const items = await SystemCompendiums.getContent(compendium, 'Item');
|
||||
const items = await SystemCompendiums.getPackContent(compendium, 'Item');
|
||||
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)
|
||||
static async getContent(compendium, type, filter, itemFrequence, sorting) {
|
||||
let elements = await SystemCompendiums.getPackContent(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);
|
||||
return elements;
|
||||
}
|
||||
|
||||
static async getDefaultItems(compendium) {
|
||||
@ -180,48 +167,69 @@ export class SystemCompendiums extends FormApplication {
|
||||
}
|
||||
}
|
||||
|
||||
export class SystemCompendiumTable {
|
||||
/**
|
||||
* ======= Gestion de jets dans une table correspondant à un compendium =======
|
||||
*/
|
||||
export class CompendiumTable {
|
||||
|
||||
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
|
||||
this.sorting = sorting ?? Misc.ascending(it => it.name);
|
||||
}
|
||||
|
||||
typeName() {
|
||||
return Misc.typeName(this.type, this.subType);
|
||||
}
|
||||
applyType(filter) {
|
||||
return it => it.type == this.subType && filter(it);
|
||||
async getContent(itemFrequence = it => it.system.frequence, filter = it => true) {
|
||||
return await SystemCompendiums.getContent(this.compendium,
|
||||
this.type,
|
||||
it => this.subType == it.type && filter(it),
|
||||
itemFrequence,
|
||||
this.sorting);
|
||||
}
|
||||
|
||||
async getRandom(toChat = true, itemFrequence = it => it.system.frequence, filter = it => true, forcedRoll = undefined) {
|
||||
const table = await this.$buildTable(itemFrequence, filter);
|
||||
async buildTable(itemFrequence = it => it.system.frequence, filter = it => true) {
|
||||
const elements = await this.getContent(filter, itemFrequence);
|
||||
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
||||
}
|
||||
|
||||
async getRandom(itemFrequence = it => it.system.frequence, filter = it => true, forcedRoll = undefined) {
|
||||
const table = await this.buildTable(itemFrequence, filter);
|
||||
return await CompendiumTableHelpers.getRandom(table, this.type, this.subType, forcedRoll, SystemCompendiums.getCompendium(compendium));
|
||||
}
|
||||
|
||||
async toChatMessage(itemFrequence = it => it.system.frequence, filter = it => true, typeName = undefined) {
|
||||
const table = await this.buildTable(itemFrequence, filter);
|
||||
await CompendiumTableHelpers.tableToChatMessage(table, this.type, this.subType, typeName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ======= Gestion de tables correspondant à un compendium =======
|
||||
*/
|
||||
export class CompendiumTableHelpers {
|
||||
|
||||
static buildTable(elements, itemFrequence) {
|
||||
let max = 0;
|
||||
const total = elements.map(it => itemFrequence(it)).reduce(Misc.sum(), 0);
|
||||
return elements.map(it => {
|
||||
const frequence = itemFrequence(it);
|
||||
let row = { document: it, frequence: frequence, min: max + 1, max: max + frequence, total: total };
|
||||
max += frequence;
|
||||
return row;
|
||||
});
|
||||
}
|
||||
|
||||
static async getRandom(table, type, subType, forcedRoll = undefined, localisation = undefined) {
|
||||
if (table.length == 0) {
|
||||
ui.notifications.warn(`Aucun ${this.typeName()} dans ${this.sourceCompendium}`);
|
||||
ui.notifications.warn(`Aucun ${Misc.typeName(type, subType)} trouvé dans ${localisation ?? ' les compendiums'}`);
|
||||
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);
|
||||
return await CompendiumTableHelpers.selectRow(table, forcedRoll);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async $selectRow(table, forcedRoll = undefined) {
|
||||
static async selectRow(table, forcedRoll = undefined) {
|
||||
if (table.length == 0) {
|
||||
return undefined
|
||||
}
|
||||
@ -238,14 +246,16 @@ export class SystemCompendiumTable {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async $chatRolledResult(row) {
|
||||
static async tableRowToChatMessage(row, type = 'Item') {
|
||||
if (!row) {
|
||||
return;
|
||||
}
|
||||
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,
|
||||
document: row.document,
|
||||
percentages,
|
||||
typeName: this.typeName(),
|
||||
sourceCompendium: this.sourceCompendium,
|
||||
typeName: Misc.typeName(type, row.document.type),
|
||||
isGM: game.user.isGM,
|
||||
});
|
||||
const messageData = {
|
||||
@ -260,11 +270,10 @@ export class SystemCompendiumTable {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async $chatSystemCompendiumTable(table, typeName) {
|
||||
static async tableToChatMessage(table, type, subType, typeName = undefined) {
|
||||
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,
|
||||
img: RdDItem.getDefaultImg(subType),
|
||||
typeName: typeName ?? Misc.typeName(type, subType),
|
||||
table,
|
||||
isGM: game.user.isGM,
|
||||
});
|
||||
@ -275,5 +284,4 @@ export class SystemCompendiumTable {
|
||||
}, { rollMode: "gmroll" });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { SystemCompendiums, SystemCompendiumTable } from "./settings/system-compendiums.js";
|
||||
import { SystemCompendiums, CompendiumTable, CompendiumTableHelpers } from "./settings/system-compendiums.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ export class TMRRencontres {
|
||||
}
|
||||
|
||||
constructor(){
|
||||
this.table = new SystemCompendiumTable('rencontres', 'Item', 'rencontre', Misc.ascending(it => it.system.ordreTri));
|
||||
this.table = new CompendiumTable('rencontres', 'Item', 'rencontre', Misc.ascending(it => it.system.ordreTri));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -36,9 +36,12 @@ export class TMRRencontres {
|
||||
const codeTerrain = Grammar.toLowerCaseNoAccent(terrain)
|
||||
const filtreMauvaise = codeTerrain == 'mauvaise' ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
|
||||
const frequence = it => it.system.frequence[codeTerrain];
|
||||
const random = await this.table.getRandom(true, frequence, filtreMauvaise, forcedRoll);
|
||||
const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll);
|
||||
if (row) {
|
||||
await CompendiumTableHelpers.tableRowToChatMessage(row);
|
||||
}
|
||||
|
||||
return random?.document;
|
||||
return row?.document;
|
||||
}
|
||||
|
||||
async chatTable(terrain) {
|
||||
@ -47,9 +50,9 @@ export class TMRRencontres {
|
||||
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
|
||||
return await this.table.toChatMessage(frequence, filtreMauvaise, typeName);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async createRencontre(rencontre, tmr = undefined) {
|
||||
return rencontre.clone({
|
||||
@ -95,7 +98,7 @@ export class TMRRencontres {
|
||||
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);
|
||||
const row = await this.table.getRandom(frequence, filtreMauvaise);
|
||||
if (row) {
|
||||
row.document = this.createRencontre(row.document, tmr);
|
||||
await this.$chatRolledRencontre(row, tmr);
|
||||
|
@ -1738,7 +1738,41 @@ display: inline-flex;
|
||||
/* Change color of dropdown links on hover */
|
||||
.button-dropdown-content a:hover {background-color: #ddd;}
|
||||
|
||||
/* ======== autocomplete ======= */
|
||||
.autocomplete {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.autocomplete-items {
|
||||
position: absolute;
|
||||
border: 1px solid var(--color-border-dark);
|
||||
border-bottom: none;
|
||||
border-top: none;
|
||||
z-index: 99;
|
||||
/*position the autocomplete items to be the same width as the container:*/
|
||||
top: 100%;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.autocomplete-items div {
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
background-color: #fff;
|
||||
border-bottom: 1px solid #d4d4d4;
|
||||
}
|
||||
|
||||
/*when hovering an item:*/
|
||||
.autocomplete-items div:hover {
|
||||
background-color: #e9e9e9;
|
||||
}
|
||||
|
||||
/*when navigating through the items using the arrow keys:*/
|
||||
.autocomplete-active {
|
||||
background-color: DodgerBlue !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
/*************************************************************/
|
||||
#pause
|
||||
|
@ -591,6 +591,10 @@
|
||||
"quantite": 1,
|
||||
"qualite": 0,
|
||||
"cout": 0
|
||||
},
|
||||
"environnement": {
|
||||
"milieu": "",
|
||||
"environnement": []
|
||||
}
|
||||
},
|
||||
"competence": {
|
||||
@ -704,19 +708,15 @@
|
||||
"exotisme": 0
|
||||
},
|
||||
"herbe": {
|
||||
"templates": [ "description", "inventaire" ],
|
||||
"templates": [ "description", "inventaire", "environnement"],
|
||||
"niveau": 0,
|
||||
"base": 0,
|
||||
"milieu": "",
|
||||
"rarete": "",
|
||||
"categorie": ""
|
||||
},
|
||||
"ingredient": {
|
||||
"templates": [ "description", "inventaire" ],
|
||||
"templates": [ "description", "inventaire", "environnement" ],
|
||||
"niveau": 0,
|
||||
"base": 0,
|
||||
"milieu": "",
|
||||
"rarete": "",
|
||||
"categorie": ""
|
||||
},
|
||||
"livre": {
|
||||
|
@ -1,11 +1,11 @@
|
||||
<img class="chat-icon" src="{{rencontre.img}}" alt="{{rencontre.name}}" />
|
||||
<h4>{{#if mauvaise}}Mauvaise rencontre{{else}}Rencontre{{/if}} en {{typeTmr-name tmr.type}}</h4>
|
||||
<div>{{sourceCompendium}}</div>
|
||||
<div>{{rencontre.pack}}</div>
|
||||
<div>Jet: {{roll.formula}} : {{roll.total}}{{percentages}}</div>
|
||||
<hr>
|
||||
<div>
|
||||
<p>{{rencontre.name}} {{rencontre.system.force}} ({{rencontre.system.formule}})</p>
|
||||
<p>{{linkCompendium sourceCompendium rencontre.id rencontre.name}}</p>
|
||||
<p>{{linkCompendium rencontre.pack rencontre.id rencontre.name}}</p>
|
||||
{{#if rencontre.system.description}}
|
||||
<div class="poesie-extrait">
|
||||
{{{rencontre.system.description}}}
|
||||
|
@ -1,10 +1,10 @@
|
||||
<h4>Tirage aléatoire: {{typeName}}</h4>
|
||||
<div>{{sourceCompendium}}</div>
|
||||
<div>{{document.pack}}</div>
|
||||
<div>Jet {{roll.formula}} : {{roll.total}}{{percentages}}</div>
|
||||
<hr>
|
||||
<div>
|
||||
<img class="chat-icon" src="{{document.img}}" alt="{{document.name}}" />
|
||||
<p>{{linkCompendium @root.sourceCompendium document.id document.name}}</p>
|
||||
<p>{{linkCompendium document.pack document.id document.name}}</p>
|
||||
{{#if document.system.description}}
|
||||
<div class="poesie-extrait">
|
||||
{{{document.system.description}}}
|
||||
|
@ -1,7 +1,11 @@
|
||||
<div>
|
||||
<img class="chat-icon" src="{{img}}" alt="{{typeName}}" />
|
||||
<h4>Table aléatoire: {{typeName}}</h4>
|
||||
<div>{{sourceCompendium}}</div>
|
||||
{{#with (lookup table 0) as |row|}}
|
||||
<div>
|
||||
{{row.document.pack}}
|
||||
</div>
|
||||
{{/with}}
|
||||
<br>
|
||||
</div>
|
||||
<div>
|
||||
@ -9,7 +13,7 @@
|
||||
{{#each table as |row|}}
|
||||
<li class="select-target item list-item" >
|
||||
<span>{{row.min}}{{#unless (eq row.min row.max)}}-{{row.max}}{{/unless}} : </span>
|
||||
<span>{{linkCompendium @root.sourceCompendium row.document.id row.document.name}}</span>
|
||||
<span>{{linkCompendium row.document.pack row.document.id row.document.name}}</span>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
@ -1,4 +1,3 @@
|
||||
<option value=""></option>
|
||||
<option value="Commune">Commune</option>
|
||||
<option value="Frequente">Fréquente</option>
|
||||
<option value="Rare">Rare</option>
|
||||
|
@ -11,38 +11,31 @@
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{{!-- Sheet Body --}}
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item" data-tab="informations">Informations</a>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html"}}
|
||||
</nav>
|
||||
|
||||
<section class="sheet-body">
|
||||
<div class="flexcol">
|
||||
<div class="form-group">
|
||||
<label>Niveau (si applicable)</label>
|
||||
<input class="attribute-value" type="text" name="system.niveau" value="{{system.niveau}}" data-dtype="Number" />
|
||||
<div class="tab items" data-group="primary" data-tab="informations">
|
||||
<div class="flexcol">
|
||||
<div class="form-group">
|
||||
<label>Niveau (si applicable)</label>
|
||||
<input class="attribute-value" type="text" name="system.niveau" value="{{system.niveau}}" data-dtype="Number" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Catégorie</label>
|
||||
<select name="system.categorie" class="categorie" data-dtype="String">
|
||||
{{#select system.categorie}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html"}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html"}}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Milieu</label>
|
||||
<input class="attribute-value" type="text" name="system.milieu" value="{{system.milieu}}" data-dtype="String" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Fréquence</label>
|
||||
<select name="system.rarete" class="rarete" data-dtype="String">
|
||||
{{#select system.rarete}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Catégorie</label>
|
||||
<select name="system.categorie" class="categorie" data-dtype="String">
|
||||
{{#select system.categorie}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html"}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html"}}
|
||||
|
||||
</div>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html"}}
|
||||
</section>
|
||||
|
||||
</form>
|
@ -1,34 +1,28 @@
|
||||
<form class="{{cssClass}}" autocomplete="off">
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/header-item.html"}}
|
||||
|
||||
{{!-- Sheet Body --}}
|
||||
<section class="sheet-body">
|
||||
<div class="form-group">
|
||||
<label>Niveau (si applicable) </label>
|
||||
<input class="attribute-value" type="text" name="system.niveau" value="{{system.niveau}}" data-dtype="Number" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Milieu</label>
|
||||
<input class="attribute-value" type="text" name="system.milieu" value="{{system.milieu}}" data-dtype="String" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Fréquence</label>
|
||||
<select name="system.rarete" class="rarete" data-dtype="String">
|
||||
{{#select system.rarete}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Catégorie</label>
|
||||
<select name="system.categorie" class="categorie" data-dtype="String">
|
||||
{{#select system.categorie}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html"}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item" data-tab="informations">Informations</a>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html"}}
|
||||
</nav>
|
||||
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html"}}
|
||||
<section class="sheet-body">
|
||||
<div class="tab items" data-group="primary" data-tab="informations">
|
||||
<div class="form-group">
|
||||
<label>Niveau (si applicable) </label>
|
||||
<input class="attribute-value" type="text" name="system.niveau" value="{{system.niveau}}" data-dtype="Number" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Catégorie</label>
|
||||
<select name="system.categorie" class="categorie" data-dtype="String">
|
||||
{{#select system.categorie}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html"}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html"}}
|
||||
</div>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html"}}
|
||||
</section>
|
||||
</form>
|
@ -17,6 +17,7 @@
|
||||
<label>Fréquence</label>
|
||||
<select name="system.rarete" class="rarete" data-dtype="String">
|
||||
{{#select system.rarete}}
|
||||
<option value=""></option>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}}
|
||||
{{/select}}
|
||||
</select>
|
||||
|
36
templates/item/partial-environnement.html
Normal file
36
templates/item/partial-environnement.html
Normal file
@ -0,0 +1,36 @@
|
||||
{{>'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs'}}
|
||||
|
||||
<div class="tab items" data-group="primary" data-tab="environnement">
|
||||
<div class="form-group">
|
||||
<label>Description du milieu</label>
|
||||
<input class="attribute-value" type="text" name="system.milieu" value="{{system.milieu}}" data-dtype="String" />
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<label>Ajouter un fréquence</label>
|
||||
<div class="flexrow">
|
||||
<div class="autocomplete">
|
||||
<input type="text" class="input-selection-milieu" placeholder="Milieu" data-dtype="String"/>
|
||||
</div>
|
||||
{{>'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs' proposals=milieux className='input-selection-milieu'}}
|
||||
<a class="milieu-add"><i class="fas fa-plus-circle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
{{#each system.environnement as |env|}}
|
||||
<div class="form-group environnement-milieu" data-milieu="{{env.milieu}}">
|
||||
<label>
|
||||
{{env.milieu}}
|
||||
<a class="milieu-delete" title="Supprimer {{env.milieu}}"><i class="fas fa-trash"></i></a>
|
||||
</label>
|
||||
<div class="flexrow">
|
||||
<select class="environnement-rarete" class="flex-shrink" data-dtype="String">
|
||||
{{#select env.rarete}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}}
|
||||
{{/select}}
|
||||
</select>
|
||||
{{rangePicker name="environnement-frequence" value=env.frequence min=(getFrequenceRarete env.rarete 'min') max=(getFrequenceRarete env.rarete 'max') step=1}}
|
||||
<label>[{{getFrequenceRarete env.rarete 'min'}}-{{getFrequenceRarete env.rarete 'max'}}]</label>
|
||||
</div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
1
templates/item/partial-tab-environnement.html
Normal file
1
templates/item/partial-tab-environnement.html
Normal file
@ -0,0 +1 @@
|
||||
<a class="item" data-tab="environnement">Environnement</a>
|
96
templates/scripts/autocomplete-script.hbs
Normal file
96
templates/scripts/autocomplete-script.hbs
Normal file
@ -0,0 +1,96 @@
|
||||
<script>
|
||||
function autocomplete(input, proposals) {
|
||||
var currentFocus;
|
||||
|
||||
function createCompletionContainer(id) {
|
||||
let div = document.createElement("DIV");
|
||||
div.setAttribute("id", id + "autocomplete-list");
|
||||
div.setAttribute("class", "autocomplete-items");
|
||||
return div;
|
||||
}
|
||||
|
||||
function createCompletionProposal(inputElement, incomplete, complete) {
|
||||
let div = document.createElement("DIV");
|
||||
/*make the matching letters bold:*/
|
||||
const start = complete.toUpperCase().indexOf(incomplete.toUpperCase());
|
||||
div.innerHTML = complete.substr(0, start)
|
||||
+ "<strong>" + complete.substr(start, incomplete.length) + "</strong>"
|
||||
+ complete.substr(start+incomplete.length)
|
||||
/*insert a input field that will hold the current array item's value:*/
|
||||
+ "<input type='hidden' value='" + complete + "'>";
|
||||
/*execute a function when someone clicks on the item value (DIV element):*/
|
||||
div.addEventListener("click", function(e) {
|
||||
/*insert the value for the autocomplete text field:*/
|
||||
inputElement.value = this.getElementsByTagName("input")[0].value;
|
||||
/*close the list of autocompleted values, or any other open lists of autocompleted values:*/
|
||||
closeAllOpenedLists();
|
||||
});
|
||||
return div;
|
||||
}
|
||||
|
||||
function addActive(x) {
|
||||
if (!x) return false;
|
||||
removeActive(x);
|
||||
if (currentFocus >= x.length) currentFocus = 0;
|
||||
if (currentFocus < 0) currentFocus = (x.length - 1);
|
||||
x[currentFocus].classList.add("autocomplete-active");
|
||||
}
|
||||
|
||||
function removeActive(x) {
|
||||
for (var i = 0; i < x.length; i++) {
|
||||
x[i].classList.remove("autocomplete-active");
|
||||
}
|
||||
}
|
||||
|
||||
function closeAllOpenedLists(elmnt) {
|
||||
/*close all autocomplete lists in the document, except the one passed as an argument:*/
|
||||
var x = document.getElementsByClassName("autocomplete-items");
|
||||
for (var i = 0; i < x.length; i++) {
|
||||
if (elmnt != x[i] && elmnt != input) {
|
||||
x[i].parentNode.removeChild(x[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*execute a function when someone writes in the text field:*/
|
||||
input.addEventListener("input", function(e) {
|
||||
const incomplete = this.value;
|
||||
closeAllOpenedLists();
|
||||
if (!incomplete) { return false; }
|
||||
|
||||
currentFocus = -1;
|
||||
const container = createCompletionContainer(this.id)
|
||||
this.parentNode.appendChild(container);
|
||||
/*for each item in the array...*/
|
||||
for (let i = 0; i < proposals.length; i++) {
|
||||
/*check if the item starts with the same letters as the text field value:*/
|
||||
if (proposals[i].toUpperCase().includes(incomplete.toUpperCase())) {
|
||||
/*create a DIV element for each matching element:*/
|
||||
container.appendChild(createCompletionProposal(input, incomplete, proposals[i]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*execute a function presses a key on the keyboard:*/
|
||||
input.addEventListener("keydown", function(e) {
|
||||
var container = document.getElementById(this.id + "autocomplete-list")?.getElementsByTagName("div");
|
||||
if (e.keyCode == 40) {
|
||||
currentFocus++;
|
||||
addActive(container);
|
||||
} else if (e.keyCode == 38) { //up
|
||||
currentFocus--;
|
||||
addActive(container);
|
||||
} else if (e.keyCode == 13) {
|
||||
e.preventDefault();
|
||||
if (currentFocus > -1 && container) {
|
||||
container[currentFocus].click();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/*execute a function when someone clicks in the document:*/
|
||||
document.addEventListener("click", function (e) {
|
||||
closeAllOpenedLists(e.target);
|
||||
});
|
||||
}
|
||||
</script>
|
5
templates/scripts/autocomplete.hbs
Normal file
5
templates/scripts/autocomplete.hbs
Normal file
@ -0,0 +1,5 @@
|
||||
<script>
|
||||
var proposals = [ {{#each proposals as |val|}}"{{val}}",{{/each}} ];
|
||||
Array.from(document.getElementsByClassName('{{className}}'))
|
||||
.forEach(element => autocomplete(element, proposals))
|
||||
</script>
|
Loading…
Reference in New Issue
Block a user