Vincent Vandemeulebrouck
fc63835a71
Correction sur les achats: l'objet acheté vient forcément soit d'un personnage-vendeur, soit des Items globaux. Ne pas essayer d'acheter autrement car on aurait des données d'item non structurées, et donc ça ne fonctionnerait pas.
632 lines
22 KiB
JavaScript
632 lines
22 KiB
JavaScript
import { ChatUtility } from "../chat-utility.js";
|
|
import { SYSTEM_SOCKET_ID } from "../constants.js";
|
|
import { Monnaie } from "../item-monnaie.js";
|
|
import { Misc } from "../misc.js";
|
|
import { RdDAudio } from "../rdd-audio.js";
|
|
import { RdDConfirm } from "../rdd-confirm.js";
|
|
import { RdDUtility } from "../rdd-utility.js";
|
|
import { SystemCompendiums } from "../settings/system-compendiums.js";
|
|
import { APP_ASTROLOGIE_REFRESH } from "../sommeil/app-astrologie.js";
|
|
|
|
export class RdDBaseActor extends Actor {
|
|
|
|
static getDefaultImg(itemType) {
|
|
return game.system.rdd.actorClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static init() {
|
|
Hooks.on("preUpdateItem", (item, change, options, id) => RdDBaseActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id));
|
|
Hooks.on("createItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onCreateItem(item, options, id));
|
|
Hooks.on("deleteItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onDeleteItem(item, options, id));
|
|
Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId));
|
|
}
|
|
|
|
static onSocketMessage(sockmsg) {
|
|
switch (sockmsg.msg) {
|
|
case "msg_remote_actor_call":
|
|
return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId);
|
|
case "msg_reset_nombre_astral":
|
|
game.user.character.resetNombresAstraux();
|
|
game.system.rdd.calendrier.notifyChangeNombresAstraux();
|
|
return;
|
|
case "msg_refresh_nombre_astral":
|
|
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
|
return;
|
|
}
|
|
}
|
|
|
|
static remoteActorCall(callData, userId = undefined) {
|
|
userId = userId ?? Misc.firstConnectedGMId();
|
|
if (userId == game.user.id) {
|
|
RdDBaseActor.onRemoteActorCall(callData, userId);
|
|
return false;
|
|
}
|
|
else {
|
|
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_remote_actor_call", data: callData, userId: userId });
|
|
return true;
|
|
}
|
|
}
|
|
|
|
static onRemoteActorCall(callData, userId) {
|
|
if (userId == game.user.id) {
|
|
const actor = game.actors.get(callData?.actorId);
|
|
if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
|
|
const args = callData.args;
|
|
console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')');
|
|
actor[callData.method](...args);
|
|
}
|
|
}
|
|
}
|
|
|
|
static getParentActor(document) {
|
|
return document?.parent instanceof Actor ? document.parent : undefined
|
|
}
|
|
|
|
/**
|
|
* Cet methode surcharge Actor.create() pour ajouter si besoin des Items par défaut:
|
|
* compétences et monnaies.
|
|
*
|
|
* @param {Object} actorData template d'acteur auquel ajouter des informations.
|
|
* @param {Object} options optionspour customiser la création
|
|
*/
|
|
static async create(actorData, options) {
|
|
// import depuis un compendium
|
|
if (actorData instanceof Array) {
|
|
return super.create(actorData, options);
|
|
}
|
|
// Création d'un acteur avec des items (uniquement en cas de duplication): pas besoin d'ajouter d'items
|
|
if (actorData.items) {
|
|
return await super.create(actorData, options);
|
|
}
|
|
actorData.items = [];
|
|
if (actorData.type == "personnage") {
|
|
const competences = await SystemCompendiums.getCompetences(actorData.type);
|
|
actorData.items = actorData.items.concat(competences.map(i => i.toObject()))
|
|
.concat(Monnaie.monnaiesStandard());
|
|
}
|
|
else if (actorData.type == "commerce") {
|
|
actorData.items = actorData.items.concat(Monnaie.monnaiesStandard());
|
|
}
|
|
return super.create(actorData, options);
|
|
}
|
|
|
|
constructor(docData, context = {}) {
|
|
if (!context.rdd?.ready) {
|
|
mergeObject(context, { rdd: { ready: true } });
|
|
const ActorConstructor = game.system.rdd.actorClasses[docData.type];
|
|
if (ActorConstructor) {
|
|
if (!docData.img) {
|
|
docData.img = ActorConstructor.defaultIcon;
|
|
}
|
|
return new ActorConstructor(docData, context);
|
|
}
|
|
}
|
|
super(docData, context);
|
|
}
|
|
|
|
isCreatureEntite() { return this.type == 'creature' || this.type == 'entite'; }
|
|
isCreature() { return this.type == 'creature'; }
|
|
isEntite() { return this.type == 'entite'; }
|
|
isPersonnage() { return this.type == 'personnage'; }
|
|
isVehicule() { return this.type == 'vehicule'; }
|
|
getItem(id, type = undefined) {
|
|
const item = this.items.get(id);
|
|
if (type == undefined || (item?.type == type)) {
|
|
return item;
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); }
|
|
filterItems(filter, type = undefined) { return type ? this.itemTypes[type]?.filter(filter) ?? [] : []; }
|
|
findItemLike(idOrName, type) {
|
|
return this.getItem(idOrName, type)
|
|
?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) });
|
|
}
|
|
|
|
getMonnaie(id) { return this.findItemLike(id, 'monnaie'); }
|
|
|
|
recompute() { }
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
async onPreUpdateItem(item, change, options, id) { }
|
|
|
|
async onCreateItem(item, options, id) { }
|
|
|
|
async onDeleteItem(item, options, id) { }
|
|
|
|
async onUpdateActor(update, options, actorId) { }
|
|
|
|
async onTimeChanging(oldTimestamp, newTimestamp) {
|
|
this.items.filter(it => it.isFinPeriode(oldTimestamp, newTimestamp))
|
|
.forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp))
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
getFortune() {
|
|
return Monnaie.getFortune(this.itemTypes['monnaie']);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async itemQuantiteIncDec(id, value) {
|
|
let item = this.getItem(id);
|
|
if (item && item.isInventaire()) {
|
|
const quantite = Math.max(0, item.system.quantite + value);
|
|
await this.updateEmbeddedDocuments('Item', [{ _id: item.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?.isService() ? undefined : 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 quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
|
|
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id);
|
|
if (!itemVendu) {
|
|
ChatUtility.notifyUser(achat.userId, 'warn', vendeur ? `Le vendeur n'a pas plus de ${achat.vente.item.name} !`: `Impossible de retrouver: ${achat.vente.item.name} !`);
|
|
return;
|
|
}
|
|
if (vendeur && !this.verifierQuantite(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);
|
|
const createdItemId = await acheteur.creerQuantiteItem(itemVendu, quantite);
|
|
await acheteur.consommerNourritureAchetee(achat, achat.vente, createdItemId);
|
|
}
|
|
if (cout > 0) {
|
|
RdDAudio.PlayContextAudio("argent");
|
|
}
|
|
const chatAchatItem = duplicate(achat.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 (!achat.vente.quantiteIllimite) {
|
|
if (achat.vente.quantiteNbLots <= achat.choix.nombreLots) {
|
|
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
|
|
}
|
|
else if (achat.chatMessageIdVente) {
|
|
achat.vente.properties = itemVendu.getProprietes();
|
|
achat.vente.quantiteNbLots -= achat.choix.nombreLots;
|
|
achat.vente.jsondata = JSON.stringify(achat.vente.item);
|
|
const messageVente = game.messages.get(achat.chatMessageIdVente);
|
|
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', achat.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(item, quantiteDemande) {
|
|
const disponible = item?.getQuantite();
|
|
return disponible == undefined || disponible >= quantiteDemande;
|
|
}
|
|
|
|
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 }) {
|
|
if (item.isService()) {
|
|
return;
|
|
}
|
|
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) {
|
|
if (this.canReceive(item)) {
|
|
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;
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
computeMalusSurEncombrement() {
|
|
return 0;
|
|
}
|
|
|
|
getEncombrementMax() {
|
|
return 0;
|
|
}
|
|
|
|
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) {
|
|
if (!name) {
|
|
name = 'Nouveau ' + Misc.typeName('Item', type);
|
|
}
|
|
await this.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
|
|
}
|
|
|
|
canReceive(item) {
|
|
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('all') && 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) {
|
|
let chatData = {
|
|
doctype: 'Actor',
|
|
id: this.id,
|
|
type: this.type,
|
|
img: this.img,
|
|
pack: this.pack,
|
|
name: this.name,
|
|
system: { description: this.system.description }
|
|
}
|
|
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.html', chatData)
|
|
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
|
|
}
|
|
|
|
|
|
} |