diff --git a/module/actor/export-scriptarium/export-scriptarium.js b/module/actor/export-scriptarium/export-scriptarium.js
new file mode 100644
index 00000000..5cf6b165
--- /dev/null
+++ b/module/actor/export-scriptarium/export-scriptarium.js
@@ -0,0 +1,73 @@
+import { LOG_HEAD } from "../../constants.js"
+import { ACTOR_TYPES } from "../../item.js"
+import { Misc } from "../../misc.js"
+import { EXPORT_CSV_SCRIPTARIUM, OptionsAvancees } from "../../settings/options-avancees.js"
+import { Mapping } from "./mapping.js"
+
+const IMG_SCRIPTARIUM = ''
+
+export class ExportScriptarium {
+
+ static init() {
+ ExportScriptarium.INSTANCE = new ExportScriptarium()
+ }
+
+ constructor() {
+ this.mapping = Mapping.getMapping()
+ Hooks.on("getActorDirectoryFolderContext", (actorDirectory, menus) => { ExportScriptarium.INSTANCE.onActorDirectoryMenu(actorDirectory, menus) })
+ Hooks.on("getActorDirectoryEntryContext", (actorDirectory, menus) => { ExportScriptarium.INSTANCE.onActorDirectoryMenu(actorDirectory, menus) })
+ }
+
+ onActorDirectoryMenu(actorDirectory, menus) {
+ menus.push({
+ name: 'Export Personnages',
+ icon: IMG_SCRIPTARIUM,
+ condition: (target) => game.user.isGM &&
+ OptionsAvancees.isUsing(EXPORT_CSV_SCRIPTARIUM) &&
+ this.$getActors(actorDirectory, target).length > 0,
+ callback: target => this.exportActors(this.$getActors(actorDirectory, target))
+ })
+ }
+
+ $getActors(actorDirectory, target) {
+ const li = target.closest(".directory-item")
+ const folderId = li.data("folderId")
+ const actorId = li.data("documentId")
+ const actors = actorId
+ ? [game.actors.get(actorId)]
+ : folderId
+ ? actorDirectory.folders.find(it => it.id == folderId).contents
+ : []
+ return actors.filter(it => it.type == ACTOR_TYPES.personnage)
+ }
+
+ exportActors(actors) {
+ console.log(LOG_HEAD + 'exportActors', actors)
+ const header = Misc.join(this.getHeaderLine(), ';')
+ console.log(header)
+ actors.forEach(actor => {
+ const actorLine = Misc.join(this.getActorLine(actor), ';')
+ console.log(actorLine)
+ })
+ }
+
+ getHeaderLine() {
+ return this.mapping.map(it => it.column)
+ }
+
+ getActorLine(actor) {
+ const context = Mapping.prepareContext(actor)
+ return this.mapping.map(it => it.getter(actor, context))
+ .map(it => this.$escapeQuotes(it))
+ .map(it => it.replaceAll("\n", " ").replaceAll("\r", ""))
+ }
+
+ $escapeQuotes(it) {
+ it = '' + it
+ if (it.includes('"') || it.includes(';')) {
+ return `"${it.replaceAll('"', '\\"')}"`
+ }
+ return it
+ }
+
+}
diff --git a/module/actor/export-scriptarium/mapping.js b/module/actor/export-scriptarium/mapping.js
new file mode 100644
index 00000000..567645d8
--- /dev/null
+++ b/module/actor/export-scriptarium/mapping.js
@@ -0,0 +1,303 @@
+import { Grammar } from "../../grammar.js"
+import { RdDItemArme } from "../../item-arme.js"
+import { RdDItemCompetence } from "../../item-competence.js"
+import { RdDItemSort } from "../../item-sort.js"
+import { ITEM_TYPES } from "../../item.js"
+import { Misc } from "../../misc.js"
+import { RdDTimestamp } from "../../time/rdd-timestamp.js"
+import { TMRConstants } from "../../tmr-constants.js"
+import { TMRUtility } from "../../tmr-utility.js"
+
+const CATEGORIES_COMPETENCES = [
+ "generale",
+ "particuliere",
+ "specialisee",
+ "connaissance",
+]
+const CATEGORIES_DRACONIC = [
+ "draconic",
+]
+
+const CATEGORIES_COMBAT = [
+ "melee",
+ "tir",
+ "lancer"
+]
+
+const NIVEAU_BASE = {
+ "generale": -4,
+ "particuliere": -8,
+ "specialisee": -11,
+ "connaissance": -11,
+ "draconic": -11,
+ "melee": -6,
+ "tir": -8,
+ "lancer": -8,
+}
+
+class ColumnMappingFactory {
+ static createMappingArme(part, i) {
+ return { column: `arme-${part}-${i}`, getter: (actor, context) => Mapping.getArme(actor, context, part, i) }
+ }
+
+ static createMappingSort(part, i) {
+ return { column: `sort-${part}-${i}`, getter: (actor, context) => Mapping.getSort(actor, context, part, i) }
+ }
+}
+
+const NB_ARMES = 10
+const NB_SORTS = 20
+const TABLEAU_ARMES = [...Array(NB_ARMES).keys()]
+const TABLEAU_SORTS = [...Array(NB_SORTS).keys()]
+
+const MAPPING_BASE = [
+ { column: "ID", getter: (actor, context) => actor.id },
+ { column: "name", getter: (actor, context) => actor.name },
+ // { column: "biographie", getter: (actor, context) => actor.system.biographie },
+ { column: "taille", getter: (actor, context) => actor.system.carac.taille.value },
+ { column: "apparence", getter: (actor, context) => actor.system.carac.apparence.value },
+ { column: "constitution", getter: (actor, context) => actor.system.carac.constitution.value },
+ { column: "force", getter: (actor, context) => actor.system.carac.force.value },
+ { column: "agilite", getter: (actor, context) => actor.system.carac.agilite.value },
+ { column: "dexterite", getter: (actor, context) => actor.system.carac.dexterite.value },
+ { column: "vue", getter: (actor, context) => actor.system.carac.vue.value },
+ { column: "ouie", getter: (actor, context) => actor.system.carac.ouie.value },
+ { column: "odoratgout", getter: (actor, context) => actor.system.carac.odoratgout.value },
+ { column: "volonte", getter: (actor, context) => actor.system.carac.volonte.value },
+ { column: "intellect", getter: (actor, context) => actor.system.carac.intellect.value },
+ { column: "empathie", getter: (actor, context) => actor.system.carac.empathie.value },
+ { column: "reve", getter: (actor, context) => actor.system.carac.reve.value },
+ { column: "chance", getter: (actor, context) => actor.system.carac.chance.value },
+ { column: "melee", getter: (actor, context) => actor.system.carac.melee.value },
+ { column: "tir", getter: (actor, context) => actor.system.carac.tir.value },
+ { column: "lancer", getter: (actor, context) => actor.system.carac.lancer.value },
+ { column: "derobee", getter: (actor, context) => actor.system.carac.derobee.value },
+ { column: "vie", getter: (actor, context) => actor.system.sante.vie.max },
+ { column: "plusdom", getter: (actor, context) => actor.system.attributs.plusdom.value },
+ { column: "protectionnaturelle", getter: (actor, context) => actor.system.attributs.protection.value },
+ { column: "endurance", getter: (actor, context) => actor.system.sante.endurance.max },
+ { column: "description", getter: (actor, context) => Mapping.getDescription(actor) },
+ { column: "armure", getter: (actor, context) => Mapping.getArmure(actor, context) },
+ { column: "protection", getter: (actor, context) => Mapping.getProtectionArmure(actor, context) },
+ { column: "malus-armure", getter: (actor, context) => Mapping.getMalusArmure(actor, context) },
+ { column: "esquive", getter: (actor, context) => Mapping.getEsquive(actor, context) },
+ { column: "esquive-niv", getter: (actor, context) => Mapping.getEsquiveNiveau(context) },
+ { column: "competences", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_COMPETENCES) },
+ { column: "draconic", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_DRACONIC) },
+]
+
+const MAPPING_ARMES = TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('name', i))
+ .concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('niveau', i)))
+ .concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('init', i)))
+ .concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('dom', i)))
+const MAPPING_SORTS = TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('voie', i))
+ .concat(TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('description', i)))
+ .concat(TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('bonus', i)))
+const MAPPING = MAPPING_BASE
+ .concat(MAPPING_ARMES)
+ .concat(MAPPING_SORTS)
+
+export class Mapping {
+
+ static getMapping() {
+ return MAPPING
+ }
+
+ static prepareContext(actor) {
+ return {
+ armes: Mapping.prepareArmes(actor),
+ armure: Mapping.prepareArmure(actor),
+ esquive: Mapping.prepareEsquive(actor),
+ sorts: Mapping.prepareSorts(actor)
+ }
+ }
+
+ static prepareArmes(actor) {
+ return actor.items.filter(it => it.type == ITEM_TYPES.arme)
+ .map(arme => {
+ const compToUse = RdDItemArme.getCompetenceArme(arme, 'competence');
+ const comp = actor.getCompetence(compToUse);
+ const bonusDom = Mapping.calculBonusDom(comp, actor)
+ return {
+ name: arme.name,
+ niveau: comp.system.niveau,
+ init: Mapping.calculBaseInit(actor, comp.system.categorie) + comp.system.niveau,
+ dom: Number(arme.system.dommages) + bonusDom
+ };
+ });
+ }
+
+ static calculBonusDom(comp, actor) {
+ // TODO: reuse dmg calc?
+ const appliesBonusDom = ['melee', 'lancer'].includes(comp.system.categorie)
+ return appliesBonusDom ? Number(actor.system.attributs.plusdom.value) : 0
+ }
+
+ static calculBaseInit(actor, categorie) {
+ // TODO: reuse init calc?
+ const mapping = MAPPING_BASE.find(it => it.column == categorie)
+ if (mapping) {
+ switch (categorie) {
+ case 'melee':
+ case 'tir':
+ case 'lancer':
+ const caracteristique = Number(actor.system.carac[categorie].value)
+ return Math.floor(caracteristique / 2)
+ }
+ }
+ return 0
+ }
+
+ static prepareArmure(actor) {
+ const armures = actor.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe)
+ if (armures.length > 1) {
+ console.warn(`${actor.name} a équipé ${armures.length} armures, seule la première sera considérée`)
+ }
+ if (armures.length > 0) {
+ const armure = armures[0]
+ return {
+ name: armure.name,
+ protection: armure.system.protection,
+ malus: armure.system.malus ?? 0
+ }
+ }
+ return {
+ name: '',
+ protection: actor.system.attributs.protection.value,
+ malus: 0
+ }
+ }
+
+ static prepareEsquive(actor) {
+ const esquives = actor.getCompetences("Esquive")
+ if (esquives.length > 0) {
+ const esquive = esquives[0]
+ return {
+ name: esquive.name,
+ niveau: esquive.system.niveau
+ }
+ }
+ return undefined
+ }
+
+ static prepareSorts(actor) {
+ return actor.itemTypes[ITEM_TYPES.sort].map(it => {
+ return {
+ voie: it.system.voie,
+ description: Mapping.descriptionSort(it),
+ bonus: Mapping.bonusCase(it)
+ }
+ })
+ }
+
+ static descriptionSort(sort) {
+ const ptSeuil = Array(sort.system.coutseuil).map(it => '*')
+ const caseTMR = sort.system.caseTMRspeciale.length > 0 ? sort.system.caseTMRspeciale : sort.system.caseTMR
+ return `${sort.name}${ptSeuil} (${caseTMR}) R${sort.system.difficulte} r${sort.system.ptreve}`
+ }
+
+ static bonusCase(sort) {
+ const list = RdDItemSort.buildBonusCaseList(sort.system.bonuscase, false).sort(Misc.descending(it => it.bonus))
+ if (list.length > 0) {
+ const bonus = list[0]
+ return `+${bonus.bonus}% en ${bonus.case}`
+ }
+ }
+
+ static getDescription(actor) {
+ const sexe = actor.system.sexe
+ const sexeFeminin = sexe.length > 0 && sexe.charAt(0).toLowerCase() == 'f' ? 'Née' : 'Né'
+ const race = ['', 'humain'].includes(Grammar.toLowerCaseNoAccent(actor.system.race)) ? '' : (actor.system.race + ' ')
+ const heure = actor.system.heure
+ const hn = `${sexeFeminin} à l'heure ${RdDTimestamp.definition(heure).avecArticle}`
+ const age = actor.system.age ? `${actor.system.age} ans` : undefined
+ const taille = actor.system.taille
+ const poids = actor.system.poids
+ const cheveux = actor.system.cheveux ? `cheveux ${actor.system.cheveux}` : undefined
+ const yeux = actor.system.yeux ? `yeux ${actor.system.yeux}` : undefined
+ const beaute = actor.system.beaute ? `Beauté ${actor.system.beaute}` : undefined
+ const list = [race, hn, age, taille, poids, cheveux, yeux, beaute]
+ return Misc.join(list.filter(it => it), ', ')
+ }
+
+ static getArmure(actor, context) {
+ return context.armure?.name ?? ''
+ }
+
+ static getProtectionArmure(actor, context) {
+ return Number(context?.armure?.protection ?? 0) + Number(actor.system.attributs.protection.value)
+ }
+
+ static getMalusArmure(actor, context) {
+ return context?.armure?.malus ?? 0
+ }
+
+ static getEsquive(actor, context) {
+ return context.esquive?.name ?? ''
+ }
+
+ static getEsquiveNiveau(context) {
+ if (context.esquive) {
+ const niveau = context.esquive.niveau + context.armure.malus
+ return niveau > 0 ? ('+' + niveau) : ('' + niveau)
+ }
+ return ''
+ }
+
+ static getCompetences(actor, categories) {
+ const competences = Mapping.getCompetencesCategorie(actor, categories)
+ if (competences.length == 0) {
+ return ''
+ }
+ const byCartegories = Mapping.competencesByCategoriesByNiveau(competences, categories)
+ const txtByCategories = Object.values(byCartegories)
+ .map(it => it.competencesParNiveau)
+ .map(byNiveau => {
+ const niveaux = Object.keys(byNiveau).map(it => Number(it)).sort(Misc.ascending())
+ if (niveaux.length == 0) {
+ return ''
+ }
+ const txtCategorieByNiveau = niveaux.map(niveau => {
+ const names = Misc.join(byNiveau[niveau].map(it => it.name).sort(Misc.ascending()), ', ')
+ return names + ': ' + Misc.toSignedString(niveau)
+ }
+ )
+ const txtCategorie = Misc.join(txtCategorieByNiveau, ' / ')
+ return txtCategorie
+ }).filter(it => it != '')
+
+ return Misc.join(txtByCategories, ' / ')
+ }
+
+ static competencesByCategoriesByNiveau(competences, categories) {
+ return categories.map(c => {
+ return {
+ categorie: c,
+ competencesParNiveau: Misc.classify(
+ competences.filter(comp => comp.system.categorie == c),
+ comp => comp.system.niveau)
+ }
+ })
+ }
+
+ static getArme(actor, context, part, numero) {
+ if (numero < context.armes.length) {
+ return context.armes[numero][part] ?? ''
+ }
+ return ''
+ }
+
+ static getCompetencesCategorie(actor, categories) {
+ return actor.itemTypes[ITEM_TYPES.competence]
+ .filter(it => categories.includes(it.system.categorie))
+ .filter(it => !RdDItemCompetence.isNiveauBase(it))
+ }
+
+ static getSort(actor, context, part, numero) {
+ if (numero < context.sorts.length) {
+ return context.sorts[numero][part]
+ }
+ return ''
+ }
+}
+
diff --git a/module/rdd-main.js b/module/rdd-main.js
index e16e7948..ffcf00e8 100644
--- a/module/rdd-main.js
+++ b/module/rdd-main.js
@@ -65,6 +65,8 @@ import { AutoAdjustDarkness as AutoAdjustDarkness } from "./time/auto-adjust-dar
import { RdDCreature } from "./actor/creature.js"
import { RdDTMRDialog } from "./rdd-tmr-dialog.js"
import { RdDActorExportSheet } from "./actor/actor-export-sheet.js"
+import { OptionsAvancees } from "./settings/options-avancees.js"
+import { ExportScriptarium } from "./actor/export-scriptarium/export-scriptarium.js"
/**
* RdD system
@@ -197,6 +199,7 @@ export class SystemReveDeDragon {
SystemCompendiums.init()
DialogChronologie.init()
ReglesOptionnelles.init()
+ OptionsAvancees.init()
RdDUtility.init()
RdDDice.init()
RdDCommands.init()
@@ -211,6 +214,7 @@ export class SystemReveDeDragon {
RdDPossession.init()
TMRRencontres.init()
Environnement.init()
+ ExportScriptarium.init()
}
initSystemSettings() {
diff --git a/module/settings/options-avancees.js b/module/settings/options-avancees.js
new file mode 100644
index 00000000..1e4cad4e
--- /dev/null
+++ b/module/settings/options-avancees.js
@@ -0,0 +1,91 @@
+import { SYSTEM_RDD } from "../constants.js"
+import { Misc } from "../misc.js"
+
+export const EXPORT_CSV_SCRIPTARIUM = 'export-csv-scriptarium'
+
+const OPTIONS_AVANCEES = [
+ { group: 'Menus', name: EXPORT_CSV_SCRIPTARIUM, descr: "Proposer le menu d'export csv Scriptarium (raffraichissement requis)" },
+]
+
+export class OptionsAvancees extends FormApplication {
+ static init() {
+ for (const regle of OPTIONS_AVANCEES) {
+ const name = regle.name
+ const id = OptionsAvancees._getId(name)
+ game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean })
+ }
+
+ game.settings.registerMenu(SYSTEM_RDD, "rdd-options-avancees", {
+ name: "Configurer les options avancées",
+ label: "Options avancées",
+ hint: "Ouvre la fenêtre de configuration des options avancées",
+ icon: "fas fa-bars",
+ type: OptionsAvancees
+ })
+ }
+
+ constructor(...args) {
+ super(...args)
+ }
+
+ static _getId(name) {
+ return `rdd-advanced-${name}`
+ }
+
+ static get defaultOptions() {
+ return foundry.utils.mergeObject(super.defaultOptions, {
+ id: "options-avancees",
+ template: "systems/foundryvtt-reve-de-dragon/templates/settings/options-avancees.hbs",
+ height: 650,
+ width: 550,
+ minimizable: false,
+ closeOnSubmit: true,
+ title: "Options avancées"
+ }, { inplace: false })
+ }
+
+ getData() {
+ let formData = super.getData()
+ const regles = OPTIONS_AVANCEES.filter(it => game.user.isGM || it.scope == "client")
+ .map(it => {
+ it = foundry.utils.duplicate(it)
+ it.id = OptionsAvancees._getId(it.name)
+ it.active = OptionsAvancees.isSet(it.name)
+ return it
+ })
+ formData.regles = regles
+ formData.groups = Misc.classify(regles, it => it.group)
+ return formData
+ }
+
+ static getSettingKey(name){
+ return `${SYSTEM_RDD}.${this._getId(name)}`
+ }
+
+ static isUsing(name) {
+ return OptionsAvancees.isSet(name)
+ }
+
+ static isSet(name) {
+ return game.settings.get(SYSTEM_RDD, OptionsAvancees._getId(name))
+ }
+
+ static set(name, value) {
+ return game.settings.set(SYSTEM_RDD, OptionsAvancees._getId(name), value ? true : false)
+ }
+
+ activateListeners(html) {
+ html.find(".select-option").click((event) => {
+ if (event.currentTarget.attributes.name) {
+ let id = event.currentTarget.attributes.name.value
+ let isChecked = event.currentTarget.checked
+ game.settings.set(SYSTEM_RDD, id, isChecked)
+ }
+ })
+ }
+
+ async _updateObject(event, formData) {
+ this.close()
+ }
+}
+
diff --git a/module/time/rdd-timestamp.js b/module/time/rdd-timestamp.js
index 2f12d5c3..c10d55f6 100644
--- a/module/time/rdd-timestamp.js
+++ b/module/time/rdd-timestamp.js
@@ -15,18 +15,18 @@ export const RDD_MINUTES_PAR_JOUR = 1440; //RDD_HEURES_PAR_JOUR * RDD_MINUTES_PA
const ROUNDS_PAR_MINUTE = 10;
const DEFINITION_HEURES = [
- { key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "Printemps", darkness: 0.9 },
- { key: "sirene", label: "Sirène", lettreFont: 'i', saison: "Printemps", darkness: 0.1 },
- { key: "faucon", label: "Faucon", lettreFont: 'f', saison: "Printemps", darkness: 0 },
- { key: "couronne", label: "Couronne", lettreFont: '', saison: "Eté", darkness: 0 },
- { key: "dragon", label: "Dragon", lettreFont: 'd', saison: "Eté", darkness: 0 },
- { key: "epees", label: "Epées", lettreFont: 'e', saison: "Eté", darkness: 0 },
- { key: "lyre", label: "Lyre", lettreFont: 'l', saison: "Automne", darkness: 0.1 },
- { key: "serpent", label: "Serpent", lettreFont: 's', saison: "Automne", darkness: 0.9 },
- { key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne", darkness: 1 },
- { key: "araignee", label: "Araignée", lettreFont: 'a', saison: "Hiver", darkness: 1 },
- { key: "roseau", label: "Roseau", lettreFont: 'r', saison: "Hiver", darkness: 1 },
- { key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "Hiver", darkness: 1 },
+ { key: "vaisseau", article: "du ", label: "Vaisseau", lettreFont: 'v', saison: "Printemps", darkness: 0.9 },
+ { key: "sirene", article: "de la ", label: "Sirène", lettreFont: 'i', saison: "Printemps", darkness: 0.1 },
+ { key: "faucon", article: "du ", label: "Faucon", lettreFont: 'f', saison: "Printemps", darkness: 0 },
+ { key: "couronne", article: "de la ", label: "Couronne", lettreFont: '', saison: "Eté", darkness: 0 },
+ { key: "dragon", article: "du ", label: "Dragon", lettreFont: 'd', saison: "Eté", darkness: 0 },
+ { key: "epees", article: "des ", label: "Epées", lettreFont: 'e', saison: "Eté", darkness: 0 },
+ { key: "lyre", article: "de la ", label: "Lyre", lettreFont: 'l', saison: "Automne", darkness: 0.1 },
+ { key: "serpent", article: "du ", label: "Serpent", lettreFont: 's', saison: "Automne", darkness: 0.9 },
+ { key: "poissonacrobate", article: "du ", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne", darkness: 1 },
+ { key: "araignee", article: "de l'", label: "Araignée", lettreFont: 'a', saison: "Hiver", darkness: 1 },
+ { key: "roseau", article: "du ", label: "Roseau", lettreFont: 'r', saison: "Hiver", darkness: 1 },
+ { key: "chateaudormant", article: "du ", label: "Château Dormant", lettreFont: 'c', saison: "Hiver", darkness: 1 },
]
const FORMULES_DUREE = [
@@ -64,6 +64,7 @@ export class RdDTimestamp {
DEFINITION_HEURES[i].hh = RdDTimestamp.hh(i);
DEFINITION_HEURES[i].icon = RdDTimestamp.iconeHeure(i);
DEFINITION_HEURES[i].webp = DEFINITION_HEURES[i].icon.replace(".svg", ".webp");
+ DEFINITION_HEURES[i].avecArticle = DEFINITION_HEURES[i].article + DEFINITION_HEURES[i].label
}
}
@@ -241,7 +242,7 @@ export class RdDTimestamp {
get darkness() {
const darknessDebut = 100 * RdDTimestamp.definition(this.heure).darkness
- const darknessFin = 100 * RdDTimestamp.definition(this.heure + 1).darkness
+ const darknessFin = 100 * RdDTimestamp.definition(this.heure + 1).darkness
const darknessMinute = Math.round((darknessFin - darknessDebut) * this.minute / RDD_MINUTES_PAR_HEURES);
return (darknessDebut + darknessMinute) / 100
}
diff --git a/styles/img/ui/scriptarium.svg b/styles/img/ui/scriptarium.svg
new file mode 100644
index 00000000..9d066697
--- /dev/null
+++ b/styles/img/ui/scriptarium.svg
@@ -0,0 +1,65 @@
+
+
diff --git a/styles/simple.css b/styles/simple.css
index da09b65a..77a3b277 100644
--- a/styles/simple.css
+++ b/styles/simple.css
@@ -572,6 +572,15 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) {
border: none;
padding: 0.1rem;
}
+.context-menu-img {
+ max-width: 2rem;
+ max-height: 1rem;
+ flex-grow: 0;
+ margin: 0.2rem 0.3rem 0 0;
+ vertical-align: middle;
+ border: none;
+ padding: 0rem;
+}
.button-img {
vertical-align: baseline;
diff --git a/templates/settings/options-avancees.hbs b/templates/settings/options-avancees.hbs
new file mode 100644
index 00000000..6ea970cd
--- /dev/null
+++ b/templates/settings/options-avancees.hbs
@@ -0,0 +1,13 @@
+