Esprit de la Loi + Automaton

This commit is contained in:
2026-05-02 23:16:10 +02:00
parent d6b5891519
commit 0df4a5a9fb
280 changed files with 10668 additions and 419 deletions
@@ -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