Esprit de la Loi + Automaton
This commit is contained in:
@@ -57,6 +57,10 @@ export default class MournbladeActorSheet extends HandlebarsApplicationMixin(fou
|
||||
preparePotion: MournbladeActorSheet.#onPreparePotion,
|
||||
invoquerElementaire: MournbladeActorSheet.#onInvoquerElementaire,
|
||||
bannirElementaire: MournbladeActorSheet.#onBannirElementaire,
|
||||
invoquerDemon: MournbladeActorSheet.#onInvoquerDemon,
|
||||
libererDemon: MournbladeActorSheet.#onLibererDemon,
|
||||
invoquerEsprit: MournbladeActorSheet.#onInvoquerEsprit,
|
||||
enchanter: MournbladeActorSheet.#onEnchanter,
|
||||
rollArmeOffensif: MournbladeActorSheet.#onRollArmeOffensif,
|
||||
rollArmeSpecial: MournbladeActorSheet.#onRollArmeSpecial,
|
||||
rollArmeDegats: MournbladeActorSheet.#onRollArmeDegats,
|
||||
@@ -110,6 +114,21 @@ export default class MournbladeActorSheet extends HandlebarsApplicationMixin(fou
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_preSyncPartState(partId, newElement, priorElement, state) {
|
||||
super._preSyncPartState(partId, newElement, priorElement, state)
|
||||
// Save scrollable tab positions for deferred restoration in _onRender.
|
||||
// Tabs are hidden (display:none) at _syncPartState time, so scrollTop
|
||||
// assignments have no effect. We re-apply them after making tabs visible.
|
||||
const part = this.constructor.PARTS?.[partId]
|
||||
if (part?.scrollable) {
|
||||
this._pendingScrollRestores = part.scrollable.map(selector => {
|
||||
const el = selector ? priorElement.querySelector(selector) : priorElement
|
||||
return el ? { selector, scrollTop: el.scrollTop } : null
|
||||
}).filter(Boolean)
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options)
|
||||
@@ -136,22 +155,37 @@ export default class MournbladeActorSheet extends HandlebarsApplicationMixin(fou
|
||||
const nav = this.element.querySelector('nav.tabs[data-group]')
|
||||
if (nav) {
|
||||
const group = nav.dataset.group
|
||||
// Activate the current tab
|
||||
const activeTab = this.tabGroups[group] || "stats"
|
||||
|
||||
const switchTab = (tab) => {
|
||||
this.tabGroups[group] = tab
|
||||
nav.querySelectorAll('[data-tab]').forEach(link => {
|
||||
link.classList.toggle('active', link.dataset.tab === tab)
|
||||
})
|
||||
this.element.querySelectorAll('[data-group="' + group + '"][data-tab]').forEach(content => {
|
||||
content.classList.toggle('active', content.dataset.tab === tab)
|
||||
})
|
||||
}
|
||||
|
||||
// Set initial state (makes active tab visible)
|
||||
switchTab(activeTab)
|
||||
|
||||
// Restore scroll positions now that the active tab is visible
|
||||
if (this._pendingScrollRestores?.length) {
|
||||
for (const { selector, scrollTop } of this._pendingScrollRestores) {
|
||||
const el = selector ? this.element.querySelector(selector) : this.element
|
||||
if (el) el.scrollTop = scrollTop
|
||||
}
|
||||
this._pendingScrollRestores = null
|
||||
}
|
||||
|
||||
// Tab clicks: DOM-only, no re-render (preserves scroll positions)
|
||||
nav.querySelectorAll('[data-tab]').forEach(link => {
|
||||
const tab = link.dataset.tab
|
||||
link.classList.toggle('active', tab === activeTab)
|
||||
link.addEventListener('click', (event) => {
|
||||
event.preventDefault()
|
||||
this.tabGroups[group] = tab
|
||||
this.render()
|
||||
switchTab(link.dataset.tab)
|
||||
})
|
||||
})
|
||||
|
||||
// Show/hide tab content
|
||||
this.element.querySelectorAll('[data-group="' + group + '"][data-tab]').forEach(content => {
|
||||
content.classList.toggle('active', content.dataset.tab === activeTab)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,6 +417,40 @@ export default class MournbladeActorSheet extends HandlebarsApplicationMixin(fou
|
||||
await this.document.bannirElementaire(invocIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle invoking a demon
|
||||
*/
|
||||
static async #onInvoquerDemon(event, target) {
|
||||
event.preventDefault()
|
||||
await this.document.invoquerDemon()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle releasing a demon invocation
|
||||
*/
|
||||
static async #onLibererDemon(event, target) {
|
||||
event.preventDefault()
|
||||
const invocIndex = parseInt(target.dataset.invocIndex ?? "0")
|
||||
await this.document.libererDemon(invocIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle invoking a Law Spirit into an Automaton
|
||||
*/
|
||||
static async #onInvoquerEsprit(event, target) {
|
||||
event.preventDefault()
|
||||
await this.document.invoquerEspritLoi()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle enchanting an item with Loi power
|
||||
*/
|
||||
static async #onEnchanter(event, target) {
|
||||
event.preventDefault()
|
||||
const itemId = target.dataset.itemId
|
||||
await this.document.enchanter(itemId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle rolling an arme offensif
|
||||
* @param {Event} event - The triggering event
|
||||
|
||||
@@ -32,6 +32,7 @@ export default class MournbladeItemSheet extends HandlebarsApplicationMixin(foun
|
||||
actions: {
|
||||
editImage: MournbladeItemSheet.#onEditImage,
|
||||
postItem: MournbladeItemSheet.#onPostItem,
|
||||
enchanter: MournbladeItemSheet.#onEnchanter,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -43,17 +44,24 @@ export default class MournbladeItemSheet extends HandlebarsApplicationMixin(foun
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const item = this.document
|
||||
const enchantableTypes = ["arme", "equipement", "protection", "bouclier"]
|
||||
const actorIsLoyal = item.actor?.getAlignement?.() === "loyal"
|
||||
const alreadyEnchanted = enchantableTypes.includes(item.type) && (item.system.enchantementLoi?.actif ?? false)
|
||||
const canEnchant = enchantableTypes.includes(item.type) && !!item.actor && actorIsLoyal && !alreadyEnchanted
|
||||
const context = {
|
||||
fields: this.document.schema.fields,
|
||||
systemFields: this.document.system.schema.fields,
|
||||
item: this.document,
|
||||
system: this.document.system,
|
||||
source: this.document.toObject(),
|
||||
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true }),
|
||||
fields: item.schema.fields,
|
||||
systemFields: item.system.schema.fields,
|
||||
item,
|
||||
system: item.system,
|
||||
source: item.toObject(),
|
||||
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(item.system.description, { async: true }),
|
||||
isEditMode: true,
|
||||
isEditable: this.isEditable,
|
||||
isGM: game.user.isGM,
|
||||
config: game.system.mournblade.config,
|
||||
canEnchant,
|
||||
enchantementActif: alreadyEnchanted,
|
||||
}
|
||||
return context
|
||||
}
|
||||
@@ -96,6 +104,19 @@ export default class MournbladeItemSheet extends HandlebarsApplicationMixin(foun
|
||||
|
||||
// #region Actions
|
||||
|
||||
/**
|
||||
* Handle enchanting this item with Loi power
|
||||
*/
|
||||
static async #onEnchanter(event) {
|
||||
event.preventDefault()
|
||||
const item = this.document
|
||||
if (!item.actor) {
|
||||
ui.notifications.warn("Cet objet doit être sur un personnage pour être enchanté.")
|
||||
return
|
||||
}
|
||||
await item.actor.enchanter(item.id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle editing the item image
|
||||
* @param {Event} event - The triggering event
|
||||
@@ -137,7 +158,8 @@ export default class MournbladeItemSheet extends HandlebarsApplicationMixin(foun
|
||||
protection: "Protection", equipement: "Équipement", heritage: "Héritage",
|
||||
metier: "Métier", capacite: "Capacité", tendance: "Tendance",
|
||||
traitchaotique: "Trait Chaotique", traitespece: "Trait d'Espèce",
|
||||
origine: "Origine", modifier: "Modificateur", monnaie: "Monnaie"
|
||||
origine: "Origine", modifier: "Modificateur", monnaie: "Monnaie",
|
||||
potion: "Potion"
|
||||
}
|
||||
chatData.typeLabel = typeLabels[chatData.type] ?? chatData.type
|
||||
|
||||
@@ -148,10 +170,30 @@ export default class MournbladeItemSheet extends HandlebarsApplicationMixin(foun
|
||||
pacte: "fa-scroll", protection: "fa-shield", equipement: "fa-box",
|
||||
heritage: "fa-dna", metier: "fa-hammer", capacite: "fa-bolt",
|
||||
tendance: "fa-yin-yang", traitchaotique: "fa-skull", traitespece: "fa-paw",
|
||||
origine: "fa-compass", modifier: "fa-sliders", monnaie: "fa-coins"
|
||||
origine: "fa-compass", modifier: "fa-sliders", monnaie: "fa-coins",
|
||||
potion: "fa-flask"
|
||||
}
|
||||
chatData.typeIcon = typeIcons[chatData.type] ?? "fa-cube"
|
||||
|
||||
// Potion: add localized labels for statut and forme
|
||||
if (chatData.type === "potion") {
|
||||
const statutLabels = {
|
||||
inconnue: game.i18n.localize("MNBL.potionInconnue"),
|
||||
efficace: game.i18n.localize("MNBL.potionEfficace"),
|
||||
heroique: game.i18n.localize("MNBL.potionHeroique"),
|
||||
inefficace: game.i18n.localize("MNBL.potionInefficace"),
|
||||
poison: game.i18n.localize("MNBL.potionPoison"),
|
||||
}
|
||||
const formeLabels = {
|
||||
liquide: game.i18n.localize("MNBL.potionLiquide"),
|
||||
onguent: game.i18n.localize("MNBL.potionOnguent"),
|
||||
cachets: game.i18n.localize("MNBL.potionCachets"),
|
||||
pilules: game.i18n.localize("MNBL.potionPilules"),
|
||||
}
|
||||
chatData.system.statutLabel = statutLabels[chatData.system.statut] ?? chatData.system.statut
|
||||
chatData.system.formeLabel = formeLabels[chatData.system.forme] ?? chatData.system.forme
|
||||
}
|
||||
|
||||
const html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-mournblade/templates/post-item.hbs', chatData)
|
||||
ChatMessage.create({ user: game.user.id, content: html })
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ export default class MournbladeCreatureSheet extends MournbladeActorSheet {
|
||||
static PARTS = {
|
||||
sheet: {
|
||||
template: "systems/fvtt-mournblade/templates/creature-sheet.hbs",
|
||||
scrollable: [".tab.competences", ".tab.equipement", ".tab.biodata"],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ export default class MournbladePersonnageSheet extends MournbladeActorSheet {
|
||||
static PARTS = {
|
||||
sheet: {
|
||||
template: "systems/fvtt-mournblade/templates/actor-sheet.hbs",
|
||||
scrollable: [".tab.principal", ".tab.competences", ".tab.dons", ".tab.equipement"],
|
||||
},
|
||||
}
|
||||
|
||||
@@ -35,6 +36,8 @@ export default class MournbladePersonnageSheet extends MournbladeActorSheet {
|
||||
context.dons = foundry.utils.duplicate(actor.getDons())
|
||||
context.pactes = foundry.utils.duplicate(actor.getPactes())
|
||||
context.alignement = actor.getAlignement()
|
||||
context.isChaotique = context.alignement === "chaotique"
|
||||
context.isLoyal = context.alignement === "loyal"
|
||||
context.aspect = actor.getAspect()
|
||||
context.marge = actor.getMarge()
|
||||
context.tendances = foundry.utils.duplicate(actor.getTendances())
|
||||
@@ -46,6 +49,7 @@ export default class MournbladePersonnageSheet extends MournbladeActorSheet {
|
||||
context.metier = foundry.utils.duplicate(actor.getMetier() || {})
|
||||
context.combat = actor.getCombatValues()
|
||||
context.equipements = foundry.utils.duplicate(actor.getEquipments())
|
||||
context.potions = foundry.utils.duplicate(actor.getPotions())
|
||||
context.modifiers = foundry.utils.duplicate(actor.getModifiers())
|
||||
context.monnaies = foundry.utils.duplicate(actor.getMonnaies())
|
||||
context.runeEffects = foundry.utils.duplicate(actor.getRuneEffects())
|
||||
|
||||
Reference in New Issue
Block a user