Merge branch 'v1.4-regrouper' into 'v1.4'

Regrouper des équipements #169

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!199
This commit is contained in:
Leratier Bretonnien 2021-04-13 20:56:29 +00:00
commit 93865f2c4b
5 changed files with 151 additions and 123 deletions

View File

@ -161,7 +161,7 @@ export class RdDActorSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onDrop(event) { async _onDrop(event) {
let toSuper = await RdDUtility.processItemDropEvent(this, event); let toSuper = await this.actor.processItemDropEvent(event, this.objetVersConteneur);
if (toSuper) { if (toSuper) {
super._onDrop(event); super._onDrop(event);
} }

View File

@ -68,7 +68,7 @@ export class RdDActorVehiculeSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onDrop(event) { async _onDrop(event) {
let toSuper = await RdDUtility.processItemDropEvent(this, event); let toSuper = await this.actor.processItemDropEvent(event, this.objetVersConteneur);
if ( toSuper) { if ( toSuper) {
super._onDrop(event); super._onDrop(event);
} }

View File

@ -826,22 +826,8 @@ export class RdDActor extends Actor {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
validateConteneur(itemId, conteneurId) {
const dest = this.getObjet(conteneurId);
if (dest?.type != 'conteneur') {
ui.notifications.warn(`Impossible de déplacer un objet (${item.name}) vers un ${dest.type} qui n'est pas un conteneur (${dest.name}) !`);
return false;
}
const item = this.getObjet(itemId);
if (this._isConteneurContenu(item, conteneurId)) {
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${dest.name} !`);
return false; // Loop detected !
}
return true;
}
_isConteneurContenu(item, conteneurId) { _isConteneurContenu(item, conteneurId) {
if (item?.type == 'conteneur') { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant if (Misc.data(item)?.type == 'conteneur') { // 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 Misc.templateData(item).contenu) { for (let id of Misc.templateData(item).contenu) {
let subObjet = this.getObjet(id); let subObjet = this.getObjet(id);
if (subObjet?.id == conteneurId) { if (subObjet?.id == conteneurId) {
@ -869,41 +855,6 @@ export class RdDActor extends Actor {
+ Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/ + Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/
} }
/* -------------------------------------------- */
isConteneurSuffisant(itemId, conteneurId) {
if (!conteneurId) {
// on peut toujours vider son sac
return true;
}
return this.validateConteneur(itemId, conteneurId) && this.testConteneurCapacite(itemId, conteneurId);
}
/* -------------------------------------------- */
/** Teste si le conteneur de destination a suffisament de capacité
* pour recevoir le nouvel objet
*/
testConteneurCapacite(itemId, conteneurId) {
let conteneur = this.getObjet(conteneurId); // recup conteneur (ou undefined)
//console.log("Conteneur trouvé : ", conteneur);
if (conteneur?.type != "conteneur") {
return true;
}
const tplConteneur = Misc.templateData(conteneur);
// Calculer le total actuel des contenus
let encContenu = this.getRecursiveEnc(conteneur) - Number(tplConteneur.encombrement);
let nouvelObjet = this.getObjet(itemId);
let newEnc = this.getRecursiveEnc(nouvelObjet); // Calculer le total actuel du nouvel objet
//console.log( currentEnc, newEnc, tplConteneur.capacite, conteneur.name);
if (nouvelObjet && ((encContenu + newEnc) > Number(tplConteneur.capacite))) {
ui.notifications.warn(
`Le conteneur ${conteneur.name} a une capacité de ${tplConteneur.capacite}, et contient déjà ${encContenu}.
Impossible d'y ranger: ${nouvelObjet.name} d'encombrement ${newEnc}!`);
return false;
}
return true;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
buildSubConteneurObjetList(conteneurId, deleteList) { buildSubConteneurObjetList(conteneurId, deleteList) {
let conteneur = this.getObjet(conteneurId); let conteneur = this.getObjet(conteneurId);
@ -931,9 +882,8 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** Supprime un item d'un conteneur, sur la base /** Supprime un item d'un conteneur, sur la base
* de leurs ID */ * de leurs ID */
async enleverDeConteneur(itemId, conteneurId) { async enleverDeConteneur(itemId, conteneur) {
let conteneur = this.getObjet(conteneurId); if (conteneur?.isConteneur()) { // Si présent
if (conteneur?.type == 'conteneur') { // Si présent
let data2use = duplicate(Misc.data(conteneur)); let data2use = duplicate(Misc.data(conteneur));
//console.log("Suppression du conteneur1", conteneurId, itemId, data2use.data.contenu); //console.log("Suppression du conteneur1", conteneurId, itemId, data2use.data.contenu);
let contenu = data2use.data.contenu; let contenu = data2use.data.contenu;
@ -949,9 +899,8 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** Ajoute un item dans un conteneur, sur la base /** Ajoute un item dans un conteneur, sur la base
* de leurs ID */ * de leurs ID */
async ajouterAConteneur(itemId, conteneurId) { async ajouterDansConteneur(itemId, conteneur) {
let conteneur = this.getObjet(conteneurId); if (conteneur?.isConteneur()) {
if (conteneur?.type == 'conteneur') {
let data2use = duplicate(Misc.data(conteneur)); let data2use = duplicate(Misc.data(conteneur));
data2use.data.contenu.push(itemId); data2use.data.contenu.push(itemId);
await this.updateEmbeddedDocuments('Item', [data2use]); await this.updateEmbeddedDocuments('Item', [data2use]);
@ -972,6 +921,74 @@ export class RdDActor extends Actor {
await this.updateEmbeddedDocuments('Item', conteneurFixedList); await this.updateEmbeddedDocuments('Item', conteneurFixedList);
} }
/* -------------------------------------------- */
async processItemDropEvent(event, objetVersConteneur) {
let dragData = JSON.parse(event.dataTransfer.getData("text/plain"));
console.log("DRAG", this.id, dragData);
let itemId = dragData.id || dragData.data._id;
if (dragData.type == 'Item') {
if (dragData.actorId && dragData.actorId != this.id) {
console.log("Moving objects", dragData);
this.moveItemsBetweenActors(itemId, dragData.actorId);
return false;
}
if (dragData.actorId == this.id) {
// rangement
const destId = $(event.target).parents(".item").attr("data-item-id");
const srcId = objetVersConteneur[itemId];
if (srcId != destId && itemId != destId) { // déplacement de l'objet
const item = this.getObjet(itemId);
const dest = this.getObjet(destId);
const src = this.getObjet(srcId);
if (!dest) {
// on peut toujours vider son sac
await this.enleverDeConteneur(itemId, src);
}
else if (!dest.isConteneur()) {
// regrouper?
await this.regrouperEquipementsSimilaires(item, dest);
}
else if (this.conteneurPeutContenir(dest, item)) {
// déplacer?
await this.enleverDeConteneur(itemId, src);
await this.ajouterDansConteneur(itemId, dest);
}
}
}
this.computeEncombrementTotalEtMalusArmure();
}
if (dragData.type == "Actor") {
this.addSubacteur(itemId);
}
return true;
}
conteneurPeutContenir(dest, item) {
const destData = Misc.data(dest);
if (destData?.type != 'conteneur') {
ui.notifications.warn(`Impossible de déplacer un objet (${item.name}) vers un ${destData.type} qui n'est pas un conteneur (${dest.name}) !`);
return false;
}
if (this._isConteneurContenu(item, conteneurId)) {
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.data.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.data.capacite) < encContenu + newEnc) {
ui.notifications.warn(
`Le conteneur ${dest.name} a une capacité de ${destData.data.capacite}, et contient déjà ${encContenu}.
Impossible d'y ranger: ${item.name} d'encombrement ${newEnc}!`);
return false;
}
return true;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async moveItemsBetweenActors(itemId, sourceActorId) { async moveItemsBetweenActors(itemId, sourceActorId) {
let itemsList = [] let itemsList = []
@ -995,7 +1012,7 @@ export class RdDActor extends Actor {
let newItemId = itemMap[item.id]; // Get newItem let newItemId = itemMap[item.id]; // Get newItem
console.log('New conteneur filling!', newConteneur, newItemId, item); console.log('New conteneur filling!', newConteneur, newItemId, item);
let contenu = duplicate(newConteneur.data.contenu); let contenu = duplicate(Misc.templateData(newConteneur).contenu);
contenu.push(newItemId); contenu.push(newItemId);
await this.updateEmbeddedDocuments('Item', [{ _id: newConteneurId, 'data.contenu': contenu }]); await this.updateEmbeddedDocuments('Item', [{ _id: newConteneurId, 'data.contenu': contenu }]);
} }
@ -1005,6 +1022,13 @@ export class RdDActor extends Actor {
} }
} }
async regrouperEquipementsSimilaires(item, dest) {
if (item.isEquipementSimilaire(dest)) {
await dest.quantiteIncDec(Misc.templateData(item).quantite);
await this.deleteEmbeddedDocuments('Item', [item.id]);
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
detectSurEncombrement() { detectSurEncombrement() {
return Math.max(0, Math.ceil(Number(this.encTotal) - this.getEncombrementMax())); return Math.max(0, Math.ceil(Number(this.encTotal) - this.getEncombrementMax()));
@ -3396,7 +3420,7 @@ export class RdDActor extends Actor {
async diminuerQuantiteObjet(id, nb, options = { supprimerSiZero: false }) { async diminuerQuantiteObjet(id, nb, options = { supprimerSiZero: false }) {
const item = this.getObjet(id); const item = this.getObjet(id);
if (item){ if (item) {
await item.diminuerQuantite(nb, options); await item.diminuerQuantite(nb, options);
} }
} }

View File

@ -4,7 +4,8 @@ import { RdDUtility } from "./rdd-utility.js";
const typesObjetsEquipement = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "nourritureboisson", "monnaie"]; const typesObjetsEquipement = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "nourritureboisson", "monnaie"];
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]; const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"];
const encBrin = 0.00005; const encBrin = 0.00005;// un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDItem extends Item { export class RdDItem extends Item {
@ -16,17 +17,42 @@ export class RdDItem extends Item {
return typesObjetsOeuvres; return typesObjetsOeuvres;
} }
isConteneur() {
return Misc.data(this).type == 'conteneur';
}
isAlcool() {
const itemData = Misc.data(this);
return itemData.type == 'nourritureboisson' && itemData.data.boisson && itemData.data.alcoolise;
}
isPotion() {
return Misc.data(this).type == 'potion';
}
isEquipement() {
return RdDItem.getTypeObjetsEquipement().includes(Misc.data(this).type);
}
getEnc() {
const itemData = Misc.data(this);
switch (itemData.type) {
case 'herbe':
return encBrin;
}
return itemData.data.encombrement
}
prepareDerivedData() { prepareDerivedData() {
super.prepareDerivedData(); super.prepareDerivedData();
const itemData = Misc.data(this); if (this.isEquipement(this)) {
if (RdDItem.getTypeObjetsEquipement().includes(itemData.type)) {
this._calculsEquipement(); this._calculsEquipement();
} }
if (itemData.type == 'potion') { if (this.isPotion()) {
this.prepareDataPotion() this.prepareDataPotion()
} }
const itemData = Misc.data(this);
itemData.data.actionPrincipale = this.getActionPrincipale({ warnIfNot: false }); itemData.data.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
} }
prepareDataPotion() { prepareDataPotion() {
@ -42,7 +68,7 @@ export class RdDItem extends Item {
_calculsEquipement() { _calculsEquipement() {
const tplData = Misc.templateData(this); const tplData = Misc.templateData(this);
const quantite = Misc.data(this).type == 'conteneur' ? 1 : (tplData.quantite ?? 0); const quantite = this.isConteneur() ? 1 : (tplData.quantite ?? 0);
const enc = this.getEnc(); const enc = this.getEnc();
if (enc != undefined) { if (enc != undefined) {
tplData.encTotal = Math.max(enc, 0) * quantite; tplData.encTotal = Math.max(enc, 0) * quantite;
@ -52,15 +78,6 @@ export class RdDItem extends Item {
} }
} }
getEnc() {
const itemData = Misc.data(this);
switch (itemData.type) {
case 'herbe':
return encBrin;
}
return itemData.data.encombrement
}
getActionPrincipale(options = { warnIfNot: true }) { getActionPrincipale(options = { warnIfNot: true }) {
const itemData = Misc.data(this); const itemData = Misc.data(this);
if ((itemData.data.quantite ?? 0) <= 0) { if ((itemData.data.quantite ?? 0) <= 0) {
@ -80,31 +97,53 @@ export class RdDItem extends Item {
return undefined; return undefined;
} }
isAlcool() {
const itemData = Misc.data(this);
return itemData.type == 'nourritureboisson' && itemData.data.boisson && itemData.data.alcoolise;
}
async diminuerQuantite(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) { async diminuerQuantite(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
if (options.diminuerQuantite == false) return; if (options.diminuerQuantite == false) return;
await this.quantiteIncDec(-nombre, options);
}
async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
const itemData = Misc.data(this); const itemData = Misc.data(this);
const quantite = itemData.data.quantite; const quantite = itemData.data.quantite;
if (quantite != undefined) { if (quantite != undefined) {
const reste = Math.max(quantite - nombre, 0); const reste = Math.max(quantite + nombre, 0);
if (options.supprimerSiZero && reste == 0) { if (reste == 0) {
ui.notifications.notify(`${itemData.name} supprimé de votre équipement`); if (options.supprimerSiZero){
await this.delete(); ui.notifications.notify(`${itemData.name} supprimé de votre équipement`);
await this.delete();
}
else {
ui.notifications.notify(`Il ne vous reste plus de ${itemData.name}, vous pouvez le supprimer de votre équipement, ou trouver un moyen de vous en procurer.`);
await this.update({ "data.quantite": 0 });
}
} }
else { else {
ui.notifications.notify(`Quantité de ${itemData.name} réduite de ${nombre}.${reste == 0
? "Il ne vous en reste plus, vous pouvez le supprimer de votre équipement, ou trouver un moyen de vous en procurer."
: ""}`);
await this.update({ "data.quantite": reste }); await this.update({ "data.quantite": reste });
} }
} }
} }
/* -------------------------------------------- */
// détermine si deux équipements sont similaires: de même type, et avec les même champs hormis la quantité
isEquipementSimilaire(other) {
const itemData = Misc.data(this);
const otherData = Misc.data(other);
const tplData = Misc.templateData(this);
const otherTplData = Misc.templateData(other);
if (!this.isEquipement()) return false;
if (itemData.type != otherData.type) return false;
if (itemData.name != otherData.name) return false;
if (tplData.quantite == undefined) return false;
for (const [key, value] of Object.entries(tplData)) {
if (['quantite', 'encTotal', 'prixTotal'].includes(key)) continue;
if (value != otherTplData[key]) return false;
}
return true;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async postItem() { async postItem() {
console.log(this); console.log(this);

View File

@ -281,41 +281,6 @@ export class RdDUtility {
formData.competences = (formData.itemsByType.competence ?? []).concat(formData.itemsByType.competencecreature ?? []); formData.competences = (formData.itemsByType.competence ?? []).concat(formData.itemsByType.competencecreature ?? []);
} }
/* -------------------------------------------- */
static async processItemDropEvent(actorSheet, event) {
let dragData = JSON.parse(event.dataTransfer.getData("text/plain"));
console.log(dragData, actorSheet.actor.id);
let objetId = dragData.id || dragData.data._id;
console.log("DRAG", dragData);
if (dragData.type == 'Item') {
if (dragData.actorId) {
if (dragData.actorId != actorSheet.actor.id) {
console.log("Moving objects", dragData);
actorSheet.actor.moveItemsBetweenActors(objetId, dragData.actorId);
return false;
}
else {
// rangement
const destId = $(event.target).parents(".item").attr("data-item-id");
const srcId = actorSheet.objetVersConteneur[objetId];
if (srcId != destId && objetId != destId && actorSheet.actor.isConteneurSuffisant(objetId, destId)) {
if (srcId) {
await actorSheet.actor.enleverDeConteneur(objetId, srcId);
}
if (destId) { // Dropped over an item !!!
await actorSheet.actor.ajouterAConteneur(objetId, destId);
}
}
}
}
actorSheet.actor.computeEncombrementTotalEtMalusArmure();
} else if (dragData.type == "Actor") {
actorSheet.actor.addSubacteur(objetId);
}
return true;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static buildArbreDeConteneur(actorSheet, formData) { static buildArbreDeConteneur(actorSheet, formData) {
actorSheet.objetVersConteneur = {}; // Table de hash locale pour recupération rapide du conteneur parent (si existant) actorSheet.objetVersConteneur = {}; // Table de hash locale pour recupération rapide du conteneur parent (si existant)