- min: 0 sur reliability (l'update à 0 était clippé à 1 par le schéma — l'état 'détruit' était inatteignable) - réparation de fortune (règles p. 39) : +1D si le personnage possède la Compétence requise, sinon Handicap de Rareté de cette Compétence (rarity du skill de l'acteur) ; select toujours visible (compétence requise) et pré-rempli depuis needSkill/skill de l'item - dés marqués 'dommage' uniquement pour les Dommages réellement comptés (Étanche/Coque absorbe → dés non marqués) - destruction : damages.value réel conservé (difficulté de réparation honnête au lieu de 5 forcé) - états de panne localisés (VERMINE.damages_state_N), aussi dans panneState() - ReliabilityDialog invoqué via .create() (convention du codebase)
138 lines
5.3 KiB
JavaScript
138 lines
5.3 KiB
JavaScript
const { HandlebarsApplicationMixin } = foundry.applications.api
|
|
|
|
/**
|
|
* Fiche de base pour tous les items Vermine 2047 (ApplicationV2).
|
|
*/
|
|
export class VermineBaseItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
|
|
|
|
// ── Mode édition ────────────────────────────────────────────────────
|
|
|
|
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
|
|
|
|
_sheetMode = this.constructor.SHEET_MODES.PLAY
|
|
|
|
get isPlayMode() { return this._sheetMode === this.constructor.SHEET_MODES.PLAY }
|
|
get isEditMode() { return this._sheetMode === this.constructor.SHEET_MODES.EDIT }
|
|
|
|
// ── Options par défaut ──────────────────────────────────────────────
|
|
|
|
static DEFAULT_OPTIONS = {
|
|
classes: ["vermine2047", "item"],
|
|
position: { width: 560, height: "auto" },
|
|
form: { submitOnChange: true },
|
|
window: { resizable: true },
|
|
actions: {
|
|
editImage: VermineBaseItemSheet.#onEditImage,
|
|
toggleSheet: VermineBaseItemSheet.#onToggleSheet,
|
|
clickDamage: VermineBaseItemSheet.#onClickDamage,
|
|
openTraits: VermineBaseItemSheet.#onOpenTraits,
|
|
reliabilityTest: VermineBaseItemSheet.#onReliabilityTest,
|
|
reliabilityRepair: VermineBaseItemSheet.#onReliabilityRepair
|
|
}
|
|
}
|
|
|
|
// ── Drag & Drop ─────────────────────────────────────────────────────
|
|
|
|
#dragDrop
|
|
|
|
constructor(options = {}) {
|
|
super(options)
|
|
this.#dragDrop = this.#createDragDropHandlers()
|
|
}
|
|
|
|
#createDragDropHandlers() {
|
|
if (!this.options.dragDrop) return []
|
|
return this.options.dragDrop.map(d => {
|
|
d.permissions = {
|
|
dragstart: this._canDragStart.bind(this),
|
|
drop: this._canDragDrop.bind(this)
|
|
}
|
|
d.callbacks = {
|
|
dragover: this._onDragOver.bind(this),
|
|
drop: this._onDrop.bind(this)
|
|
}
|
|
return new foundry.applications.ux.DragDrop.implementation(d)
|
|
})
|
|
}
|
|
|
|
_canDragStart() { return this.isEditable }
|
|
_canDragDrop() { return this.isEditable }
|
|
|
|
// ── Contexte commun ─────────────────────────────────────────────────
|
|
|
|
async _prepareContext() {
|
|
return {
|
|
fields: this.document.schema.fields,
|
|
systemFields: this.document.system.schema.fields,
|
|
item: this.document,
|
|
system: this.document.system,
|
|
source: this.document.toObject(),
|
|
config: CONFIG.VERMINE,
|
|
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true }),
|
|
isEditMode: this.isEditMode,
|
|
isPlayMode: this.isPlayMode,
|
|
isEditable: this.isEditable
|
|
}
|
|
}
|
|
|
|
// ── Rendu ───────────────────────────────────────────────────────────
|
|
|
|
_onRender(context, options) {
|
|
super._onRender(context, options);
|
|
this.#dragDrop.forEach(d => d.bind(this.element))
|
|
}
|
|
|
|
// ── Sauvegarde ───────────────────────────────────────────────────────
|
|
|
|
/** @override */
|
|
_prepareSubmitData(event, form, formData, updateData) {
|
|
return super._prepareSubmitData(event, form, formData, updateData)
|
|
}
|
|
|
|
// ── Actions ─────────────────────────────────────────────────────────
|
|
|
|
static #onToggleSheet() {
|
|
const modes = this.constructor.SHEET_MODES
|
|
this._sheetMode = this.isEditMode ? modes.PLAY : modes.EDIT
|
|
this.render()
|
|
}
|
|
|
|
static async #onEditImage(event, target) {
|
|
const attr = target.dataset.edit ?? "img"
|
|
const current = foundry.utils.getProperty(this.document, attr)
|
|
const fp = new FilePicker({
|
|
current,
|
|
type: "image",
|
|
callback: (path) => this.document.update({ [attr]: path }),
|
|
top: this.position.top + 40,
|
|
left: this.position.left + 10
|
|
})
|
|
return fp.browse()
|
|
}
|
|
|
|
static #onClickDamage(event, target) {
|
|
// Les radios de dégâts sont 1-based dans le template (value="{{@index}}" avec index 1..max)
|
|
// mais le stockage est 0-based. On soustrait 1 avant de sauvegarder.
|
|
const prop = target.name
|
|
const value = parseInt(target.value) - 1
|
|
this.document.update({ [prop]: value })
|
|
}
|
|
|
|
static async #onOpenTraits(event, target) {
|
|
const { TraitSelector } = await import("../../system/applications.mjs")
|
|
new TraitSelector(this.document).render(true)
|
|
}
|
|
|
|
static async #onReliabilityTest() {
|
|
const { ReliabilityDialog } = await import("../../system/dialogs/reliabilityDialog.mjs")
|
|
const dialog = await ReliabilityDialog.create({ item: this.document, mode: "test" })
|
|
await dialog.render(true)
|
|
}
|
|
|
|
static async #onReliabilityRepair() {
|
|
const { ReliabilityDialog } = await import("../../system/dialogs/reliabilityDialog.mjs")
|
|
const dialog = await ReliabilityDialog.create({ item: this.document, mode: "repair" })
|
|
await dialog.render(true)
|
|
}
|
|
}
|