diff --git a/lang/en.json b/lang/en.json
index 955638d..3493e62 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -140,6 +140,9 @@
"level": "Level",
"experience": "Experience",
"reputation": "Reputation",
+ "sheet": {
+ "description": "Description"
+ },
"pool": "Reserve",
"pools": "Reserves",
"self_control": "Self-control",
diff --git a/lang/fr.json b/lang/fr.json
index e88258b..bc7fe65 100644
--- a/lang/fr.json
+++ b/lang/fr.json
@@ -146,6 +146,9 @@
"level": "Niveau",
"experience": "Expérience",
"reputation": "Réputation",
+ "sheet": {
+ "description": "Description"
+ },
"pool": "Réserve",
"pools": "Réserves",
"reserves": "Réserves",
diff --git a/less/actor/actor.less b/less/actor/actor.less
index e31f8aa..fdaa3d0 100644
--- a/less/actor/actor.less
+++ b/less/actor/actor.less
@@ -207,16 +207,20 @@
.hexa-style();
.transition();
margin: 0.2rem;
+ position: relative;
&:hover {
.hexa-style(rgba(255, 255, 255, 0.425), rgba(0, 0, 0, 0.288));
}
input {
- opacity: 1;
- min-width: 100%;
- min-height: 100%;
+ position: absolute;
+ width: 100%;
+ height: 100%;
opacity: 0;
+ z-index: 1;
+ margin: 0;
+ cursor: pointer;
}
&.checked {
diff --git a/less/actor/npc.less b/less/actor/npc.less
index 29d9d87..f3d61cc 100644
--- a/less/actor/npc.less
+++ b/less/actor/npc.less
@@ -5,7 +5,7 @@
.sheet-header {
.background-image(url("@{ui-path}/barre_haut.webp"), no-repeat, 100% 100%, right top);
padding: 0.5rem;
- max-height: 110px;
+ max-height: 150px;
}
.ability-value,
@@ -179,7 +179,12 @@
flex: 1;
display: flex;
flex-direction: column;
- gap: 10px;
+ gap: 4px;
+ }
+
+ .sheet-header .resource {
+ padding: 4px 8px;
+ margin-bottom: 0;
}
.resources {
diff --git a/less/actor/totem.less b/less/actor/totem.less
index 0594a5f..ebe773d 100644
--- a/less/actor/totem.less
+++ b/less/actor/totem.less
@@ -64,6 +64,9 @@
.adapted-dice i {
padding-top: 0.5rem;
color: @totem-human-color;
+ position: relative;
+ z-index: 0;
+ pointer-events: none;
}
.adapted-dice {
diff --git a/less/items.less b/less/items.less
index bb24167..608468c 100644
--- a/less/items.less
+++ b/less/items.less
@@ -71,11 +71,11 @@
font-size: 0.875rem;
text-align: center;
text-shadow: 0 0 3px rgba(0, 0, 0, 0.9);
- }
- option {
- background: #1a1a1a;
- color: @color-text-light-1;
+ option {
+ background: @color-bg-option;
+ color: @color-text-dark-primary;
+ }
}
.traits {
@@ -83,6 +83,15 @@
h3, h4 { margin: 0; }
}
+
+ .editor,
+ .editor-content {
+ color: @color-text-dark-primary;
+ background: rgba(255, 255, 255, 0.3);
+ min-height: 6rem;
+
+ p { margin: 0.25rem 0; }
+ }
}
ol#chat-log div.item-card header img,
diff --git a/module/applications/sheets/base-actor-sheet.mjs b/module/applications/sheets/base-actor-sheet.mjs
index 651e4ba..d0eb1e5 100644
--- a/module/applications/sheets/base-actor-sheet.mjs
+++ b/module/applications/sheets/base-actor-sheet.mjs
@@ -96,6 +96,10 @@ export default class VermineBaseActorSheet extends HandlebarsApplicationMixin(fo
// ── Contexte commun ─────────────────────────────────────────────────
async _prepareContext() {
+ const enrich = async (path) => {
+ const val = foundry.utils.getProperty(this.document.system, path);
+ return val ? await foundry.applications.ux.TextEditor.implementation.enrichHTML(val, { async: true }) : "";
+ };
return {
fields: this.document.schema.fields,
systemFields: this.document.system.schema.fields,
@@ -107,7 +111,10 @@ export default class VermineBaseActorSheet extends HandlebarsApplicationMixin(fo
isGM: game.user.isGM,
isEditMode: this.isEditMode,
isPlayMode: this.isPlayMode,
- isEditable: this.isEditable
+ isEditable: this.isEditable,
+ enrichedNotes: await enrich("identity.notes"),
+ enrichedBiography: await enrich("identity.biography"),
+ enrichedRelations: await enrich("identity.relations")
}
}
@@ -138,6 +145,19 @@ export default class VermineBaseActorSheet extends HandlebarsApplicationMixin(fo
for (const [group, tab] of Object.entries(this.tabGroups ?? {})) {
this.changeTab(tab, group, {force: true})
}
+ // Move toggle from hidden main tab to visible position (only for sheets where
+ // .tab.main is not already displayed as a permanent sidebar via !important)
+ const mainTab = this.element.querySelector(".tab.main")
+ const tabs = this.element.querySelector('nav.tabs[data-application-part="tabs"]')
+ if ( mainTab && tabs && getComputedStyle(mainTab).display === "none" ) {
+ const existing = tabs.parentNode.querySelector('.sheet-header-toggle[data-moved]')
+ if (existing) existing.remove()
+ const toggle = mainTab.querySelector(".sheet-header-toggle")
+ if (toggle) {
+ toggle.dataset.moved = "true"
+ tabs.parentNode.insertBefore(toggle, tabs)
+ }
+ }
this.#dragDrop.forEach(d => d.bind(this.element))
this.element.querySelectorAll(".rollable").forEach(el => {
el.addEventListener("click", this._onRoll.bind(this))
diff --git a/module/applications/sheets/creature-sheet.mjs b/module/applications/sheets/creature-sheet.mjs
index 41eadcc..e5978c7 100644
--- a/module/applications/sheets/creature-sheet.mjs
+++ b/module/applications/sheets/creature-sheet.mjs
@@ -50,7 +50,12 @@ export default class VermineCreatureSheetV2 extends VermineBaseActorSheet {
async _preparePartContext(partId, context) {
const doc = this.document
switch (partId) {
- case "main": break
+ case "main":
+ context.patternOptions = CONFIG.VERMINE.creaturePatternLevels
+ context.roleOptions = CONFIG.VERMINE.creatureRoleLevels
+ context.sizeOptions = CONFIG.VERMINE.creatureSizeLevels
+ context.packOptions = CONFIG.VERMINE.creaturePackLevels
+ break
case "info":
context.tab = context.tabs.info
break
diff --git a/module/applications/sheets/npc-sheet.mjs b/module/applications/sheets/npc-sheet.mjs
index 8f8b0c6..8c9a633 100644
--- a/module/applications/sheets/npc-sheet.mjs
+++ b/module/applications/sheets/npc-sheet.mjs
@@ -44,7 +44,13 @@ export default class VermineNpcSheetV2 extends VermineBaseActorSheet {
async _preparePartContext(partId, context) {
const doc = this.document
switch (partId) {
- case "main": break
+ case "main":
+ context.npcThreatOptions = CONFIG.VERMINE.npcThreatLevels
+ context.npcExperienceOptions = CONFIG.VERMINE.npcExperienceLevels
+ context.npcRoleOptions = CONFIG.VERMINE.npcRoleLevels
+ context.totemOptions = CONFIG.VERMINE.totems
+ context.originOptions = CONFIG.VERMINE.origins
+ break
case "characteristics":
context.tab = context.tabs.characteristics
break
diff --git a/module/documents/item.mjs b/module/documents/item.mjs
index 54a3b1a..650a15b 100644
--- a/module/documents/item.mjs
+++ b/module/documents/item.mjs
@@ -80,7 +80,7 @@ export default class VermineItem extends Item {
rollMode: rollMode,
flavor: label,
};
- mess.content = await foundry.applications.handlebars.renderTemplate(`systems/vermine2047/templates/item/chatCards/${this.type}.hbs`, { item: this, message: mess }) ?? null;
+ mess.content = await foundry.applications.handlebars.renderTemplate(`systems/vermine2047/templates/item/chatCards/${this.type}.hbs`, { item: this, message: mess, config: CONFIG.VERMINE }) ?? null;
ChatMessage.create(mess)
}
diff --git a/module/models/character.mjs b/module/models/character.mjs
index ddfa705..f08c470 100644
--- a/module/models/character.mjs
+++ b/module/models/character.mjs
@@ -61,8 +61,8 @@ export default class VermineCharacterData extends foundry.abstract.TypeDataModel
instincts: new fields.StringField({ required: true, nullable: false, initial: "" }),
prohibits: new fields.StringField({ required: true, nullable: false, initial: "" }),
objectives: new fields.StringField({ required: true, nullable: false, initial: "" }),
- relations: new fields.StringField({ required: true, nullable: false, initial: "" }),
- biography: new fields.StringField({ required: true, nullable: false, initial: "" })
+ relations: new fields.HTMLField({ required: true, initial: "" }),
+ biography: new fields.HTMLField({ required: true, initial: "" })
}),
// Équipement
diff --git a/module/models/creature.mjs b/module/models/creature.mjs
index b05e085..6f5a13b 100644
--- a/module/models/creature.mjs
+++ b/module/models/creature.mjs
@@ -32,8 +32,8 @@ export default class VermineCreatureData extends foundry.abstract.TypeDataModel
profile: new fields.StringField({ required: true, nullable: false, initial: "" }),
origin: new fields.StringField({ required: true, nullable: false, initial: "" }),
theme: new fields.StringField({ required: true, nullable: false, initial: "" }),
- notes: new fields.StringField({ required: true, nullable: false, initial: "" }),
- biography: new fields.StringField({ required: true, nullable: false, initial: "" })
+ notes: new fields.HTMLField({ required: true, initial: "" }),
+ biography: new fields.HTMLField({ required: true, initial: "" })
}),
// Compétences (description libre)
diff --git a/module/models/group.mjs b/module/models/group.mjs
index 774b60f..1ecb4db 100644
--- a/module/models/group.mjs
+++ b/module/models/group.mjs
@@ -36,7 +36,7 @@ export default class VermineGroupData extends foundry.abstract.TypeDataModel {
theme: new fields.StringField({ required: true, nullable: false, initial: "" }),
instincts: new fields.StringField({ required: true, nullable: false, initial: "" }),
prohibits: new fields.StringField({ required: true, nullable: false, initial: "" }),
- notes: new fields.StringField({ required: true, nullable: false, initial: "" })
+ notes: new fields.HTMLField({ required: true, initial: "" })
}),
// Équipement
diff --git a/module/models/npc.mjs b/module/models/npc.mjs
index eff05ae..8279138 100644
--- a/module/models/npc.mjs
+++ b/module/models/npc.mjs
@@ -55,7 +55,7 @@ export default class VermineNpcData extends foundry.abstract.TypeDataModel {
origin: new fields.StringField({ required: true, nullable: false, initial: "" }),
totem: new fields.StringField({ required: true, nullable: false, initial: "" }),
theme: new fields.StringField({ required: true, nullable: false, initial: "" }),
- notes: new fields.StringField({ required: true, nullable: false, initial: "" })
+ notes: new fields.HTMLField({ required: true, initial: "" })
}),
// Attributs (XP, réputation, sang-froid, effort)
diff --git a/module/system/handlebars-manager.mjs b/module/system/handlebars-manager.mjs
index 4c4b7fd..06abb83 100644
--- a/module/system/handlebars-manager.mjs
+++ b/module/system/handlebars-manager.mjs
@@ -90,22 +90,9 @@ export const registerHandlebarsHelpers = function () {
return str.toLowerCase();
});
Handlebars.registerHelper('romanNumber', function (numb) {
- switch (numb) {
- case 0:
- return '';
- case 1:
- return 'I';
- case 2:
- return 'II';
- case 3:
- return 'III';
- case 4:
- return 'IV';
- case 5:
- return 'V';
- default:
- throw new Error('Le handicap rareté doit être comprise entre 0 et 5');
- }
+ const n = Number(numb);
+ if ( !Number.isFinite(n) || n < 0 ) return '';
+ return ['', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X'][n] ?? '';
});
// search translation with variables
@@ -386,7 +373,9 @@ export const registerHandlebarsHelpers = function () {
Handlebars.registerHelper('repeat', function (times, start, indexLabel, block) {
var accum = '';
if (!indexLabel) { indexLabel = "index" }
- if (!start) { start = 0; }
+ times = Number(times);
+ start = Number(start ?? 0);
+ if ( !Number.isFinite(times) || !Number.isFinite(start) || times < 0 ) return '';
for (var i = start; i < times + start; ++i) {
block.data[indexLabel] = i;
block.data.first = i === start;
diff --git a/templates/actor/appv2/character-stories.hbs b/templates/actor/appv2/character-stories.hbs
index fb0a2ed..707df2c 100644
--- a/templates/actor/appv2/character-stories.hbs
+++ b/templates/actor/appv2/character-stories.hbs
@@ -35,14 +35,16 @@
{{ localize 'IDENTITY.notes'}}
- {{editor system.identity.biography target="system.identity.biography"
- button=true owner=owner editable=editable}}
+
{{ localize 'IDENTITY.relations'}}
- {{editor system.identity.relations target="system.identity.relations"
- button=true owner=owner editable=editable}}
+