Migration complétée vers appv2
This commit is contained in:
@@ -1,179 +1,227 @@
|
||||
/**
|
||||
* Extend the basic ActorSheet with some very simple modifications
|
||||
* @extends {ActorSheet}
|
||||
* Feuille de personnage Te Deum - AppV2
|
||||
*/
|
||||
|
||||
import { TeDeumUtility } from "../common/tedeum-utility.js";
|
||||
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class TeDeumActorPJSheet extends foundry.appv1.sheets.ActorSheet {
|
||||
export class TeDeumActorPJSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
||||
|
||||
constructor(options = {}) {
|
||||
super(options)
|
||||
this._sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||
}
|
||||
|
||||
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["fvtt-te-deum", "sheet", "actor"],
|
||||
template: "systems/fvtt-te-deum/templates/actors/actor-sheet.hbs",
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["fvtt-te-deum", "sheet", "actor"],
|
||||
position: {
|
||||
width: 860,
|
||||
height: 680,
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "skills" }],
|
||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
||||
editScore: true
|
||||
});
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
||||
actions: {
|
||||
editImage: TeDeumActorPJSheet.#onEditImage,
|
||||
toggleSheet: TeDeumActorPJSheet.#onToggleSheet,
|
||||
editItem: TeDeumActorPJSheet.#onEditItem,
|
||||
deleteItem: TeDeumActorPJSheet.#onDeleteItem,
|
||||
createItem: TeDeumActorPJSheet.#onCreateItem,
|
||||
createBlessure: TeDeumActorPJSheet.#onCreateBlessure,
|
||||
createCompetence: TeDeumActorPJSheet.#onCreateCompetence,
|
||||
equipItem: TeDeumActorPJSheet.#onEquipItem,
|
||||
modifyQuantity: TeDeumActorPJSheet.#onModifyQuantity,
|
||||
rollCompetence: TeDeumActorPJSheet.#onRollCompetence,
|
||||
rollArme: TeDeumActorPJSheet.#onRollArme,
|
||||
rollDegats: TeDeumActorPJSheet.#onRollDegats,
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
sheet: {
|
||||
template: "systems/fvtt-te-deum/templates/actors/actor-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
tabGroups = { primary: "principal" }
|
||||
|
||||
get isEditMode() {
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.EDIT
|
||||
}
|
||||
|
||||
get isPlayMode() {
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.PLAY
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
|
||||
let formData = {
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const actor = this.document
|
||||
return {
|
||||
title: this.title,
|
||||
id: this.actor.id,
|
||||
type: this.actor.type,
|
||||
img: this.actor.img,
|
||||
name: this.actor.name,
|
||||
id: actor.id,
|
||||
type: actor.type,
|
||||
img: actor.img,
|
||||
name: actor.name,
|
||||
editable: this.isEditable,
|
||||
cssClass: this.isEditable ? "editable" : "locked",
|
||||
system: foundry.utils.duplicate(this.object.system),
|
||||
limited: this.object.limited,
|
||||
competences: this.actor.getCompetences(),
|
||||
system: foundry.utils.duplicate(actor.system),
|
||||
systemFields: actor.system.schema.fields,
|
||||
limited: actor.limited,
|
||||
competences: actor.getCompetences(),
|
||||
config: foundry.utils.duplicate(game.system.tedeum.config),
|
||||
armes: this.actor.getArmes(),
|
||||
caracList: this.actor.prepareCaracteristiques(),
|
||||
providence: this.actor.prepareProvidence(),
|
||||
arbreCompetences: this.actor.prepareArbreCompetences(),
|
||||
equipements: this.actor.getEquipements(),
|
||||
simples: this.actor.getSimples(),
|
||||
armures: this.actor.getArmures(),
|
||||
graces: this.actor.getGraces(),
|
||||
blessures: this.actor.getBlessures(),
|
||||
maladies: this.actor.getMaladies(),
|
||||
poisons: this.actor.getPoisons(),
|
||||
combat: this.actor.prepareCombat(),
|
||||
bonusDegats: this.actor.getBonusDegats(),
|
||||
nbActions: this.actor.getNbActions(),
|
||||
initiative: this.actor.getInitiative(),
|
||||
pointsArmuresLourdes: this.actor.getNbArmures(),
|
||||
nbArmuresLourdes: this.actor.getNbArmuresLourdesActuel(),
|
||||
santeModifier: this.actor.getSanteModifier(),
|
||||
educations: this.actor.getEducations(),
|
||||
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, { async: true }),
|
||||
equipmentfree: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.equipmentfree, { async: true }),
|
||||
notes: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.notes, { async: true }),
|
||||
histoire: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.histoire, { async: true }),
|
||||
options: this.options,
|
||||
owner: this.document.isOwner,
|
||||
editScore: this.options.editScore,
|
||||
isGM: game.user.isGM
|
||||
armes: actor.getArmes(),
|
||||
caracList: actor.prepareCaracteristiques(),
|
||||
providence: actor.prepareProvidence(),
|
||||
arbreCompetences: actor.prepareArbreCompetences(),
|
||||
equipements: actor.getEquipements(),
|
||||
simples: actor.getSimples(),
|
||||
armures: actor.getArmures(),
|
||||
graces: actor.getGraces(),
|
||||
blessures: actor.getBlessures(),
|
||||
maladies: actor.getMaladies(),
|
||||
poisons: actor.getPoisons(),
|
||||
combat: actor.prepareCombat(),
|
||||
bonusDegats: actor.getBonusDegats(),
|
||||
nbActions: actor.getNbActions(),
|
||||
initiative: actor.getInitiative(),
|
||||
pointsArmuresLourdes: actor.getNbArmures(),
|
||||
nbArmuresLourdes: actor.getNbArmuresLourdesActuel(),
|
||||
santeModifier: actor.getSanteModifier(),
|
||||
educations: actor.getEducations(),
|
||||
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.description, { async: true }),
|
||||
enrichedEquipmentFree: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.equipmentfree, { async: true }),
|
||||
enrichedNotes: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.notes, { async: true }),
|
||||
enrichedHistoire: await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.histoire, { async: true }),
|
||||
owner: actor.isOwner,
|
||||
isEditMode: this.isEditMode,
|
||||
isPlayMode: this.isPlayMode,
|
||||
isGM: game.user.isGM,
|
||||
}
|
||||
this.formData = formData;
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
html.bind("keydown", function (e) { // Ignore Enter in actores sheet
|
||||
if (e.keyCode === 13) return false;
|
||||
});
|
||||
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item-id")
|
||||
let itemId = li.data("item-id")
|
||||
const item = this.actor.items.get(itemId);
|
||||
item.sheet.render(true);
|
||||
});
|
||||
// Delete Inventory Item
|
||||
html.find('.item-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item-id")
|
||||
TeDeumUtility.confirmDelete(this, li).catch("Error : No deletion confirmed")
|
||||
})
|
||||
html.find('.item-add').click(ev => {
|
||||
let dataType = $(ev.currentTarget).data("type")
|
||||
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouveau " + dataType, type: dataType }], { renderSheet: true })
|
||||
})
|
||||
html.find('.blessure-add').click(ev => {
|
||||
let dataType = $(ev.currentTarget).data("type")
|
||||
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvelle " + dataType, type: dataType, system: { typeBlessure: "estafilade", localisation: "corps", value: 0, appliquee: true, description: "" } }], { renderSheet: true })
|
||||
})
|
||||
html.find('.competence-add').click(ev => {
|
||||
let dataType = $(ev.currentTarget).data("type")
|
||||
let caracKey = $(ev.currentTarget).data("carac-key")
|
||||
this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvelle " + dataType, type: dataType, system: { caracteristique: caracKey } }], { renderSheet: true })
|
||||
})
|
||||
|
||||
html.find('.subactor-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
let actorId = li.data("actor-id");
|
||||
let actor = game.actors.get(actorId);
|
||||
actor.sheet.render(true);
|
||||
});
|
||||
|
||||
html.find('.subactor-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
let actorId = li.data("actor-id");
|
||||
this.actor.delSubActor(actorId);
|
||||
});
|
||||
html.find('.quantity-minus').click(event => {
|
||||
const li = $(event.currentTarget).parents(".item");
|
||||
this.actor.incDecQuantity(li.data("item-id"), -1);
|
||||
});
|
||||
html.find('.quantity-plus').click(event => {
|
||||
const li = $(event.currentTarget).parents(".item");
|
||||
this.actor.incDecQuantity(li.data("item-id"), +1);
|
||||
});
|
||||
|
||||
html.find('.roll-competence').click((event) => {
|
||||
let compId = $(event.currentTarget).data("comp-id")
|
||||
this.actor.rollCompetence(compId)
|
||||
});
|
||||
html.find('.roll-arme').click((event) => {
|
||||
const armeId = $(event.currentTarget).data("arme-id")
|
||||
this.actor.rollArme(armeId)
|
||||
});
|
||||
html.find('.roll-degats').click((event) => {
|
||||
const armeId = $(event.currentTarget).data("arme-id")
|
||||
this.actor.rollDegatsArme(armeId)
|
||||
});
|
||||
|
||||
|
||||
html.find('.lock-unlock-sheet').click((event) => {
|
||||
this.options.editScore = !this.options.editScore;
|
||||
this.render(true);
|
||||
});
|
||||
html.find('.item-equip').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
this.actor.equipItem(li.data("item-id"));
|
||||
this.render(true);
|
||||
});
|
||||
html.find('.update-field').change(ev => {
|
||||
const fieldName = $(ev.currentTarget).data("field-name");
|
||||
let value = Number(ev.currentTarget.value);
|
||||
this.actor.update({ [`${fieldName}`]: value });
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
setPosition(options = {}) {
|
||||
const position = super.setPosition(options);
|
||||
const sheetBody = this.element.find(".sheet-body");
|
||||
const bodyHeight = position.height - 192;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options)
|
||||
|
||||
// Tab navigation
|
||||
const nav = this.element.querySelector('nav.tabs[data-group]')
|
||||
if (nav) {
|
||||
const group = nav.dataset.group
|
||||
const activeTab = this.tabGroups[group] || "principal"
|
||||
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()
|
||||
})
|
||||
})
|
||||
this.element.querySelectorAll(`[data-group="${group}"][data-tab]`).forEach(content => {
|
||||
content.classList.toggle('active', content.dataset.tab === activeTab)
|
||||
})
|
||||
}
|
||||
|
||||
// Ignore Enter key in sheet inputs
|
||||
this.element.addEventListener('keydown', e => {
|
||||
if (e.keyCode === 13 && e.target.tagName !== 'TEXTAREA') e.preventDefault()
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
// Update the Actor
|
||||
return this.object.update(formData);
|
||||
// #region Static action handlers
|
||||
|
||||
static async #onEditImage(event) {
|
||||
const fp = new FilePicker({
|
||||
type: "image",
|
||||
current: this.document.img,
|
||||
callback: path => this.document.update({ img: path }),
|
||||
})
|
||||
fp.browse()
|
||||
}
|
||||
|
||||
static async #onToggleSheet(event) {
|
||||
this._sheetMode = this.isEditMode
|
||||
? this.constructor.SHEET_MODES.PLAY
|
||||
: this.constructor.SHEET_MODES.EDIT
|
||||
this.render()
|
||||
}
|
||||
|
||||
static async #onEditItem(event, target) {
|
||||
const li = target.closest("[data-item-id]")
|
||||
const item = this.actor.items.get(li?.dataset.itemId)
|
||||
if (item) item.sheet.render(true)
|
||||
}
|
||||
|
||||
static async #onDeleteItem(event, target) {
|
||||
const li = target.closest("[data-item-id]")
|
||||
await TeDeumUtility.confirmDelete(this, li)
|
||||
}
|
||||
|
||||
static async #onCreateItem(event, target) {
|
||||
const type = target.dataset.type
|
||||
await this.actor.createEmbeddedDocuments('Item', [{ name: "Nouveau " + type, type }], { renderSheet: true })
|
||||
}
|
||||
|
||||
static async #onCreateBlessure(event, target) {
|
||||
const type = target.dataset.type
|
||||
await this.actor.createEmbeddedDocuments('Item', [{
|
||||
name: "Nouvelle " + type, type,
|
||||
system: { typeBlessure: "estafilade", localisation: "corps", value: 0, appliquee: true, description: "" }
|
||||
}], { renderSheet: true })
|
||||
}
|
||||
|
||||
static async #onCreateCompetence(event, target) {
|
||||
const type = target.dataset.type
|
||||
const caracKey = target.dataset.caracKey
|
||||
await this.actor.createEmbeddedDocuments('Item', [{ name: "Nouvelle " + type, type, system: { caracteristique: caracKey } }], { renderSheet: true })
|
||||
}
|
||||
|
||||
static async #onEquipItem(event, target) {
|
||||
const li = target.closest("[data-item-id]")
|
||||
if (!li?.dataset.itemId) return
|
||||
await this.actor.equipItem(li.dataset.itemId)
|
||||
}
|
||||
|
||||
static async #onModifyQuantity(event, target) {
|
||||
const li = target.closest("[data-item-id]")
|
||||
if (!li?.dataset.itemId) return
|
||||
const item = this.actor.items.get(li.dataset.itemId)
|
||||
if (!item) return
|
||||
const delta = parseInt(target.dataset.qty) || 0
|
||||
await this.actor.incDecQuantity(li.dataset.itemId, delta)
|
||||
}
|
||||
|
||||
static async #onRollCompetence(event, target) {
|
||||
const li = target.closest("[data-item-id]")
|
||||
if (!li?.dataset.itemId) return
|
||||
await this.actor.rollCompetence(li.dataset.itemId)
|
||||
}
|
||||
|
||||
static async #onRollArme(event, target) {
|
||||
const li = target.closest("[data-item-id]")
|
||||
if (!li?.dataset.itemId) return
|
||||
await this.actor.rollArme(li.dataset.itemId)
|
||||
}
|
||||
|
||||
static async #onRollDegats(event, target) {
|
||||
const li = target.closest("[data-item-id]")
|
||||
if (!li?.dataset.itemId) return
|
||||
await this.actor.rollDegatsArme(li.dataset.itemId)
|
||||
}
|
||||
|
||||
// #endregion
|
||||
}
|
||||
|
||||
@@ -785,8 +785,7 @@ export class TeDeumActor extends Actor {
|
||||
/* -------------------------------------------- */
|
||||
async startRoll(rollData) {
|
||||
console.log("startRoll", rollData)
|
||||
let rollDialog = await TeDeumRollDialog.create(this, rollData)
|
||||
rollDialog.render(true)
|
||||
await TeDeumRollDialog.create(this, rollData)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -575,7 +575,7 @@ export class TeDeumCharacterCreator {
|
||||
for (let compName in this.competenceBonus) {
|
||||
let comp = actor.items.find( i => i.type == "competence" && i.name.toLowerCase() === compName.toLowerCase())
|
||||
if (comp) {
|
||||
updateComp.push({ _id: comp._id, "system.score": this.competenceBonus[compName].value })
|
||||
updateComp.push({ _id: comp._id, "system.score": comp.system.score + this.competenceBonus[compName].value })
|
||||
} else {
|
||||
toAdd.push( compName)
|
||||
}
|
||||
|
||||
@@ -147,6 +147,14 @@ export class TeDeumUtility {
|
||||
}
|
||||
return value
|
||||
})
|
||||
// Handle v12 removal of this helper
|
||||
Handlebars.registerHelper('select', function (selected, options) {
|
||||
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
|
||||
const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']');
|
||||
const html = options.fn(this);
|
||||
return html.replace(rgx, "$& selected");
|
||||
});
|
||||
|
||||
|
||||
// Load compendium data
|
||||
const competences = await TeDeumUtility.loadCompendium("fvtt-te-deum.competences")
|
||||
@@ -389,7 +397,17 @@ export class TeDeumUtility {
|
||||
'systems/fvtt-te-deum/templates/actors/editor-notes-gm.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/partial-item-nav.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/partial-item-description.hbs',
|
||||
'systems/fvtt-te-deum/templates/dialogs/partial-creator-status.hbs'
|
||||
'systems/fvtt-te-deum/templates/dialogs/partial-creator-status.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/item-arme-sheet.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/item-armure-sheet.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/item-blessure-sheet.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/item-competence-sheet.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/item-education-sheet.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/item-equipement-sheet.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/item-grace-sheet.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/item-maladie-sheet.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/item-origine-sheet.hbs',
|
||||
'systems/fvtt-te-deum/templates/items/item-simple-sheet.hbs',
|
||||
]
|
||||
return foundry.applications.handlebars.loadTemplates(templatePaths);
|
||||
}
|
||||
@@ -885,7 +903,7 @@ export class TeDeumUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async confirmDelete(actorSheet, li) {
|
||||
let itemId = li.data("item-id");
|
||||
let itemId = li.dataset ? li.dataset.itemId : li.data("item-id");
|
||||
let msgTxt = "<p>Etes vous certain de supprimer cet item ?";
|
||||
let buttons = {
|
||||
delete: {
|
||||
@@ -893,7 +911,12 @@ export class TeDeumUtility {
|
||||
label: "Oui, aucun souci",
|
||||
callback: () => {
|
||||
actorSheet.actor.deleteEmbeddedDocuments("Item", [itemId]);
|
||||
li.slideUp(200, () => actorSheet.render(false));
|
||||
if (li.slideUp) {
|
||||
li.slideUp(200, () => actorSheet.render(false));
|
||||
} else {
|
||||
li.style.display = "none";
|
||||
actorSheet.render(false);
|
||||
}
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
|
||||
@@ -1,102 +1,103 @@
|
||||
import { TeDeumUtility } from "../common/tedeum-utility.js";
|
||||
|
||||
export class TeDeumRollDialog extends Dialog {
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class TeDeumRollDialog extends HandlebarsApplicationMixin(foundry.applications.api.ApplicationV2) {
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["fvtt-te-deum", "te-deum-roll-dialog"],
|
||||
window: { title: "Lancer !", resizable: false },
|
||||
position: { width: 540 },
|
||||
actions: {
|
||||
roll: TeDeumRollDialog.#onRoll,
|
||||
cancel: TeDeumRollDialog.#onCancel,
|
||||
}
|
||||
}
|
||||
|
||||
static PARTS = {
|
||||
content: { template: "systems/fvtt-te-deum/templates/dialogs/roll-dialog-generic.hbs" }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(actor, rollData, options = {}) {
|
||||
super(options)
|
||||
this.actor = actor
|
||||
this.rollData = rollData
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async create(actor, rollData) {
|
||||
|
||||
let options = { classes: ["tedeum-roll-dialog"], width: 540, height: 'fit-content', 'z-index': 99999 }
|
||||
let html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-te-deum/templates/dialogs/roll-dialog-generic.hbs', rollData);
|
||||
return new TeDeumRollDialog(actor, rollData, html, options);
|
||||
const dialog = new TeDeumRollDialog(actor, rollData)
|
||||
dialog.render(true)
|
||||
return dialog
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(actor, rollData, html, options, close = undefined) {
|
||||
let conf = {
|
||||
title: "Lancer !",
|
||||
content: html,
|
||||
buttons: {
|
||||
roll: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: "Lancer",
|
||||
callback: () => { this.roll() }
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: "Annuler",
|
||||
callback: () => { this.close() }
|
||||
}
|
||||
},
|
||||
close: close
|
||||
}
|
||||
|
||||
super(conf, options);
|
||||
|
||||
this.actor = actor;
|
||||
this.rollData = rollData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
roll() {
|
||||
TeDeumUtility.rollTeDeum(this.rollData)
|
||||
async _prepareContext() {
|
||||
return { ...this.rollData }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async refreshDialog() {
|
||||
const content = await foundry.applications.handlebars.renderTemplate("systems/fvtt-te-deum/templates/dialogs/roll-dialog-generic.hbs", this.rollData)
|
||||
this.data.content = content
|
||||
this.render(true)
|
||||
this.render()
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
static #onRoll(event, target) {
|
||||
TeDeumUtility.rollTeDeum(this.rollData)
|
||||
this.close()
|
||||
}
|
||||
|
||||
let dialog = this;
|
||||
function onLoad() {
|
||||
}
|
||||
$(function () { onLoad(); });
|
||||
/* -------------------------------------------- */
|
||||
static #onCancel(event, target) {
|
||||
this.close()
|
||||
}
|
||||
|
||||
html.find('#bonusMalusPerso').change((event) => {
|
||||
/* -------------------------------------------- */
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options)
|
||||
|
||||
const html = this.element
|
||||
|
||||
html.querySelector('#bonusMalusPerso')?.addEventListener('change', (event) => {
|
||||
this.rollData.bonusMalusPerso = Number(event.currentTarget.value)
|
||||
})
|
||||
html.find('#roll-allonge').change((event) => {
|
||||
html.querySelector('#roll-allonge')?.addEventListener('change', (event) => {
|
||||
this.rollData.allongeId = event.currentTarget.value
|
||||
})
|
||||
html.find('#roll-main-gauche').change((event) => {
|
||||
html.querySelector('#roll-main-gauche')?.addEventListener('change', (event) => {
|
||||
this.rollData.isMainGauche = event.currentTarget.checked
|
||||
})
|
||||
html.find('#roll-difficulty').change((event) => {
|
||||
html.querySelector('#roll-difficulty')?.addEventListener('change', (event) => {
|
||||
this.rollData.difficulty = String(event.currentTarget.value) || "pardefaut"
|
||||
})
|
||||
html.find('#roll-attaque-ciblee').change((event) => {
|
||||
html.querySelector('#roll-attaque-ciblee')?.addEventListener('change', (event) => {
|
||||
this.rollData.attaqueCiblee = event.currentTarget.value || "0"
|
||||
})
|
||||
html.find('#roll-bonus-malus').change((event) => {
|
||||
html.querySelector('#roll-bonus-malus')?.addEventListener('change', (event) => {
|
||||
this.rollData.bonusMalus = event.currentTarget.value || "0"
|
||||
})
|
||||
html.find('#roll-enable-providence').change((event) => {
|
||||
html.querySelector('#roll-enable-providence')?.addEventListener('change', (event) => {
|
||||
this.rollData.enableProvidence = event.currentTarget.checked
|
||||
})
|
||||
html.find('#roll-portee-tir').change((event) => {
|
||||
html.querySelector('#roll-portee-tir')?.addEventListener('change', (event) => {
|
||||
this.rollData.porteeTir = event.currentTarget.value
|
||||
this.rollData.difficulty = game.system.tedeum.config.ARME_PORTEES[this.rollData.porteeTir].difficulty
|
||||
this.rollData.porteeLabel = game.system.tedeum.config.ARME_PORTEES[this.rollData.porteeTir].label
|
||||
this.refreshDialog()
|
||||
})
|
||||
html.find('#roll-tir-viser').change((event) => {
|
||||
html.querySelector('#roll-tir-viser')?.addEventListener('change', (event) => {
|
||||
this.rollData.isViser = event.currentTarget.checked
|
||||
})
|
||||
html.find('#roll-tir-mouvement').change((event) => {
|
||||
html.querySelector('#roll-tir-mouvement')?.addEventListener('change', (event) => {
|
||||
this.rollData.isMouvement = event.currentTarget.checked
|
||||
})
|
||||
html.find('#roll-charge-a-pied').change((event) => {
|
||||
html.querySelector('#roll-charge-a-pied')?.addEventListener('change', (event) => {
|
||||
this.rollData.isChargeAPied = event.currentTarget.checked
|
||||
})
|
||||
html.find('#roll-charge-a-cheval').change((event) => {
|
||||
html.querySelector('#roll-charge-a-cheval')?.addEventListener('change', (event) => {
|
||||
this.rollData.isChargeACheval = event.currentTarget.checked
|
||||
})
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,172 +1,154 @@
|
||||
import { TeDeumUtility } from "../common/tedeum-utility.js";
|
||||
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
/**
|
||||
* Extend the basic ItemSheet with some very simple modifications
|
||||
* @extends {ItemSheet}
|
||||
* Feuille d'item Te Deum - AppV2
|
||||
*/
|
||||
export class TeDeumItemSheet extends foundry.appv1.sheets.ItemSheet {
|
||||
export class TeDeumItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["fvtt-te-deum", "sheet", "item"],
|
||||
template: "systems/fvtt-te-deum/templates/item-sheet.hbs",
|
||||
dragDrop: [{ dragSelector: null, dropSelector: null }],
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["fvtt-te-deum", "sheet", "item"],
|
||||
position: {
|
||||
width: 620,
|
||||
height: 580,
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description" }]
|
||||
});
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
actions: {
|
||||
editImage: TeDeumItemSheet.#onEditImage,
|
||||
postItem: TeDeumItemSheet.#onPostItem,
|
||||
deleteSubitem: TeDeumItemSheet.#onDeleteSubitem,
|
||||
viewSubitem: TeDeumItemSheet.#onViewSubitem,
|
||||
},
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_getHeaderButtons() {
|
||||
let buttons = super._getHeaderButtons();
|
||||
// Add "Post to chat" button
|
||||
// We previously restricted this to GM and editable items only. If you ever find this comment because it broke something: eh, sorry!
|
||||
buttons.unshift(
|
||||
{
|
||||
class: "post",
|
||||
icon: "fas fa-comment",
|
||||
onclick: ev => { }
|
||||
})
|
||||
return buttons
|
||||
// Static PARTS pointing to the dynamic wrapper template
|
||||
static PARTS = {
|
||||
sheet: { template: "systems/fvtt-te-deum/templates/items/item-sheet.hbs" },
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
tabGroups = { primary: "description" }
|
||||
|
||||
let formData = {
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const item = this.document
|
||||
const TextEditor = foundry.applications.ux.TextEditor.implementation
|
||||
const enrich = async (val) => val !== undefined ? await TextEditor.enrichHTML(val ?? "", { async: true }) : ""
|
||||
const context = {
|
||||
title: this.title,
|
||||
id: this.id,
|
||||
type: this.object.type,
|
||||
img: this.object.img,
|
||||
name: this.object.name,
|
||||
id: item.id,
|
||||
type: item.type,
|
||||
img: item.img,
|
||||
name: item.name,
|
||||
editable: this.isEditable,
|
||||
cssClass: this.isEditable ? "editable" : "locked",
|
||||
system: foundry.utils.duplicate(this.object.system),
|
||||
system: foundry.utils.duplicate(item.system),
|
||||
systemFields: item.system.schema.fields,
|
||||
config: foundry.utils.duplicate(game.system.tedeum.config),
|
||||
competences: TeDeumUtility.getCompetencesForDropDown(),
|
||||
limited: this.object.limited,
|
||||
options: this.options,
|
||||
owner: this.document.isOwner,
|
||||
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, { async: true }),
|
||||
notes: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.notes, { async: true }),
|
||||
isGM: game.user.isGM
|
||||
limited: item.limited,
|
||||
owner: item.isOwner,
|
||||
enrichedDescription: await enrich(item.system.description),
|
||||
enrichedTransmission: await enrich(item.system.transmission),
|
||||
enrichedSymptomes: await enrich(item.system.symptomes),
|
||||
enrichedComplications: await enrich(item.system.complications),
|
||||
enrichedVertus: await enrich(item.system.vertus),
|
||||
enrichedToxicite: await enrich(item.system.toxicite),
|
||||
isGM: game.user.isGM,
|
||||
itemPartialName: `systems/fvtt-te-deum/templates/items/item-${item.type}-sheet.hbs`,
|
||||
}
|
||||
|
||||
if (this.object.type == "education") {
|
||||
TeDeumUtility.prepareEducationContent(formData);
|
||||
if (item.type === "education") {
|
||||
TeDeumUtility.prepareEducationContent(context)
|
||||
}
|
||||
|
||||
this.options.editable = !(this.object.origin == "embeddedItem");
|
||||
return formData;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_getHeaderButtons() {
|
||||
let buttons = super._getHeaderButtons();
|
||||
buttons.unshift({
|
||||
class: "post",
|
||||
icon: "fas fa-comment",
|
||||
onclick: ev => this.postItem()
|
||||
});
|
||||
return buttons
|
||||
return context
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
postItem() {
|
||||
let chatData = duplicate(this.item)
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options)
|
||||
|
||||
// Tab navigation
|
||||
const nav = this.element.querySelector('nav.tabs[data-group]')
|
||||
if (nav) {
|
||||
const group = nav.dataset.group
|
||||
const activeTab = this.tabGroups[group] || "description"
|
||||
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()
|
||||
})
|
||||
})
|
||||
this.element.querySelectorAll(`[data-group="${group}"][data-tab]`).forEach(content => {
|
||||
content.classList.toggle('active', content.dataset.tab === activeTab)
|
||||
})
|
||||
}
|
||||
|
||||
// Ignore Enter key in inputs
|
||||
this.element.addEventListener('keydown', e => {
|
||||
if (e.keyCode === 13 && e.target.tagName !== 'TEXTAREA') e.preventDefault()
|
||||
})
|
||||
}
|
||||
|
||||
// #region Static action handlers
|
||||
|
||||
static async #onEditImage(event, target) {
|
||||
const fp = new FilePicker({
|
||||
type: "image",
|
||||
current: this.document.img,
|
||||
callback: path => this.document.update({ img: path }),
|
||||
})
|
||||
fp.browse()
|
||||
}
|
||||
|
||||
static async #onPostItem(event, target) {
|
||||
const chatData = foundry.utils.duplicate(this.item)
|
||||
if (this.actor) {
|
||||
chatData.actor = { id: this.actor.id };
|
||||
chatData.actor = { id: this.actor.id }
|
||||
}
|
||||
// Don't post any image for the item (which would leave a large gap) if the default image is used
|
||||
if (chatData.img.includes("/blank.png")) {
|
||||
chatData.img = null;
|
||||
if (chatData.img?.includes("/blank.png")) {
|
||||
chatData.img = null
|
||||
}
|
||||
// JSON object for easy creation
|
||||
chatData.jsondata = JSON.stringify(
|
||||
{
|
||||
compendium: "postedItem",
|
||||
payload: chatData,
|
||||
});
|
||||
|
||||
foundry.applications.handlebars.renderTemplate('systems/fvtt-te-deum/templates/post-item.html', chatData).then(html => {
|
||||
let chatOptions = TeDeumUtility.chatDataSetup(html);
|
||||
ChatMessage.create(chatOptions)
|
||||
});
|
||||
chatData.jsondata = JSON.stringify({ compendium: "postedItem", payload: chatData })
|
||||
const html = await foundry.applications.handlebars.renderTemplate(
|
||||
'systems/fvtt-te-deum/templates/post-item.html', chatData
|
||||
)
|
||||
ChatMessage.create(TeDeumUtility.chatDataSetup(html))
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async viewSubitem(ev) {
|
||||
let levelIndex = Number($(ev.currentTarget).parents(".item").data("level-index"))
|
||||
let choiceIndex = Number($(ev.currentTarget).parents(".item").data("choice-index"))
|
||||
let featureId = $(ev.currentTarget).parents(".item").data("feature-id")
|
||||
|
||||
let itemData = this.object.system.levels[levelIndex].choices[choiceIndex].features[featureId]
|
||||
|
||||
if (itemData.name != 'None') {
|
||||
let item = await Item.create(itemData, { temporary: true });
|
||||
item.system.origin = "embeddedItem";
|
||||
new TeDeumItemSheet(item).render(true);
|
||||
static async #onDeleteSubitem(event, target) {
|
||||
const field = target.dataset.type
|
||||
const idx = parseInt(target.dataset.index)
|
||||
const oldArray = this.document.system[field]
|
||||
if (Array.isArray(oldArray) && oldArray[idx]?.name !== 'None') {
|
||||
const newArray = oldArray.filter((_, i) => i !== idx)
|
||||
this.document.update({ [`system.${field}`]: newArray })
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async deleteSubitem(ev) {
|
||||
let field = $(ev.currentTarget).data('type');
|
||||
let idx = Number($(ev.currentTarget).data('index'));
|
||||
let oldArray = this.object.system[field];
|
||||
let itemData = this.object.system[field][idx];
|
||||
if (itemData.name != 'None') {
|
||||
let newArray = [];
|
||||
for (let i = 0; i < oldArray.length; i++) {
|
||||
if (i != idx) {
|
||||
newArray.push(oldArray[i]);
|
||||
}
|
||||
}
|
||||
this.object.update({ [`system.${field}`]: newArray });
|
||||
static async #onViewSubitem(event, target) {
|
||||
const li = target.closest(".item")
|
||||
const levelIndex = parseInt(li?.dataset.levelIndex)
|
||||
const choiceIndex = parseInt(li?.dataset.choiceIndex)
|
||||
const featureId = li?.dataset.featureId
|
||||
const itemData = this.document.system.levels?.[levelIndex]?.choices?.[choiceIndex]?.features?.[featureId]
|
||||
if (itemData?.name !== 'None') {
|
||||
const item = await Item.create(itemData, { temporary: true })
|
||||
item.system.origin = "embeddedItem"
|
||||
new TeDeumItemSheet(item).render(true)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.object.options.actor.getOwnedItem(li.data("item-id"));
|
||||
item.sheet.render(true);
|
||||
});
|
||||
|
||||
html.find('.delete-subitem').click(ev => {
|
||||
this.deleteSubitem(ev);
|
||||
});
|
||||
|
||||
// Update Inventory Item
|
||||
html.find('.item-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
let itemId = li.data("item-id");
|
||||
let itemType = li.data("item-type");
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
get template() {
|
||||
let type = this.item.type;
|
||||
return `systems/fvtt-te-deum/templates/items/item-${type}-sheet.hbs`
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
return this.object.update(formData)
|
||||
}
|
||||
// #endregion
|
||||
}
|
||||
Reference in New Issue
Block a user