Vincent Vandemeulebrouck
d53da1f011
On ne se limite plus aux manipulations alchimiques, et les jets apparaissent comme tous les autres types de jets
362 lines
14 KiB
JavaScript
362 lines
14 KiB
JavaScript
import { RdDItemSort } from "./item-sort.js";
|
|
import { RdDUtility } from "./rdd-utility.js";
|
|
import { RdDItemCompetence } from "./item-competence.js";
|
|
import { RdDHerbes } from "./rdd-herbes.js";
|
|
import { RdDGemme } from "./rdd-gemme.js";
|
|
import { HtmlUtility } from "./html-utility.js";
|
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
|
import { SYSTEM_RDD } from "./constants.js";
|
|
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
|
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
|
import { Misc } from "./misc.js";
|
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
|
import { ACTOR_TYPES, ITEM_TYPES, RdDItem } from "./item.js";
|
|
import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js";
|
|
import { RdDTextEditor } from "./apps/rdd-text-roll.js";
|
|
|
|
/**
|
|
* Extend the basic ItemSheet for RdD specific items
|
|
*/
|
|
export class RdDItemSheet extends ItemSheet {
|
|
|
|
static get ITEM_TYPE() {
|
|
return undefined
|
|
}
|
|
|
|
static defaultTemplate(type) {
|
|
return type ?
|
|
`systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html` :
|
|
"systems/foundryvtt-reve-de-dragon/templates/item-sheet.html";
|
|
}
|
|
|
|
static register(sheetClass) {
|
|
Items.registerSheet(SYSTEM_RDD, sheetClass, {
|
|
label: Misc.typeName('Item', sheetClass.ITEM_TYPE),
|
|
types: [sheetClass.ITEM_TYPE],
|
|
makeDefault: true
|
|
})
|
|
}
|
|
|
|
/** @override */
|
|
static get defaultOptions() {
|
|
return foundry.utils.mergeObject(super.defaultOptions, {
|
|
classes: [SYSTEM_RDD, "sheet", "item"],
|
|
template: RdDItemSheet.defaultTemplate(RdDItemSheet.ITEM_TYPE),
|
|
width: 550,
|
|
height: 550
|
|
}, { inplace: false });
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
get template() {
|
|
return RdDItemSheet.defaultTemplate(this.item.type);
|
|
}
|
|
|
|
get title() {
|
|
const owner = (this.item.parent instanceof Actor) ? `(${this.item.parent.name})` : '';
|
|
return `${Misc.typeName('Item', this.item.type)}: ${this.item.name} ${owner}`;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_getHeaderButtons() {
|
|
let buttons = super._getHeaderButtons();
|
|
if (this.item.isInventaire() && this.item.isVideOuNonConteneur()) {
|
|
buttons.unshift({
|
|
class: "vendre",
|
|
icon: "fas fa-comments-dollar",
|
|
onclick: ev => this.item.proposerVente(1)
|
|
});
|
|
}
|
|
buttons.unshift({
|
|
class: "montrer",
|
|
icon: "fas fa-comment",
|
|
onclick: ev => this.item.postItemToChat()
|
|
});
|
|
return buttons
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
/** @override */
|
|
setPosition(options = {}) {
|
|
const position = super.setPosition(options);
|
|
const sheetHeader = this.element.find(".sheet-header");
|
|
const sheetBody = this.element.find(".sheet-body");
|
|
const bodyHeight = position.height - sheetHeader[0].clientHeight;
|
|
sheetBody.css("height", bodyHeight);
|
|
return position;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async getData() {
|
|
let formData = {
|
|
title: this.item.name,
|
|
id: this.item.id,
|
|
type: this.item.type,
|
|
img: this.item.img,
|
|
name: this.item.name,
|
|
system: this.item.system,
|
|
actorId: this.actor?.id,
|
|
description: await RdDTextEditor.enrichHTML(this.item.system.description, this.item),
|
|
descriptionmj: await RdDTextEditor.enrichHTML(this.item.system.descriptionmj, this.item),
|
|
isComestible: this.item.getUtilisationCuisine(),
|
|
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable),
|
|
competences: await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage),
|
|
categories: RdDItem.getCategories(this.item.type),
|
|
}
|
|
|
|
if (this.item.type == ITEM_TYPES.competencecreature) {
|
|
formData.isparade = RdDItemCompetenceCreature.isParade(this.item)
|
|
formData.isdommages = RdDItemCompetenceCreature.isDommages(this.item)
|
|
}
|
|
if (this.item.type == ITEM_TYPES.tache ||
|
|
this.item.type == ITEM_TYPES.livre ||
|
|
this.item.type == ITEM_TYPES.meditation ||
|
|
this.item.type == ITEM_TYPES.oeuvre) {
|
|
formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac)
|
|
formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve)
|
|
}
|
|
if (this.item.type == ITEM_TYPES.arme) {
|
|
formData.competences = formData.competences.filter(it => it.isCompetenceArme())
|
|
}
|
|
if (this.item.type == ITEM_TYPES.recettecuisine) {
|
|
formData.ingredients = await RdDTextEditor.enrichHTML(this.item.system.ingredients, this.item)
|
|
}
|
|
if (this.item.type == ITEM_TYPES.extraitpoetique) {
|
|
formData.extrait = await RdDTextEditor.enrichHTML(this.item.system.extrait, this.item)
|
|
formData.texte = await RdDTextEditor.enrichHTML(this.item.system.texte, this.item)
|
|
}
|
|
if (this.item.type == ITEM_TYPES.recettealchimique) {
|
|
formData.manipulation = await RdDTextEditor.enrichHTML(this.item.system.manipulation, this.item)
|
|
formData.utilisation = await RdDTextEditor.enrichHTML(this.item.system.utilisation, this.item)
|
|
formData.enchantement = await RdDTextEditor.enrichHTML(this.item.system.enchantement, this.item)
|
|
formData.sureffet = await RdDTextEditor.enrichHTML(this.item.system.sureffet, this.item)
|
|
}
|
|
if (this.item.type == ITEM_TYPES.gemme) {
|
|
formData.gemmeTypeList = RdDGemme.getGemmeTypeOptionList();
|
|
RdDGemme.calculDataDerivees(this.item)
|
|
}
|
|
if (this.item.type == ITEM_TYPES.potion) {
|
|
RdDHerbes.calculFormData(formData, this.item)
|
|
}
|
|
if (this.item.type == ITEM_TYPES.herbe) {
|
|
if (formData.options.isOwned && ['Soin', 'Repos'].includes(formData.system.categorie)) {
|
|
formData.isIngredientPotionBase = true;
|
|
}
|
|
}
|
|
if (this.item.type == ITEM_TYPES.sortreserve) {
|
|
const sortId = this.item.system.sortid;
|
|
formData.competences = formData.competences.filter(it => RdDItemCompetence.isDraconic(it));
|
|
formData.sort = formData.options.isOwned ? this.item.actor.items.get(sortId) : game.items.get(sortId);
|
|
}
|
|
if (this.item.type == ITEM_TYPES.sort) {
|
|
formData.competences = formData.competences.filter(it => RdDItemCompetence.isDraconic(it));
|
|
formData.bonusCaseList = RdDItemSort.getBonusCaseList(this.item);
|
|
}
|
|
return formData;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
/** @override */
|
|
activateListeners(html) {
|
|
super.activateListeners(html);
|
|
this.html = html;
|
|
|
|
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionnelles.isUsing('afficher-prix-joueurs')
|
|
|| game.user.isGM
|
|
|| !this.item.isOwned);
|
|
HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
|
|
|
|
// Everything below here is only needed if the sheet is editable
|
|
if (!this.options.editable) return;
|
|
|
|
this.form.ondragstart = (event) => this._onDragStart(event);
|
|
this.form.ondrop = (event) => this._onDrop(event);
|
|
|
|
// Select competence categorie
|
|
this.html.find(".categorie").change(event => this._onSelectCategorie(event));
|
|
|
|
this.html.find('.sheet-competence-xp').change((event) => {
|
|
if (this.item.isCompetencePersonnage()) {
|
|
RdDUtility.checkThanatosXP(this.item.name);
|
|
}
|
|
});
|
|
this.html.find(".item-cout input[name='system.cout']").change(event => {
|
|
if (this.item.isMonnaie()) {
|
|
const value = event.currentTarget.value;
|
|
if (Number(value) == 0) {
|
|
ui.notifications.error(`${this.actor?.name ?? 'Monnaie'}: La monnaie ${this.item.name} a maintenant une valeur de 0, et ne peut plus être utilisée pour payer!`)
|
|
}
|
|
}
|
|
})
|
|
this.html.find('.delete-bonus-case').click((event) => {
|
|
this.supprimerBonusCase(event.currentTarget.attributes['data-deleteCoord'].value)
|
|
})
|
|
|
|
this.html.find('.date-enchantement').change((event) => {
|
|
const jour = Number(this.html.find('input.date-enchantement[name="enchantement.jour"]').val());
|
|
const mois = RdDTimestamp.definition(this.html.find('select.date-enchantement[name="enchantement.mois"]').val());
|
|
const indexDate = game.system.rdd.calendrier.getIndexFromDate(jour, mois.heure);
|
|
this.item.update({ 'system.prdate': indexDate });
|
|
console.warn(`Date d'enchantement modifiée ${jour}/${mois.heure}: ${indexDate}`)
|
|
});
|
|
|
|
this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item));
|
|
this.html.find('.consommer-potion').click((event) => this._getEventActor(event).consommerPotion(this.item, this.getActionRenderItem()));
|
|
this.html.find('.creer-potion-base').click((event) => this._getEventActor(event).actionHerbe(this.item));
|
|
this.html.find('input[name="system.cacher_points_de_tache"]').change(async event => await this.item.update({ 'system.cacher_points_de_tache': event.currentTarget.checked }));
|
|
|
|
this.html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor))
|
|
|
|
if (this.actor) {
|
|
this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, this.getActionRenderItem()));
|
|
this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true));
|
|
this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, RdDSheetUtility.getItem(event, this.actor)));
|
|
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
|
|
this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItemToChat());
|
|
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, this.getActionRenderItem()));
|
|
|
|
this.html.find('.item-quantite-plus').click(async event => {
|
|
await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), 1)
|
|
this.render();
|
|
});
|
|
this.html.find('.item-quantite-moins').click(async event => {
|
|
await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), -1)
|
|
this.render();
|
|
});
|
|
}
|
|
|
|
const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: foundry.utils.duplicate(timestamp) })
|
|
|
|
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', updateItemTimestamp);
|
|
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp);
|
|
}
|
|
|
|
getActionRenderItem() {
|
|
return async () => {
|
|
let item = this.item;
|
|
while (item) {
|
|
await item.sheet?.render()
|
|
item = this.actor.getContenant(item)
|
|
}
|
|
}
|
|
}
|
|
|
|
_getEventActor(event) {
|
|
let actorId = event.currentTarget.attributes['data-actor-id'].value;
|
|
let actor = game.actors.get(actorId);
|
|
return actor;
|
|
}
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
async _onSelectCategorie(event) {
|
|
event.preventDefault();
|
|
|
|
if (this.item.isCompetence()) {
|
|
const categorie = event.currentTarget.value;
|
|
const level = RdDItemCompetence.getNiveauBase(categorie, this.item.type);
|
|
this.item.system.base = level;
|
|
this.html.find('[name="system.base"]').val(level);
|
|
}
|
|
}
|
|
|
|
async supprimerBonusCase(deleteCoord) {
|
|
if (this.item.type == ITEM_TYPES.sort) {
|
|
const oldList = RdDItemSort.getBonusCaseList(this.item)
|
|
const newList = oldList.filter(it => it.case != deleteCoord);
|
|
if (newList.length != oldList.length) {
|
|
await this.item.update({
|
|
'system.bonuscase': RdDItemSort.bonuscasesToString(newList)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
/** @override */
|
|
_updateObject(event, formData) {
|
|
switch (this.item.type) {
|
|
case ITEM_TYPES.sort:
|
|
formData['system.bonuscase'] = RdDItemSort.bonuscasesToString(RdDItemSheet._listCaseTmr(
|
|
formData.caseTmrCoord,
|
|
formData.caseTmrBonus,
|
|
formData.caseTmrAdd
|
|
))
|
|
break
|
|
case ITEM_TYPES.competence:
|
|
formData['system.niveau'] = formData['system.niveau'] ?? formData['system.base']
|
|
break
|
|
}
|
|
|
|
return this.item.update(formData);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
/**
|
|
* reconstruit les bonus de cases
|
|
* @param {*} caseTmrCoord tableau des coordonées
|
|
* @param {*} caseTmrBonus tableau des bonus
|
|
* @param {*} caseTmrAdd case à ajouter
|
|
* @returns list d'objets {coord, bonus}
|
|
*/
|
|
static _listCaseTmr(caseTmrCoord, caseTmrBonus, caseTmrAdd) {
|
|
const listCaseTmrCoord = caseTmrCoord == undefined ? [] : Array.isArray(caseTmrCoord) ? caseTmrCoord : [caseTmrCoord]
|
|
const listCaseTmrBonus = caseTmrBonus == undefined ? [] : Array.isArray(caseTmrBonus) ? caseTmrBonus : [caseTmrBonus]
|
|
if (caseTmrAdd != undefined && caseTmrAdd != '' && TMRUtility.verifyTMRCoord(caseTmrAdd) && !listCaseTmrCoord.includes(caseTmrAdd)) {
|
|
listCaseTmrCoord.push(TMRUtility.getTMR(caseTmrAdd).coord)
|
|
listCaseTmrBonus.push(1)
|
|
}
|
|
|
|
const list = [];
|
|
const caseChecked = {};
|
|
for (let i = 0; i < listCaseTmrBonus.length && i < listCaseTmrCoord.length; i++) {
|
|
const coord = listCaseTmrCoord[i] == FLEUVE_COORD ? FLEUVE_COORD : (listCaseTmrCoord[i]?.toUpperCase() ?? 'A1')
|
|
const bonus = listCaseTmrBonus[i] ?? 0
|
|
if (TMRUtility.verifyTMRCoord(coord) && bonus >= 0 && !caseChecked[coord]) {
|
|
caseChecked[coord] = coord
|
|
list.push({ case: coord, bonus: bonus })
|
|
}
|
|
}
|
|
return list
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async _onDragStart(event) {
|
|
}
|
|
|
|
async _onDrop(event) {
|
|
// Try to extract the dragData
|
|
let dragData = RdDItemSheet.$extractDragData(event);
|
|
if (!dragData) return false;
|
|
const allowed = Hooks.call("dropActorSheetData", this.actor, this, dragData);
|
|
if (allowed === false) return false;
|
|
|
|
// Handle different dragData types
|
|
switch (dragData.type) {
|
|
case "Item":
|
|
return this._onDropItem(event, dragData);
|
|
case "Actor":
|
|
return this._onDropActor(event, dragData);
|
|
}
|
|
return super._onDrop(event);
|
|
}
|
|
|
|
static $extractDragData(event) {
|
|
try {
|
|
const eventData = event?.dataTransfer?.getData('text/plain');
|
|
if (eventData) {
|
|
return JSON.parse(eventData);
|
|
}
|
|
} catch (err) { }
|
|
return undefined;
|
|
}
|
|
|
|
async _onDropItem(event, dragData) {
|
|
}
|
|
|
|
async _onDropActor(event, dragData) {
|
|
}
|
|
|
|
}
|