From c4cb3bf60dd8a24b035fa2144f713eb648dff581 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Fri, 7 May 2021 17:27:02 +0200 Subject: [PATCH] Ecole de commerce --- module/actor-sheet.js | 6 + module/actor.js | 106 ++++++++++++++++-- module/dialog-item-achat.js | 86 ++++++++++++++ module/dialog-item-vente.js | 90 +++++++++++++++ module/item-monnaie.js | 4 + module/item-sheet.js | 101 +++++++++-------- module/item.js | 56 ++++++--- module/rdd-utility.js | 33 ++++-- .../actor-sheet-inventaire-conteneur.html | 6 +- templates/chat-achat-item.html | 8 ++ templates/chat-vente-item.html | 36 ++++++ templates/dialog-item-achat.html | 49 ++++++++ templates/dialog-item-vente.html | 41 +++++++ 13 files changed, 539 insertions(+), 83 deletions(-) create mode 100644 module/dialog-item-achat.js create mode 100644 module/dialog-item-vente.js create mode 100644 templates/chat-achat-item.html create mode 100644 templates/chat-vente-item.html create mode 100644 templates/dialog-item-achat.html create mode 100644 templates/dialog-item-vente.html diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 49b6e088..455b3c98 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -239,6 +239,12 @@ export class RdDActorSheet extends ActorSheet { const li = $(ev.currentTarget).parents(".item"); RdDUtility.confirmerSuppression(this, li); }); + html.find('.item-vendre').click(ev => { + const li = $(ev.currentTarget).parents(".item"); + const itemId = li.data("item-id"); + const item = this.actor.getObjet(itemId); + item?.proposerVente(); + }); html.find('.item-action').click(ev => { const li = $(ev.currentTarget).parents(".item"); const itemId = li.data("item-id"); diff --git a/module/actor.js b/module/actor.js index 0e885c0c..9e987212 100644 --- a/module/actor.js +++ b/module/actor.js @@ -969,12 +969,11 @@ export class RdDActor extends Actor { this.moveItemsBetweenActors(droppedItemId, dragData.actorId); return false; } - let result = true; const destId = $(event.target).parents(".item").attr("data-item-id"); const itemId = dragData.id || dragData.data._id; const item = this.getObjet(itemId); - if (item.isEquipement()) { + if (item?.isEquipement()) { if (dragData.actorId == this.id) { // rangement const srcId = objetVersConteneur[itemId]; @@ -1000,8 +999,8 @@ export class RdDActor extends Actor { } } } - await this.computeEncombrementTotalEtMalusArmure(); } + await this.computeEncombrementTotalEtMalusArmure(); return result; } /* -------------------------------------------- */ @@ -1472,7 +1471,7 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async santeIncDec(name, inc, options = {isCritique: false, ethylisme: false}) { + async santeIncDec(name, inc, options = { isCritique: false, ethylisme: false }) { const sante = duplicate(Misc.templateData(this).sante); let compteur = sante[name]; @@ -1667,7 +1666,7 @@ export class RdDActor extends Actor { let enduranceLost = new Roll("1d6").roll().total; rollDataView.enduranceLost = enduranceLost; - await this.santeIncDec("endurance", -enduranceLost, {ethylisme:true}); + await this.santeIncDec("endurance", -enduranceLost, { ethylisme: true }); // Qui a bu boira (p 164) let rollVolonte = await RdDResolutionTable.roll(actorData.data.carac.volonte.value, Math.min(ethylisme.value, 0) + actorData.data.compteurs.moral.value); rollDataView.rollVolonteIsSuccess = rollVolonte.isSuccess; @@ -1741,7 +1740,7 @@ export class RdDActor extends Actor { return; } if (choix.doses > itemData.data.quantite) { - ui.notifications.warn(`Il n'y a pas assez de ${itemData.name} poour manger ${choix.doses}`) + ui.notifications.warn(`Il n'y a pas assez de ${itemData.name} pour manger ${choix.doses}`) return; } const surmonteExotisme = await this.surmonterExotisme(item, choix); @@ -2946,7 +2945,7 @@ export class RdDActor extends Actor { const perteVie = this.isEntiteCauchemar() ? { newValue: 0 } : await this.santeIncDec("vie", - encaissement.vie); - const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, {critiques: encaissement.critiques > 0}); + const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, { critiques: encaissement.critiques > 0 }); this.computeEtatGeneral(); this.sheet.render(false); @@ -3210,9 +3209,7 @@ export class RdDActor extends Actor { if (fortune >= depense) { fortune -= depense; const toActor = game.actors.get(toActorId) - if (toActor) { - toActor.ajouterDeniers(depense, this.id); - } + await toActor?.ajouterDeniers(depense, this.id); await this.optimizeArgent(fortune); msg = `Vous avez payé ${depense} Deniers${toActor ? " à " + toActor.name : ''}, qui ont été soustraits de votre argent.`; RdDAudio.PlayContextAudio("argent"); // Petit son @@ -3235,6 +3232,17 @@ export class RdDActor extends Actor { ChatMessage.create(message); } + async depenser(depense) { + depense = Number(depense); + let fortune = this.getFortune(); + let reste = fortune - depense; + if (reste >= 0) { + fortune -= depense; + await this.optimizeArgent(fortune); + } + return reste; + } + async ajouterDeniers(gain, fromActorId = undefined) { if (fromActorId && !game.user.isGM) { RdDActor.remoteActorCall({ userId: Misc.connectedGMOrUser(), actorId: this.id, method: 'ajouterDeniers', args: [gain, fromActorId] }); @@ -3248,7 +3256,7 @@ export class RdDActor extends Actor { RdDAudio.PlayContextAudio("argent"); // Petit son ChatMessage.create({ whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), - content: `Vous avez reçu ${gain} Deniers ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés de votre argent.` + content: `Vous avez reçu ${gain} Deniers ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.` }); } } @@ -3262,6 +3270,82 @@ export class RdDActor extends Actor { } } + /* -------------------------------------------- */ + async achatVente(vendeurId, acheteurId, venteData, chatMessageIdVente) { + if (!game.user.isGM) { + RdDActor.remoteActorCall({ + userId: Misc.connectedGMOrUser(), + actorId: this.vendeur?.id ?? this.acheteur?.id, + method: 'achatVente', args: [vendeurId, acheteurId, venteData, chatMessageIdVente] + }); + return; + } + + const acheteur = acheteurId ? game.actors.get(acheteurId) : undefined; + const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined; + const itemId = venteData.item._id; + + const coutDeniers = Math.floor((venteData.prixTotal ?? 0) * 100); + const achat = duplicate(venteData.item); + venteData.quantiteTotal = (venteData.nombreLots ?? 1) * (venteData.tailleLot); + if (acheteur) { + let resteAcheteur = await acheteur.depenser(coutDeniers); + if (resteAcheteur < 0) { + ui.notifications.warn(`Vous n'avez pas assez d'argent pour payer ${venteData.prixTotal} sols !`); + return; + } + } + if (vendeur) { + let itemData = Misc.data(vendeur.getObjet(itemId)); + // diminuer QuantiteVendeur + if (("quantite" in itemData.data && itemData.data.quantite < venteData.nombreLots) + || (!("quantite" in itemData.data) && venteData.nombreLots != 1)) { + // pas assez de quantite + await acheteur?.ajouterDeniers(coutDeniers); + ui.notifications.warn(`Le vendeur n'a plus assez de ${venteData.item.name} !`); + return; + } + vendeur.ajouterDeniers(coutDeniers); + let qtReste = (itemData.data.quantite ?? 1) - venteData.nombreLots; + if (qtReste == 0) { + vendeur.deleteEmbeddedDocuments("Item", itemId); + } + else { + vendeur.updateEmbeddedDocuments("Item", [{ _id: itemId, 'data.quantite': qtReste }]); + } + } + + if (acheteur) { + // ajouter l'objet à l'acheteur + achat._id = undefined; + if ("quantite" in achat.data) { + achat.data.quantite = venteData.quantiteTotal; + } + await acheteur.createEmbeddedDocuments("Item", [achat]); + } + if (coutDeniers > 0) { + RdDAudio.PlayContextAudio("argent"); + } + + ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), + content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html', venteData) + }); + + venteData.quantiteNbLots -= venteData.nombreLots; + if (venteData.quantiteNbLots <= 0) { + ChatUtility.removeChatMessageId(chatMessageIdVente); + } + else { + venteData.jsondata = JSON.stringify(venteData.item); + let newMessageVente = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', venteData); + const messageVente = game.messages.get(chatMessageIdVente); + messageVente.update({ content: newMessageVente }); + messageVente.render(true); + } + + } + /* -------------------------------------------- */ async effectuerTacheAlchimie(recetteId, tacheAlchimie, texteTache) { let recetteData = Misc.data(this.getItemOfType(recetteId, 'recettealchimique')); diff --git a/module/dialog-item-achat.js b/module/dialog-item-achat.js new file mode 100644 index 00000000..d6b16f5d --- /dev/null +++ b/module/dialog-item-achat.js @@ -0,0 +1,86 @@ +import { RdDActor } from "./actor.js"; +import { HtmlUtility } from "./html-utility.js"; +import { Misc } from "./misc.js"; +import { RdDUtility } from "./rdd-utility.js"; + +export class DialogItemAchat extends Dialog { + + static async onButtonAcheter(event) { + let jsondata = event.currentTarget.attributes['data-jsondata']?.value; + if (!jsondata) { + ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes") + return; + } + const vendeurId = event.currentTarget.attributes['data-actorId']?.value; + const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined; + const acheteur = RdDUtility.getSelectedActor(); + + if (!acheteur && !vendeur) { + ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement"); + return; + } + + const chatMessageIdVente = RdDUtility.findChatMessageId(event.currentTarget); + const itemData = JSON.parse(jsondata); + const prixLot = event.currentTarget.attributes['data-prixLot']?.value ?? 0; + let venteData = { + item: itemData, + vendeur: Misc.data(vendeur), + acheteur: Misc.data(acheteur), + tailleLot: event.currentTarget.attributes['data-tailleLot']?.value ?? 1, + quantiteNbLots: event.currentTarget.attributes['data-quantiteNbLots']?.value, + nombreLots: 1, + prixLot: prixLot, + prixTotal: prixLot, + isVente: prixLot > 0 + }; + const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData); + const dialog = new DialogItemAchat(html, vendeur, acheteur, venteData, chatMessageIdVente); + dialog.render(true); + } + + constructor(html, vendeur, acheteur, venteData, chatMessageIdVente) { + let options = { classes: ["dialogachat"], width: 400, height: 300, 'z-index': 99999 }; + + const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre"; + let conf = { + title: actionAchat, + content: html, + default: actionAchat, + buttons: { + [actionAchat]: { label: actionAchat, callback: it => { this.onAchat(); } }, + "decliner": { label: "Décliner", callback: it => { } } + } + }; + + super(conf, options); + + this.vendeur = vendeur; + this.acheteur = acheteur; + this.chatMessageIdVente = chatMessageIdVente; + this.venteData = venteData; + } + + async onAchat() { + (this.vendeur ?? this.acheteur).achatVente( + this.vendeur?.id, + this.acheteur?.id, + this.venteData, + this.chatMessageIdVente + ); + } + + /* -------------------------------------------- */ + activateListeners(html) { + super.activateListeners(html); + + html.find(".nombreLots").change(event => this.setnombreLots(Number(event.currentTarget.value))); + } + + setnombreLots(nombreLots) { + this.venteData.nombreLots = nombreLots; + this.venteData.prixTotal = (nombreLots * this.venteData.prixLot).toFixed(2); + $(".prixTotal").text(this.venteData.prixTotal); + } + +} \ No newline at end of file diff --git a/module/dialog-item-vente.js b/module/dialog-item-vente.js new file mode 100644 index 00000000..dea6aa77 --- /dev/null +++ b/module/dialog-item-vente.js @@ -0,0 +1,90 @@ +import { HtmlUtility } from "./html-utility.js"; +import { Misc } from "./misc.js"; + +export class DialogItemVente extends Dialog { + + static async create(item, callback) { + const itemData = Misc.data(item); + const venteData = { + item: itemData, + alias: item.actor?.name ?? game.user.name, + actorId: item.actor?.id, + prixOrigine: itemData.data.cout, + prixUnitaire: itemData.data.cout, + prixLot: itemData.data.cout, + tailleLot: 1, + quantiteNbLots: itemData.data.quantite, + quantiteMaxLots: itemData.data.quantite, + quantiteMax: itemData.data.quantite, + quantiteIllimite: !item.isOwned, + isOwned: item.isOwned, + }; + const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData); + return new DialogItemVente(venteData, html, callback); + } + + constructor(venteData, html, callback) { + let options = { classes: ["dialogvente"], width: 400, height: 300, 'z-index': 99999 }; + + let conf = { + title: "Proposer", + content: html, + default: "proposer", + buttons: { "proposer": { label: "Proposer", callback: it => { this.onProposer(); } } } + }; + + super(conf, options); + this.callback = callback; + this.venteData = venteData; + } + + async onProposer() { + this.callback(this.venteData); + } + + /* -------------------------------------------- */ + activateListeners(html) { + super.activateListeners(html); + + HtmlUtility._showControlWhen($(".quantiteNbLots"), !this.venteData.quantiteIllimite) + + html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value))); + html.find(".quantiteNbLots").change(event => this.setNbLots(Number(event.currentTarget.value))); + html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked)); + html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value))); + } + + setPrixLot(prixLot) { + this.venteData.prixLot = prixLot; + } + + setTailleLot(tailleLot) { + // recalculer le prix du lot + if (tailleLot != this.venteData.tailleLot) { + this.venteData.prixLot = (tailleLot * this.venteData.prixOrigine).toFixed(2); + $(".prixLot").val(this.venteData.prixLot); + } + this.venteData.tailleLot = tailleLot; + if (this.venteData.isOwned) { + // recalculer le nombre de lots max + this.venteData.quantiteMaxLots = Math.floor(this.venteData.quantiteMax / tailleLot); + this.venteData.quantiteNbLots = Math.min(this.venteData.quantiteMaxLots, this.venteData.quantiteNbLots); + $(".quantiteNbLots").val(this.venteData.quantiteNbLots); + $(".quantiteNbLots").attr("max", this.venteData.quantiteMaxLots) + } + } + + setNbLots(nbLots) { + if (this.venteData.isOwned) { + nbLots = Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots)); + } + this.venteData.quantiteNbLots = nbLots; + $(".quantiteNbLots").val(this.venteData.quantiteNbLots); + } + + setQuantiteIllimite(checked) { + this.venteData.quantiteIllimite = checked; + $(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles"); + HtmlUtility._showControlWhen($(".quantiteNbLots"), !this.venteData.quantiteIllimite) + } +} \ No newline at end of file diff --git a/module/item-monnaie.js b/module/item-monnaie.js index 4aae467b..5850a3e3 100644 --- a/module/item-monnaie.js +++ b/module/item-monnaie.js @@ -43,4 +43,8 @@ export class Monnaie { static deValeur(monnaie, v) { return v != monnaie.data.valeur_deniers; } + + static arrondiDeniers(sols) { + return sols.toFixed(2); + } } diff --git a/module/item-sheet.js b/module/item-sheet.js index 41f57438..7a926413 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -1,6 +1,5 @@ import { RdDItemSort } from "./item-sort.js"; import { RdDUtility } from "./rdd-utility.js"; -import { RdDItem } from "./item.js"; import { RdDAlchimie } from "./rdd-alchimie.js"; import { RdDItemCompetence } from "./item-competence.js"; import { RdDHerbes } from "./rdd-herbes.js"; @@ -15,45 +14,54 @@ import { ReglesOptionelles } from "./regles-optionelles.js"; export class RdDItemSheet extends ItemSheet { /** @override */ - static get defaultOptions() { - return mergeObject(super.defaultOptions, { - classes: ["foundryvtt-reve-de-dragon", "sheet", "item"], - template: "systems/foundryvtt-reve-de-dragon/templates/item-sheet.html", - width: 550, - height: 550 + static get defaultOptions() { + return mergeObject(super.defaultOptions, { + classes: ["foundryvtt-reve-de-dragon", "sheet", "item"], + template: "systems/foundryvtt-reve-de-dragon/templates/item-sheet.html", + width: 550, + height: 550 //tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}] - }); + }); } /* -------------------------------------------- */ _getHeaderButtons() { let buttons = super._getHeaderButtons(); + const videSiConteneur = this.object.isConteneur() ? this.object.isVide() : true; // Add "Post to chat" button // We previously restricted this to GM and editable items only. If you ever find this comment because it broke something: eh, sorry! - buttons.unshift( - { + if ("cout" in Misc.templateData(this.object) && videSiConteneur) { + buttons.unshift({ + class: "post", + icon: "fas fa-comments-dollar", + onclick: ev => this.item.proposerVente() + }); + } + else { + buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => this.item.postItem() - }) + }); + } return buttons } /* -------------------------------------------- */ /** @override */ - setPosition(options={}) { + setPosition(options = {}) { const position = super.setPosition(options); const sheetBody = this.element.find(".sheet-body"); const bodyHeight = position.height - 192; sheetBody.css("height", bodyHeight); return position; } - + /* -------------------------------------------- */ async getData() { const objectData = Misc.data(this.object); - let formData ={ + let formData = { title: objectData.name, id: objectData.id, type: objectData.type, @@ -66,57 +74,57 @@ export class RdDItemSheet extends ItemSheet { cssClass: this.isEditable ? "editable" : "locked", isSoins: false } - if ( this.actor ) { + if (this.actor) { formData.isOwned = true; formData.actorId = this.actor.id; } formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences(); - if ( formData.type == 'tache' || formData.type == 'livre' || formData.type == 'meditation' || formData.type == 'oeuvre') { + if (formData.type == 'tache' || formData.type == 'livre' || formData.type == 'meditation' || formData.type == 'oeuvre') { formData.caracList = duplicate(game.system.model.Actor.personnage.carac); - formData.competences = await RdDUtility.loadCompendium( 'foundryvtt-reve-de-dragon.competences' ); + formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences'); } - if (formData.type == 'arme') { - formData.competences = await RdDUtility.loadCompendium( 'foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it)); + if (formData.type == 'arme') { + formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it)); console.log(formData.competences); } - if ( formData.type == 'recettealchimique' ) { - RdDAlchimie.processManipulation(objectData, this.actor && this.actor.id ); + if (formData.type == 'recettealchimique') { + RdDAlchimie.processManipulation(objectData, this.actor && this.actor.id); } - if ( formData.type == 'potion') { + if (formData.type == 'potion') { if (this.dateUpdated) { formData.data.prdate = this.dateUpdated; this.dateUpdated = undefined; } RdDHerbes.updatePotionData(formData); - } - if ( formData.isOwned && formData.type == 'herbe' && (formData.data.categorie == 'Soin' || formData.data.categorie == 'Repos') ) { - formData.isIngredientPotionBase = true; + } + if (formData.isOwned && formData.type == 'herbe' && (formData.data.categorie == 'Soin' || formData.data.categorie == 'Repos')) { + formData.isIngredientPotionBase = true; } formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true); return formData; } - + /* -------------------------------------------- */ /** @override */ - activateListeners(html) { + activateListeners(html) { super.activateListeners(html); HtmlUtility._showControlWhen($(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.object.isOwned); - + HtmlUtility._showControlWhen($(".item-magique"), this.object.isMagique()); + // Everything below here is only needed if the sheet is editable if (!this.options.editable) return; - // Select competence categorie html.find(".categorie").change(event => this._onSelectCategorie(event)); html.find('.sheet-competence-xp').change((event) => { - if ( this.object.data.type == 'competence') { - RdDUtility.checkThanatosXP( this.object.data.name ); + if (this.object.data.type == 'competence') { + RdDUtility.checkThanatosXP(this.object.data.name); } - } ); + }); html.find('.enchanteDate').change((event) => { let jour = Number($('#jourMois').val()); @@ -126,35 +134,35 @@ export class RdDItemSheet extends ItemSheet { html.find('.creer-tache-livre').click((event) => { let actorId = event.currentTarget.attributes['data-actor-id'].value; - let actor = game.actors.get( actorId ); - actor.creerTacheDepuisLivre( this.item ); + let actor = game.actors.get(actorId); + actor.creerTacheDepuisLivre(this.item); }); html.find('.consommer-potion').click((event) => { let actorId = event.currentTarget.attributes['data-actor-id'].value; - let actor = game.actors.get( actorId ); - actor.consommerPotion( this.item ); + let actor = game.actors.get(actorId); + actor.consommerPotion(this.item); }); html.find('.creer-potion-base').click((event) => { let actorId = event.currentTarget.attributes['data-actor-id'].value; - let actor = game.actors.get( actorId ); - actor.dialogFabriquerPotion( this.item ); + let actor = game.actors.get(actorId); + actor.dialogFabriquerPotion(this.item); }); - + html.find('.alchimie-tache a').click((event) => { let actorId = event.currentTarget.attributes['data-actor-id'].value; let recetteId = event.currentTarget.attributes['data-recette-id'].value; let tacheName = event.currentTarget.attributes['data-alchimie-tache'].value; let tacheData = event.currentTarget.attributes['data-alchimie-data'].value; - let actor = game.actors.get( actorId ); - if ( actor ) { + let actor = game.actors.get(actorId); + if (actor) { actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData); } else { ui.notifications.info("Impossible trouver un actur pour réaliser cette tache Alchimique."); } }); - + } - + /* -------------------------------------------- */ async _onSelectCategorie(event) { event.preventDefault(); @@ -167,8 +175,7 @@ export class RdDItemSheet extends ItemSheet { } /* -------------------------------------------- */ - get template() - { + get template() { //console.log(this); let type = this.object.data.type; return `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`; @@ -180,8 +187,8 @@ export class RdDItemSheet extends ItemSheet { _updateObject(event, formData) { // Deprecated en v0.8 à clarifier //console.log("UPDATE !", formData); // Données de bonus de cases ? - formData = RdDItemSort.buildBonusCaseStringFromFormData( formData ); - + formData = RdDItemSort.buildBonusCaseStringFromFormData(formData); + return this.object.update(formData); } } diff --git a/module/item.js b/module/item.js index 2f74d075..75610267 100644 --- a/module/item.js +++ b/module/item.js @@ -1,3 +1,4 @@ +import { DialogItemVente } from "./dialog-item-vente.js"; import { Grammar } from "./grammar.js"; import { Misc } from "./misc.js"; import { RdDUtility } from "./rdd-utility.js"; @@ -24,6 +25,9 @@ export class RdDItem extends Item { isConteneur() { return Misc.data(this).type == 'conteneur'; } + isVide() { + return this.isConteneur() && (Misc.templateData(this).contenu ?? []).length == 0; + } isAlcool() { const itemData = Misc.data(this); @@ -37,13 +41,13 @@ export class RdDItem extends Item { isEquipement() { return RdDItem.getTypeObjetsEquipement().includes(Misc.data(this).type); } - + isCristalAlchimique() { const itemData = Misc.data(this); return itemData.type == 'objet' && Grammar.toLowerCaseNoAccent(itemData.name) == 'cristal alchimique' && itemData.data.quantite > 0; } - isMagique(){ + isMagique() { return Misc.templateData(this.object).magique; } @@ -118,12 +122,12 @@ export class RdDItem extends Item { async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) { const itemData = Misc.data(this); - const quantite = Number(itemData.data.quantite ??-1); - if (quantite >=0 ) { + const quantite = Number(itemData.data.quantite ?? -1); + if (quantite >= 0) { const reste = Math.max(quantite + Number(nombre), 0); if (reste == 0) { - if (options.supprimerSiZero){ + if (options.supprimerSiZero) { ui.notifications.notify(`${itemData.name} supprimé de votre équipement`); await this.delete(); } @@ -157,6 +161,26 @@ export class RdDItem extends Item { return true; } + async proposerVente() { + console.log(this); + const dialog = await DialogItemVente.create(this, (vente) => this._onProposerVente(vente)) + dialog.render(true); + } + + async _onProposerVente(venteData) { + venteData["properties"] = this[`_${venteData.item.type}ChatData`](); + if (venteData.isOwned) { + if (venteData.quantiteNbLots * venteData.tailleLot > venteData.quantiteMax) { + ui.notifications.warn(`Vous avez ${venteData.quantiteMax} ${venteData.item.name}, ce n'est pas suffisant pour vendre ${venteData.quantiteNbLots} de ${venteData.tailleLot}`) + return; + } + } + venteData.jsondata = JSON.stringify(venteData.item); + + console.log(venteData); + let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', venteData); + ChatMessage.create( RdDUtility.chatDataSetup(html)); + } /* -------------------------------------------- */ async postItem() { @@ -164,8 +188,8 @@ export class RdDItem extends Item { let chatData = duplicate(Misc.data(this)); const properties = this[`_${chatData.type}ChatData`](); chatData["properties"] = properties - if (this.actor){ - chatData.actor = {id: this.actor.id }; + if (this.actor) { + chatData.actor = { id: this.actor.id }; } //Check if the posted item should have availability/pay buttons chatData.hasPrice = "cout" in chatData.data; @@ -184,7 +208,7 @@ export class RdDItem extends Item {

Modifier la prix?

- +
`, @@ -201,7 +225,7 @@ export class RdDItem extends Item { }) } - let quantiteEnvoi = Math.min(dialogResult[0], chatData.data.quantite); + let quantiteEnvoi = this.isOwned ? Math.min(dialogResult[0], chatData.data.quantite) : dialogResult[0]; const prixTotal = dialogResult[1]; if (quantiteEnvoi > 0) { if (this.isOwned) { @@ -247,16 +271,18 @@ export class RdDItem extends Item { }); } - static propertyIfDefined(name, val, condition) { + static propertyIfDefined(name, val, condition = (it) => true) { return condition ? [`${name}: ${val}`] : []; } /* -------------------------------------------- */ _objetChatData() { const tplData = Misc.templateData(this); - let properties = [ - `Encombrement: ${tplData.encombrement}` - ] + let properties = [].concat( + RdDItem.propertyIfDefined('Résistance', tplData.resistance, tplData.resistance), + RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite), + RdDItem.propertyIfDefined('Encombrement', tplData.encombrement), + ); return properties; } @@ -268,8 +294,8 @@ export class RdDItem extends Item { RdDItem.propertyIfDefined('Désaltère', tplData.desaltere, tplData.boisson), RdDItem.propertyIfDefined('Force alcool', tplData.force, tplData.boisson && tplData.alcoolise), RdDItem.propertyIfDefined('Exotisme', tplData.exotisme, tplData.exotisme < 0), - [`Qualité: ${tplData.qualité}`], - [`Encombrement: ${tplData.encombrement}`], + RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite), + RdDItem.propertyIfDefined('Encombrement', tplData.encombrement), ); return properties; } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 97c852f6..3206e2b1 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -5,6 +5,7 @@ import { RdDCombat } from "./rdd-combat.js"; import { Misc } from "./misc.js"; import { Grammar } from "./grammar.js"; import { TMRUtility } from "./tmr-utility.js"; +import { DialogItemAchat } from "./dialog-item-achat.js"; /* -------------------------------------------- */ // This table starts at 0 -> niveau -10 @@ -546,6 +547,10 @@ export class RdDUtility { let actor = game.actors.get(actorId); actor.tmrApp.lancerSortEnReserve(coord, sortId); }); + + // gestion bouton tchat Acheter + html.on("click", '.button-acheter', event => DialogItemAchat.onButtonAcheter(event)); + // Gestion du bouton payer html.on("click", '.payer-button', event => { let sumdenier = event.currentTarget.attributes['data-somme-denier']?.value ?? 0; @@ -571,8 +576,15 @@ export class RdDUtility { } static findChatMessageId(current) { - const isChatMessageWithId = it => it.classList.contains('chat-message') && it.attributes.getNamedItem('data-message-id'); - return RdDUtility.findNodeMatching(current, isChatMessageWithId)?.attributes.getNamedItem('data-message-id').value; + return RdDUtility.getChatMessageId(RdDUtility.findChatMessage(current)); + } + + static getChatMessageId(node) { + return node?.attributes.getNamedItem('data-message-id')?.value; + } + + static findChatMessage(current) { + return RdDUtility.findNodeMatching(current, it => it.classList.contains('chat-message') && it.attributes.getNamedItem('data-message-id')); } static findNodeMatching(current, predicate) { @@ -585,22 +597,25 @@ export class RdDUtility { return undefined; } - static getSelectedActor(msgPlayer = '') { + static getSelectedActor(msgPlayer = undefined) { if (canvas.tokens.controlled.length == 1) { let token = canvas.tokens.controlled[0]; if (token.actor && token.data.actorLink) { return token.actor; } - msgPlayer += "
le token sélectionné doit être lié à un personnage"; + if (msgPlayer != undefined){ + msgPlayer += "
le token sélectionné doit être lié à un personnage"; + } } if (game.user.character) { return game.user.character; } - msgPlayer += "
vous pouvez sélectionner un seul token lié à un personnage"; - msgPlayer += "
vous devez être connecté comme joueur avec un personnage sélectionné"; - - ui.notifications.warn(msgPlayer); - ChatMessage.create({ content: msgPlayer, whisper: [game.user] }); + if (msgPlayer != undefined){ + msgPlayer += "
vous pouvez sélectionner un seul token lié à un personnage"; + msgPlayer += "
vous devez être connecté comme joueur avec un personnage sélectionné"; + ui.notifications.warn(msgPlayer); + ChatMessage.create({ content: msgPlayer, whisper: [game.user] }); + } return undefined; } diff --git a/templates/actor-sheet-inventaire-conteneur.html b/templates/actor-sheet-inventaire-conteneur.html index cfbd9a5a..235ceebf 100644 --- a/templates/actor-sheet-inventaire-conteneur.html +++ b/templates/actor-sheet-inventaire-conteneur.html @@ -14,10 +14,14 @@ {{numberFormat item.data.encTotal decimals=2}}
{{#unless item.estContenu}} - {{#if item.data.equipe}}{{else}}{{/if}} + {{#if item.data.equipe}}{{else}}{{/if}} {{/unless}} + {{#if (or (eq item.type 'arme') (eq item.type 'conteneur') item.data.quantite)}} +   + + {{/if}} {{#if item.data.actionPrincipale}} {{item.data.actionPrincipale}} {{/if}} diff --git a/templates/chat-achat-item.html b/templates/chat-achat-item.html new file mode 100644 index 00000000..8cf107f1 --- /dev/null +++ b/templates/chat-achat-item.html @@ -0,0 +1,8 @@ +{{item.name}} +

{{#if isVente}}Achat{{else}}Don{{/if}}

+

+ {{#if acheteur}}{{acheteur.name}}{{else}}L'acheteur{{/if}} a + {{#if isVente}}acheté{{else}}pris{{/if}} + {{#if vendeur}}à {{vendeur.name}}{{/if}} + {{quantiteTotal}} {{item.name}} pour {{prixTotal}} sols. +

\ No newline at end of file diff --git a/templates/chat-vente-item.html b/templates/chat-vente-item.html new file mode 100644 index 00000000..f9d4c0b3 --- /dev/null +++ b/templates/chat-vente-item.html @@ -0,0 +1,36 @@ +
+

Acheter {{#if alias}}{{alias}} propose: {{/if}}{{item.name}}

+ {{#if item.img}} + + {{/if}} +

{{{item.data.description}}}

+

+ {{#each properties as |property p|}} + {{{property}}}
+ {{/each}} +

+
+

+ {{#unless quantiteIllimite}} + Lots disponibles: {{quantiteNbLots}}
+ {{/unless}} + {{#if (gt tailleLot 1)}} + Lots de: {{tailleLot}}
+ {{/if}} + {{#if prixLot}} + Prix {{#if (gt tailleLot 1)}}du lot {{else}}unitaire{{/if}}: + {{prixLot}} Sols
+ {{/if}} +

+ + + + {{#if prixLot}}Acheter{{else}}Prendre{{/if}} + +
diff --git a/templates/dialog-item-achat.html b/templates/dialog-item-achat.html new file mode 100644 index 00000000..c5256965 --- /dev/null +++ b/templates/dialog-item-achat.html @@ -0,0 +1,49 @@ +
+
+ {{#if vendeur}} + {{vendeur.name}} + {{/if}} + {{item.name}} + {{!-- + {{#if acheteur}} + {{acheteur.name}} + {{/if}} + --}} +

+ {{#if isVente}}Acheter{{else}}Prendre{{/if}} + {{#if vendeur}}à {{vendeur.name}} {{/if}}: + {{item.name}}

+
+ + {{#unless quantiteIllimite}} +
+ + +
+ {{/unless}} +
+ +
+ +
+
+ {{#if isVente}} +
+ + +
+
+ + + {{prixTotal}} + Sols + +
+ {{/if}} +
+ \ No newline at end of file diff --git a/templates/dialog-item-vente.html b/templates/dialog-item-vente.html new file mode 100644 index 00000000..c85235f8 --- /dev/null +++ b/templates/dialog-item-vente.html @@ -0,0 +1,41 @@ +
+ {{item.name}} +

{{item.name}}

+
+ {{#if isOwned}} +
+ + +
+ {{/if}} +
+ +
+ {{#unless isOwned}} + + + {{/unless}} + +
+
+
+ + +
+
+ + +
+
+ + + + + +
+
+
\ No newline at end of file