226 lines
6.7 KiB
JavaScript
226 lines
6.7 KiB
JavaScript
const { HandlebarsApplicationMixin } = foundry.applications.api
|
|
|
|
import { MaleficesUtility } from "../../malefices-utility.js"
|
|
|
|
export default class MaleficesActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
|
|
|
constructor(options = {}) {
|
|
super(options)
|
|
this.#dragDrop = this.#createDragDropHandlers()
|
|
this._editScore = true
|
|
}
|
|
|
|
#dragDrop
|
|
|
|
/** @override */
|
|
static DEFAULT_OPTIONS = {
|
|
classes: ["fvtt-malefices", "actor"],
|
|
position: {
|
|
width: 640,
|
|
height: 680,
|
|
},
|
|
form: {
|
|
submitOnChange: true,
|
|
},
|
|
window: {
|
|
resizable: true,
|
|
},
|
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
|
actions: {
|
|
editImage: MaleficesActorSheet.#onEditImage,
|
|
toggleSheet: MaleficesActorSheet.#onToggleSheet,
|
|
editItem: MaleficesActorSheet.#onEditItem,
|
|
deleteItem: MaleficesActorSheet.#onDeleteItem,
|
|
createItem: MaleficesActorSheet.#onCreateItem,
|
|
equipItem: MaleficesActorSheet.#onEquipItem,
|
|
modifyQuantity: MaleficesActorSheet.#onModifyQuantity,
|
|
modifyAmmo: MaleficesActorSheet.#onModifyAmmo,
|
|
rollAttribut: MaleficesActorSheet.#onRollAttribut,
|
|
rollArme: MaleficesActorSheet.#onRollArme,
|
|
editSubActor: MaleficesActorSheet.#onEditSubActor,
|
|
deleteSubActor: MaleficesActorSheet.#onDeleteSubActor,
|
|
},
|
|
}
|
|
|
|
/** @type {object} */
|
|
tabGroups = { primary: "main" }
|
|
|
|
/** @override */
|
|
async _prepareContext() {
|
|
const actor = this.document
|
|
return {
|
|
actor,
|
|
system: actor.system,
|
|
source: actor.toObject(),
|
|
fields: actor.schema.fields,
|
|
systemFields: actor.system.schema.fields,
|
|
isEditable: this.isEditable,
|
|
cssClass: this.isEditable ? "editable" : "locked",
|
|
isGM: game.user.isGM,
|
|
config: game.system.malefices.config,
|
|
editScore: this._editScore,
|
|
}
|
|
}
|
|
|
|
/** @override */
|
|
_onRender(context, options) {
|
|
super._onRender(context, options)
|
|
this.#dragDrop.forEach((d) => d.bind(this.element))
|
|
|
|
// Ignore Enter key in text inputs (not textarea)
|
|
this.element.addEventListener('keydown', (e) => {
|
|
if (e.key === 'Enter' && e.target.tagName !== 'TEXTAREA') e.preventDefault()
|
|
})
|
|
|
|
// Manual tab navigation
|
|
const nav = this.element.querySelector('nav.tabs[data-group]')
|
|
if (nav) {
|
|
const group = nav.dataset.group
|
|
const activeTab = this.tabGroups[group] || "main"
|
|
nav.querySelectorAll('[data-tab]').forEach(link => {
|
|
link.classList.toggle('active', link.dataset.tab === activeTab)
|
|
link.addEventListener('click', (event) => {
|
|
event.preventDefault()
|
|
this.tabGroups[group] = link.dataset.tab
|
|
this.render()
|
|
})
|
|
})
|
|
this.element.querySelectorAll(`[data-group="${group}"][data-tab]`).forEach(content => {
|
|
content.classList.toggle('active', content.dataset.tab === activeTab)
|
|
})
|
|
}
|
|
|
|
// Handle .update-field change events (legacy support)
|
|
this.element.querySelectorAll('.update-field').forEach(el => {
|
|
el.addEventListener('change', (ev) => {
|
|
const fieldName = ev.currentTarget.dataset.fieldName
|
|
const value = Number(ev.currentTarget.value)
|
|
this.actor.update({ [fieldName]: value })
|
|
})
|
|
})
|
|
}
|
|
|
|
// #region Drag-and-Drop
|
|
#createDragDropHandlers() {
|
|
return this.options.dragDrop.map((d) => {
|
|
d.permissions = {
|
|
dragstart: this._canDragStart.bind(this),
|
|
drop: this._canDragDrop.bind(this),
|
|
}
|
|
d.callbacks = {
|
|
dragstart: this._onDragStart.bind(this),
|
|
dragover: this._onDragOver.bind(this),
|
|
drop: this._onDrop.bind(this),
|
|
}
|
|
return new foundry.applications.ux.DragDrop.implementation(d)
|
|
})
|
|
}
|
|
|
|
_canDragStart(selector) { return this.isEditable }
|
|
_canDragDrop(selector) { return this.isEditable }
|
|
|
|
_onDragStart(event) {
|
|
const li = event.currentTarget.closest('.item')
|
|
if (!li) return
|
|
const itemId = li.dataset.itemId
|
|
const item = this.actor.items.get(itemId)
|
|
if (item) {
|
|
event.dataTransfer.setData("text/plain", JSON.stringify({ type: "Item", uuid: item.uuid }))
|
|
}
|
|
}
|
|
|
|
_onDragOver(event) {}
|
|
|
|
async _onDrop(event) {
|
|
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
|
|
if (data?.type === "Actor") {
|
|
const actor = await fromUuid(data.uuid)
|
|
if (actor) this.actor.addSubActor(actor.id)
|
|
} else {
|
|
super._onDrop(event)
|
|
}
|
|
}
|
|
// #endregion
|
|
|
|
// #region Actions
|
|
static async #onEditImage(event, target) {
|
|
const fp = new FilePicker({
|
|
type: "image",
|
|
current: this.document.img,
|
|
callback: (path) => { this.document.update({ img: path }) },
|
|
})
|
|
return fp.browse()
|
|
}
|
|
|
|
static async #onToggleSheet(event, target) {
|
|
this._editScore = !this._editScore
|
|
this.render()
|
|
}
|
|
|
|
static async #onEditItem(event, target) {
|
|
const li = target.closest(".item")
|
|
const itemId = li?.dataset.itemId
|
|
if (!itemId) return
|
|
this.actor.items.get(itemId)?.sheet.render(true)
|
|
}
|
|
|
|
static async #onDeleteItem(event, target) {
|
|
const li = target.closest(".item")
|
|
MaleficesUtility.confirmDelete(this, li)
|
|
}
|
|
|
|
static async #onCreateItem(event, target) {
|
|
const dataType = target.dataset.type
|
|
this.actor.createEmbeddedDocuments('Item', [{ name: "NewItem", type: dataType }], { renderSheet: true })
|
|
}
|
|
|
|
static async #onEquipItem(event, target) {
|
|
const li = target.closest(".item")
|
|
const itemId = li?.dataset.itemId
|
|
if (!itemId) return
|
|
await this.actor.equipItem(itemId)
|
|
this.render()
|
|
}
|
|
|
|
static async #onModifyQuantity(event, target) {
|
|
const li = target.closest(".item")
|
|
const itemId = li?.dataset.itemId
|
|
if (!itemId) return
|
|
const delta = parseInt(target.dataset.delta) || 0
|
|
this.actor.incDecQuantity(itemId, delta)
|
|
}
|
|
|
|
static async #onModifyAmmo(event, target) {
|
|
const li = target.closest(".item")
|
|
const itemId = li?.dataset.itemId
|
|
if (!itemId) return
|
|
const delta = parseInt(target.dataset.delta) || 0
|
|
this.actor.incDecAmmo(itemId, delta)
|
|
}
|
|
|
|
static async #onRollAttribut(event, target) {
|
|
const attrKey = target.dataset.attrKey
|
|
this.actor.rollAttribut(attrKey)
|
|
}
|
|
|
|
static async #onRollArme(event, target) {
|
|
const armeId = target.dataset.armeId
|
|
this.actor.rollArme(armeId)
|
|
}
|
|
|
|
static async #onEditSubActor(event, target) {
|
|
const li = target.closest(".item")
|
|
const actorId = li?.dataset.actorId
|
|
if (!actorId) return
|
|
game.actors.get(actorId)?.sheet.render(true)
|
|
}
|
|
|
|
static async #onDeleteSubActor(event, target) {
|
|
const li = target.closest(".item")
|
|
const actorId = li?.dataset.actorId
|
|
if (!actorId) return
|
|
this.actor.delSubActor(actorId)
|
|
}
|
|
// #endregion
|
|
}
|