DIvers rework de CSS/LESS et améliorations de messages/layout

This commit is contained in:
2026-05-03 20:20:30 +02:00
parent 4f8735f86f
commit 267f992874
113 changed files with 11565 additions and 843 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ import LesOubliesItemSheet from "./base-item-sheet.mjs"
export default class LesOubliesArmeSheet extends LesOubliesItemSheet {
static PARTS = {
sheet: {
template: "systems/fvtt-les-oublies/templates/item-arme-sheet.hbs",
template: "systems/fvtt-les-oublies/templates/item-arme-sheet-v2.hbs",
},
}
}
@@ -32,9 +32,11 @@ export default class LesOubliesActorSheet extends HandlebarsApplicationMixin(fou
rollSkill: LesOubliesActorSheet.#onRollSkill,
useWeapon: LesOubliesActorSheet.#onUseWeapon,
resolveWeaponDamage: LesOubliesActorSheet.#onResolveWeaponDamage,
toggleEquipped: LesOubliesActorSheet.#onToggleEquipped,
useSpell: LesOubliesActorSheet.#onUseSpell,
openCombatPreset: LesOubliesActorSheet.#onOpenCombatPreset,
openThreadHarvest: LesOubliesActorSheet.#onOpenThreadHarvest,
openLinkedActor: LesOubliesActorSheet.#onOpenLinkedActor,
},
}
@@ -49,6 +51,14 @@ export default class LesOubliesActorSheet extends HandlebarsApplicationMixin(fou
}
async _prepareContext() {
const config = CONFIG.LESOUBLIES
const enriched = await LesOubliesUtility.prepareEnrichedHtml("Actor", this.document.type, this.document.system)
const choiceSets = {
profileOptions: config.profiles.map((profile) => ({ value: profile.id, label: profile.label })),
personnageSizeOptions: LesOubliesUtility.createRangeChoices(1, 4, config.sizes),
creatureSizeOptions: LesOubliesUtility.createRangeChoices(1, 8, config.sizes),
}
return {
actor: this.document,
system: this.document.system,
@@ -59,8 +69,10 @@ export default class LesOubliesActorSheet extends HandlebarsApplicationMixin(fou
isEditMode: this.isEditMode,
isPlayMode: this.isPlayMode,
isGM: game.user.isGM,
config: CONFIG.LESOUBLIES,
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.biodata?.description ?? this.document.system.description ?? "", { async: true }),
config,
choiceSets,
enriched,
enrichedDescription: foundry.utils.getProperty(enriched, "biodata.description") ?? foundry.utils.getProperty(enriched, "description") ?? "",
}
}
@@ -99,6 +111,7 @@ export default class LesOubliesActorSheet extends HandlebarsApplicationMixin(fou
static async #onEditImage(event, target) {
const attr = target.dataset.edit
const current = foundry.utils.getProperty(this.document, attr)
const FilePicker = foundry.applications.apps.FilePicker.implementation
const fp = new FilePicker({
current,
type: "image",
@@ -113,11 +126,17 @@ export default class LesOubliesActorSheet extends HandlebarsApplicationMixin(fou
const type = target.dataset.type
if (!type) return
const label = game.i18n.localize(`TYPES.Item.${type}`)
return this.document.createEmbeddedDocuments("Item", [{
const itemData = {
name: label,
type,
img: LesOubliesUtility.getDefaultItemImage(type),
}])
}
if (type === "competence") {
itemData.system = {
profileKey: CONFIG.LESOUBLIES.profiles[0]?.id ?? "",
}
}
return this.document.createEmbeddedDocuments("Item", [itemData])
}
static async #onEditItem(event, target) {
@@ -168,6 +187,14 @@ export default class LesOubliesActorSheet extends HandlebarsApplicationMixin(fou
await this.document.openDamageDialog({ itemId })
}
static async #onToggleEquipped(event, target) {
const itemId = target.dataset.itemId
if (!itemId) return
const item = this.document.items.get(itemId)
if (!item || !("equipped" in (item.system ?? {}))) return
await item.update({ "system.equipped": !item.system.equipped })
}
static async #onUseSpell(event, target) {
const itemId = target.dataset.itemId
if (!itemId) return
@@ -183,4 +210,11 @@ export default class LesOubliesActorSheet extends HandlebarsApplicationMixin(fou
static async #onOpenThreadHarvest() {
await this.document.openThreadHarvestDialog()
}
static async #onOpenLinkedActor(event, target) {
const actorId = target.dataset.actorId
if (!actorId) return
const actor = game.actors.get(actorId)
if (actor) actor.sheet.render(true)
}
}
@@ -1,5 +1,7 @@
const { HandlebarsApplicationMixin } = foundry.applications.api
import { LesOubliesUtility } from "../../les-oublies-utility.js"
export default class LesOubliesItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
@@ -33,6 +35,62 @@ export default class LesOubliesItemSheet extends HandlebarsApplicationMixin(foun
}
async _prepareContext() {
const config = CONFIG.LESOUBLIES
const enriched = await LesOubliesUtility.prepareEnrichedHtml("Item", this.document.type, this.document.system)
const skillLabels = Object.fromEntries(Object.entries(config.skills).map(([key, skill]) => [key, skill.label]))
const choiceSets = {
profileOptions: config.profiles.map((profile) => ({ value: profile.id, label: profile.label })),
skillOptions: LesOubliesUtility.createChoices(Object.keys(config.skills), skillLabels),
spellSkillOptions: LesOubliesUtility.createChoices(["magie", "onirologie", "chimerisme"], skillLabels),
weaponCategoryOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.createChoices(Object.keys(config.weaponCategoryLabels), config.weaponCategoryLabels),
this.document.system.category,
),
weaponOriginOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.createChoices(Object.keys(config.weaponOriginLabels), config.weaponOriginLabels),
this.document.system.origin,
),
armorStateOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.createChoices(Object.keys(config.armorStateLabels), config.armorStateLabels),
this.document.system.state,
),
equipmentCategoryOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.createChoices(Object.keys(config.equipmentCategoryLabels), config.equipmentCategoryLabels),
this.document.system.category,
),
spellTraditionOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.createChoices(Object.keys(config.spellTraditionLabels), config.spellTraditionLabels),
this.document.system.tradition,
),
polarityOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.createChoices(Object.keys(config.polarityLabels), config.polarityLabels),
this.document.system.polarity,
),
stackingOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.createChoices(Object.keys(config.stackingLabels), config.stackingLabels),
this.document.system.stacking,
),
companyPowerScopeOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.createChoices(Object.keys(config.companyPowerScopeLabels), config.companyPowerScopeLabels),
this.document.system.scope,
),
companyPowerModeOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.createChoices(Object.keys(config.companyPowerModeLabels), config.companyPowerModeLabels),
this.document.system.effectMode,
),
raceSizeOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.createRangeChoices(1, 4, config.sizes),
this.document.system.size,
),
mainRaceOptions: LesOubliesUtility.ensureChoice(
LesOubliesUtility.sortByName(game.items.filter((item) => item.type === "race")).map((item) => ({
value: item.name,
label: item.name,
})),
this.document.system.mainRace,
),
}
return {
item: this.document,
system: this.document.system,
@@ -43,8 +101,10 @@ export default class LesOubliesItemSheet extends HandlebarsApplicationMixin(foun
isEditMode: this.isEditMode,
isPlayMode: this.isPlayMode,
isGM: game.user.isGM,
config: CONFIG.LESOUBLIES,
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description ?? "", { async: true }),
config,
choiceSets,
enriched,
enrichedDescription: foundry.utils.getProperty(enriched, "description") ?? "",
}
}
@@ -1,9 +1,14 @@
import LesOubliesActorSheet from "./base-actor-sheet.mjs"
import { LesOubliesUtility } from "../../les-oublies-utility.js"
export default class LesOubliesCompagnieSheet extends LesOubliesActorSheet {
static DEFAULT_OPTIONS = {
...super.DEFAULT_OPTIONS,
classes: [...super.DEFAULT_OPTIONS.classes, "compagnie"],
actions: {
...super.DEFAULT_OPTIONS.actions,
switchTab: LesOubliesCompagnieSheet.#onSwitchTab,
},
window: {
...super.DEFAULT_OPTIONS.window,
title: "TYPES.Actor.compagnie",
@@ -12,12 +17,30 @@ export default class LesOubliesCompagnieSheet extends LesOubliesActorSheet {
static PARTS = {
sheet: {
template: "systems/fvtt-les-oublies/templates/actor-compagnie-sheet.hbs",
template: "systems/fvtt-les-oublies/templates/actor-compagnie-sheet-v4.hbs",
},
}
_activeTab = "power"
#getTabs() {
const tabs = {
power: { id: "power", label: "Pouvoir", icon: "fa-solid fa-burst" },
members: { id: "members", label: "Membres & liens", icon: "fa-solid fa-people-group" },
notes: { id: "notes", label: "Notes", icon: "fa-solid fa-feather-pointed" },
}
for (const tab of Object.values(tabs)) {
tab.active = this._activeTab === tab.id
tab.cssClass = tab.active ? "active" : ""
}
return tabs
}
async _prepareContext() {
const context = await super._prepareContext()
context.tabs = this.#getTabs()
context.members = (this.document.system.memberIds ?? []).map((id) => game.actors.get(id)).filter(Boolean)
context.captain = this.document.system.captainId ? game.actors.get(this.document.system.captainId) : null
context.shadow = this.document.system.ombreDuTourmentId ? game.actors.get(this.document.system.ombreDuTourmentId) : null
@@ -28,6 +51,19 @@ export default class LesOubliesCompagnieSheet extends LesOubliesActorSheet {
sourceLabel: game.actors.get(link.sourceId)?.name ?? link.sourceId,
targetLabel: game.actors.get(link.targetId)?.name ?? link.targetId,
}))
const actorChoices = LesOubliesUtility.sortByName(game.actors.filter((actor) => actor.type === "personnage")).map((actor) => ({
value: actor.id,
label: actor.name,
}))
context.choiceSets.captainOptions = LesOubliesUtility.ensureChoice(actorChoices, this.document.system.captainId, context.captain?.name)
context.choiceSets.shadowOptions = LesOubliesUtility.ensureChoice(actorChoices, this.document.system.ombreDuTourmentId, context.shadow?.name)
return context
}
static #onSwitchTab(event, target) {
const tab = target.dataset.tab
if (!tab || this._activeTab === tab) return
this._activeTab = tab
this.render()
}
}
+31 -1
View File
@@ -4,6 +4,10 @@ export default class LesOubliesCreatureSheet extends LesOubliesActorSheet {
static DEFAULT_OPTIONS = {
...super.DEFAULT_OPTIONS,
classes: [...super.DEFAULT_OPTIONS.classes, "creature"],
actions: {
...super.DEFAULT_OPTIONS.actions,
switchTab: LesOubliesCreatureSheet.#onSwitchTab,
},
window: {
...super.DEFAULT_OPTIONS.window,
title: "TYPES.Actor.creature",
@@ -12,12 +16,31 @@ export default class LesOubliesCreatureSheet extends LesOubliesActorSheet {
static PARTS = {
sheet: {
template: "systems/fvtt-les-oublies/templates/actor-creature-sheet.hbs",
template: "systems/fvtt-les-oublies/templates/actor-creature-sheet-v5.hbs",
},
}
_activeTab = "overview"
#getTabs() {
const tabs = {
overview: { id: "overview", label: "Aperçu", icon: "fa-solid fa-dragon" },
aptitudes: { id: "aptitudes", label: "Aptitudes", icon: "fa-solid fa-book-open" },
combat: { id: "combat", label: "Combat & équipement", icon: "fa-solid fa-shield-halved" },
notes: { id: "notes", label: "Notes", icon: "fa-solid fa-feather-pointed" },
}
for (const tab of Object.values(tabs)) {
tab.active = this._activeTab === tab.id
tab.cssClass = tab.active ? "active" : ""
}
return tabs
}
async _prepareContext() {
const context = await super._prepareContext()
context.tabs = this.#getTabs()
context.derived = this.document.getDerivedOverview()
context.skillGroups = this.document.getGroupedCompetences()
context.spells = this.document.getEmbeddedItems("sortilege")
@@ -26,4 +49,11 @@ export default class LesOubliesCreatureSheet extends LesOubliesActorSheet {
context.equipment = this.document.getEmbeddedItems("equipement")
return context
}
static #onSwitchTab(event, target) {
const tab = target.dataset.tab
if (!tab || this._activeTab === tab) return
this._activeTab = tab
this.render()
}
}
@@ -1,9 +1,17 @@
import LesOubliesActorSheet from "./base-actor-sheet.mjs"
import { LesOubliesUtility } from "../../les-oublies-utility.js"
export default class LesOubliesPersonnageSheet extends LesOubliesActorSheet {
static CREATION_DROP_TYPES = new Set(["race", "tribu", "metier"])
static DEFAULT_OPTIONS = {
...super.DEFAULT_OPTIONS,
classes: [...super.DEFAULT_OPTIONS.classes, "personnage"],
actions: {
...super.DEFAULT_OPTIONS.actions,
switchTab: LesOubliesPersonnageSheet.#onSwitchTab,
removeCreationItem: LesOubliesPersonnageSheet.#onRemoveCreationItem,
},
window: {
...super.DEFAULT_OPTIONS.window,
title: "TYPES.Actor.personnage",
@@ -12,26 +20,121 @@ export default class LesOubliesPersonnageSheet extends LesOubliesActorSheet {
static PARTS = {
sheet: {
template: "systems/fvtt-les-oublies/templates/actor-personnage-sheet.hbs",
template: "systems/fvtt-les-oublies/templates/actor-personnage-sheet-v14.hbs",
},
}
_activeTab = "overview"
#getTabs() {
const tabs = {
overview: { id: "overview", label: "Portrait", icon: "fa-solid fa-id-card" },
skills: { id: "skills", label: "Compétences", icon: "fa-solid fa-book-open" },
actions: { id: "actions", label: "Combat & magie", icon: "fa-solid fa-wand-sparkles" },
equipment: { id: "equipment", label: "Équipement", icon: "fa-solid fa-suitcase" },
notes: { id: "notes", label: "Notes", icon: "fa-solid fa-feather-pointed" },
}
for (const tab of Object.values(tabs)) {
tab.active = this._activeTab === tab.id
tab.cssClass = tab.active ? "active" : ""
}
return tabs
}
async _prepareContext() {
const context = await super._prepareContext()
context.tabs = this.#getTabs()
context.derived = this.document.getDerivedOverview()
context.creation = {
race: this.document.getCreationItem("race"),
tribu: this.document.getCreationItem("tribu"),
metier: this.document.getCreationItem("metier"),
}
context.profileEntries = this.document.system.profils
context.creationSlots = [
this.#buildCreationSlot("race", context.creation.race, "Glissez une race ici depuis un compendium ou le répertoire des objets."),
this.#buildCreationSlot("tribu", context.creation.tribu, "Glissez une tribu ici depuis un compendium ou le répertoire des objets."),
this.#buildCreationSlot("metier", context.creation.metier, "Glissez un métier ici depuis un compendium ou le répertoire des objets."),
]
context.skillGroups = this.document.getGroupedCompetences()
const splitIndex = Math.ceil(context.skillGroups.length / 2)
context.skillColumns = [
context.skillGroups.slice(0, splitIndex),
context.skillGroups.slice(splitIndex),
]
context.spells = this.document.getEmbeddedItems("sortilege")
context.weapons = this.document.getEmbeddedItems("arme")
context.equippedWeapons = context.weapons.filter((item) => item.system.equipped)
context.armors = this.document.getEmbeddedItems("armure")
context.equipment = this.document.getEmbeddedItems("equipement")
context.companyPowers = this.document.getEmbeddedItems("pouvoircompagnie")
context.activeCompanyPower = context.derived.compagnie?.getEmbeddedItems?.("pouvoircompagnie")?.[0] ?? null
context.choiceSets.companyOptions = LesOubliesUtility.ensureChoice(
LesOubliesUtility.sortByName(game.actors.filter((actor) => actor.type === "compagnie")).map((actor) => ({
value: actor.id,
label: actor.name,
})),
this.document.system.references?.compagnieId,
context.derived.compagnie?.name,
)
return context
}
#buildCreationSlot(type, item, emptyHint) {
return {
type,
label: game.i18n.localize(`TYPES.Item.${type}`),
item,
emptyHint,
filledHint: "Déposez un autre élément du même type pour le remplacer.",
}
}
async _onDrop(event) {
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
if (data.type !== "Item" || !data.uuid) return super._onDrop(event)
const item = await fromUuid(data.uuid)
if (!item) return
const slot = event.target?.closest?.("[data-drop-creation-type]")
const slotType = slot?.dataset?.dropCreationType ?? ""
const inCreationZone = Boolean(event.target?.closest?.("[data-creation-drop-zone]"))
if (!LesOubliesPersonnageSheet.CREATION_DROP_TYPES.has(item.type)) {
if (slot || inCreationZone) {
ui.notifications.warn("Seules les races, tribus et métiers peuvent être déposés dans cette zone.")
return
}
return super._onDrop(event)
}
if (slotType && slotType !== item.type) {
ui.notifications.warn(`Déposez ici un élément de type ${game.i18n.localize(`TYPES.Item.${slotType}`)}.`)
return
}
if (slot || inCreationZone) {
await this.document.assignCreationItem(item)
this.render()
return
}
return super._onDrop(event)
}
static #onSwitchTab(event, target) {
const tab = target.dataset.tab
if (!tab || this._activeTab === tab) return
this._activeTab = tab
this.render()
}
static async #onRemoveCreationItem(event, target) {
const type = target.dataset.type
if (!LesOubliesPersonnageSheet.CREATION_DROP_TYPES.has(type)) return
await this.document.clearCreationItem(type)
this.render()
}
}