déplacement gestion equipement
Déplacement de la gestion d'équipement dans base-actor
This commit is contained in:
parent
274009d3fa
commit
92388df5c7
@ -10,7 +10,6 @@ import { DialogSplitItem } from "./dialog-split-item.js";
|
|||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
import { STATUSES } from "./settings/status-effects.js";
|
||||||
import { Monnaie } from "./item-monnaie.js";
|
|
||||||
import { MAINS_DIRECTRICES } from "./actor.js";
|
import { MAINS_DIRECTRICES } from "./actor.js";
|
||||||
import { RdDBaseActorSheet } from "./actor/base-actor-sheet.js";
|
import { RdDBaseActorSheet } from "./actor/base-actor-sheet.js";
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
@ -46,10 +45,8 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
|
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
|
||||||
limited: this.actor.limited,
|
limited: this.actor.limited,
|
||||||
owner: this.actor.isOwner,
|
owner: this.actor.isOwner,
|
||||||
description: await TextEditor.enrichHTML(this.object.system.description, { async: true }),
|
biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }),
|
||||||
biographie: await TextEditor.enrichHTML(this.object.system.biographie, { async: true }),
|
notes: await TextEditor.enrichHTML(this.actor.system.notes, { 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, {
|
mergeObject(formData.calc, {
|
||||||
surenc: this.actor.computeMalusSurEncombrement(),
|
surenc: this.actor.computeMalusSurEncombrement(),
|
||||||
|
449
module/actor.js
449
module/actor.js
@ -13,7 +13,6 @@ import { RdDItemSort } from "./item-sort.js";
|
|||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { RdDEncaisser } from "./rdd-roll-encaisser.js";
|
import { RdDEncaisser } from "./rdd-roll-encaisser.js";
|
||||||
import { RdDCombat } from "./rdd-combat.js";
|
import { RdDCombat } from "./rdd-combat.js";
|
||||||
import { RdDAudio } from "./rdd-audio.js";
|
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
import { RdDItemArme } from "./item-arme.js";
|
import { RdDItemArme } from "./item-arme.js";
|
||||||
import { RdDAlchimie } from "./rdd-alchimie.js";
|
import { RdDAlchimie } from "./rdd-alchimie.js";
|
||||||
@ -24,13 +23,11 @@ import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
|||||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||||
import { Draconique } from "./tmr/draconique.js";
|
import { Draconique } from "./tmr/draconique.js";
|
||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
import { Monnaie } from "./item-monnaie.js";
|
|
||||||
import { DialogConsommer } from "./dialog-item-consommer.js";
|
import { DialogConsommer } from "./dialog-item-consommer.js";
|
||||||
import { DialogFabriquerPotion } from "./dialog-fabriquer-potion.js";
|
import { DialogFabriquerPotion } from "./dialog-fabriquer-potion.js";
|
||||||
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
||||||
import { RdDItem } from "./item.js";
|
|
||||||
import { RdDPossession } from "./rdd-possession.js";
|
import { RdDPossession } from "./rdd-possession.js";
|
||||||
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
import { RdDConfirm } from "./rdd-confirm.js";
|
import { RdDConfirm } from "./rdd-confirm.js";
|
||||||
import { DialogValidationEncaissement } from "./dialog-validation-encaissement.js";
|
import { DialogValidationEncaissement } from "./dialog-validation-encaissement.js";
|
||||||
import { RdDRencontre } from "./item-rencontre.js";
|
import { RdDRencontre } from "./item-rencontre.js";
|
||||||
@ -77,12 +74,12 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_prepareCreatureData(actorData) {
|
_prepareCreatureData(actorData) {
|
||||||
this.computeEncombrementTotalEtMalusArmure();
|
this.computeEncTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_prepareVehiculeData(actorData) {
|
_prepareVehiculeData(actorData) {
|
||||||
this.computeEncombrementTotalEtMalusArmure();
|
this.computeEncTotal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -94,7 +91,8 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
RdDCarac.computeCarac(actorData.system)
|
RdDCarac.computeCarac(actorData.system)
|
||||||
this.computeIsHautRevant();
|
this.computeIsHautRevant();
|
||||||
await this.cleanupConteneurs();
|
await this.cleanupConteneurs();
|
||||||
await this.computeEncombrementTotalEtMalusArmure();
|
await this.computeEncTotal();
|
||||||
|
await this.computeMalusArmure();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -234,10 +232,6 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getMonnaie(id) {
|
|
||||||
return this.findItemLike(id, 'monnaie');
|
|
||||||
}
|
|
||||||
|
|
||||||
getTache(id) {
|
getTache(id) {
|
||||||
return this.findItemLike(id, 'tache');
|
return this.findItemLike(id, 'tache');
|
||||||
}
|
}
|
||||||
@ -993,237 +987,7 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
await this.update({ [`system.attributs.${fieldName}.value`]: fieldValue });
|
await this.update({ [`system.attributs.${fieldName}.value`]: fieldValue });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
_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.getItem(id);
|
|
||||||
if (subObjet?.id == conteneur.id) {
|
|
||||||
return true; // Loop detected !
|
|
||||||
}
|
|
||||||
if (subObjet?.isConteneur()) {
|
|
||||||
return this._isConteneurContenu(subObjet, conteneur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getRecursiveEnc(objet) {
|
|
||||||
if (!objet) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const tplData = objet.system;
|
|
||||||
if (objet.type != 'conteneur') {
|
|
||||||
return Number(tplData.encombrement) * Number(tplData.quantite);
|
|
||||||
}
|
|
||||||
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.getItem(conteneurId);
|
|
||||||
if (conteneur?.type == 'conteneur') { // Si c'est un conteneur
|
|
||||||
for (let subId of conteneur.system.contenu) {
|
|
||||||
let subObj = this.getItem(subId);
|
|
||||||
if (subObj) {
|
|
||||||
if (subObj.type == 'conteneur') {
|
|
||||||
this.buildSubConteneurObjetList(subId, deleteList);
|
|
||||||
}
|
|
||||||
deleteList.push({ id: subId, conteneurId: conteneurId });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async deleteAllConteneur(itemId, options) {
|
|
||||||
let list = [];
|
|
||||||
list.push({ id: itemId, conteneurId: undefined }); // Init list
|
|
||||||
this.buildSubConteneurObjetList(itemId, list);
|
|
||||||
await this.deleteEmbeddedDocuments('Item', list.map(it => it.id), options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** Supprime un item d'un conteneur, sur la base
|
|
||||||
* de leurs ID */
|
|
||||||
async enleverDeConteneur(item, conteneur, onEnleverDeConteneur) {
|
|
||||||
if (conteneur?.isConteneur()) {
|
|
||||||
item.estContenu = false;
|
|
||||||
await this.updateEmbeddedDocuments('Item', [{
|
|
||||||
_id: conteneur.id,
|
|
||||||
'system.contenu': conteneur.system.contenu.filter(id => id != item.id)
|
|
||||||
}]);
|
|
||||||
onEnleverDeConteneur();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** Ajoute un item dans un conteneur, sur la base
|
|
||||||
* de leurs ID */
|
|
||||||
async ajouterDansConteneur(item, conteneur, onAjouterDansConteneur) {
|
|
||||||
if (!conteneur) {
|
|
||||||
// TODO: afficher
|
|
||||||
item.estContenu = false;
|
|
||||||
}
|
|
||||||
else if (conteneur.isConteneur()) {
|
|
||||||
item.estContenu = true;
|
|
||||||
await this.updateEmbeddedDocuments('Item', [{
|
|
||||||
_id: conteneur.id,
|
|
||||||
'system.contenu': [...conteneur.system.contenu, item.id]
|
|
||||||
}]);
|
|
||||||
onAjouterDansConteneur(item.id, conteneur.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */
|
|
||||||
async nettoyerConteneurs() {
|
|
||||||
RdDConfirm.confirmer({
|
|
||||||
settingConfirmer: "confirmation-vider",
|
|
||||||
content: `<p>Etes vous certain de vouloir vider tous les conteneurs ?</p>`,
|
|
||||||
title: 'Vider les conteneurs',
|
|
||||||
buttonLabel: 'Vider',
|
|
||||||
onAction: async () => {
|
|
||||||
const corrections = [];
|
|
||||||
for (let item of this.items) {
|
|
||||||
if (item.estContenu) {
|
|
||||||
item.estContenu = undefined;
|
|
||||||
}
|
|
||||||
if (item.type == 'conteneur' && item.system.contenu.length > 0) {
|
|
||||||
corrections.push({ _id: item.id, 'system.contenu': [] });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (corrections.length > 0) {
|
|
||||||
await this.updateEmbeddedDocuments('Item', corrections);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async processDropItem(params) {
|
|
||||||
const targetActorId = this.id;
|
|
||||||
const sourceActorId = params.sourceActorId;
|
|
||||||
const itemId = params.itemId;
|
|
||||||
const destId = params.destId;
|
|
||||||
const srcId = params.srcId;
|
|
||||||
if (sourceActorId && sourceActorId != targetActorId) {
|
|
||||||
console.log("Moving objects", sourceActorId, targetActorId, itemId);
|
|
||||||
this.moveItemsBetweenActors(itemId, sourceActorId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let result = true;
|
|
||||||
const item = this.getItem(itemId);
|
|
||||||
if (item?.isInventaire() && sourceActorId == targetActorId) {
|
|
||||||
// rangement
|
|
||||||
if (srcId != destId && itemId != destId) { // déplacement de l'objet
|
|
||||||
const src = this.getItem(srcId);
|
|
||||||
const dest = this.getItem(destId);
|
|
||||||
const cible = this.getContenantOrParent(dest);
|
|
||||||
const [empilable, message] = item.isInventaireEmpilable(dest);
|
|
||||||
if (empilable) {
|
|
||||||
await dest.empiler(item)
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
// changer de conteneur
|
|
||||||
else if (!cible || this.conteneurPeutContenir(cible, item)) {
|
|
||||||
await this.enleverDeConteneur(item, src, params.onEnleverConteneur);
|
|
||||||
await this.ajouterDansConteneur(item, cible, params.onAjouterDansConteneur);
|
|
||||||
if (message && !dest.isConteneur()) {
|
|
||||||
ui.notifications.info(cible
|
|
||||||
? `${message}<br>${item.name} a été déplacé dans: ${cible.name}`
|
|
||||||
: `${message}<br>${item.name} a été sorti du conteneur`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await this.computeEncombrementTotalEtMalusArmure();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
getContenantOrParent(dest) {
|
|
||||||
if (!dest || dest.isConteneur()) {
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
return this.getContenant(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
getContenant(item) {
|
|
||||||
return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
conteneurPeutContenir(dest, item) {
|
|
||||||
if (!dest) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!dest.isConteneur()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const destData = dest
|
|
||||||
if (this._isConteneurContenu(item, dest)) {
|
|
||||||
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${destData.name} !`);
|
|
||||||
return false; // Loop detected !
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculer le total actuel des contenus
|
|
||||||
let encContenu = this.getRecursiveEnc(dest) - Number(destData.system.encombrement);
|
|
||||||
let newEnc = this.getRecursiveEnc(item); // Calculer le total actuel du nouvel objet
|
|
||||||
|
|
||||||
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
|
|
||||||
if (Number(destData.system.capacite) < encContenu + newEnc) {
|
|
||||||
ui.notifications.warn(
|
|
||||||
`Le conteneur ${dest.name} a une capacité de ${destData.system.capacite}, et contient déjà ${encContenu}.
|
|
||||||
Impossible d'y ranger: ${item.name} d'encombrement ${newEnc}!`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async moveItemsBetweenActors(itemId, sourceActorId) {
|
|
||||||
let itemsList = []
|
|
||||||
let sourceActor = game.actors.get(sourceActorId);
|
|
||||||
itemsList.push({ id: itemId, conteneurId: undefined }); // Init list
|
|
||||||
sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
let itemMap = this._buildMapOldNewId(itemsList, newItems);
|
|
||||||
|
|
||||||
for (let item of itemsList) { // Second boucle pour traiter la remise en conteneurs
|
|
||||||
// gestion conteneur/contenu
|
|
||||||
if (item.conteneurId) { // l'Objet était dans un conteneur
|
|
||||||
let newConteneurId = itemMap[item.conteneurId]; // Get conteneur
|
|
||||||
let newConteneur = this.getItem(newConteneurId);
|
|
||||||
|
|
||||||
let newItemId = itemMap[item.id]; // Get newItem
|
|
||||||
|
|
||||||
console.log('New conteneur filling!', newConteneur, newItemId, item);
|
|
||||||
let contenu = duplicate(newConteneur.system.contenu);
|
|
||||||
contenu.push(newItemId);
|
|
||||||
await this.updateEmbeddedDocuments('Item', [{ _id: newConteneurId, 'system.contenu': contenu }]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let item of itemsList) {
|
|
||||||
await sourceActor.deleteEmbeddedDocuments('Item', [item.id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_buildMapOldNewId(itemsList, newItems) {
|
|
||||||
let itemMap = {};
|
|
||||||
for (let i = 0; i < itemsList.length; i++) {
|
|
||||||
itemMap[itemsList[i].id] = newItems[i].id; // Pour garder le lien ancien / nouveau
|
|
||||||
}
|
|
||||||
return itemMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
isSurenc() {
|
isSurenc() {
|
||||||
return this.isPersonnage() ? (this.computeMalusSurEncombrement() < 0) : false
|
return this.isPersonnage() ? (this.computeMalusSurEncombrement() < 0) : false
|
||||||
@ -1268,16 +1032,6 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
return this.listItems(type).find(it => Grammar.toLowerCaseNoAccent(it.name) == name);
|
return this.listItems(type).find(it => Grammar.toLowerCaseNoAccent(it.name) == name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async computeEncombrementTotalEtMalusArmure() {
|
|
||||||
if (!this.pack) {
|
|
||||||
await this.computeMalusArmure();
|
|
||||||
this.encTotal = this.items.map(it => it.getEncTotal()).reduce(Misc.sum(), 0);
|
|
||||||
return this.encTotal;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async computeMalusArmure() {
|
async computeMalusArmure() {
|
||||||
if (this.isPersonnage()) {
|
if (this.isPersonnage()) {
|
||||||
@ -1291,15 +1045,6 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
computePrixTotalEquipement() {
|
|
||||||
const valeur = this.items.filter(it => it.isInventaire())
|
|
||||||
.filter(it => !it.isMonnaie())
|
|
||||||
.map(it => it.valeurTotale())
|
|
||||||
.reduce(Misc.sum(), 0);
|
|
||||||
return valeur;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
computeResumeBlessure(blessures = undefined) {
|
computeResumeBlessure(blessures = undefined) {
|
||||||
blessures = blessures ?? this.system.blessures;
|
blessures = blessures ?? this.system.blessures;
|
||||||
@ -1332,7 +1077,7 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recompute(){
|
recompute() {
|
||||||
this.computeEtatGeneral();
|
this.computeEtatGeneral();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3282,7 +3027,7 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
if (item && ['arme', 'armure'].includes(item.type)) {
|
if (item && ['arme', 'armure'].includes(item.type)) {
|
||||||
const isEquipe = !item.system.equipe;
|
const isEquipe = !item.system.equipe;
|
||||||
await this.updateEmbeddedDocuments('Item', [{ _id: item.id, "system.equipe": isEquipe }]);
|
await this.updateEmbeddedDocuments('Item', [{ _id: item.id, "system.equipe": isEquipe }]);
|
||||||
this.computeEncombrementTotalEtMalusArmure(); // Mise à jour encombrement
|
this.computeEncTotal(); // Mise à jour encombrement
|
||||||
if (isEquipe)
|
if (isEquipe)
|
||||||
this.verifierForceMin(item);
|
this.verifierForceMin(item);
|
||||||
}
|
}
|
||||||
@ -3575,186 +3320,6 @@ export class RdDActor extends RdDBaseActor {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async payerSols(depense) {
|
|
||||||
depense = Number(depense);
|
|
||||||
if (depense == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let fortune = super.getFortune();
|
|
||||||
console.log("payer", game.user.character, depense, fortune);
|
|
||||||
let msg = "";
|
|
||||||
if (fortune >= depense) {
|
|
||||||
await Monnaie.optimiserFortune(this, fortune - depense);
|
|
||||||
msg = `Vous avez payé <strong>${depense} Sols</strong>, qui ont été soustraits de votre argent.`;
|
|
||||||
RdDAudio.PlayContextAudio("argent"); // Petit son
|
|
||||||
} else {
|
|
||||||
msg = "Vous n'avez pas assez d'argent pour payer cette somme !";
|
|
||||||
}
|
|
||||||
|
|
||||||
let message = {
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
|
||||||
content: msg
|
|
||||||
};
|
|
||||||
ChatMessage.create(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
async depenserSols(sols) {
|
|
||||||
let reste = super.getFortune() - Number(sols);
|
|
||||||
if (reste >= 0) {
|
|
||||||
await Monnaie.optimiserFortune(this, reste);
|
|
||||||
}
|
|
||||||
return reste;
|
|
||||||
}
|
|
||||||
|
|
||||||
async ajouterSols(sols, fromActorId = undefined) {
|
|
||||||
sols = Number(sols);
|
|
||||||
if (sols == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sols < 0) {
|
|
||||||
ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (fromActorId && !game.user.isGM) {
|
|
||||||
RdDBaseActor.remoteActorCall({
|
|
||||||
userId: Misc.connectedGMOrUser(),
|
|
||||||
actorId: this.id,
|
|
||||||
method: 'ajouterSols', args: [sols, fromActorId]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const fromActor = game.actors.get(fromActorId)
|
|
||||||
await Monnaie.optimiserFortune(this, sols + this.getFortune());
|
|
||||||
|
|
||||||
RdDAudio.PlayContextAudio("argent"); // Petit son
|
|
||||||
ChatMessage.create({
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
|
||||||
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async monnaieIncDec(id, value) {
|
|
||||||
let monnaie = this.getMonnaie(id);
|
|
||||||
if (monnaie) {
|
|
||||||
const quantite = Math.max(0, monnaie.system.quantite + value);
|
|
||||||
await this.updateEmbeddedDocuments('Item', [{ _id: monnaie.id, 'system.quantite': quantite }]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async achatVente(achat) {
|
|
||||||
if (achat.vendeurId == achat.acheteurId) {
|
|
||||||
ui.notifications.info("Inutile de se vendre à soi-même");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!Misc.isUniqueConnectedGM()) {
|
|
||||||
RdDBaseActor.remoteActorCall({
|
|
||||||
actorId: achat.vendeurId ?? achat.acheteurId,
|
|
||||||
method: 'achatVente',
|
|
||||||
args: [achat]
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cout = Number(achat.prixTotal ?? 0);
|
|
||||||
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : 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?.getItem(vente.item._id) ?? (await RdDItem.getCorrespondingItem(vente.item));
|
|
||||||
if (!this.verifierQuantite(vendeur, itemVendu, quantite)) {
|
|
||||||
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
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(vendeur, itemVendu, quantite, cout);
|
|
||||||
if (acheteur) {
|
|
||||||
await acheteur.depenserSols(cout);
|
|
||||||
let createdItemId = await acheteur.creerQuantiteItem(vente.item, quantite);
|
|
||||||
await acheteur.consommerNourritureAchetee(achat, vente, createdItemId);
|
|
||||||
}
|
|
||||||
if (cout > 0) {
|
|
||||||
RdDAudio.PlayContextAudio("argent");
|
|
||||||
}
|
|
||||||
const chatAchatItem = duplicate(vente);
|
|
||||||
chatAchatItem.quantiteTotal = quantite;
|
|
||||||
ChatMessage.create({
|
|
||||||
user: achat.userId,
|
|
||||||
speaker: { alias: (acheteur ?? vendeur).name },
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
|
||||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html', chatAchatItem)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!vente.quantiteIllimite) {
|
|
||||||
if (vente.quantiteNbLots <= achat.choix.nombreLots) {
|
|
||||||
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
vente["properties"] = itemVendu.getProprietes();
|
|
||||||
vente.quantiteNbLots -= achat.choix.nombreLots;
|
|
||||||
vente.jsondata = JSON.stringify(vente.item);
|
|
||||||
const messageVente = game.messages.get(achat.chatMessageIdVente);
|
|
||||||
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente) });
|
|
||||||
messageVente.render(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async decrementerVente(vendeur, itemVendu, quantite, cout) {
|
|
||||||
if (vendeur) {
|
|
||||||
await vendeur.ajouterSols(cout);
|
|
||||||
await vendeur.decrementerQuantiteItem(itemVendu, quantite);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
verifierQuantite(vendeur, item, quantiteTotal) {
|
|
||||||
const disponible = vendeur ? (item?.getQuantite() ?? 0) : quantiteTotal;
|
|
||||||
return disponible >= quantiteTotal;
|
|
||||||
}
|
|
||||||
|
|
||||||
async consommerNourritureAchetee(achat, vente, createdItemId) {
|
|
||||||
if (achat.choix.consommer && vente.item.type == 'nourritureboisson' && createdItemId != undefined) {
|
|
||||||
achat.choix.doses = achat.choix.nombreLots;
|
|
||||||
await this.consommerNourritureboisson(createdItemId, achat.choix, vente.actingUserId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async decrementerQuantiteItem(item, quantite) {
|
|
||||||
let resteQuantite = (item.system.quantite ?? 1) - quantite;
|
|
||||||
if (resteQuantite <= 0) {
|
|
||||||
await this.deleteEmbeddedDocuments("Item", [item.id]);
|
|
||||||
if (resteQuantite < 0) {
|
|
||||||
ui.notifications.warn(`La quantité de ${item.name} était insuffisante, l'objet a donc été supprimé`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (resteQuantite > 0) {
|
|
||||||
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': resteQuantite }]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async creerQuantiteItem(item, quantite) {
|
|
||||||
const items = await this.createEmbeddedDocuments("Item", RdDActor.$prepareListeAchat(item, quantite));
|
|
||||||
return items.length > 0 ? items[0].id : undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
static $prepareListeAchat(item, quantite) {
|
|
||||||
const isItemEmpilable = "quantite" in item.system;
|
|
||||||
const achatData = {
|
|
||||||
type: item.type,
|
|
||||||
img: item.img,
|
|
||||||
name: item.name,
|
|
||||||
system: mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }),
|
|
||||||
};
|
|
||||||
return isItemEmpilable ? [achatData] : Array.from({ length: quantite }, (_, i) => achatData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async effectuerTacheAlchimie(recetteId, tacheAlchimie, texteTache) {
|
async effectuerTacheAlchimie(recetteId, tacheAlchimie, texteTache) {
|
||||||
let recetteData = this.findItemLike(recetteId, 'recettealchimique');
|
let recetteData = this.findItemLike(recetteId, 'recettealchimique');
|
||||||
|
@ -40,6 +40,7 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
isLimited: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED,
|
isLimited: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED,
|
||||||
isObserver: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER,
|
isObserver: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER,
|
||||||
isOwner: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER,
|
isOwner: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER,
|
||||||
|
owner: this.actor.isOwner,
|
||||||
});
|
});
|
||||||
|
|
||||||
let formData = {
|
let formData = {
|
||||||
@ -49,13 +50,15 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
img: this.actor.img,
|
img: this.actor.img,
|
||||||
name: this.actor.name,
|
name: this.actor.name,
|
||||||
system: foundry.utils.deepClone(this.actor.system),
|
system: foundry.utils.deepClone(this.actor.system),
|
||||||
|
description: await TextEditor.enrichHTML(this.actor.system.description, { async: true }),
|
||||||
|
notesmj: await TextEditor.enrichHTML(this.actor.system.notesmj, { async: true }),
|
||||||
options: options,
|
options: options,
|
||||||
}
|
}
|
||||||
this.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
this.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
||||||
formData.calc = {
|
formData.calc = {
|
||||||
fortune: this.toSolsDeniers(this.actor.getFortune()),
|
fortune: this.toSolsDeniers(this.actor.getFortune()),
|
||||||
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
||||||
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
encTotal: await this.actor.computeEncTotal(),
|
||||||
}
|
}
|
||||||
|
|
||||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||||
@ -138,22 +141,22 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
this.html = html;
|
this.html = html;
|
||||||
|
|
||||||
this.html.find('.conteneur-name a').click(async event => {
|
this.html.find('.conteneur-name a').click(async event => {
|
||||||
RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event));
|
RdDUtility.toggleAfficheContenu(this.getItemId(event));
|
||||||
this.render(true);
|
this.render(true);
|
||||||
});
|
});
|
||||||
this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true))
|
this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true))
|
||||||
this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItemToChat());
|
this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat());
|
||||||
this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat());
|
this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat());
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
// Everything below here is only needed if the sheet is editable
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
this.html.find('.item-split').click(async event => {
|
this.html.find('.item-split').click(async event => {
|
||||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
const item = this.getItem(event);
|
||||||
RdDSheetUtility.splitItem(item, 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-delete').click(async event => RdDUtility.confirmActorItemDelete(this, this.getItem(event)));
|
||||||
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente(this.getQuantiteMax(item)));
|
this.html.find('.item-vendre').click(async event => this.vendre(this.getItem(event)));
|
||||||
|
|
||||||
this.html.find('.creer-un-objet').click(async event => {
|
this.html.find('.creer-un-objet').click(async event => {
|
||||||
this.selectObjetTypeToCreate();
|
this.selectObjetTypeToCreate();
|
||||||
@ -162,16 +165,19 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
this.actor.nettoyerConteneurs();
|
this.actor.nettoyerConteneurs();
|
||||||
});
|
});
|
||||||
this.html.find('.monnaie-plus').click(async event => {
|
this.html.find('.monnaie-plus').click(async event => {
|
||||||
this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), 1);
|
this.actor.monnaieIncDec(this.getItemId(event), 1);
|
||||||
});
|
});
|
||||||
this.html.find('.monnaie-moins').click(async event => {
|
this.html.find('.monnaie-moins').click(async event => {
|
||||||
this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), -1);
|
this.actor.monnaieIncDec(this.getItemId(event), -1);
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getQuantiteMax(item) {
|
getItemId(event) {
|
||||||
return item.system.quantite;
|
return RdDSheetUtility.getItemId(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
getItem(event) {
|
||||||
|
return RdDSheetUtility.getItem(event, this.actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -197,7 +203,6 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async selectObjetTypeToCreate() {
|
async selectObjetTypeToCreate() {
|
||||||
let typeObjets = RdDItem.getItemTypesInventaire();
|
let typeObjets = RdDItem.getItemTypesInventaire();
|
||||||
@ -256,4 +261,8 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vendre(item) {
|
||||||
|
item?.proposerVente(this.actor.getQuantiteDisponible(item));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
|
import { ChatUtility } from "../chat-utility.js";
|
||||||
import { SYSTEM_SOCKET_ID } from "../constants.js";
|
import { SYSTEM_SOCKET_ID } from "../constants.js";
|
||||||
import { Monnaie } from "../item-monnaie.js";
|
import { Monnaie } from "../item-monnaie.js";
|
||||||
|
import { RdDItem } from "../item.js";
|
||||||
import { Misc } from "../misc.js";
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDAudio } from "../rdd-audio.js";
|
||||||
import { RdDUtility } from "../rdd-utility.js";
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
import { SystemCompendiums } from "../settings/system-compendiums.js";
|
import { SystemCompendiums } from "../settings/system-compendiums.js";
|
||||||
|
|
||||||
@ -73,14 +76,14 @@ export class RdDBaseActor extends Actor {
|
|||||||
if (actorData.items) {
|
if (actorData.items) {
|
||||||
return await super.create(actorData, options);
|
return await super.create(actorData, options);
|
||||||
}
|
}
|
||||||
|
actorData.items = [];
|
||||||
if (actorData.type == "personnage") {
|
if (actorData.type == "personnage") {
|
||||||
const competences = await SystemCompendiums.getCompetences(actorData.type);
|
const competences = await SystemCompendiums.getCompetences(actorData.type);
|
||||||
actorData.items = competences.map(i => i.toObject())
|
actorData.items = actorData.items.concat(competences.map(i => i.toObject()))
|
||||||
.concat(Monnaie.monnaiesStandard());
|
.concat(Monnaie.monnaiesStandard());
|
||||||
}
|
}
|
||||||
else {
|
else if (actorData.type == "commerce") {
|
||||||
actorData.items = [];
|
actorData.items = actorData.items.concat(Monnaie.monnaiesStandard());
|
||||||
}
|
}
|
||||||
return super.create(actorData, options);
|
return super.create(actorData, options);
|
||||||
}
|
}
|
||||||
@ -120,9 +123,11 @@ export class RdDBaseActor extends Actor {
|
|||||||
?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) });
|
?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMonnaie(id) { return this.findItemLike(id, 'monnaie'); }
|
||||||
|
|
||||||
recompute() { }
|
recompute() { }
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onPreUpdateItem(item, change, options, id) { }
|
async onPreUpdateItem(item, change, options, id) { }
|
||||||
|
|
||||||
@ -132,11 +137,218 @@ export class RdDBaseActor extends Actor {
|
|||||||
|
|
||||||
async onUpdateActor(update, options, actorId) { }
|
async onUpdateActor(update, options, actorId) { }
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
getFortune() {
|
getFortune() {
|
||||||
return Monnaie.getFortune(this.itemTypes['monnaie']);
|
return Monnaie.getFortune(this.itemTypes['monnaie']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async monnaieIncDec(id, value) {
|
||||||
|
let monnaie = this.getMonnaie(id);
|
||||||
|
if (monnaie) {
|
||||||
|
const quantite = Math.max(0, monnaie.system.quantite + value);
|
||||||
|
await this.updateEmbeddedDocuments('Item', [{ _id: monnaie.id, 'system.quantite': quantite }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
computePrixTotalEquipement() {
|
||||||
|
return this.items.filter(it => it.isInventaire())
|
||||||
|
.filter(it => !it.isMonnaie())
|
||||||
|
.map(it => it.valeurTotale())
|
||||||
|
.reduce(Misc.sum(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async payerSols(depense) {
|
||||||
|
depense = Number(depense);
|
||||||
|
if (depense == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let fortune = this.getFortune();
|
||||||
|
console.log("payer", game.user.character, depense, fortune);
|
||||||
|
let msg = "";
|
||||||
|
if (fortune >= depense) {
|
||||||
|
await Monnaie.optimiserFortune(this, fortune - depense);
|
||||||
|
msg = `Vous avez payé <strong>${depense} Sols</strong>, qui ont été soustraits de votre argent.`;
|
||||||
|
RdDAudio.PlayContextAudio("argent"); // Petit son
|
||||||
|
} else {
|
||||||
|
msg = "Vous n'avez pas assez d'argent pour payer cette somme !";
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = {
|
||||||
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
||||||
|
content: msg
|
||||||
|
};
|
||||||
|
ChatMessage.create(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
async depenserSols(sols) {
|
||||||
|
let reste = this.getFortune() - Number(sols);
|
||||||
|
if (reste >= 0) {
|
||||||
|
await Monnaie.optimiserFortune(this, reste);
|
||||||
|
}
|
||||||
|
return reste;
|
||||||
|
}
|
||||||
|
|
||||||
|
async ajouterSols(sols, fromActorId = undefined) {
|
||||||
|
sols = Number(sols);
|
||||||
|
if (sols == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sols < 0) {
|
||||||
|
ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fromActorId && !game.user.isGM) {
|
||||||
|
RdDBaseActor.remoteActorCall({
|
||||||
|
userId: Misc.connectedGMOrUser(),
|
||||||
|
actorId: this.id,
|
||||||
|
method: 'ajouterSols', args: [sols, fromActorId]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const fromActor = game.actors.get(fromActorId)
|
||||||
|
await Monnaie.optimiserFortune(this, sols + this.getFortune());
|
||||||
|
|
||||||
|
RdDAudio.PlayContextAudio("argent"); // Petit son
|
||||||
|
ChatMessage.create({
|
||||||
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
||||||
|
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
getQuantiteDisponible(item) {
|
||||||
|
return item?.getQuantite();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async achatVente(achat) {
|
||||||
|
if (achat.vendeurId == achat.acheteurId) {
|
||||||
|
ui.notifications.info("Inutile de se vendre à soi-même");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!Misc.isUniqueConnectedGM()) {
|
||||||
|
RdDBaseActor.remoteActorCall({
|
||||||
|
actorId: achat.vendeurId ?? achat.acheteurId,
|
||||||
|
method: 'achatVente',
|
||||||
|
args: [achat]
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cout = Number(achat.prixTotal ?? 0);
|
||||||
|
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : 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?.getItem(vente.item._id);
|
||||||
|
if (!this.verifierQuantite(vendeur, itemVendu, quantite)) {
|
||||||
|
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (acheteur && !acheteur.verifierFortune(cout)) {
|
||||||
|
ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.decrementerVente(vendeur, itemVendu, quantite, cout);
|
||||||
|
if (acheteur) {
|
||||||
|
await acheteur.depenserSols(cout);
|
||||||
|
let createdItemId = await acheteur.creerQuantiteItem(vente.item, quantite);
|
||||||
|
await acheteur.consommerNourritureAchetee(achat, vente, createdItemId);
|
||||||
|
}
|
||||||
|
if (cout > 0) {
|
||||||
|
RdDAudio.PlayContextAudio("argent");
|
||||||
|
}
|
||||||
|
const chatAchatItem = duplicate(vente);
|
||||||
|
chatAchatItem.quantiteTotal = quantite;
|
||||||
|
ChatMessage.create({
|
||||||
|
user: achat.userId,
|
||||||
|
speaker: { alias: (acheteur ?? vendeur).name },
|
||||||
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
||||||
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html', chatAchatItem)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!vente.quantiteIllimite) {
|
||||||
|
if (vente.quantiteNbLots <= achat.choix.nombreLots) {
|
||||||
|
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
|
||||||
|
}
|
||||||
|
else if (achat.chatMessageIdVente) {
|
||||||
|
vente["properties"] = itemVendu.getProprietes();
|
||||||
|
vente.quantiteNbLots -= achat.choix.nombreLots;
|
||||||
|
vente.jsondata = JSON.stringify(vente.item);
|
||||||
|
const messageVente = game.messages.get(achat.chatMessageIdVente);
|
||||||
|
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente) });
|
||||||
|
messageVente.render(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async decrementerVente(vendeur, itemVendu, quantite, cout) {
|
||||||
|
if (vendeur) {
|
||||||
|
await vendeur.ajouterSols(cout);
|
||||||
|
await vendeur.decrementerQuantiteItem(itemVendu, quantite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verifierFortune(cout) {
|
||||||
|
return this.getFortune() >= cout;
|
||||||
|
}
|
||||||
|
|
||||||
|
verifierQuantite(vendeur, item, quantiteTotal) {
|
||||||
|
const disponible = vendeur?.getQuantiteDisponible(item);
|
||||||
|
return disponible == undefined || disponible >= quantiteTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
async consommerNourritureAchetee(achat, vente, createdItemId) {
|
||||||
|
if (achat.choix.consommer && vente.item.type == 'nourritureboisson' && createdItemId != undefined) {
|
||||||
|
achat.choix.doses = achat.choix.nombreLots;
|
||||||
|
await this.consommerNourritureboisson(createdItemId, achat.choix, vente.actingUserId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async decrementerQuantiteItem(item, quantite, options={supprimerSiZero: true}) {
|
||||||
|
let resteQuantite = (item.system.quantite ?? 1) - quantite;
|
||||||
|
if (resteQuantite <= 0) {
|
||||||
|
if (options.supprimerSiZero) {
|
||||||
|
await this.deleteEmbeddedDocuments("Item", [item.id]);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': 0 }]);
|
||||||
|
}
|
||||||
|
if (resteQuantite < 0) {
|
||||||
|
ui.notifications.warn(`La quantité de ${item.name} était insuffisante, l'objet a donc été supprimé`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (resteQuantite > 0) {
|
||||||
|
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': resteQuantite }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async creerQuantiteItem(item, quantite) {
|
||||||
|
const isItemEmpilable = "quantite" in item.system;
|
||||||
|
const baseItem = {
|
||||||
|
type: item.type,
|
||||||
|
img: item.img,
|
||||||
|
name: item.name,
|
||||||
|
system: mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined })
|
||||||
|
};
|
||||||
|
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
|
||||||
|
const items = await this.createEmbeddedDocuments("Item", newItems);
|
||||||
|
return items.length > 0 ? items[0].id : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async computeEncTotal() {
|
||||||
|
if (!this.pack) {
|
||||||
|
this.encTotal = this.items.map(it => it.getEncTotal()).reduce(Misc.sum(), 0);
|
||||||
|
return this.encTotal;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
async createItem(type, name = undefined) {
|
async createItem(type, name = undefined) {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
name = 'Nouveau ' + Misc.typeName('Item', type);
|
name = 'Nouveau ' + Misc.typeName('Item', type);
|
||||||
@ -148,6 +360,237 @@ export class RdDBaseActor extends Actor {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async processDropItem(params) {
|
||||||
|
const targetActorId = this.id;
|
||||||
|
const sourceActorId = params.sourceActorId;
|
||||||
|
const itemId = params.itemId;
|
||||||
|
const destId = params.destId;
|
||||||
|
const srcId = params.srcId;
|
||||||
|
if (sourceActorId && sourceActorId != targetActorId) {
|
||||||
|
console.log("Moving objects", sourceActorId, targetActorId, itemId);
|
||||||
|
this.moveItemsBetweenActors(itemId, sourceActorId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let result = true;
|
||||||
|
const item = this.getItem(itemId);
|
||||||
|
if (item?.isInventaire() && sourceActorId == targetActorId) {
|
||||||
|
// rangement
|
||||||
|
if (srcId != destId && itemId != destId) { // déplacement de l'objet
|
||||||
|
const src = this.getItem(srcId);
|
||||||
|
const dest = this.getItem(destId);
|
||||||
|
const cible = this.getContenantOrParent(dest);
|
||||||
|
const [empilable, message] = item.isInventaireEmpilable(dest);
|
||||||
|
if (empilable) {
|
||||||
|
await dest.empiler(item)
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
// changer de conteneur
|
||||||
|
else if (!cible || this.conteneurPeutContenir(cible, item)) {
|
||||||
|
await this.enleverDeConteneur(item, src, params.onEnleverConteneur);
|
||||||
|
await this.ajouterDansConteneur(item, cible, params.onAjouterDansConteneur);
|
||||||
|
if (message && !dest.isConteneur()) {
|
||||||
|
ui.notifications.info(cible
|
||||||
|
? `${message}<br>${item.name} a été déplacé dans: ${cible.name}`
|
||||||
|
: `${message}<br>${item.name} a été sorti du conteneur`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.computeEncTotal();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getContenantOrParent(dest) {
|
||||||
|
if (!dest || dest.isConteneur()) {
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
return this.getContenant(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
getContenant(item) {
|
||||||
|
return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
conteneurPeutContenir(dest, item) {
|
||||||
|
if (!dest) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!dest.isConteneur()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const destData = dest
|
||||||
|
if (this._isConteneurContenu(item, dest)) {
|
||||||
|
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${destData.name} !`);
|
||||||
|
return false; // Loop detected !
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculer le total actuel des contenus
|
||||||
|
let encContenu = this.getRecursiveEnc(dest) - Number(destData.system.encombrement);
|
||||||
|
let newEnc = this.getRecursiveEnc(item); // Calculer le total actuel du nouvel objet
|
||||||
|
|
||||||
|
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
|
||||||
|
if (Number(destData.system.capacite) < encContenu + newEnc) {
|
||||||
|
ui.notifications.warn(
|
||||||
|
`Le conteneur ${dest.name} a une capacité de ${destData.system.capacite}, et contient déjà ${encContenu}.
|
||||||
|
Impossible d'y ranger: ${item.name} d'encombrement ${newEnc}!`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
_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.getItem(id);
|
||||||
|
if (subObjet?.id == conteneur.id) {
|
||||||
|
return true; // Loop detected !
|
||||||
|
}
|
||||||
|
if (subObjet?.isConteneur()) {
|
||||||
|
return this._isConteneurContenu(subObjet, conteneur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getRecursiveEnc(objet) {
|
||||||
|
if (!objet) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const tplData = objet.system;
|
||||||
|
if (objet.type != 'conteneur') {
|
||||||
|
return Number(tplData.encombrement) * Number(tplData.quantite);
|
||||||
|
}
|
||||||
|
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...*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** Ajoute un item dans un conteneur, sur la base
|
||||||
|
* de leurs ID */
|
||||||
|
async ajouterDansConteneur(item, conteneur, onAjouterDansConteneur) {
|
||||||
|
if (!conteneur) {
|
||||||
|
// TODO: afficher
|
||||||
|
item.estContenu = false;
|
||||||
|
}
|
||||||
|
else if (conteneur.isConteneur()) {
|
||||||
|
item.estContenu = true;
|
||||||
|
await this.updateEmbeddedDocuments('Item', [{
|
||||||
|
_id: conteneur.id,
|
||||||
|
'system.contenu': [...conteneur.system.contenu, item.id]
|
||||||
|
}]);
|
||||||
|
onAjouterDansConteneur(item.id, conteneur.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */
|
||||||
|
async nettoyerConteneurs() {
|
||||||
|
RdDConfirm.confirmer({
|
||||||
|
settingConfirmer: "confirmation-vider",
|
||||||
|
content: `<p>Etes vous certain de vouloir vider tous les conteneurs ?</p>`,
|
||||||
|
title: 'Vider les conteneurs',
|
||||||
|
buttonLabel: 'Vider',
|
||||||
|
onAction: async () => {
|
||||||
|
const corrections = [];
|
||||||
|
for (let item of this.items) {
|
||||||
|
if (item.estContenu) {
|
||||||
|
item.estContenu = undefined;
|
||||||
|
}
|
||||||
|
if (item.type == 'conteneur' && item.system.contenu.length > 0) {
|
||||||
|
corrections.push({ _id: item.id, 'system.contenu': [] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (corrections.length > 0) {
|
||||||
|
await this.updateEmbeddedDocuments('Item', corrections);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
buildSubConteneurObjetList(conteneurId, deleteList) {
|
||||||
|
let conteneur = this.getItem(conteneurId);
|
||||||
|
if (conteneur?.type == 'conteneur') { // Si c'est un conteneur
|
||||||
|
for (let subId of conteneur.system.contenu) {
|
||||||
|
let subObj = this.getItem(subId);
|
||||||
|
if (subObj) {
|
||||||
|
if (subObj.type == 'conteneur') {
|
||||||
|
this.buildSubConteneurObjetList(subId, deleteList);
|
||||||
|
}
|
||||||
|
deleteList.push({ id: subId, conteneurId: conteneurId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async deleteAllConteneur(itemId, options) {
|
||||||
|
let list = [];
|
||||||
|
list.push({ id: itemId, conteneurId: undefined }); // Init list
|
||||||
|
this.buildSubConteneurObjetList(itemId, list);
|
||||||
|
await this.deleteEmbeddedDocuments('Item', list.map(it => it.id), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** Supprime un item d'un conteneur, sur la base
|
||||||
|
* de leurs ID */
|
||||||
|
async enleverDeConteneur(item, conteneur, onEnleverDeConteneur) {
|
||||||
|
if (conteneur?.isConteneur()) {
|
||||||
|
item.estContenu = false;
|
||||||
|
await this.updateEmbeddedDocuments('Item', [{
|
||||||
|
_id: conteneur.id,
|
||||||
|
'system.contenu': conteneur.system.contenu.filter(id => id != item.id)
|
||||||
|
}]);
|
||||||
|
onEnleverDeConteneur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async moveItemsBetweenActors(itemId, sourceActorId) {
|
||||||
|
let itemsList = []
|
||||||
|
let sourceActor = game.actors.get(sourceActorId);
|
||||||
|
itemsList.push({ id: itemId, conteneurId: undefined }); // Init list
|
||||||
|
sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
let itemMap = this._buildMapOldNewId(itemsList, newItems);
|
||||||
|
|
||||||
|
for (let item of itemsList) { // Second boucle pour traiter la remise en conteneurs
|
||||||
|
// gestion conteneur/contenu
|
||||||
|
if (item.conteneurId) { // l'Objet était dans un conteneur
|
||||||
|
let newConteneurId = itemMap[item.conteneurId]; // Get conteneur
|
||||||
|
let newConteneur = this.getItem(newConteneurId);
|
||||||
|
|
||||||
|
let newItemId = itemMap[item.id]; // Get newItem
|
||||||
|
|
||||||
|
console.log('New conteneur filling!', newConteneur, newItemId, item);
|
||||||
|
let contenu = duplicate(newConteneur.system.contenu);
|
||||||
|
contenu.push(newItemId);
|
||||||
|
await this.updateEmbeddedDocuments('Item', [{ _id: newConteneurId, 'system.contenu': contenu }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let item of itemsList) {
|
||||||
|
await sourceActor.deleteEmbeddedDocuments('Item', [item.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildMapOldNewId(itemsList, newItems) {
|
||||||
|
let itemMap = {};
|
||||||
|
for (let i = 0; i < itemsList.length; i++) {
|
||||||
|
itemMap[itemsList[i].id] = newItems[i].id; // Pour garder le lien ancien / nouveau
|
||||||
|
}
|
||||||
|
return itemMap;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async postActorToChat(modeOverride) {
|
async postActorToChat(modeOverride) {
|
||||||
let chatData = {
|
let chatData = {
|
||||||
|
@ -101,7 +101,7 @@ export class SystemReveDeDragon {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// Define custom Entity classes
|
// Define custom Entity classes
|
||||||
CONFIG.Actor.documentClass = RdDActor;
|
CONFIG.Actor.documentClass = RdDBaseActor;
|
||||||
CONFIG.Item.documentClass = RdDItem;
|
CONFIG.Item.documentClass = RdDItem;
|
||||||
CONFIG.RDD = {
|
CONFIG.RDD = {
|
||||||
resolutionTable: RdDResolutionTable.resolutionTable,
|
resolutionTable: RdDResolutionTable.resolutionTable,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { RdDActor } from "./actor.js";
|
import { RdDBaseActor } from "./actor/base-actor.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ export class RdDNameGen {
|
|||||||
|
|
||||||
static async onCreerActeur(event) {
|
static async onCreerActeur(event) {
|
||||||
const button = event.currentTarget;
|
const button = event.currentTarget;
|
||||||
await RdDActor.create({
|
await RdDBaseActor.create({
|
||||||
name: button.attributes['data-nom'].value,
|
name: button.attributes['data-nom'].value,
|
||||||
type: button.attributes['data-type'].value
|
type: button.attributes['data-type'].value
|
||||||
},
|
},
|
||||||
|
@ -189,7 +189,7 @@
|
|||||||
<article class="flexcol">
|
<article class="flexcol">
|
||||||
<h3>Biographie : </h3>
|
<h3>Biographie : </h3>
|
||||||
<div class="form-group large-editor">
|
<div class="form-group large-editor">
|
||||||
{{editor biographie target="system.biographie" button=true owner=owner editable=true engine="prosemirror"}}
|
{{editor biographie target="system.biographie" button=true owner=options.owner editable=true engine="prosemirror"}}
|
||||||
</div>
|
</div>
|
||||||
<h3>Notes : </h3>
|
<h3>Notes : </h3>
|
||||||
<div class="form-group large-editor">
|
<div class="form-group large-editor">
|
||||||
|
Loading…
Reference in New Issue
Block a user