406 lines
12 KiB
JavaScript
406 lines
12 KiB
JavaScript
const { HandlebarsApplicationMixin } = foundry.applications.api
|
|
|
|
import { MournbladeUtility } from "../../mournblade-utility.js"
|
|
|
|
export default class MournbladeActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
|
/**
|
|
* Different sheet modes.
|
|
* @enum {number}
|
|
*/
|
|
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
|
|
|
|
constructor(options = {}) {
|
|
super(options)
|
|
this.#dragDrop = this.#createDragDropHandlers()
|
|
this._sheetMode = this.constructor.SHEET_MODES.PLAY // Commencer en mode visualisation
|
|
}
|
|
|
|
#dragDrop
|
|
|
|
/** @override */
|
|
static DEFAULT_OPTIONS = {
|
|
classes: ["fvtt-mournblade", "sheet", "actor"],
|
|
position: {
|
|
width: 650,
|
|
height: 720,
|
|
},
|
|
form: {
|
|
submitOnChange: true,
|
|
closeOnSubmit: false,
|
|
},
|
|
window: {
|
|
resizable: true,
|
|
},
|
|
tabs: [
|
|
{
|
|
navSelector: 'nav[data-group="primary"]',
|
|
contentSelector: "section.sheet-body",
|
|
initial: "stats",
|
|
},
|
|
],
|
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
|
actions: {
|
|
editImage: MournbladeActorSheet.#onEditImage,
|
|
toggleSheet: MournbladeActorSheet.#onToggleSheet,
|
|
editItem: MournbladeActorSheet.#onEditItem,
|
|
deleteItem: MournbladeActorSheet.#onDeleteItem,
|
|
createItem: MournbladeActorSheet.#onCreateItem,
|
|
equipItem: MournbladeActorSheet.#onEquipItem,
|
|
modifyQuantity: MournbladeActorSheet.#onModifyQuantity,
|
|
modifySante: MournbladeActorSheet.#onModifySante,
|
|
modifyAme: MournbladeActorSheet.#onModifyAme,
|
|
rollAttribut: MournbladeActorSheet.#onRollAttribut,
|
|
rollCompetence: MournbladeActorSheet.#onRollCompetence,
|
|
rollRune: MournbladeActorSheet.#onRollRune,
|
|
rollArmeOffensif: MournbladeActorSheet.#onRollArmeOffensif,
|
|
rollArmeSpecial: MournbladeActorSheet.#onRollArmeSpecial,
|
|
rollArmeDegats: MournbladeActorSheet.#onRollArmeDegats,
|
|
rollAssommer: MournbladeActorSheet.#onRollAssommer,
|
|
rollImmobiliser: MournbladeActorSheet.#onRollImmobiliser,
|
|
rollFuir: MournbladeActorSheet.#onRollFuir,
|
|
},
|
|
}
|
|
|
|
/**
|
|
* Is the sheet currently in 'Play' mode?
|
|
* @type {boolean}
|
|
*/
|
|
get isPlayMode() {
|
|
if (this._sheetMode === undefined) this._sheetMode = this.constructor.SHEET_MODES.PLAY
|
|
return this._sheetMode === this.constructor.SHEET_MODES.PLAY
|
|
}
|
|
|
|
/**
|
|
* Is the sheet currently in 'Edit' mode?
|
|
* @type {boolean}
|
|
*/
|
|
get isEditMode() {
|
|
if (this._sheetMode === undefined) this._sheetMode = this.constructor.SHEET_MODES.PLAY
|
|
return this._sheetMode === this.constructor.SHEET_MODES.EDIT
|
|
}
|
|
|
|
/**
|
|
* Tab groups state
|
|
* @type {object}
|
|
*/
|
|
tabGroups = { primary: "stats" }
|
|
|
|
/** @override */
|
|
async _prepareContext() {
|
|
const actor = this.document
|
|
|
|
const context = {
|
|
actor: actor,
|
|
system: actor.system,
|
|
source: actor.toObject(),
|
|
fields: actor.schema.fields,
|
|
systemFields: actor.system.schema.fields,
|
|
isEditable: this.isEditable,
|
|
isEditMode: this.isEditMode,
|
|
isPlayMode: this.isPlayMode,
|
|
isGM: game.user.isGM,
|
|
config: game.system.mournblade.config,
|
|
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.description || "", { async: true }),
|
|
}
|
|
return context
|
|
}
|
|
|
|
/** @override */
|
|
_onRender(context, options) {
|
|
super._onRender(context, options)
|
|
this.#dragDrop.forEach((d) => d.bind(this.element))
|
|
|
|
// Handle edit-item-data changes
|
|
this.element.querySelectorAll('.edit-item-data').forEach(element => {
|
|
element.addEventListener('change', async (event) => {
|
|
const target = event.currentTarget
|
|
const itemElement = target.closest('[data-item-id]')
|
|
if (!itemElement) return
|
|
|
|
const itemId = itemElement.dataset.itemId
|
|
const itemType = itemElement.dataset.itemType
|
|
const itemField = target.dataset.itemField
|
|
const dataType = target.dataset.dtype
|
|
const value = target.value
|
|
|
|
await this.document.editItemField(itemId, itemType, itemField, dataType, value)
|
|
})
|
|
})
|
|
|
|
// Activate tab navigation manually
|
|
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"
|
|
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()
|
|
})
|
|
})
|
|
|
|
// Show/hide tab content
|
|
this.element.querySelectorAll('[data-group="' + group + '"][data-tab]').forEach(content => {
|
|
content.classList.toggle('active', content.dataset.tab === activeTab)
|
|
})
|
|
}
|
|
}
|
|
|
|
// #region Drag-and-Drop Workflow
|
|
/**
|
|
* Create drag-and-drop workflow handlers for this Application
|
|
*/
|
|
#createDragDropHandlers() {
|
|
return []
|
|
}
|
|
|
|
// #region Actions
|
|
/** @override */
|
|
static ACTIONS = {
|
|
editImage: MournbladeActorSheet.#onEditImage,
|
|
toggleSheet: MournbladeActorSheet.#onToggleSheet,
|
|
editItem: MournbladeActorSheet.#onEditItem,
|
|
deleteItem: MournbladeActorSheet.#onDeleteItem,
|
|
createItem: MournbladeActorSheet.#onCreateItem,
|
|
equipItem: MournbladeActorSheet.#onEquipItem,
|
|
modifyQuantity: MournbladeActorSheet.#onModifyQuantity,
|
|
rollAttribut: MournbladeActorSheet.#onRollAttribut,
|
|
rollCompetence: MournbladeActorSheet.#onRollCompetence,
|
|
rollArmeOffensif: MournbladeActorSheet.#onRollArmeOffensif,
|
|
rollArmeDegats: MournbladeActorSheet.#onRollArmeDegats,
|
|
rollAssommer: MournbladeActorSheet.#onRollAssommer,
|
|
rollImmobiliser: MournbladeActorSheet.#onRollImmobiliser,
|
|
rollFuir: MournbladeActorSheet.#onRollFuir,
|
|
}
|
|
|
|
/**
|
|
* Handle editing the actor image
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onEditImage(event) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
const filePicker = new FilePicker({
|
|
type: "image",
|
|
current: sheet.document.img,
|
|
callback: (path) => {
|
|
sheet.document.update({ img: path })
|
|
},
|
|
})
|
|
filePicker.browse()
|
|
}
|
|
|
|
/**
|
|
* Handle toggling the sheet mode
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onToggleSheet(event) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
sheet._sheetMode = sheet._sheetMode === sheet.constructor.SHEET_MODES.PLAY ? sheet.constructor.SHEET_MODES.EDIT : sheet.constructor.SHEET_MODES.PLAY
|
|
sheet.render()
|
|
}
|
|
|
|
/**
|
|
* Handle editing an item
|
|
* @param {Event} event - The triggering event
|
|
* @param {HTMLElement} target - The target element
|
|
*/
|
|
static async #onEditItem(event, target) {
|
|
const li = target.closest(".item")
|
|
const itemId = li?.dataset.itemId
|
|
if (!itemId) return
|
|
const item = this.actor.items.get(itemId)
|
|
if (item) item.sheet.render(true)
|
|
}
|
|
|
|
/**
|
|
* Handle deleting an item
|
|
* @param {Event} event - The triggering event
|
|
* @param {HTMLElement} target - The target element
|
|
*/
|
|
static async #onDeleteItem(event, target) {
|
|
const li = target.closest(".item")
|
|
await MournbladeUtility.confirmDelete(this, li)
|
|
}
|
|
|
|
/**
|
|
* Handle creating an item
|
|
* @param {Event} event - The triggering event
|
|
* @param {HTMLElement} target - The target element
|
|
*/
|
|
static async #onCreateItem(event, target) {
|
|
const itemType = target.dataset.type
|
|
await this.actor.createEmbeddedDocuments("Item", [{ name: `Nouveau ${itemType}`, type: itemType }], { renderSheet: true })
|
|
}
|
|
|
|
/**
|
|
* Handle equipping an item
|
|
* @param {Event} event - The triggering event
|
|
* @param {HTMLElement} target - The target element
|
|
*/
|
|
static async #onEquipItem(event, target) {
|
|
const li = target.closest(".item")
|
|
const itemId = li?.dataset.itemId
|
|
if (!itemId) return
|
|
const item = this.actor.items.get(itemId)
|
|
if (item) {
|
|
await item.update({ "system.equipped": !item.system.equipped })
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle modifying the quantity of an item
|
|
* @param {Event} event - The triggering event
|
|
* @param {HTMLElement} target - The target element
|
|
*/
|
|
static async #onModifyQuantity(event, target) {
|
|
const li = target.closest('[data-item-id]')
|
|
const itemId = li?.dataset.itemId
|
|
const value = Number.parseInt(target.dataset.quantiteValue)
|
|
const item = this.document.items.get(itemId)
|
|
if (item) {
|
|
const newQuantity = Math.max(0, (item.system.quantite || 0) + value)
|
|
await item.update({ "system.quantite": newQuantity })
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle modifying santé (health) values
|
|
* @param {Event} event - The triggering event
|
|
* @param {HTMLElement} target - The target element
|
|
*/
|
|
static async #onModifySante(event, target) {
|
|
const type = target.dataset.type
|
|
const value = Number.parseInt(target.dataset.value)
|
|
const actor = this.document
|
|
const currentValue = actor.system.sante[type] || 0
|
|
const newValue = Math.max(0, currentValue + value)
|
|
await actor.update({ [`system.sante.${type}`]: newValue })
|
|
}
|
|
|
|
/**
|
|
* Handle modifying âme (soul) value
|
|
* @param {Event} event - The triggering event
|
|
* @param {HTMLElement} target - The target element
|
|
*/
|
|
static async #onModifyAme(event, target) {
|
|
const value = Number.parseInt(target.dataset.value)
|
|
const actor = this.document
|
|
const currentValue = actor.system.ame.value || 0
|
|
const newValue = Math.max(0, currentValue + value)
|
|
await actor.update({ "system.ame.value": newValue })
|
|
}
|
|
|
|
/**
|
|
* Handle rolling an attribut
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onRollAttribut(event, target) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
const attrKey = target.dataset.attrKey
|
|
const actor = sheet.document
|
|
await actor.rollAttribut(attrKey)
|
|
}
|
|
|
|
/**
|
|
* Handle rolling a competence
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onRollCompetence(event, target) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
const attrKey = target.dataset.attrKey
|
|
const li = target.closest('[data-item-id]')
|
|
const compId = li?.dataset.itemId
|
|
const actor = sheet.document
|
|
await actor.rollCompetence(attrKey, compId)
|
|
}
|
|
|
|
/**
|
|
* Handle rolling a rune
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onRollRune(event, target) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
const li = target.closest('[data-item-id]')
|
|
const runeId = li?.dataset.itemId
|
|
const actor = sheet.document
|
|
await actor.rollRune(runeId)
|
|
}
|
|
|
|
/**
|
|
* Handle rolling an arme offensif
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onRollArmeOffensif(event, target) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
const armeId = target.dataset.armeId
|
|
const actor = sheet.document
|
|
await actor.rollArmeOffensif(armeId)
|
|
}
|
|
|
|
/**
|
|
* Handle rolling an arme degats
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onRollArmeDegats(event, target) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
const armeId = target.dataset.armeId
|
|
const actor = sheet.document
|
|
await actor.rollArmeDegats(armeId)
|
|
}
|
|
|
|
/**
|
|
* Handle rolling an arme special
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onRollArmeSpecial(event, target) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
const armeId = target.dataset.armeId
|
|
const actor = sheet.document
|
|
await actor.rollArmeSpecial(armeId)
|
|
}
|
|
|
|
/**
|
|
* Handle rolling an assommer
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onRollAssommer(event, target) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
const actor = sheet.document
|
|
await actor.rollAssomer()
|
|
}
|
|
|
|
/**
|
|
* Handle rolling an immobiliser
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onRollImmobiliser(event, target) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
const actor = sheet.document
|
|
await actor.rollImmobiliser()
|
|
}
|
|
|
|
/**
|
|
* Handle rolling a fuir
|
|
* @param {Event} event - The triggering event
|
|
*/
|
|
static async #onRollFuir(event, target) {
|
|
event.preventDefault()
|
|
const sheet = this
|
|
const actor = sheet.document
|
|
await actor.rollFuir()
|
|
}
|
|
} |