From 2546b89b4404bef79ea7e18dc519ca636f5c4e42 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Fri, 30 Dec 2022 02:28:17 +0100 Subject: [PATCH 1/9] =?UTF-8?q?Fix:=20vente=20de=20service=20avec=20quanti?= =?UTF-8?q?t=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- module/actor.js | 6 +++--- module/dialog-item-achat.js | 3 ++- module/item-service.js | 3 ++- module/item.js | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/module/actor.js b/module/actor.js index e3a955ee..30908c8b 100644 --- a/module/actor.js +++ b/module/actor.js @@ -3776,7 +3776,7 @@ export class RdDActor extends Actor { const vente = achat.vente; const quantite = (achat.choix.nombreLots ?? 1) * (vente.tailleLot); const itemVendu = vendeur?.getObjet(vente.item._id) ?? (await RdDItem.getCorrespondingItem(vente.item)); - if (!this.verifierQuantite(service, vendeur, itemVendu, quantite)) { + if (!this.verifierQuantite(service, vente.serviceSubItem, vendeur, itemVendu, quantite)) { ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`); return } @@ -3828,8 +3828,8 @@ export class RdDActor extends Actor { } } - verifierQuantite(service, vendeur, item, quantiteTotal) { - const disponible = service ? service.getQuantiteDisponible(item, quantiteTotal) : (vendeur ? (item?.getQuantite() ?? 0) : quantiteTotal); + verifierQuantite(service, serviceSubItem, vendeur, item, quantiteTotal) { + const disponible = service ? service.getQuantiteDisponible(serviceSubItem, quantiteTotal) : (vendeur ? (item?.getQuantite() ?? 0) : quantiteTotal); return disponible >= quantiteTotal; } diff --git a/module/dialog-item-achat.js b/module/dialog-item-achat.js index 5509b178..12648644 100644 --- a/module/dialog-item-achat.js +++ b/module/dialog-item-achat.js @@ -30,13 +30,14 @@ export class DialogItemAchat extends Dialog { } - static async onAcheter({ item, vendeur, acheteur, service, tailleLot, prixLot, nbLots, quantiteIllimite, chatMessageIdVente }) { + static async onAcheter({ item, vendeur, acheteur, service, serviceSubItem, tailleLot, prixLot, nbLots, quantiteIllimite, chatMessageIdVente }) { const venteData = { item, actingUserId: game.user.id, vendeurId: vendeur?.id, vendeur, acheteur, + serviceSubItem: serviceSubItem, service, tailleLot, quantiteIllimite, diff --git a/module/item-service.js b/module/item-service.js index 17fc6ab5..bc00ded4 100644 --- a/module/item-service.js +++ b/module/item-service.js @@ -23,7 +23,7 @@ export class RdDItemService extends RdDItem { getProprietes() { return []; } getServiceItem(itemRef) { - if (this.isService()) { + if (itemRef && this.isService()) { return this.system.items.find(it => it.id == itemRef.id && it.pack == itemRef.pack); } return undefined; @@ -64,6 +64,7 @@ export class RdDItemService extends RdDItem { await DialogItemAchat.onAcheter({ item: await RdDItem.getCorrespondingItem(subItem), acheteur, + serviceSubItem: subItem, service: this, quantiteIllimite: this.system.illimite, nbLots, diff --git a/module/item.js b/module/item.js index 6a2b5fed..7bcbeda6 100644 --- a/module/item.js +++ b/module/item.js @@ -428,7 +428,7 @@ export class RdDItem extends Item { } await DialogItemVente.display({ item: this, - service, + service: service, quantiteMax, callback: async (vente) => { vente["properties"] = this.getProprietes(); -- 2.35.3 From 6adeb790a01015bff2d5d138cc7183dc3334b662 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 28 Dec 2022 23:35:17 +0100 Subject: [PATCH 2/9] =?UTF-8?q?Fix:=20pas=20d'actions=20pour=20les=20v?= =?UTF-8?q?=C3=A9hicules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- module/rdd-combat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module/rdd-combat.js b/module/rdd-combat.js index b9186d1d..45202088 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -247,7 +247,7 @@ export class RdDCombatManager extends Combat { } if (actor.isCreatureEntite()) { actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature'])); - } else { + } else if (actor.isPersonnage()) { // Recupération des items 'arme' const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it)) //.concat(RdDItemArme.empoignade()) -- 2.35.3 From 2062ff0777beb1e0dc5319cbaf69f0c68793041b Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 28 Dec 2022 23:36:48 +0100 Subject: [PATCH 3/9] Support de plusieurs actors --- module/actor-creature-sheet.js | 7 - module/actor-sheet.js | 129 ++++++---------- module/actor.js | 214 +++++++-------------------- module/actor/base-actor-sheet.js | 243 +++++++++++++++++++++++++++++++ module/actor/base-actor.js | 149 +++++++++++++++++++ module/item-monnaie.js | 28 +--- module/misc.js | 17 ++- module/rdd-astrologie-joueur.js | 2 +- module/rdd-calendrier.js | 2 +- module/rdd-main.js | 9 +- module/rdd-utility.js | 52 +------ 11 files changed, 518 insertions(+), 334 deletions(-) create mode 100644 module/actor/base-actor-sheet.js create mode 100644 module/actor/base-actor.js diff --git a/module/actor-creature-sheet.js b/module/actor-creature-sheet.js index d8187818..47f5d3b7 100644 --- a/module/actor-creature-sheet.js +++ b/module/actor-creature-sheet.js @@ -40,11 +40,4 @@ export class RdDActorCreatureSheet extends RdDActorSheet { this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value)); }); } - - /* -------------------------------------------- */ - /** @override */ - _updateObject(event, formData) { - // Update the Actor - return this.object.update(formData); - } } diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 0108d369..b735fda4 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -12,13 +12,15 @@ import { RdDSheetUtility } from "./rdd-sheet-utility.js"; import { STATUSES } from "./settings/status-effects.js"; import { Monnaie } from "./item-monnaie.js"; import { MAINS_DIRECTRICES } from "./actor.js"; +import { RdDBaseActorSheet } from "./actor/base-actor-sheet.js"; +import { RdDItem } from "./item.js"; /* -------------------------------------------- */ /** * Extend the basic ActorSheet with some very simple modifications * @extends {ActorSheet} */ -export class RdDActorSheet extends ActorSheet { +export class RdDActorSheet extends RdDBaseActorSheet { /** @override */ static get defaultOptions() { @@ -36,42 +38,28 @@ export class RdDActorSheet extends ActorSheet { /* -------------------------------------------- */ async getData() { + let formData = await super.getData(); + mergeObject(formData, + { + editable: this.isEditable, + cssClass: this.isEditable ? "editable" : "locked", + effects: this.actor.effects.map(e => foundry.utils.deepClone(e)), + limited: this.actor.limited, + owner: this.actor.isOwner, + description: await TextEditor.enrichHTML(this.object.system.description, { async: true }), + biographie: await TextEditor.enrichHTML(this.object.system.biographie, { async: true }), + notes: await TextEditor.enrichHTML(this.object.system.notes, { async: true }), + notesmj: await TextEditor.enrichHTML(this.object.system.notesmj, { async: true }), + }); + mergeObject(formData.calc, { + surenc: this.actor.computeMalusSurEncombrement(), + surprise: RdDBonus.find(this.actor.getSurprise(false)).descr, + resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures), + caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute), + surEncombrementMessage: this.actor.getMessageSurEncombrement(), + }) + this.timerRecherche = undefined; - this.actor.computeEtatGeneral(); - - let formData = { - title: this.title, - id: this.actor.id, - type: this.actor.type, - img: this.actor.img, - name: this.actor.name, - editable: this.isEditable, - cssClass: this.isEditable ? "editable" : "locked", - system: foundry.utils.deepClone(this.actor.system), - effects: this.actor.effects.map(e => foundry.utils.deepClone(e)), - limited: this.actor.limited, - options: this.options, - owner: this.actor.isOwner, - description: await TextEditor.enrichHTML(this.object.system.description, { async: true }), - biographie: await TextEditor.enrichHTML(this.object.system.biographie, { async: true }), - notes: await TextEditor.enrichHTML(this.object.system.notes, { async: true }), - notesmj: await TextEditor.enrichHTML(this.object.system.notesmj, { async: true }), - calc: { - fortune: Monnaie.getFortuneSolsDeniers(this.actor), - encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(), - surenc: this.actor.computeMalusSurEncombrement(), - prixTotalEquipement: this.actor.computePrixTotalEquipement(), - surprise: RdDBonus.find(this.actor.getSurprise(false)).descr, - resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures), - caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute), - surEncombrementMessage: this.actor.getMessageSurEncombrement(), - }, - } - formData.options.isGM = game.user.isGM; - - RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes); - this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets); - formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs); if (formData.type == 'personnage') { formData.options.mainsDirectrices = MAINS_DIRECTRICES; @@ -125,22 +113,14 @@ export class RdDActorSheet extends ActorSheet { /* -------------------------------------------- */ /** @override */ activateListeners(html) { super.activateListeners(html); - this.html = html; HtmlUtility._showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue")); // Everything below here is only needed if the sheet is editable if (!this.options.editable) return; - this.html.find('.item-split').click(async event => { - const item = RdDSheetUtility.getItem(event, this.actor); - RdDSheetUtility.splitItem(item, this.actor); - }); - 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)?.postItem()); this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor)); + this.html.find('.subacteur-delete').click(async event => { const li = RdDSheetUtility.getEventElement(event); const actorId = li.data("actor-id"); @@ -174,14 +154,8 @@ export class RdDActorSheet extends ActorSheet { this.html.find('.creer-tache').click(async event => { this.createEmptyTache(); }); - this.html.find('.creer-un-objet').click(async event => { - RdDUtility.selectObjetType(this); - }); this.html.find('.creer-une-oeuvre').click(async event => { - RdDUtility.selectTypeOeuvre(this); - }); - this.html.find('.nettoyer-conteneurs').click(async event => { - this.actor.nettoyerConteneurs(); + this.selectTypeOeuvreToCreate(); }); // Blessure control @@ -325,10 +299,6 @@ export class RdDActorSheet extends ActorSheet { await this.actor.removeEffects(); } }); - this.html.find('.conteneur-name a').click(async event => { - RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event)); - this.render(true); - }); this.html.find('.carac-xp-augmenter').click(async event => { let caracName = event.currentTarget.name.replace("augmenter.", ""); this.actor.updateCaracXPAuto(caracName); @@ -418,19 +388,12 @@ export class RdDActorSheet extends ActorSheet { this.actor.setPointsDeSeuil(event.currentTarget.value); }); - this.html.find('#attribut-protection-edit').change(async event => { - this.actor.updateAttributeValue(event.currentTarget.attributes.name.value, parseInt(event.target.value)); - }); - // On stress change this.html.find('.compteur-edit').change(async event => { let fieldName = event.currentTarget.attributes.name.value; this.actor.updateCompteurValue(fieldName, parseInt(event.target.value)); }); - this.html.find('#ethylisme').change(async event => { - this.actor.setEthylisme(parseInt(event.target.value)); - }); this.html.find('.stress-test').click(async event => { this.actor.transformerStress(); }); @@ -454,13 +417,6 @@ export class RdDActorSheet extends ActorSheet { this.actor.jetEndurance(); }); - this.html.find('.monnaie-plus').click(async event => { - this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), 1); - }); - this.html.find('.monnaie-moins').click(async event => { - this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), -1); - }); - this.html.find('.vie-plus').click(async event => { this.actor.santeIncDec("vie", 1); }); @@ -499,25 +455,30 @@ export class RdDActorSheet extends ActorSheet { } /* -------------------------------------------- */ - async _onDropItem(event, dragData) { - const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id') - const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, dragData, this.objetVersConteneur) - if (dropParams) { - const callSuper = await this.actor.processDropItem(dropParams) - if (callSuper) { - await super._onDropItem(event, dragData) - } + async selectTypeOeuvreToCreate() { + let typeObjets = RdDItem.getTypesOeuvres(); + let content = `Selectionnez le type d'oeuvre'; + let dialog = new Dialog({ + title: "Créer une oeuvre", + content: content, + buttons: { + create: { + icon: '', + label: "Créer l'oeuvre", + callback: () => this.actor.createItem($(".item-type").val()) + } + } + }); + dialog.render(true); } /* -------------------------------------------- */ async createEmptyTache() { - await this.createItem('Nouvelle tache', 'tache'); + await this.actor.createItem('tache', 'Nouvelle tache'); } _optionRecherche(target) { diff --git a/module/actor.js b/module/actor.js index 30908c8b..72c90746 100644 --- a/module/actor.js +++ b/module/actor.js @@ -34,9 +34,9 @@ import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SHOW_DIC import { RdDConfirm } from "./rdd-confirm.js"; import { DialogValidationEncaissement } from "./dialog-validation-encaissement.js"; import { RdDRencontre } from "./item-rencontre.js"; -import { SystemCompendiums } from "./settings/system-compendiums.js"; import { Targets } from "./targets.js"; import { DialogRepos } from "./dialog-repos.js"; +import { RdDBaseActor } from "./actor/base-actor.js"; const POSSESSION_SANS_DRACONIC = { img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp', @@ -56,88 +56,7 @@ export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre'] * Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system. * @extends {Actor} */ -export class RdDActor extends Actor { - /* -------------------------------------------- */ - static init() { - Hooks.on("preUpdateItem", (item, change, options, id) => RdDActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id)); - // TODO: replace with pre-hooks? - Hooks.on("createItem", (item, options, id) => RdDActor.getParentActor(item)?.onCreateItem(item, options, id)); - Hooks.on("deleteItem", (item, options, id) => RdDActor.getParentActor(item)?.onDeleteItem(item, options, id)); - Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId)); - } - - static onSocketMessage(sockmsg) { - switch (sockmsg.msg) { - case "msg_remote_actor_call": - return RdDActor.onRemoteActorCall(sockmsg.data, sockmsg.userId); - case "msg_reset_nombre_astral": - console.log("RESET ASTRAL", game.user.character); - game.user.character.resetNombreAstral(); - return; - } - } - - static remoteActorCall(callData, userId = undefined) { - userId = userId ?? Misc.firstConnectedGMId(); - if (userId == game.user.id) { - RdDActor.onRemoteActorCall(callData, userId); - return false; - } - else { - game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_remote_actor_call", data: callData, userId: userId }); - return true; - } - } - - static onRemoteActorCall(callData, userId) { - if (userId == game.user.id) { - const actor = game.actors.get(callData?.actorId); - if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon - const args = callData.args; - console.info(`RdDActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDActor.${callData.method}(`, ...args, ')'); - actor[callData.method](...args); - } - } - } - - /* -------------------------------------------- */ - static getParentActor(document) { - return document?.parent instanceof Actor ? document.parent : undefined - } - - /* -------------------------------------------- */ - /** - * Override the create() function to provide additional RdD functionality. - * - * This overrided create() function adds initial items - * Namely: Basic skills, money, - * - * @param {Object} actorData Barebones actor template data which this function adds onto. - * @param {Object} options Additional options which customize the creation workflow. - * - */ - static async create(actorData, options) { - // Case of compendium global import - if (actorData instanceof Array) { - return super.create(actorData, options); - } - - const isPersonnage = actorData.type == "personnage"; - // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic - if (actorData.items) { - return await super.create(actorData, options); - } - - if (isPersonnage) { - const competences = await SystemCompendiums.getCompetences(actorData.type); - actorData.items = competences.map(i => i.toObject()) - .concat(Monnaie.monnaiesStandard()); - } - else { - actorData.items = []; - } - return super.create(actorData, options); - } +export class RdDActor extends RdDBaseActor { /* -------------------------------------------- */ prepareData() { @@ -145,6 +64,8 @@ export class RdDActor extends Actor { // Dynamic computing fields this.encTotal = 0; + // TODO: separate derived/base data preparation + // TODO: split by actor class // Make separate methods for each Actor type (character, npc, etc.) to keep // things organized. @@ -178,9 +99,9 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async cleanupConteneurs() { - let updates = this.listItemsData('conteneur') - .filter(c => c.system.contenu.filter(id => this.getObjet(id) == undefined).length > 0) - .map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getObjet(id) != undefined) } }); + let updates = this.listItems('conteneur') + .filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0) + .map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } }); if (updates.length > 0) { await this.updateEmbeddedDocuments("Item", updates) } @@ -206,23 +127,6 @@ export class RdDActor extends Actor { return false; } - /* -------------------------------------------- */ - isCreatureEntite() { - return this.type == 'creature' || this.type == 'entite'; - } - isCreature() { - return this.type == 'creature'; - } - isEntite() { - return this.type == 'entite'; - } - /* -------------------------------------------- */ - isPersonnage() { - return this.type == 'personnage'; - } - isVehicule() { - return this.type == 'vehicule'; - } /* -------------------------------------------- */ isHautRevant() { return this.isPersonnage() && this.system.attributs.hautrevant.value != "" @@ -330,50 +234,33 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - getObjet(id) { - return this.getEmbeddedDocument('Item', id); - } - - listItemsData(type) { - return this.itemTypes[type]; - } - - filterItems(filter) { - return this.items.filter(filter); - } - - getItemOfType(idOrName, type) { - return this.items.find(it => it.id == idOrName && it.type == type) - ?? Misc.findFirstLike(idOrName, this.items, { filter: it => it.type == type, description: type }); - } - getMonnaie(id) { - return this.getItemOfType(id, 'monnaie'); + return this.findItemLike(id, 'monnaie'); } getTache(id) { - return this.getItemOfType(id, 'tache'); + return this.findItemLike(id, 'tache'); } getMeditation(id) { - return this.getItemOfType(id, 'meditation'); + return this.findItemLike(id, 'meditation'); } getChant(id) { - return this.getItemOfType(id, 'chant'); + return this.findItemLike(id, 'chant'); } getDanse(id) { - return this.getItemOfType(id, 'danse'); + return this.findItemLike(id, 'danse'); } getMusique(id) { - return this.getItemOfType(id, 'musique'); + return this.findItemLike(id, 'musique'); } getOeuvre(id, type = 'oeuvre') { - return this.getItemOfType(id, type); + return this.findItemLike(id, type); } getJeu(id) { - return this.getItemOfType(id, 'jeu'); + return this.findItemLike(id, 'jeu'); } getRecetteCuisine(id) { - return this.getItemOfType(id, 'recettecuisine'); + return this.findItemLike(id, 'recettecuisine'); } /* -------------------------------------------- */ getDraconicList() { @@ -476,6 +363,7 @@ export class RdDActor extends Actor { ); dialog.render(true); } + async repos() { await DialogRepos.create(this); } @@ -1109,7 +997,7 @@ export class RdDActor extends Actor { _isConteneurContenu(item, conteneur) { if (item?.isConteneur()) { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant for (let id of item.system.contenu) { - let subObjet = this.getObjet(id); + let subObjet = this.getItem(id); if (subObjet?.id == conteneur.id) { return true; // Loop detected ! } @@ -1130,17 +1018,17 @@ export class RdDActor extends Actor { if (objet.type != 'conteneur') { return Number(tplData.encombrement) * Number(tplData.quantite); } - const encContenus = tplData.contenu.map(idContenu => this.getRecursiveEnc(this.getObjet(idContenu))); + const encContenus = tplData.contenu.map(idContenu => this.getRecursiveEnc(this.getItem(idContenu))); return encContenus.reduce(Misc.sum(), 0) + Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/ } /* -------------------------------------------- */ buildSubConteneurObjetList(conteneurId, deleteList) { - let conteneur = this.getObjet(conteneurId); + let conteneur = this.getItem(conteneurId); if (conteneur?.type == 'conteneur') { // Si c'est un conteneur for (let subId of conteneur.system.contenu) { - let subObj = this.getObjet(subId); + let subObj = this.getItem(subId); if (subObj) { if (subObj.type == 'conteneur') { this.buildSubConteneurObjetList(subId, deleteList); @@ -1228,12 +1116,12 @@ export class RdDActor extends Actor { return false; } let result = true; - const item = this.getObjet(itemId); + const item = this.getItem(itemId); if (item?.isInventaire() && sourceActorId == targetActorId) { // rangement if (srcId != destId && itemId != destId) { // déplacement de l'objet - const src = this.getObjet(srcId); - const dest = this.getObjet(destId); + const src = this.getItem(srcId); + const dest = this.getItem(destId); const cible = this.getContenantOrParent(dest); const [empilable, message] = item.isInventaireEmpilable(dest); if (empilable) { @@ -1303,7 +1191,7 @@ export class RdDActor extends Actor { itemsList.push({ id: itemId, conteneurId: undefined }); // Init list sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list - const itemsDataToCreate = itemsList.map(it => sourceActor.getObjet(it.id)) + const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id)) .map(it => duplicate(it)) .map(it => { it.system.contenu = []; return it; }); let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate); @@ -1314,7 +1202,7 @@ export class RdDActor extends Actor { // gestion conteneur/contenu if (item.conteneurId) { // l'Objet était dans un conteneur let newConteneurId = itemMap[item.conteneurId]; // Get conteneur - let newConteneur = this.getObjet(newConteneurId); + let newConteneur = this.getItem(newConteneurId); let newItemId = itemMap[item.id]; // Get newItem @@ -1377,7 +1265,7 @@ export class RdDActor extends Actor { hasItemNamed(type, name) { name = Grammar.toLowerCaseNoAccent(name); - return this.listItemsData(type).find(it => Grammar.toLowerCaseNoAccent(it.name) == name); + return this.listItems(type).find(it => Grammar.toLowerCaseNoAccent(it.name) == name); } /* -------------------------------------------- */ @@ -1444,6 +1332,10 @@ export class RdDActor extends Actor { } } + recompute(){ + this.computeEtatGeneral(); + } + /* -------------------------------------------- */ computeEtatGeneral() { // Pas d'état général pour les entités forçage à 0 @@ -2027,7 +1919,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async consommerNourritureboisson(itemId, choix = { doses: 1, seForcer: false, supprimerSiZero: false }, userId = undefined) { if (userId != undefined && userId != game.user.id) { - RdDActor.remoteActorCall({ + RdDBaseActor.remoteActorCall({ actorId: this.id, method: 'consommerNourritureboisson', args: [itemId, choix, userId] @@ -2035,7 +1927,7 @@ export class RdDActor extends Actor { userId) return; } - const item = this.getObjet(itemId) + const item = this.getItem(itemId) if (!item.isComestible()) { return; } @@ -2792,7 +2684,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async rollDanse(id) { const artData = { art: 'danse', verbe: 'Danser', forceCarac: {} }; - const oeuvre = duplicate(this.getItemOfType(id, artData.art)); + const oeuvre = duplicate(this.findItemLike(id, artData.art)); if (oeuvre.system.agilite) { artData.forceCarac['agilite'] = duplicate(this.system.carac.agilite); } @@ -2814,7 +2706,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async rollMusique(id) { const artData = { art: 'musique', verbe: 'Jouer' }; - const oeuvre = this.getItemOfType(id, artData.art); + const oeuvre = this.findItemLike(id, artData.art); await this._rollArt(artData, "ouie", oeuvre); } @@ -2911,7 +2803,7 @@ export class RdDActor extends Actor { async rollOeuvre(id) { const artData = { art: 'oeuvre', verbe: 'Interpréter' } - const oeuvre = duplicate(this.getItemOfType(id, artData.art)) + const oeuvre = duplicate(this.findItemLike(id, artData.art)) await this._rollArt(artData, oeuvre.system.default_carac, oeuvre) } @@ -2963,7 +2855,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ _getSignesDraconiques(coord) { const type = TMRUtility.getTMRType(coord); - return this.listItemsData("signedraconique").filter(it => it.system.typesTMR.includes(type)); + return this.listItems("signedraconique").filter(it => it.system.typesTMR.includes(type)); } /* -------------------------------------------- */ @@ -3174,7 +3066,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async resetNombreAstral() { - let toDelete = this.listItemsData('nombreastral'); + let toDelete = this.listItems('nombreastral'); const deletions = toDelete.map(it => it._id); await this.deleteEmbeddedDocuments("Item", deletions); } @@ -3194,7 +3086,7 @@ export class RdDActor extends Actor { await this.createEmbeddedDocuments("Item", [item]); // Suppression des anciens nombres astraux - let toDelete = this.listItemsData('nombreastral').filter(it => it.system.jourindex < game.system.rdd.calendrier.getCurrentDayIndex()); + let toDelete = this.listItems('nombreastral').filter(it => it.system.jourindex < game.system.rdd.calendrier.getCurrentDayIndex()); const deletions = toDelete.map(it => it._id); await this.deleteEmbeddedDocuments("Item", deletions); @@ -3256,7 +3148,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ getSortList() { - return this.listItemsData("sort"); + return this.listItems("sort"); } /* -------------------------------------------- */ @@ -3319,7 +3211,7 @@ export class RdDActor extends Actor { fatigue: RdDUtility.calculFatigueHtml(fatigue, endurance), draconic: this.getDraconicList(), sort: this.getSortList(), - signes: this.listItemsData("signedraconique"), + signes: this.listItems("signedraconique"), caracReve: this.system.carac.reve.value, pointsReve: this.getReveActuel(), isRapide: isRapide, @@ -3470,7 +3362,7 @@ export class RdDActor extends Actor { async validerEncaissement(rollData, show) { if (ReglesOptionelles.isUsing('validation-encaissement-gr') && !game.user.isGM) { - RdDActor.remoteActorCall({ + RdDBaseActor.remoteActorCall({ actorId: this.id, method: 'validerEncaissement', args: [rollData, show] @@ -3691,7 +3583,7 @@ export class RdDActor extends Actor { if (depense == 0) { return; } - let fortune = Monnaie.getFortune(this); + let fortune = super.getFortune(); console.log("payer", game.user.character, depense, fortune); let msg = ""; if (fortune >= depense) { @@ -3710,7 +3602,7 @@ export class RdDActor extends Actor { } async depenserSols(sols) { - let reste = Monnaie.getFortune(this) - Number(sols); + let reste = super.getFortune() - Number(sols); if (reste >= 0) { await Monnaie.optimiserFortune(this, reste); } @@ -3727,7 +3619,7 @@ export class RdDActor extends Actor { return; } if (fromActorId && !game.user.isGM) { - RdDActor.remoteActorCall({ + RdDBaseActor.remoteActorCall({ userId: Misc.connectedGMOrUser(), actorId: this.id, method: 'ajouterSols', args: [sols, fromActorId] @@ -3735,7 +3627,7 @@ export class RdDActor extends Actor { } else { const fromActor = game.actors.get(fromActorId) - await Monnaie.optimiserFortune(this, sols + Monnaie.getFortune(this)); + await Monnaie.optimiserFortune(this, sols + this.getFortune()); RdDAudio.PlayContextAudio("argent"); // Petit son ChatMessage.create({ @@ -3761,7 +3653,7 @@ export class RdDActor extends Actor { return; } if (!Misc.isUniqueConnectedGM()) { - RdDActor.remoteActorCall({ + RdDBaseActor.remoteActorCall({ actorId: achat.vendeurId ?? achat.acheteurId, method: 'achatVente', args: [achat] @@ -3771,21 +3663,21 @@ export class RdDActor extends Actor { const cout = Number(achat.prixTotal ?? 0); const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined; - const service = achat.serviceId ? (vendeur?.getObjet(achat.serviceId) ?? game.items.get(achat.serviceId)) : undefined; + const service = achat.serviceId ? (vendeur?.getItem(achat.serviceId) ?? game.items.get(achat.serviceId)) : undefined; const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined; const vente = achat.vente; const quantite = (achat.choix.nombreLots ?? 1) * (vente.tailleLot); - const itemVendu = vendeur?.getObjet(vente.item._id) ?? (await RdDItem.getCorrespondingItem(vente.item)); + const itemVendu = vendeur?.getItem(vente.item._id) ?? (await RdDItem.getCorrespondingItem(vente.item)); if (!this.verifierQuantite(service, vente.serviceSubItem, vendeur, itemVendu, quantite)) { ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`); return } - if (Monnaie.getFortune(acheteur) < Number(cout)) { + if ((acheteur?.getFortune() ?? 0) < Number(cout)) { ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`); return; } - await this.decrementerVente(service, vendeur, itemVendu, quantite, cout); + await this.decrementerVente(service, vendeur, itemVendu, quantite, cout); if (acheteur) { await acheteur.depenserSols(cout); let createdItemId = await acheteur.creerQuantiteItem(vente.item, quantite); @@ -3871,7 +3763,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async effectuerTacheAlchimie(recetteId, tacheAlchimie, texteTache) { - let recetteData = this.getItemOfType(recetteId, 'recettealchimique'); + let recetteData = this.findItemLike(recetteId, 'recettealchimique'); if (recetteData) { if (tacheAlchimie != "couleur" && tacheAlchimie != "consistance") { ui.notifications.warn(`L'étape alchimique ${tacheAlchimie} - ${texteTache} est inconnue`); @@ -4141,7 +4033,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async diminuerQuantiteObjet(id, nb, options = { supprimerSiZero: false }) { - const item = this.getObjet(id); + const item = this.getItem(id); if (item) { await item.diminuerQuantite(nb, options); } diff --git a/module/actor/base-actor-sheet.js b/module/actor/base-actor-sheet.js new file mode 100644 index 00000000..ecf23013 --- /dev/null +++ b/module/actor/base-actor-sheet.js @@ -0,0 +1,243 @@ +import { RdDUtility } from "../rdd-utility.js"; +import { Misc } from "../misc.js"; +import { DialogSplitItem } from "../dialog-split-item.js"; +import { RdDSheetUtility } from "../rdd-sheet-utility.js"; +import { Monnaie } from "../item-monnaie.js"; +import { RdDItem } from "../item.js"; + +/* -------------------------------------------- */ +/** + * Extend the basic ActorSheet with some very simple modifications + * @extends {ActorSheet} + */ +export class RdDBaseActorSheet extends ActorSheet { + + /** @override */ + static get defaultOptions() { + RdDUtility.initAfficheContenu(); + return mergeObject(super.defaultOptions, { + classes: ["rdd", "sheet", "actor"], + template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html", + width: 550, + tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }], + dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }], + showCompNiveauBase: false, + vueDetaillee: false + }); + } + + /* -------------------------------------------- */ + async getData() { + Monnaie.validerMonnaies(this.actor.itemTypes['monnaie']); + + this.actor.recompute(); + const userRightLevel = this.actor.getUserLevel(game.user) + const options = duplicate(this.options); + mergeObject(options, { + isGM: game.user.isGM, + editable: this.isEditable, + cssClass: this.isEditable ? "editable" : "locked", + isLimited: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED, + isObserver: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER, + isOwner: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER, + }); + + let formData = { + title: this.title, + id: this.actor.id, + type: this.actor.type, + img: this.actor.img, + name: this.actor.name, + system: foundry.utils.deepClone(this.actor.system), + options: options, + } + this.filterItemsPerTypeForSheet(formData, this.actor.itemTypes); + formData.calc = { + fortune: this.toSolsDeniers(this.actor.getFortune()), + prixTotalEquipement: this.actor.computePrixTotalEquipement(), + encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(), + } + + this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets); + formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs); + + + return formData; + } + + toSolsDeniers(fortune) { + return { + sols: Math.floor(fortune), + deniers: Math.round(100 * (fortune - Math.floor(fortune))) + }; + } + + /* -------------------------------------------- */ + filterItemsPerTypeForSheet(formData, itemTypes) { + formData.services = Misc.arrayOrEmpty(itemTypes['service']); + formData.recettescuisine = Misc.arrayOrEmpty(itemTypes['recettecuisine']); + formData.recettesAlchimiques = Misc.arrayOrEmpty(itemTypes['recettealchimique']); + formData.maladies = Misc.arrayOrEmpty(itemTypes['maladie']); + formData.poisons = Misc.arrayOrEmpty(itemTypes['poison']); + formData.possessions = Misc.arrayOrEmpty(itemTypes['possession']); + formData.maladiesPoisons = formData.maladies.concat(formData.poisons); + formData.competences = (itemTypes['competence'] ?? []).concat(itemTypes['competencecreature'] ?? []); + formData.sortsReserve = Misc.arrayOrEmpty(itemTypes['sortreserve']); + + formData.sorts = Misc.arrayOrEmpty(itemTypes['sort']); + formData.rencontres = Misc.arrayOrEmpty(itemTypes['rencontre']); + formData.casestmr = Misc.arrayOrEmpty(itemTypes['casetmr']); + formData.signesdraconiques = Misc.arrayOrEmpty(itemTypes['signedraconique']); + formData.queues = Misc.arrayOrEmpty(itemTypes['queue']); + formData.souffles = Misc.arrayOrEmpty(itemTypes['souffle']); + formData.ombres = Misc.arrayOrEmpty(itemTypes['ombre']); + formData.tetes = Misc.arrayOrEmpty(itemTypes['tete']); + formData.taches = Misc.arrayOrEmpty(itemTypes['tache']); + formData.meditations = Misc.arrayOrEmpty(itemTypes['meditation']); + formData.chants = Misc.arrayOrEmpty(itemTypes['chant']); + formData.danses = Misc.arrayOrEmpty(itemTypes['danse']); + formData.musiques = Misc.arrayOrEmpty(itemTypes['musique']); + formData.oeuvres = Misc.arrayOrEmpty(itemTypes['oeuvre']); + formData.jeux = Misc.arrayOrEmpty(itemTypes['jeu']); + + + formData.conteneurs = Misc.arrayOrEmpty(itemTypes['conteneur']); + + formData.materiel = Misc.arrayOrEmpty(itemTypes['objet']); + formData.armes = Misc.arrayOrEmpty(itemTypes['arme']); + formData.armures = Misc.arrayOrEmpty(itemTypes['armure']); + formData.munitions = Misc.arrayOrEmpty(itemTypes['munition']); + formData.livres = Misc.arrayOrEmpty(itemTypes['livre']); + formData.potions = Misc.arrayOrEmpty(itemTypes['potion']); + formData.ingredients = Misc.arrayOrEmpty(itemTypes['ingredient']); + formData.faunes = Misc.arrayOrEmpty(itemTypes['faune']); + formData.herbes = Misc.arrayOrEmpty(itemTypes['herbe']); + formData.nourritureboissons = Misc.arrayOrEmpty(itemTypes['nourritureboisson']); + formData.gemmes = Misc.arrayOrEmpty(itemTypes['gemme']); + + formData.monnaie = Misc.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere()); + + formData.objets = formData.conteneurs + .concat(formData.materiel) + .concat(formData.armes) + .concat(formData.armures) + .concat(formData.munitions) + .concat(formData.livres) + .concat(formData.potions) + .concat(formData.ingredients) + .concat(formData.herbes) + .concat(formData.faunes) + .concat(formData.monnaie) + .concat(formData.nourritureboissons) + .concat(formData.gemmes); + } + + /* -------------------------------------------- */ /** @override */ + activateListeners(html) { + super.activateListeners(html); + this.html = html; + + this.html.find('.conteneur-name a').click(async event => { + RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event)); + this.render(true); + }); + this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true)) + this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItem()); + + // Everything below here is only needed if the sheet is editable + if (!this.options.editable) return; + + this.html.find('.item-split').click(async event => { + const item = RdDSheetUtility.getItem(event, this.actor); + RdDSheetUtility.splitItem(item, this.actor); + }); + 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('.creer-un-objet').click(async event => { + this.selectObjetTypeToCreate(); + }); + this.html.find('.nettoyer-conteneurs').click(async event => { + this.actor.nettoyerConteneurs(); + }); + this.html.find('.monnaie-plus').click(async event => { + this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), 1); + }); + this.html.find('.monnaie-moins').click(async event => { + this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), -1); + }); + + } + + /* -------------------------------------------- */ + async _onDropItem(event, dragData) { + const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id') + const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, dragData, this.objetVersConteneur) + if (dropParams) { + const callSuper = await this.actor.processDropItem(dropParams) + if (callSuper) { + await super._onDropItem(event, dragData) + } + } + } + + + /* -------------------------------------------- */ + async selectObjetTypeToCreate() { + let typeObjets = RdDItem.getItemTypesInventaire(); + let content = `Selectionnez le type d'équipement'; + let d = new Dialog({ + title: "Créer un équipement", + content: content, + buttons: { + create: { + icon: '', + label: "Créer l'objet", + callback: () => this.actor.createItem($(".item-type").val()) + } + } + }); + d.render(true); + } + + /** @override */ + setPosition(options = {}) { + const position = super.setPosition(options); + const sheetHeader = this.element.find(".sheet-header"); + const sheetTabs = this.element.find(".sheet-tabs"); + const sheetBody = this.element.find(".sheet-body"); + let bodyHeight = position.height - sheetHeader[0].clientHeight; + if (sheetTabs.length > 0) { + bodyHeight -= sheetTabs[0].clientHeight; + } + sheetBody.css("height", bodyHeight); + return position; + } + + + /* -------------------------------------------- */ + /** @override */ + _updateObject(event, formData) { + // Update the Actor + return this.actor.update(formData); + } + + async splitItem(item) { + const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split)); + dialog.render(true); + } + + async _onSplitItem(item, split) { + if (split >= 1 && split < item.system.quantite) { + await item.diminuerQuantite(split); + const splitItem = duplicate(item); + splitItem.system.quantite = split; + await this.actor.createEmbeddedDocuments('Item', [splitItem]) + } + } + +} diff --git a/module/actor/base-actor.js b/module/actor/base-actor.js new file mode 100644 index 00000000..7b1e7935 --- /dev/null +++ b/module/actor/base-actor.js @@ -0,0 +1,149 @@ +import { SYSTEM_SOCKET_ID } from "../constants.js"; +import { Monnaie } from "../item-monnaie.js"; +import { Misc } from "../misc.js"; +import { SystemCompendiums } from "../settings/system-compendiums.js"; + +export class RdDBaseActor extends Actor { + + static getDefaultImg(itemType) { + return game.system.rdd.actorClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType]; + } + + /* -------------------------------------------- */ + static init() { + Hooks.on("preUpdateItem", (item, change, options, id) => RdDBaseActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id)); + Hooks.on("createItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onCreateItem(item, options, id)); + Hooks.on("deleteItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onDeleteItem(item, options, id)); + Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId)); + } + + + static onSocketMessage(sockmsg) { + switch (sockmsg.msg) { + case "msg_remote_actor_call": + return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId); + case "msg_reset_nombre_astral": + console.log("RESET ASTRAL", game.user.character); + game.user.character.resetNombreAstral(); + return; + } + } + + static remoteActorCall(callData, userId = undefined) { + userId = userId ?? Misc.firstConnectedGMId(); + if (userId == game.user.id) { + RdDBaseActor.onRemoteActorCall(callData, userId); + return false; + } + else { + game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_remote_actor_call", data: callData, userId: userId }); + return true; + } + } + + static onRemoteActorCall(callData, userId) { + if (userId == game.user.id) { + const actor = game.actors.get(callData?.actorId); + if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon + const args = callData.args; + console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')'); + actor[callData.method](...args); + } + } + } + + static getParentActor(document) { + return document?.parent instanceof Actor ? document.parent : undefined + } + + /** + * Cet methode surcharge Actor.create() pour ajouter si besoin des Items par défaut: + * compétences et monnaies. + * + * @param {Object} actorData template d'acteur auquel ajouter des informations. + * @param {Object} options optionspour customiser la création + */ + static async create(actorData, options) { + // import depuis un compendium + if (actorData instanceof Array) { + return super.create(actorData, options); + } + // Création d'un acteur avec des items (uniquement en cas de duplication): pas besoin d'ajouter d'items + if (actorData.items) { + return await super.create(actorData, options); + } + + if (actorData.type == "personnage") { + const competences = await SystemCompendiums.getCompetences(actorData.type); + actorData.items = competences.map(i => i.toObject()) + .concat(Monnaie.monnaiesStandard()); + } + else { + actorData.items = []; + } + return super.create(actorData, options); + } + + constructor(docData, context = {}) { + if (!context.rdd?.ready) { + mergeObject(context, { rdd: { ready: true } }); + const ActorConstructor = game.system.rdd.actorClasses[docData.type]; + if (ActorConstructor) { + if (!docData.img) { + docData.img = ActorConstructor.defaultIcon; + } + return new ActorConstructor(docData, context); + } + } + super(docData, context); + } + + isCreatureEntite() { return this.type == 'creature' || this.type == 'entite'; } + isCreature() { return this.type == 'creature'; } + isEntite() { return this.type == 'entite'; } + isPersonnage() { return this.type == 'personnage'; } + isVehicule() { return this.type == 'vehicule'; } + + getItem(id, type = undefined) { + const item = this.items.get(id); + if (type == undefined || (item?.type == type)) { + return item; + } + return undefined; + } + + listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); } + filterItems(filter, type = undefined) { return this.listItems(type)?.filter(filter) ?? []; } + findItemLike(idOrName, type) { + return this.getItem(idOrName, type) + ?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) }); + } + + + recompute() { } + + /* -------------------------------------------- */ + async onPreUpdateItem(item, change, options, id) { } + + async onCreateItem(item, options, id) { } + + async onDeleteItem(item, options, id) { } + + async onUpdateActor(update, options, actorId) { } + + + getFortune() { + return Monnaie.getFortune(this.itemTypes['monnaie']); + } + + async createItem(type, name = undefined) { + if (!name) { + name = 'Nouveau ' + Misc.typeName('Item', type); + } + await this.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true }); + } + + canReceive(item) { + return false; + } +} \ No newline at end of file diff --git a/module/item-monnaie.js b/module/item-monnaie.js index d766c0af..11946207 100644 --- a/module/item-monnaie.js +++ b/module/item-monnaie.js @@ -62,29 +62,17 @@ export class Monnaie { return deniers; } - static getFortune(actor) { - if (actor) { - Monnaie.validerMonnaies(actor); - return actor.itemTypes['monnaie'] - .map(m => Number(m.system.cout) * Number(m.system.quantite)) - .reduce(Misc.sum(), 0); - } - return 0; - } - - static getFortuneSolsDeniers(actor) { - const fortune = Monnaie.getFortune(actor); - return { - sols: Math.floor(fortune), - deniers: Math.round(100 * (fortune - Math.floor(fortune))) - }; + static getFortune(monnaies) { + return (monnaies??[]) + .map(m => Number(m.system.cout) * Number(m.system.quantite)) + .reduce(Misc.sum(), 0); } static async optimiserFortune(actor, fortune) { let resteEnDeniers = Math.round(fortune * 100); let monnaies = actor.itemTypes['monnaie']; let updates = []; - Monnaie.validerMonnaies(actor); + Monnaie.validerMonnaies(monnaies, actor); let parValeur = Misc.classifyFirst(monnaies, it => VALEUR_DENIERS(it.system.cout)); for (let valeurDeniers of [1000, 100, 10, 1]) { @@ -107,9 +95,9 @@ export class Monnaie { } } - static validerMonnaies(actor) { - actor.itemTypes['monnaie'].filter(it => VALEUR_DENIERS(it.system.cout) == 0) - .map(it => `La monnaie ${it.name} de l'acteur ${actor.name} a une valeur de 0!`) + static validerMonnaies(monnaies, actor = undefined) { + monnaies.filter(it => VALEUR_DENIERS(it.system.cout) == 0) + .map(it => `La monnaie ${it.name} de l'acteur ${actor?.name ?? 'sélectionné'} a une valeur de 0!`) .forEach(message => { ui.notifications.warn(message); console.warn(message); diff --git a/module/misc.js b/module/misc.js index 2aa30278..185a3933 100644 --- a/module/misc.js +++ b/module/misc.js @@ -46,6 +46,9 @@ export class Misc { : ''; } + static arrayOrEmpty(items) { + return items?.length ? items : []; + } /** * Converts the value to an integer, or to 0 if undefined/null/not representing integer * @param {*} value value to convert to an integer using parseInt @@ -135,11 +138,11 @@ export class Misc { } static isRollModeHiddenToPlayer() { - switch (game.settings.get("core", "rollMode")) { - case CONST.DICE_ROLL_MODES.BLIND: - case CONST.DICE_ROLL_MODES.SELF: return true; - } - return false + switch (game.settings.get("core", "rollMode")) { + case CONST.DICE_ROLL_MODES.BLIND: + case CONST.DICE_ROLL_MODES.SELF: return true; + } + return false } static getActiveUser(id) { @@ -150,11 +153,11 @@ export class Misc { return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active); } - static isOwnerPlayer(actor, user=undefined) { + static isOwnerPlayer(actor, user = undefined) { return actor.testUserPermission(user ?? game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER) } - static isOwnerPlayerOrUniqueConnectedGM(actor, user =undefined){ + static isOwnerPlayerOrUniqueConnectedGM(actor, user = undefined) { return Misc.isOwnerPlayer(actor, user) ?? Misc.isUniqueConnectedGM(); } diff --git a/module/rdd-astrologie-joueur.js b/module/rdd-astrologie-joueur.js index 5ec5660d..2fa46038 100644 --- a/module/rdd-astrologie-joueur.js +++ b/module/rdd-astrologie-joueur.js @@ -60,7 +60,7 @@ export class RdDAstrologieJoueur extends Dialog { /* -------------------------------------------- */ static organizeNombres(actor) { - let itemNombres = actor.listItemsData('nombreastral'); + let itemNombres = actor.listItems('nombreastral'); let itemFiltered = {}; for (let item of itemNombres) { if (itemFiltered[item.system.jourindex]) { diff --git a/module/rdd-calendrier.js b/module/rdd-calendrier.js index 554a11e2..2c1e134b 100644 --- a/module/rdd-calendrier.js +++ b/module/rdd-calendrier.js @@ -350,7 +350,7 @@ export class RdDCalendrier extends Application { } else { ChatMessage.create({ content: `${actor.name} souffre d'un mal inconnu (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` }); } - let itemMaladie = actor.getObjet(maladie.id) + let itemMaladie = actor.getItem(maladie.id) itemMaladie.postItem( 'gmroll'); } } diff --git a/module/rdd-main.js b/module/rdd-main.js index e3d456d9..b1799ce7 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -36,6 +36,7 @@ import { RdDFauneItemSheet } from "./item-faune-sheet.js"; import { RdDConteneurItemSheet } from "./item-conteneur-sheet.js"; import { RdDServiceItemSheet } from "./item-service-sheet.js"; import { RdDItemService } from "./item-service.js"; +import { RdDBaseActor } from "./actor/base-actor.js"; /** * RdD system @@ -57,6 +58,10 @@ export class SystemReveDeDragon { service: RdDItemService } this.actorClasses = { + creature: RdDActor, + entite: RdDActor, + personnage: RdDActor, + vehicule: RdDActor, } } @@ -161,7 +166,7 @@ export class SystemReveDeDragon { RdDUtility.onSocketMessage(sockmsg); RdDCombat.onSocketMessage(sockmsg); ChatUtility.onSocketMessage(sockmsg); - RdDActor.onSocketMessage(sockmsg); + RdDBaseActor.onSocketMessage(sockmsg); } catch (e) { console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg, ' => ', e) } @@ -218,7 +223,7 @@ export class SystemReveDeDragon { RdDCombat.init(); RdDCombatManager.init(); RdDTokenHud.init(); - RdDActor.init(); + RdDBaseActor.init(); RddCompendiumOrganiser.init(); EffetsDraconiques.init() TMRUtility.init(); diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 33908d61..a8150ef0 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -315,63 +315,13 @@ export class RdDUtility { } static getItem(itemId, actorId = undefined) { - return actorId ? game.actors.get(actorId)?.getObjet(itemId) : game.items.get(itemId); + return actorId ? game.actors.get(actorId)?.getItem(itemId) : game.items.get(itemId); } static linkCompendium(pack, id, name) { return `@Compendium[${pack}.${id}]{${name}}`; } - /* -------------------------------------------- */ - static async creerObjet(actorSheet) { - let itemType = $(".item-type").val(); - await actorSheet.createItem('Nouveau ' + itemType, itemType); - } - - /* -------------------------------------------- */ - static async selectObjetType(actorSheet) { - let typeObjets = RdDItem.getItemTypesInventaire(); - let options = `Selectionnez le type d'équipement'; - let d = new Dialog({ - title: "Créer un équipement", - content: options, - buttons: { - one: { - icon: '', - label: "Créer l'objet", - callback: () => this.creerObjet(actorSheet) - } - } - }); - d.render(true); - } - - /* -------------------------------------------- */ - static async selectTypeOeuvre(actorSheet) { - let typeObjets = RdDItem.getTypesOeuvres(); - let options = `Selectionnez le type d'oeuvre'; - let d = new Dialog({ - title: "Créer un équipement", - content: options, - buttons: { - one: { - icon: '', - label: "Créer l'objet", - callback: () => this.creerObjet(actorSheet) - } - } - }); - d.render(true); - } - /* -------------------------------------------- */ static buildListOptions(min, max) { let options = "" -- 2.35.3 From 26808d7b49ea6b1571691b3f043d00afac56bc3f Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Thu, 29 Dec 2022 02:24:18 +0100 Subject: [PATCH 4/9] Controle visibilite Ne pas afficher les boutons non accessibles --- templates/actor-sheet.html | 130 ++++++++++++------------ templates/actor/inventaire-item.html | 7 +- templates/actor/inventaire-monnaie.html | 10 +- 3 files changed, 81 insertions(+), 66 deletions(-) diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 20782f13..fb4fd2c5 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -21,88 +21,89 @@ {{!-- Sheet Tab Navigation --}} + {{#if options.isObserver}} + Carac. + Compétences + Combat + Savoirs&Taches + Haut-Rêve + {{/if}} + Équipement + Description + - {{!-- Sheet Body --}} -
- - {{!-- Carac Tab --}} -
-
- {{>"systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html"}} + {{!-- Sheet Body --}} +
+ {{#if options.isObserver}}{{!-- Carac Tab --}} +
+
+ {{>"systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html"}} +
+
+
+ {{>"systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html"}} + {{>"systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.html"}}
-
-
- {{>"systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html"}} - {{>"systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.html"}} -
-
- {{>"systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html"}} -
+
+ {{>"systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html"}}
- - {{!-- Compétences Tab --}} -
-
- {{>"systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html"}} - - {{#if options.showCompNiveauBase}} - Montrer tout - {{else}} - Filtrer - {{/if}} - - - - - - +
+ {{/if}} + {{#if options.isObserver}}{{!-- Compétences Tab --}} +
+
+ {{>"systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html"}} + + {{#if options.showCompNiveauBase}} + Montrer tout + {{else}} + Filtrer + {{/if}} + + + + + + +
+
+
+ {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.generale) categorie="Compétences générales"}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.particuliere) categorie="Compétences Particulières"}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.specialisee) categorie="Compétences Spécialisées"}}
-
-
- {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.generale) categorie="Compétences générales"}} - {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.particuliere) categorie="Compétences Particulières"}} - {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.specialisee) categorie="Compétences Spécialisées"}} -
-
- {{> "systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.html"}} - {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.melee) categorie="Compétences de Mêlée"}} - {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.tir) categorie="Compétences de Tir"}} - {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.lancer) categorie="Compétences de Lancer"}} - {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.connaissance) categorie="Connaissances"}} - {{#if (or system.attributs.hautrevant.value options.vueDetaillee)}} - {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.draconic) categorie="Draconic"}} - {{/if}} -
+
+ {{> "systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.html"}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.melee) categorie="Compétences de Mêlée"}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.tir) categorie="Compétences de Tir"}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.lancer) categorie="Compétences de Lancer"}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.connaissance) categorie="Connaissances"}} + {{#if (or system.attributs.hautrevant.value options.vueDetaillee)}} + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.draconic) categorie="Draconic"}} + {{/if}}
- - {{!-- Combat Tab --}} -
+
+ {{/if}} + {{#if options.isObserver}}{{!-- Combat Tab --}} +
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/combat.html"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/blessures.html"}} {{> "systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html"}} {{> "systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html"}} -
- - {{!-- Connaissances Tab --}} + {{/if}} + + {{#if options.isObserver}}{{!-- Connaissances Tab --}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/taches.html"}} {{> "systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html"}} {{> "systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html"}} {{> "systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html"}}
- - {{!-- hautreve Tab --}} + {{/if}} + {{#if options.isObserver}}{{!-- hautreve Tab --}}
{{#if system.attributs.hautrevant.value}} @@ -116,6 +117,7 @@

+ {{/if}} {{!-- Equipment Tab --}}
diff --git a/templates/actor/inventaire-item.html b/templates/actor/inventaire-item.html index 29511c41..a1f25f49 100644 --- a/templates/actor/inventaire-item.html +++ b/templates/actor/inventaire-item.html @@ -1,3 +1,4 @@ +{{#if (or @root.options.isObserver (ne item.type 'monnaie'))}}
  • {{#if (eq item.type 'conteneur')}} @@ -20,6 +21,7 @@ {{numberFormat item.system.encTotal decimals=2}} + {{#if @root.options.isOwner}} {{#unless item.estContenu}} {{#if (or (eq item.type 'arme') (eq item.type 'armure') )}} {{#if item.system.equipe}}{{else}}{{/if}} @@ -31,10 +33,13 @@ {{#if (ne item.system.quantite 0)}} {{/if}} + {{/if}} + {{#if @root.options.isOwner}} {{#if item.system.actionPrincipale}} {{item.system.actionPrincipale}} {{/if}} + {{/if}}
  • - +{{/if}} diff --git a/templates/actor/inventaire-monnaie.html b/templates/actor/inventaire-monnaie.html index 851d2188..ddb413ad 100644 --- a/templates/actor/inventaire-monnaie.html +++ b/templates/actor/inventaire-monnaie.html @@ -1,3 +1,4 @@ +{{#if @root.options.isObserver}}

    Argent et Monnaies (fortune: {{calc.fortune.sols}} sols {{calc.fortune.deniers}} deniers)

      {{#each monnaie as |piece id|}} @@ -7,19 +8,26 @@ ({{piece.system.cout}} Sols) + {{#if @root.options.isOwner}} + {{/if}} {{piece.system.quantite}} + {{#if @root.options.isOwner}} - + {{/if}} + + {{#if @root.options.isOwner}} + {{/if}} {{/each}}
    +{{/if}} -- 2.35.3 From c79298b60a504ce1ad4499c51875db5a42d5c964 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Thu, 29 Dec 2022 02:25:45 +0100 Subject: [PATCH 5/9] Post to chat pour les acteurs --- module/actor/base-actor-sheet.js | 15 ++++++++++++++- module/actor/base-actor.js | 18 ++++++++++++++++++ module/item-sheet.js | 4 ++-- module/item.js | 23 +++++++++++------------ module/rdd-calendrier.js | 2 +- module/rdd-utility.js | 12 ++++++++++-- templates/common/compendium-link.hbs | 12 ++++++++++-- templates/post-actor.html | 7 +++++++ templates/post-item-service.html | 4 ++-- templates/post-item.html | 3 +-- 10 files changed, 76 insertions(+), 24 deletions(-) create mode 100644 templates/post-actor.html diff --git a/module/actor/base-actor-sheet.js b/module/actor/base-actor-sheet.js index ecf23013..98cd8650 100644 --- a/module/actor/base-actor-sheet.js +++ b/module/actor/base-actor-sheet.js @@ -142,7 +142,8 @@ export class RdDBaseActorSheet extends ActorSheet { this.render(true); }); this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true)) - this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItem()); + this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItemToChat()); + this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat()); // Everything below here is only needed if the sheet is editable if (!this.options.editable) return; @@ -169,6 +170,18 @@ export class RdDBaseActorSheet extends ActorSheet { } + + /* -------------------------------------------- */ + _getHeaderButtons() { + let buttons = super._getHeaderButtons(); + buttons.unshift({ + class: "montrer", + icon: "fas fa-comment", + onclick: ev => this.actor.postActorToChat() + }); + return buttons + } + /* -------------------------------------------- */ async _onDropItem(event, dragData) { const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id') diff --git a/module/actor/base-actor.js b/module/actor/base-actor.js index 7b1e7935..b95a7ff5 100644 --- a/module/actor/base-actor.js +++ b/module/actor/base-actor.js @@ -1,6 +1,7 @@ import { SYSTEM_SOCKET_ID } from "../constants.js"; import { Monnaie } from "../item-monnaie.js"; import { Misc } from "../misc.js"; +import { RdDUtility } from "../rdd-utility.js"; import { SystemCompendiums } from "../settings/system-compendiums.js"; export class RdDBaseActor extends Actor { @@ -146,4 +147,21 @@ export class RdDBaseActor extends Actor { canReceive(item) { return false; } + + /* -------------------------------------------- */ + async postActorToChat(modeOverride) { + let chatData = { + doctype: 'Actor', + id: this.id, + type: this.type, + img: this.img, + pack: this.pack, + name: this.name, + system: { description: this.system.description } + } + renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.html', chatData) + .then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride))); + } + + } \ No newline at end of file diff --git a/module/item-sheet.js b/module/item-sheet.js index 27c1ebb8..11b742cb 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -66,7 +66,7 @@ export class RdDItemSheet extends ItemSheet { buttons.unshift({ class: "montrer", icon: "fas fa-comment", - onclick: ev => this.item.postItem() + onclick: ev => this.item.postItemToChat() }); return buttons } @@ -211,7 +211,7 @@ export class RdDItemSheet extends ItemSheet { 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)?.postItem()); + 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, async () => this.render(true))); } diff --git a/module/item.js b/module/item.js index 7bcbeda6..95fadacf 100644 --- a/module/item.js +++ b/module/item.js @@ -455,20 +455,19 @@ export class RdDItem extends Item { } /* -------------------------------------------- */ - async postItem(modeOverride) { + async postItemToChat(modeOverride) { console.log(this); - let chatData = duplicate(this); - chatData["properties"] = this.getProprietes(); - if (this.actor) { - chatData.actor = { id: this.actor.id }; + let chatData = { + doctype: 'Item', + id: this.id, + type: this.type, + img: this.img, + pack: this.pack, + name: this.name, + actor : this.actor ? { id: this.actor.id } : undefined, + system: { description: this.system.description }, + properties: this.getProprietes(), } - // JSON object for easy creation - chatData.jsondata = JSON.stringify( - { - compendium: "postedItem", - payload: chatData, - }); - renderTemplate(this.getChatItemTemplate(), chatData).then(html => { let chatOptions = RdDUtility.chatDataSetup(html, modeOverride); ChatMessage.create(chatOptions) diff --git a/module/rdd-calendrier.js b/module/rdd-calendrier.js index 2c1e134b..3a2e7d41 100644 --- a/module/rdd-calendrier.js +++ b/module/rdd-calendrier.js @@ -351,7 +351,7 @@ export class RdDCalendrier extends Application { ChatMessage.create({ content: `${actor.name} souffre d'un mal inconnu (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` }); } let itemMaladie = actor.getItem(maladie.id) - itemMaladie.postItem( 'gmroll'); + itemMaladie.postItemToChat('gmroll'); } } } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index a8150ef0..98d210fe 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -783,8 +783,16 @@ export class RdDUtility { } }); html.on("click", '.rdd-world-content-link', async event => { - const itemId = html.find(event.currentTarget)?.data("id"); - game.items.get(itemId)?.sheet.render(true) + const htmlElement = html.find(event.currentTarget); + const id = htmlElement?.data("id"); + const doctype= htmlElement?.data("doctype"); + switch (doctype ?? 'Item') { + case 'Actor': + return game.actors.get(id)?.sheet.render(true); + case 'Item': + default: + return game.items.get(id)?.sheet.render(true); + } }); } diff --git a/templates/common/compendium-link.hbs b/templates/common/compendium-link.hbs index 5b4a1af9..905a04b5 100644 --- a/templates/common/compendium-link.hbs +++ b/templates/common/compendium-link.hbs @@ -1,6 +1,14 @@ {{#if pack}} {{!-- draggable="true" --}} -{{name}} +{{name}} {{else}} -{{name}} +{{name}} {{/if}} diff --git a/templates/post-actor.html b/templates/post-actor.html new file mode 100644 index 00000000..fd2cc702 --- /dev/null +++ b/templates/post-actor.html @@ -0,0 +1,7 @@ +
    + {{#if img}} + + {{/if}} +

    {{> 'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs' pack=pack id=id name=name doctype=doctype}}

    +

    {{{system.description}}}

    +
    diff --git a/templates/post-item-service.html b/templates/post-item-service.html index 4073de14..73c6b1c9 100644 --- a/templates/post-item-service.html +++ b/templates/post-item-service.html @@ -1,8 +1,8 @@ -
    +
    {{#if img}} {{/if}} -

    {{> 'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs' pack=pack id=_id name=name}}

    +

    {{> 'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs' pack=pack id=id name=name docType=docType}}

    {{{system.description}}}

    diff --git a/templates/post-item.html b/templates/post-item.html index 380dcdcc..67be2ee3 100644 --- a/templates/post-item.html +++ b/templates/post-item.html @@ -1,4 +1,4 @@ -
    +

    {{name}}

    {{#if img}} @@ -10,5 +10,4 @@ {{{property}}}
    {{/each}}

    -
    -- 2.35.3 From 454193490d324a3cabf95715dee2b3c29f79498e Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Thu, 29 Dec 2022 02:31:29 +0100 Subject: [PATCH 6/9] Fix astrologie joueur --- module/actor.js | 24 ++++---- module/rdd-astrologie-joueur.js | 18 +++--- module/rdd-calendrier.js | 73 ++++++++++++++++--------- templates/actor-sheet.html | 1 + templates/dialog-astrologie-joueur.html | 2 +- 5 files changed, 66 insertions(+), 52 deletions(-) diff --git a/module/actor.js b/module/actor.js index 72c90746..f532d894 100644 --- a/module/actor.js +++ b/module/actor.js @@ -3073,32 +3073,30 @@ export class RdDActor extends RdDBaseActor { /* -------------------------------------------- */ async ajouteNombreAstral(callData) { - // Gestion expérience (si existante) - callData.competence = this.getCompetence("astrologie") - callData.selectedCarac = this.system.carac["vue"]; - this.appliquerAjoutExperience(callData, 'hide'); - // Ajout du nombre astral const item = { name: "Nombre Astral", type: "nombreastral", system: { value: callData.nbAstral, istrue: callData.isvalid, jourindex: Number(callData.date), jourlabel: game.system.rdd.calendrier.getDateFromIndex(Number(callData.date)) } }; await this.createEmbeddedDocuments("Item", [item]); - - // Suppression des anciens nombres astraux - let toDelete = this.listItems('nombreastral').filter(it => it.system.jourindex < game.system.rdd.calendrier.getCurrentDayIndex()); - const deletions = toDelete.map(it => it._id); - await this.deleteEmbeddedDocuments("Item", deletions); - // Affichage Dialog this.astrologieNombresAstraux(); } + async supprimerAnciensNombresAstraux() { + const toDelete = this.listItems('nombreastral') + .filter(it => it.system.jourindex < game.system.rdd.calendrier.getCurrentDayIndex()) + .map(it => it._id); + await this.deleteEmbeddedDocuments("Item", toDelete); + } + /* -------------------------------------------- */ async astrologieNombresAstraux() { + // Suppression des anciens nombres astraux + await this.supprimerAnciensNombresAstraux(); + // Afficher l'interface spéciale - const astrologieDialog = await RdDAstrologieJoueur.create(this, {}); - astrologieDialog.render(true); + await RdDAstrologieJoueur.create(this); } /* -------------------------------------------- */ diff --git a/module/rdd-astrologie-joueur.js b/module/rdd-astrologie-joueur.js index 2fa46038..abab8a66 100644 --- a/module/rdd-astrologie-joueur.js +++ b/module/rdd-astrologie-joueur.js @@ -10,7 +10,7 @@ import { SYSTEM_SOCKET_ID } from "./constants.js"; export class RdDAstrologieJoueur extends Dialog { /* -------------------------------------------- */ - static async create(actor, dialogConfig) { + static async create(actor) { let dialogData = { nombres: this.organizeNombres(actor), @@ -20,15 +20,14 @@ export class RdDAstrologieJoueur extends Dialog { astrologie: RdDItemCompetence.findCompetence(actor.items, 'Astrologie') } const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', dialogData); - let options = { classes: ["rdd-roll-dialog"], width: 600, height: 500, 'z-index': 99999 }; - if (dialogConfig.options) { - mergeObject(options, dialogConfig.options, { overwrite: true }); - } - return new RdDAstrologieJoueur(html, actor, dialogData); + + const options = { classes: ["rdd-roll-dialog"], width: 600, height: 'fit-content', 'z-index': 99999 }; + const dialog = new RdDAstrologieJoueur(html, actor, dialogData, options); + dialog.render(true); } /* -------------------------------------------- */ - constructor(html, actor, dialogData) { + constructor(html, actor, dialogData, dialogOptions) { const dialogConf = { title: "Nombres Astraux", content: html, @@ -37,7 +36,6 @@ export class RdDAstrologieJoueur extends Dialog { saveButton: { label: "Fermer", callback: html => this.quitDialog() } }, }; - const dialogOptions = { classes: ["rdd-roll-dialog"], width: 600, height: 300, 'z-index': 99999 }; super(dialogConf, dialogOptions); this.actor = actor; @@ -49,9 +47,7 @@ export class RdDAstrologieJoueur extends Dialog { super.activateListeners(html); this.html = html; - this.html.find(function () { - this.html.find("[name='diffConditions']").val(0); - }); + this.html.find("[name='diffConditions']").val(0); this.html.find('[name="jet-astrologie"]').click((event) => { this.requestJetAstrologie(); diff --git a/module/rdd-calendrier.js b/module/rdd-calendrier.js index 3a2e7d41..a4996963 100644 --- a/module/rdd-calendrier.js +++ b/module/rdd-calendrier.js @@ -14,7 +14,7 @@ import { DialogChronologie } from "./dialog-chronologie.js"; const dossierIconesHeures = 'systems/foundryvtt-reve-de-dragon/icons/heures/' const heuresList = ["vaisseau", "sirene", "faucon", "couronne", "dragon", "epees", "lyre", "serpent", "poissonacrobate", "araignee", "roseau", "chateaudormant"]; const heuresDef = { - "vaisseau": {key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "printemps", heure: 0, icon: 'hd01.svg' }, + "vaisseau": { key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "printemps", heure: 0, icon: 'hd01.svg' }, "sirene": { key: "sirene", label: "Sirène", lettreFont: 'i', saison: "printemps", heure: 1, icon: 'hd02.svg' }, "faucon": { key: "faucon", label: "Faucon", lettreFont: 'f', saison: "printemps", heure: 2, icon: 'hd03.svg' }, "couronne": { key: "couronne", label: "Couronne", lettreFont: '', saison: "ete", heure: 3, icon: 'hd04.svg' }, @@ -64,7 +64,7 @@ export class RdDCalendrier extends Application { const heure = (typeof value == 'string' || typeof value == 'number') && Number.isInteger(Number(value)) ? Number(value) : (typeof value == 'string') ? RdDCalendrier.getChiffreFromSigne(value) - : undefined + : undefined if (heure != undefined && ['key', 'label', 'lettreFont', 'saison', 'heure', 'icon'].includes(key)) { return RdDCalendrier.getDefSigne(heure)[key] @@ -340,21 +340,21 @@ export class RdDCalendrier extends Application { } /* -------------------------------------------- */ - checkMaladie( periode) { + checkMaladie(periode) { for (let actor of game.actors) { if (actor.type == 'personnage') { - let maladies = actor.items.filter( item => (item.type == 'maladie' || (item.type == 'poison' && item.system.active) ) && item.system.periodicite.toLowerCase().includes(periode) ); + let maladies = actor.items.filter(item => (item.type == 'maladie' || (item.type == 'poison' && item.system.active)) && item.system.periodicite.toLowerCase().includes(periode)); for (let maladie of maladies) { - if ( maladie.system.identifie) { + if (maladie.system.identifie) { ChatMessage.create({ content: `${actor.name} souffre de ${maladie.name} (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` }); } else { ChatMessage.create({ content: `${actor.name} souffre d'un mal inconnu (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` }); } let itemMaladie = actor.getItem(maladie.id) - itemMaladie.postItemToChat('gmroll'); + itemMaladie.postItem('gmroll'); } } - } + } } /* -------------------------------------------- */ @@ -366,7 +366,7 @@ export class RdDCalendrier extends Application { this.calendrier.minutesRelative -= RDD_MINUTES_PAR_HEURES; this.calendrier.heureRdD += 1; this.checkMaladie("heure"); - } + } if (this.calendrier.heureRdD >= RDD_HEURES_PAR_JOUR) { this.calendrier.heureRdD -= RDD_HEURES_PAR_JOUR; await this.incrementerJour(); @@ -434,6 +434,7 @@ export class RdDCalendrier extends Application { /* -------------------------------------------- */ async requestNombreAstral(request) { + const actor = game.actors.get(request.id); if (Misc.isUniqueConnectedGM()) { // Only once console.log(request); let jourDiff = this.getLectureAstrologieDifficulte(request.date); @@ -445,18 +446,26 @@ export class RdDCalendrier extends Application { rollMode: "blindroll" }; await RdDResolutionTable.rollData(rollData); - let nbAstral = this.getNombreAstral(request.date); request.rolled = rollData.rolled; - request.isValid = true; - if (!request.rolled.isSuccess) { - request.isValid = false; - nbAstral = await RdDDice.rollTotal("1dhr" + nbAstral, { rollMode: "selfroll" }); - // Mise à jour des nombres astraux du joueur - let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == request.date); - astralData.valeursFausses.push({ actorId: request.id, nombreAstral: nbAstral }); - game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral); + request.isValid = request.rolled.isSuccess; + request.nbAstral = this.getNombreAstral(request.date); + + if (request.rolled.isSuccess) { + if (request.rolled.isPart){ + // Gestion expérience (si existante) + request.competence = actor.getCompetence("astrologie") + request.selectedCarac = actor.system.carac["vue"]; + actor.appliquerAjoutExperience(request, 'hide'); + } } - request.nbAstral = nbAstral; + else { + request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, { + rollMode: "selfroll", showDice: HIDE_DICE + }); + // Mise à jour des nombres astraux du joueur + this.addNbAstralIncorect(request.id, request.date, request.nbAstral); + } + if (Misc.getActiveUser(request.userId)?.isGM) { RdDUtility.responseNombreAstral(request); } else { @@ -468,6 +477,12 @@ export class RdDCalendrier extends Application { } } + addNbAstralIncorect(actorId, date, nbAstral) { + let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == date); + astralData.valeursFausses.push({ actorId: actorId, nombreAstral: nbAstral }); + game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral); + } + /* -------------------------------------------- */ findHeure(heure) { heure = Grammar.toLowerCaseNoAccentNoSpace(heure); @@ -483,7 +498,7 @@ export class RdDCalendrier extends Application { return undefined; } /* -------------------------------------------- */ - getHeureNumber( hNum) { + getHeureNumber(hNum) { let heure = Object.values(heuresDef).find(it => (it.heure) == hNum); return heure } @@ -495,12 +510,16 @@ export class RdDCalendrier extends Application { if (defHeure) { let hn = defHeure.heure; let chiffreAstral = this.getCurrentNombreAstral() ?? 0; - heuresChancesMalchances[0] = { value : "+4", heures: [this.getHeureNumber((hn + chiffreAstral) % RDD_HEURES_PAR_JOUR).label]}; - heuresChancesMalchances[1] = { value : "+2", heures: [this.getHeureNumber((hn + chiffreAstral+4) % RDD_HEURES_PAR_JOUR).label, - this.getHeureNumber((hn + chiffreAstral + 8) % RDD_HEURES_PAR_JOUR).label ] }; - heuresChancesMalchances[2] = { value : "-4", heures: [this.getHeureNumber((hn + chiffreAstral+6) % RDD_HEURES_PAR_JOUR).label]}; - heuresChancesMalchances[3] = { value : "-2", heures: [this.getHeureNumber((hn + chiffreAstral+3) % RDD_HEURES_PAR_JOUR).label, - this.getHeureNumber((hn + chiffreAstral + 9) % RDD_HEURES_PAR_JOUR).label ]}; + heuresChancesMalchances[0] = { value: "+4", heures: [this.getHeureNumber((hn + chiffreAstral) % RDD_HEURES_PAR_JOUR).label] }; + heuresChancesMalchances[1] = { + value: "+2", heures: [this.getHeureNumber((hn + chiffreAstral + 4) % RDD_HEURES_PAR_JOUR).label, + this.getHeureNumber((hn + chiffreAstral + 8) % RDD_HEURES_PAR_JOUR).label] + }; + heuresChancesMalchances[2] = { value: "-4", heures: [this.getHeureNumber((hn + chiffreAstral + 6) % RDD_HEURES_PAR_JOUR).label] }; + heuresChancesMalchances[3] = { + value: "-2", heures: [this.getHeureNumber((hn + chiffreAstral + 3) % RDD_HEURES_PAR_JOUR).label, + this.getHeureNumber((hn + chiffreAstral + 9) % RDD_HEURES_PAR_JOUR).label] + }; } return heuresChancesMalchances; } @@ -634,9 +653,9 @@ export class RdDCalendrier extends Application { let heuresParActeur = {}; for (let actor of game.actors) { let heureNaissance = actor.getHeureNaissance(); - if ( heureNaissance) { + if (heureNaissance) { heuresParActeur[actor.name] = this.getHeuresChanceMalchance(heureNaissance); - } + } } //console.log("ASTRO", astrologieArray); calendrierData.astrologieData = astrologieArray; diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index fb4fd2c5..9ea52c13 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -97,6 +97,7 @@ {{#if options.isObserver}}{{!-- Connaissances Tab --}}
    + {{> "systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html"}} {{> "systems/foundryvtt-reve-de-dragon/templates/actor/taches.html"}} {{> "systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html"}} {{> "systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html"}} diff --git a/templates/dialog-astrologie-joueur.html b/templates/dialog-astrologie-joueur.html index 24096304..ce433115 100644 --- a/templates/dialog-astrologie-joueur.html +++ b/templates/dialog-astrologie-joueur.html @@ -16,7 +16,7 @@ - {{>'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs' proposals=options.mainsDirectrices className='selection-main-directrice'}} +
    + + {{>'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs' proposals=options.mainsDirectrices className='selection-main-directrice'}} +
  • diff --git a/templates/item/partial-environnement.html b/templates/item/partial-environnement.html index 9339b833..778ab451 100644 --- a/templates/item/partial-environnement.html +++ b/templates/item/partial-environnement.html @@ -10,8 +10,10 @@
    - - {{>'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs' proposals=milieux className='input-selection-milieu'}} +
    + + {{>'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs' proposals=milieux className='input-selection-milieu'}} +
    -- 2.35.3 From c933810b6b229dea84796f479aad44a9a9acbd72 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Fri, 30 Dec 2022 02:59:50 +0100 Subject: [PATCH 9/9] Fix: tab order milieux --- templates/item/partial-environnement.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/item/partial-environnement.html b/templates/item/partial-environnement.html index 778ab451..fe9e3846 100644 --- a/templates/item/partial-environnement.html +++ b/templates/item/partial-environnement.html @@ -11,25 +11,25 @@
    - + {{>'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs' proposals=milieux className='input-selection-milieu'}}
  • - {{#each system.environnement as |env|}} + {{#each system.environnement as |env key|}}
    - {{#select env.rarete}} {{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}} {{/select}} - {{rangePicker name="environnement-frequence" value=env.frequence min=(getFrequenceRarete env.rarete 'min') max=(getFrequenceRarete env.rarete 'max') step=1}} + {{rangePicker name="milieu-{{key}}-frequence" value=env.frequence min=(getFrequenceRarete env.rarete 'min') max=(getFrequenceRarete env.rarete 'max') step=1}}
    -- 2.35.3