Gestion des signes draconiques #455

Closed
vincent.vandeme wants to merge 233 commits from v1.4-signes-draconiques into master
13 changed files with 547 additions and 87 deletions
Showing only changes of commit 3625031117 - Show all commits

View File

@ -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");

View File

@ -638,7 +638,8 @@ export class RdDActor extends Actor {
}
}
else {
let deRecuperation = new Roll("1dr + 7").evaluate().total;
const roll = new Roll("1dr").evaluate();
let deRecuperation = roll.total;
console.log("recuperationReve", deRecuperation);
if (deRecuperation >= 7) {
// Rêve de Dragon !
@ -962,18 +963,16 @@ export class RdDActor extends Actor {
async processDropItem(event, dragData, objetVersConteneur) {
console.log("DRAG", this.id, dragData);
const droppedItemId = dragData.id || dragData.data._id;
const itemId = dragData.id || dragData.data._id;
if (dragData.actorId && dragData.actorId != this.id) {
console.log("Moving objects", dragData);
this.moveItemsBetweenActors(droppedItemId, dragData.actorId);
this.moveItemsBetweenActors(itemId, 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];
@ -999,8 +998,8 @@ export class RdDActor extends Actor {
}
}
}
await this.computeEncombrementTotalEtMalusArmure();
}
await this.computeEncombrementTotalEtMalusArmure();
return result;
}
/* -------------------------------------------- */
@ -1061,7 +1060,7 @@ export class RdDActor extends Actor {
async regrouperEquipementsSimilaires(item, dest) {
await dest.quantiteIncDec(Misc.templateData(item).quantite);
await this.deleteEmbeddedDocuments('Item', [item.id]);
await item.delete();
}
/* -------------------------------------------- */
@ -1471,7 +1470,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];
@ -1758,7 +1757,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);
@ -2963,7 +2962,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);
@ -3227,9 +3226,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é <strong>${depense} Deniers</strong>${toActor ? " à " + toActor.name : ''}, qui ont été soustraits de votre argent.`;
RdDAudio.PlayContextAudio("argent"); // Petit son
@ -3252,6 +3249,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] });
@ -3265,7 +3273,7 @@ export class RdDActor extends Actor {
RdDAudio.PlayContextAudio("argent"); // Petit son
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
content: `Vous avez reçu <strong>${gain} Deniers</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés de votre argent.`
content: `Vous avez reçu <strong>${gain} Deniers</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
});
}
}
@ -3279,6 +3287,85 @@ export class RdDActor extends Actor {
}
}
/* -------------------------------------------- */
async achatVente(vendeurId, acheteurId, venteData, chatMessageIdVente) {
if (vendeurId == acheteurId){
ui.notifications.info("Inutile de se vendre à soi-même");
return;
}
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);
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.quantiteTotal : 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.quantiteTotal;
if (qtReste == 0) {
vendeur.deleteEmbeddedDocuments("Item", itemId);
}
else {
vendeur.updateEmbeddedDocuments("Item", [{ _id: itemId, 'data.quantite': qtReste }]);
}
}
if (acheteur) {
// TODO: achat depuis un compendium
const achat = duplicate(Misc.data(vendeur?.getObjet(itemId) ?? game.items.get(itemId)));
achat.data.quantite = venteData.quantiteTotal;
achat._id = undefined;
// TODO: investigate bug - création marche mal...
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)
});
if (venteData.quantiteNbLots <= venteData.nombreLots) {
ChatUtility.removeChatMessageId(chatMessageIdVente);
}
else {
venteData.quantiteNbLots -= venteData.nombreLots;
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'));

View File

@ -0,0 +1,87 @@
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-vendeurId']?.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,
vendeurId: vendeurId,
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);
}
}

View File

@ -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,
vendeurId: 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)
}
}

View File

@ -43,4 +43,8 @@ export class Monnaie {
static deValeur(monnaie, v) {
return v != monnaie.data.valeur_deniers;
}
static arrondiDeniers(sols) {
return sols.toFixed(2);
}
}

View File

@ -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);
}
}

View File

@ -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 {
</div>
<p>Modifier la prix?</p>
<div class="form-group">
<label> Prix en Sols</label>
<label>Prix en Sols</label>
<input name="price" type="text" value="${chatData.data.cout}"/>
</div>
`,
@ -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 ? [`<b>${name}</b>: ${val}`] : [];
}
/* -------------------------------------------- */
_objetChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Encombrement</b>: ${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),
[`<b>Qualité</b>: ${tplData.qualité}`],
[`<b>Encombrement</b>: ${tplData.encombrement}`],
RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
RdDItem.propertyIfDefined('Encombrement', tplData.encombrement),
);
return properties;
}

View File

@ -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
@ -547,6 +548,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;
@ -572,8 +577,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) {
@ -586,22 +598,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 += "<br>le token sélectionné doit être lié à un personnage";
if (msgPlayer != undefined){
msgPlayer += "<br>le token sélectionné doit être lié à un personnage";
}
}
if (game.user.character) {
return game.user.character;
}
msgPlayer += "<br>vous pouvez sélectionner un seul token lié à un personnage";
msgPlayer += "<br>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 += "<br>vous pouvez sélectionner un seul token lié à un personnage";
msgPlayer += "<br>vous devez être connecté comme joueur avec un personnage sélectionné";
ui.notifications.warn(msgPlayer);
ChatMessage.create({ content: msgPlayer, whisper: [game.user] });
}
return undefined;
}

View File

@ -14,10 +14,14 @@
<span class="item-quantite">{{numberFormat item.data.encTotal decimals=2}}</span>
<div class="item-controls flex-grow">
{{#unless item.estContenu}}
<a class="item-control item-equip" title="Equiper">{{#if item.data.equipe}}<i class="fas fa-circle"></i>{{else}}<i class="fas fa-genderless"></i>{{/if}}</a>
<a class="item-control item-equip" title="Equiper">{{#if item.data.equipe}}<i class="fas fa-hand-rock"></i>{{else}}<i class="fas fa-genderless"></i>{{/if}}</a>
{{/unless}}
<a class="item-control item-edit" title="Editer"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
{{#if (or (eq item.type 'arme') (eq item.type 'conteneur') item.data.quantite)}}
&nbsp;
<a class="item-control item-vendre" title="Vendre ou donner"><i class="fas fa-comments-dollar"></i></a>
{{/if}}
{{#if item.data.actionPrincipale}}
<a class="item-name item-action">{{item.data.actionPrincipale}}</a>
{{/if}}

View File

@ -0,0 +1,8 @@
<img class="chat-icon" src="{{item.img}}" alt="{{item.name}}" />
<h4>{{#if isVente}}Achat{{else}}Don{{/if}}</h4>
<p>
{{#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.
</p>

View File

@ -0,0 +1,36 @@
<div class="post-item" data-transfer="{{transfer}}">
<h3>{{#if alias}}{{alias}} propose:{{else}}Acheter {{/if}}{{item.name}}</h3>
{{#if item.img}}
<img src="{{item.img}}" title="{{item.name}}" />
{{/if}}
<p class="card-content">{{{item.data.description}}}</p>
<p>
{{#each properties as |property p|}}
<span>{{{property}}}</span><br>
{{/each}}
</p>
<hr>
<p>
{{#unless quantiteIllimite}}
<span>Lots disponibles: <span class="quantiteNbLots">{{quantiteNbLots}}</span></span><br>
{{/unless}}
{{#if (gt tailleLot 1)}}
<span>Lots de: <span class="tailleLot">{{tailleLot}}</span></span><br>
{{/if}}
{{#if prixLot}}
<span><strong>Prix {{#if (gt tailleLot 1)}}du lot {{else}}unitaire{{/if}}:
<span class="prixLot">{{prixLot}}</span> Sols</strong></span><br>
{{/if}}
</p>
<span class="chat-card-button-area">
<a class="button-acheter chat-card-button"
data-jsondata='{{jsondata}}'
{{#if vendeurId}}data-vendeurId='{{vendeurId}}'{{/if}}
data-tailleLot="{{tailleLot}}"
data-quantiteNbLots="{{quantiteNbLots}}"
data-quantiteIllimite="{{#if quantiteIllimite}}true{{else}}false{{/if}}"
data-prixLot="{{prixLot}}">
{{#if prixLot}}Acheter{{else}}Prendre{{/if}}</a>
</span>
</div>

View File

@ -0,0 +1,49 @@
<form class="rdddialog">
<div>
{{#if vendeur}}
<img class="chat-icon" src="{{vendeur.img}}" title="{{vendeur.name}}" alt="{{vendeur.name}}" />
{{/if}}
<img class="chat-icon" src="{{item.img}}" title="{{item.name}}" alt="{{item.name}}" />
{{!--
{{#if acheteur}}
<img class="chat-icon" src="{{acheteur.img}}" title="{{acheteur.name}}" alt="{{acheteur.name}}" />
{{/if}}
--}}
<h4>
{{#if isVente}}Acheter{{else}}Prendre{{/if}}
{{#if vendeur}}à {{vendeur.name}} {{/if}}:
{{item.name}}</h4>
</div>
{{#unless quantiteIllimite}}
<div class="flexrow flex-group-left">
<label>{{#if (gt tailleLot 1)}}Lots disponibles
{{else}}Quantité disponible{{/if}}</label>
<label>{{quantiteNbLots}}</label>
</div>
{{/unless}}
<div class="flexrow flex-group-left">
<label>
{{#if (gt tailleLot 1)}}Nombre de lots de {{tailleLot}}
{{else}}Quantité{{/if}}
</label>
<div class="flexrow">
<input name="nombreLots" class="nombreLots flex-shrink" type="number" min="1" max="{{quantiteNbLots}}"
value="{{nombreLots}}" data-dtype="Number" />
</div>
</div>
{{#if isVente}}
<div class="flexrow flex-group-left">
<label>Prix {{#if (gt tailleLot 1)}}du lot{{else}}unitaire{{/if}}</label>
<label>{{prixLot}} Sols</label>
</div>
<div class="flexrow flex-group-left">
<label>Prix total</label>
<span class="flexrow">
<span class="prixTotal">{{prixTotal}}</span>
<span>Sols</span>
</span>
</div>
{{/if}}
</div>
</form>

View File

@ -0,0 +1,41 @@
<form class="rdddialog">
<img class="chat-icon" src="{{item.img}}" title="{{item.name}}" alt="{{item.name}}" />
<h4>{{item.name}}</h4>
<div class="flexcol">
{{#if isOwned}}
<div class="flexrow flex-group-left">
<label>Quantité disponible</label>
<label>{{quantiteMax}}</label>
</div>
{{/if}}
<div class="flexrow flex-group-left">
<label>Nombre de lots</label>
<div class="flexrow">
{{#unless isOwned}}
<input name="quantiteIllimite" class="quantiteIllimite flex-shrink" type="checkbox" {{#if
quantiteIllimite}}checked{{/if}} />
<label class="label-quantiteIllimite flex-shrink">Illimités</label>
{{/unless}}
<input name="quantiteNbLots" class="quantiteNbLots flex-shrink" type="number" min="1"
max="{{quantiteMaxLots}}" value="{{quantiteNbLots}}" data-dtype="Number" />
</div>
</div>
<div class="flexrow flex-group-left">
<label for="tailleLot">Taille d'un lot</label>
<input name="tailleLot" class="tailleLot flex-shrink" type="number" min="1"
max="{{quantiteMax}}" value="{{tailleLot}}" data-dtype="Number" />
</div>
<div class="flexrow flex-group-left">
<label>Valeur unitaire</label>
<label>{{prixOrigine}} Sols</label>
</div>
<div class="flexrow flex-group-left">
<label for="prixLot">Prix du lot</label>
<span class="flexrow">
<input name="prixLot" class="prixLot flex-shrink" type="number" value="{{prixLot}}"
data-dtype="Number" />
<label>Sols</label>
</span>
</div>
</div>
</form>