Migration datamodels !

This commit is contained in:
2026-01-10 16:05:56 +01:00
parent 627ccc707b
commit 438caf3b1c
3946 changed files with 318813 additions and 3453 deletions

View File

@@ -0,0 +1,382 @@
const { HandlebarsApplicationMixin } = foundry.applications.api
import { WastelandUtility } from "../../wasteland-utility.js"
export default class WastelandActorSheet 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
}
#dragDrop
/** @override */
static DEFAULT_OPTIONS = {
classes: ["fvtt-wasteland", "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: WastelandActorSheet.#onEditImage,
toggleSheet: WastelandActorSheet.#onToggleSheet,
editItem: WastelandActorSheet.#onEditItem,
deleteItem: WastelandActorSheet.#onDeleteItem,
createItem: WastelandActorSheet.#onCreateItem,
equipItem: WastelandActorSheet.#onEquipItem,
modifyQuantity: WastelandActorSheet.#onModifyQuantity,
incDecSante: WastelandActorSheet.#onIncDecSante,
rollAttribut: WastelandActorSheet.#onRollAttribut,
rollCompetence: WastelandActorSheet.#onRollCompetence,
rollCharme: WastelandActorSheet.#onRollCharme,
rollPouvoir: WastelandActorSheet.#onRollPouvoir,
rollArmeOffensif: WastelandActorSheet.#onRollArmeOffensif,
rollArmeDegats: WastelandActorSheet.#onRollArmeDegats,
resetPredilections: WastelandActorSheet.#onResetPredilections,
rollAssommer: WastelandActorSheet.#onRollAssommer,
rollFuir: WastelandActorSheet.#onRollFuir,
rollImmobiliser: WastelandActorSheet.#onRollImmobiliser,
},
}
/**
* 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.wasteland.config,
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.description || "", { async: true }),
enrichedComportement: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.comportement || "", { async: true }),
enrichedHabitat: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.habitat || "", { 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
/**
* 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 WastelandUtility.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
await this.actor.equipItem(itemId)
}
/**
* Handle modifying item quantity
* @param {Event} event - The triggering event
* @param {HTMLElement} target - The target element
*/
static async #onModifyQuantity(event, target) {
const li = target.closest(".item")
const itemId = li?.dataset.itemId
if (!itemId) return
const item = this.actor.items.get(itemId)
if (!item) return
const qty = parseInt(target.dataset.qty) || 0
const currentQty = item.system.quantite || 0
const newQty = Math.max(0, currentQty + qty)
await item.update({ 'system.quantite': newQty })
}
/**
* Handle modifying santé/psyché
* @param {Event} event - The triggering event
* @param {HTMLElement} target - The target element
*/
static async #onIncDecSante(event, target) {
const field = target.dataset.field
const value = parseInt(target.dataset.value) || 0
if (field === 'psyche') {
await this.actor.update({ 'system.psyche.value': this.actor.system.psyche.value + value })
} else if (field === 'nonletaux') {
await this.actor.update({ 'system.sante.nonletaux': this.actor.system.sante.nonletaux + value })
} else if (field === 'letaux') {
await this.actor.update({ 'system.sante.letaux': this.actor.system.sante.letaux + value })
}
}
/**
* Handle rolling an attribute
* @param {Event} event - The triggering event
* @param {HTMLElement} target - The target element
*/
static async #onRollAttribut(event, target) {
const attrKey = target.dataset.attrKey
await this.actor.rollAttribut(attrKey)
}
/**
* Handle rolling a competence
* @param {Event} event - The triggering event
* @param {HTMLElement} target - The target element
*/
static async #onRollCompetence(event, target) {
const li = target.closest(".item")
const itemId = li?.dataset.itemId
const attrKey = target.dataset.attrKey
if (!itemId) return
await this.actor.rollCompetence(attrKey, itemId)
}
/**
* Handle rolling a charme
* @param {Event} event - The triggering event
* @param {HTMLElement} target - The target element
*/
static async #onRollCharme(event, target) {
const li = target.closest(".item")
const itemId = li?.dataset.itemId
if (!itemId) return
await this.actor.rollCharme(itemId)
}
/**
* Handle rolling a pouvoir
* @param {Event} event - The triggering event
* @param {HTMLElement} target - The target element
*/
static async #onRollPouvoir(event, target) {
const li = target.closest(".item")
const itemId = li?.dataset.itemId
if (!itemId) return
await this.actor.rollPouvoir(itemId)
}
/**
* Handle rolling weapon attack
* @param {Event} event - The triggering event
* @param {HTMLElement} target - The target element
*/
static async #onRollArmeOffensif(event, target) {
const li = target.closest(".item")
const itemId = li?.dataset.itemId
if (!itemId) return
await this.actor.rollArmeOffensif(itemId)
}
/**
* Handle rolling weapon damage
* @param {Event} event - The triggering event
* @param {HTMLElement} target - The target element
*/
static async #onRollArmeDegats(event, target) {
const li = target.closest(".item")
const itemId = li?.dataset.itemId
if (!itemId) return
await this.actor.rollArmeDegats(itemId)
}
/**
* Handle resetting all predilections
* @param {Event} event - The originating click event
* @param {HTMLElement} target - The target element
*/
static async #onResetPredilections(event, target) {
await this.actor.resetAllPredilections()
}
/**
* Handle Assommer roll
* @param {Event} event - The originating click event
* @param {HTMLElement} target - The target element
*/
static async #onRollAssommer(event, target) {
await this.actor.rollAssommer()
}
/**
* Handle Fuir roll
* @param {Event} event - The originating click event
* @param {HTMLElement} target - The target element
*/
static async #onRollFuir(event, target) {
await this.actor.rollFuir()
}
/**
* Handle Immobiliser roll
* @param {Event} event - The originating click event
* @param {HTMLElement} target - The target element
*/
static async #onRollImmobiliser(event, target) {
await this.actor.rollImmobiliser()
}
}