Consommation part le consommateur

Pour afficher la fenêtre d'appréciation côté acheteur, et utiliser ses
dés
This commit is contained in:
2025-12-15 01:09:34 +01:00
parent 455beb2820
commit e33727ac8d
7 changed files with 351 additions and 313 deletions
+8
View File
@@ -1,5 +1,13 @@
# 13.0 # 13.0
## 13.0.23 - Le marché d'Illysis
- Améliorations
- lors de la consoimmation suite à un achat, les jets d'appréciation/éthylisme
sont faits par l'acheteur. Du coup, c'est lui qui lance le jet d'appréciation
(pour un service ou un plat de qualité), et ses dés sont utilisés avec dice-so-nice
## 13.0.22 - Les reflets d'Illysis ## 13.0.22 - Les reflets d'Illysis
- Améliorations - Améliorations
+11 -7
View File
@@ -40,17 +40,21 @@ export class ChatVente {
static async diminuerQuantiteAchatVente(chatMessageId, quantite) { static async diminuerQuantiteAchatVente(chatMessageId, quantite) {
const chatMessage = game.messages.get(chatMessageId) const chatMessage = game.messages.get(chatMessageId)
const vente = ChatVente.getDetailVente(chatMessageId)
vente.nbLots = Math.max(0, vente.nbLots - quantite)
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.hbs', vente); const vente = ChatVente.getDetailVente(chatMessageId)
chatMessage.update({ content: html }); if (vente.nbLots <= quantite) {
chatMessage.render(true); ChatUtility.removeChatMessageId(chatMessageIdVente);
}
else {
vente.nbLots = vente.nbLots - quantite
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.hbs', vente)
await chatMessage.update({ content: html }, { render: true })
}
} }
static async displayAchatVente(vente) { static async displayAchatVente(vente) {
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.hbs', vente); const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.hbs', vente)
const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html)) const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html))
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots) await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
await chatMessage.setFlag(SYSTEM_RDD, DETAIL_VENTE, { await chatMessage.setFlag(SYSTEM_RDD, DETAIL_VENTE, {
+22 -20
View File
@@ -220,7 +220,7 @@ export class RdDActor extends RdDBaseActorSang {
initiative: RdDInitiative.getRollInitiative(caracValue, niveau, ajustement) initiative: RdDInitiative.getRollInitiative(caracValue, niveau, ajustement)
}; };
attaque.isDistance = Distance.typeAttaqueDistance(attaque), attaque.isDistance = Distance.typeAttaqueDistance(attaque),
actions.push(attaque) actions.push(attaque)
} }
addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS) addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS)
@@ -1092,7 +1092,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
$createSortReserve(sort) { $createSortReserve(sort) {
const ptReve = Number.isInteger(sort.system.ptreve) ? Number(sort.system.ptreve) :Number(sort.system.ptreve.match(/\d+/)) const ptReve = Number.isInteger(sort.system.ptreve) ? Number(sort.system.ptreve) : Number(sort.system.ptreve.match(/\d+/))
this.createEmbeddedDocuments("Item", this.createEmbeddedDocuments("Item",
[{ [{
type: ITEM_TYPES.sortreserve, type: ITEM_TYPES.sortreserve,
@@ -1316,14 +1316,6 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async consommerNourritureboisson(itemId, choix = { doses: 1, seForcer: false, supprimerSiZero: false }) { async consommerNourritureboisson(itemId, choix = { doses: 1, seForcer: false, supprimerSiZero: false }) {
if (!this.isOwner) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'consommerNourritureboisson', args: [itemId, choix]
})
return
}
const item = this.getItem(itemId) const item = this.getItem(itemId)
if (!item.getUtilisationCuisine()) { if (!item.getUtilisationCuisine()) {
return return
@@ -1333,26 +1325,36 @@ export class RdDActor extends RdDBaseActorSang {
return return
} }
const onManger = [ if (!this.isOwner) {
async () => await this.manger(item, choix.doses, { diminuerQuantite: false }), RdDBaseActor.remoteActorCall({
async () => await this.boire(item, choix.doses, { diminuerQuantite: false }), tokenId: this.token?.id,
async () => await item.diminuerQuantite(choix.doses, choix) actorId: this.id,
] method: 'consommerNourritureboisson', args: [itemId, choix]
})
return
}
if (await this._surmonterExotisme(item)) { if (await this._surmonterExotisme(item)) {
const appreciation = item.system.appreciation; if (item.system.qualite > 0) {
new Apprecier(this, appreciation, item.system.qualite) new Apprecier(this, item.system.appreciation, item.system.qualite).apprecier()
.apprecier(onManger) }
await this.onConsommerNourritureboisson(item, choix)
} }
else if (choix.seForcer) { else if (choix.seForcer) {
await this.jetDeMoral(MORAL.MALHEUREUX) await this.jetDeMoral(MORAL.MALHEUREUX)
await Promise.all(onManger.map(async callback => await callback())) await this.onConsommerNourritureboisson(item, choix)
} }
else { else {
ui.notifications.info(`${this.name} ne n'arrive pas à manger de ${item.name}`) ui.notifications.info(`${this.name} ne n'arrive pas à manger de ${item.name}`)
} }
} }
async onConsommerNourritureboisson(item, choix) {
await this.manger(item, choix.doses, { diminuerQuantite: false })
await this.boire(item, choix.doses, { diminuerQuantite: false })
await item.diminuerQuantite(choix.doses, choix)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async _surmonterExotisme(item) { async _surmonterExotisme(item) {
const qualite = Math.min(item.system.qualite, 0) const qualite = Math.min(item.system.qualite, 0)
@@ -1363,7 +1365,7 @@ export class RdDActor extends RdDBaseActorSang {
const rolled = await this.doRollCaracCompetence(CARACS.VOLONTE, competence, difficulte, { title: `tente de surmonter l'exotisme de ${item.name}` }) const rolled = await this.doRollCaracCompetence(CARACS.VOLONTE, competence, difficulte, { title: `tente de surmonter l'exotisme de ${item.name}` })
return rolled.isSuccess return rolled.isSuccess
} }
return true; return true
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
+303 -279
View File
@@ -62,14 +62,14 @@ export class RdDBaseActor extends Actor {
} }
} }
static remoteActorCall(callData) { static remoteActorCall(callData, userId = undefined) {
if (game.user.isGM) { if (game.user.isGM) {
RdDBaseActor.onRemoteActorCall(callData, game.user.id) RdDBaseActor.onRemoteActorCall(callData, game.user.id)
return false return false
} }
else { else {
const gmUserId = Misc.firstConnectedGMId() const gmUserId = Misc.firstConnectedGMId()
if (gmUserId){ if (gmUserId) {
game.socket.emit(SYSTEM_SOCKET_ID, { game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_remote_actor_call", msg: "msg_remote_actor_call",
data: callData, data: callData,
@@ -417,6 +417,14 @@ export class RdDBaseActor extends Actor {
} }
async depenserSols(sols) { async depenserSols(sols) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
userId: Misc.connectedGMOrUser(),
tokenId: this.token?.id,
actorId: this.id,
method: 'depenserSols', args: [sols]
})
}
let reste = this.getFortune() - Number(sols); let reste = this.getFortune() - Number(sols);
if (reste >= 0) { if (reste >= 0) {
await Monnaie.optimiserFortune(this, reste); await Monnaie.optimiserFortune(this, reste);
@@ -425,32 +433,31 @@ export class RdDBaseActor extends Actor {
} }
async ajouterSols(sols, fromActorId = undefined) { async ajouterSols(sols, fromActorId = undefined) {
sols = Number(sols); sols = Number(sols)
if (sols == 0) { if (sols == 0) {
return; return
} }
if (sols < 0) { if (sols < 0) {
ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`); ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`)
return; return
} }
if (fromActorId && !this.isOwner) { if (fromActorId && !this.isOwner) {
RdDBaseActor.remoteActorCall({ return RdDBaseActor.remoteActorCall({
userId: Misc.connectedGMOrUser(), userId: Misc.connectedGMOrUser(),
tokenId: this.token?.id, tokenId: this.token?.id,
actorId: this.id, actorId: this.id,
method: 'ajouterSols', args: [sols, fromActorId] method: 'ajouterSols', args: [sols, fromActorId]
}); })
} }
else {
const fromActor = game.actors.get(fromActorId)
await Monnaie.optimiserFortune(this, sols + this.getFortune());
RdDAudio.PlayContextAudio("argent"); // Petit son const fromActor = game.actors.get(fromActorId)
ChatMessage.create({ await Monnaie.optimiserFortune(this, sols + this.getFortune());
whisper: ChatUtility.getOwners(this),
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.` RdDAudio.PlayContextAudio("argent"); // Petit son
}); ChatMessage.create({
} whisper: ChatUtility.getOwners(this),
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
})
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -462,24 +469,28 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async achatVente(achat) { async achatVente(achat) {
if (achat.vendeurId == achat.acheteurId) { if (achat.vendeurId == achat.acheteurId) {
ui.notifications.info("Inutile de se vendre à soi-même"); ui.notifications.info("Inutile de se vendre à soi-même")
return; return
} }
if (!game.user.isGM) { const cout = Number(achat.prixTotal ?? 0)
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined
if (acheteur && !acheteur.isOwner) {
ui.notifications.warn(`${game.user.id} n'est pas propriétaire de ${this.name} et effectue un achat pour lui!`)
RdDBaseActor.remoteActorCall({ RdDBaseActor.remoteActorCall({
actorId: achat.vendeurId ?? achat.acheteurId, actorId: achat.acheteurId,
method: 'achatVente', args: [achat] method: 'achatVente', args: [achat]
}); });
return 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 vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot); const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id); const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id);
if (!itemVendu) { 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} !`); 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; return
} }
if (vendeur && !vendeur.verifierQuantite(itemVendu, quantite)) { if (vendeur && !vendeur.verifierQuantite(itemVendu, quantite)) {
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`); ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
@@ -487,10 +498,10 @@ export class RdDBaseActor extends Actor {
} }
if (acheteur && !acheteur.verifierFortune(cout)) { if (acheteur && !acheteur.verifierFortune(cout)) {
ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`); ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`);
return; return
} }
await vendeur?.vendre(itemVendu, quantite, cout); await vendeur?.vendre(itemVendu, quantite, cout, acheteur);
await acheteur?.acheter(itemVendu, quantite, cout, achat) await acheteur?.acheter(itemVendu, quantite, cout, achat, vendeur)
if (cout > 0) { if (cout > 0) {
RdDAudio.PlayContextAudio("argent"); RdDAudio.PlayContextAudio("argent");
@@ -505,22 +516,32 @@ export class RdDBaseActor extends Actor {
}); });
if (!achat.vente.quantiteIllimite) { if (!achat.vente.quantiteIllimite) {
if (achat.vente.nbLots <= achat.choix.nombreLots) { await this.updateMessageVente(achat.chatMessageIdVente, achat.choix.nombreLots);
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
}
else if (achat.chatMessageIdVente) {
await ChatVente.diminuerQuantiteAchatVente(achat.chatMessageIdVente, achat.choix.nombreLots)
}
} }
} }
async vendre(item, quantite, cout) { async updateMessageVente(chatMessageIdVente, nombreLots) {
await this.ajouterSols(cout); const chatMessage = game.messages.get(chatMessageIdVente)
await this.decrementerQuantiteItem(item, quantite); if (!chatMessage.isOwner) {
return RdDBaseActor.remoteActorCall({
userId: Misc.firstConnectedGMId(),
actorId: this.id,
method: 'updateMessageVente', args: [chatMessageIdVente, nombreLots]
})
}
await ChatVente.diminuerQuantiteAchatVente(chatMessageIdVente, nombreLots);
}
async vendre(item, quantite, cout, acheteur) {
await this.ajouterSols(cout, acheteur?.id)
await this.decrementerQuantiteItem(item.id, quantite)
} }
async acheter(item, quantite, cout, achat) { async acheter(item, quantite, cout, achat) {
await this.depenserSols(cout) await this.depenserSols(cout)
if (!this.isOwner) {
ui.notifications.warn(`${game.user.id} n'est pas propriétaire de ${this.name} et effectue un achat!`)
}
const createdItemId = await this.creerQuantiteItem(item, quantite) const createdItemId = await this.creerQuantiteItem(item, quantite)
if (item.type == ITEM_TYPES.nourritureboisson && achat.choix.consommer && createdItemId != undefined) { if (item.type == ITEM_TYPES.nourritureboisson && achat.choix.consommer && createdItemId != undefined) {
achat.choix.doses = achat.choix.nombreLots; achat.choix.doses = achat.choix.nombreLots;
@@ -542,328 +563,331 @@ export class RdDBaseActor extends Actor {
async consommerNourritureboisson(itemId, choix, userId) { } async consommerNourritureboisson(itemId, choix, userId) { }
async decrementerQuantiteItem(item, quantite, options = { supprimerSiZero: true }) { async decrementerQuantiteItem(itemId, quantite, options = { supprimerSiZero: true }) {
const item = this.items.get(itemId)
if (item.isService()) { if (item.isService()) {
return; return
} }
const itemId = item.id;
let resteQuantite = (item.system.quantite ?? 1) - quantite; if (!this.isOwner) {
if (resteQuantite <= 0) { return RdDBaseActor.remoteActorCall({
if (options.supprimerSiZero) { userId: Misc.connectedGMOrUser(),
await this.deleteEmbeddedDocuments("Item", [item.id]); tokenId: this.token?.id,
} actorId: this.id,
else { method: 'decrementerQuantiteItem', args: [itemId, quantite, options]
await this.updateEmbeddedDocuments("Item", [{ _id: itemId, '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) {
const realItem = this.getItem(item.id) const resteQuantite = Math.max((item.system.quantite ?? 1) - quantite, 0)
realItem.update({ 'system.quantite': resteQuantite }); if (resteQuantite <= 0 && options.supprimerSiZero) {
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': resteQuantite }]); await this.deleteEmbeddedDocuments("Item", [itemId]);
}
else {
await this.updateEmbeddedDocuments("Item", [{ _id: itemId, 'system.quantite': resteQuantite }])
} }
} }
async creerQuantiteItem(item, quantite) { async creerQuantiteItem(item, quantite) {
if (this.canReceive(item)) { if (!this.canReceive(item)) {
const isItemEmpilable = "quantite" in item.system; return
const baseItem = {
type: item.type,
img: item.img,
name: item.name,
system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }, { inplace: false })
};
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;
} }
const isItemEmpilable = "quantite" in item.system;
const baseItem = {
type: item.type,
img: item.img,
name: item.name,
system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }, { inplace: false })
}
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
const items = await this.createEmbeddedDocuments("Item", newItems);
return newItems.length > 0 ? items[0].id : undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async computeEncTotal() { async computeEncTotal() {
if (this.pack) { if (this.pack) {
this.encTotal = 0 this.encTotal = 0
}
else {
const wasSurenc = this.isSurenc()
this.encTotal = this.items.filter(it => RdDItem.getItemTypesInventaire().includes(it.type))
.map(it => it.getEncTotal()).reduce(Misc.sum(), 0)
const isSurenc = this.isSurenc()
if (isSurenc != wasSurenc) {
await this.setEffect(STATUSES.StatusSurEnc, isSurenc)
} }
else { }
const wasSurenc = this.isSurenc() }
this.encTotal = this.items.filter(it => RdDItem.getItemTypesInventaire().includes(it.type))
.map(it => it.getEncTotal()).reduce(Misc.sum(), 0) getEncTotal() {
const isSurenc = this.isSurenc() return Number(this.encTotal?.toFixed(2) ?? 0.00)
if (isSurenc != wasSurenc) { }
await this.setEffect(STATUSES.StatusSurEnc, isSurenc)
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 sourceTokenId = params.sourceTokenId
const itemId = params.itemId
const destId = params.destId
const srcId = params.srcId
if (sourceActorId && sourceActorId != targetActorId) {
console.log("Moving objects", sourceActorId, sourceTokenId, targetActorId, itemId);
this.moveItemsBetweenActors(itemId, sourceActorId, sourceTokenId);
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;
}
getEncTotal() { getContenantOrParent(dest) {
return Number(this.encTotal?.toFixed(2) ?? 0.00) if (!dest || dest.isConteneur()) {
return dest;
} }
return this.getContenant(dest);
}
async createItem(type, name = undefined) { getContenant(item) {
if (!name) { return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id));
name = 'Nouveau ' + Misc.typeName('Item', type); }
}
await this.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
/* -------------------------------------------- */
conteneurPeutContenir(dest, moved) {
if (!dest) {
return true;
} }
if (!dest.isConteneur()) {
canReceive(item) { return false;
}
if (moved.isConteneurContenu(dest)) {
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${moved.name}) dans un de ses contenus ${dest.name} !`);
return false; return false;
} }
async processDropItem(params) { // Calculer le total actuel des contenus
const targetActorId = this.id const encContenu = dest.getEncContenu();
const sourceActorId = params.sourceActorId const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet
const sourceTokenId = params.sourceTokenId const placeDisponible = Misc.keepDecimals(dest.system.capacite - encContenu - newEnc, 4)
const itemId = params.itemId
const destId = params.destId
const srcId = params.srcId
if (sourceActorId && sourceActorId != targetActorId) {
console.log("Moving objects", sourceActorId, sourceTokenId, targetActorId, itemId);
this.moveItemsBetweenActors(itemId, sourceActorId, sourceTokenId);
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) { // Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
if (!dest || dest.isConteneur()) { if (placeDisponible < 0) {
return dest; ui.notifications.warn(
} `Le conteneur ${dest.name} a une capacité de ${dest.system.capacite}, et contient déjà ${encContenu}.
return this.getContenant(dest);
}
getContenant(item) {
return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id));
}
/* -------------------------------------------- */
conteneurPeutContenir(dest, moved) {
if (!dest) {
return true;
}
if (!dest.isConteneur()) {
return false;
}
if (moved.isConteneurContenu(dest)) {
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${moved.name}) dans un de ses contenus ${dest.name} !`);
return false;
}
// Calculer le total actuel des contenus
const encContenu = dest.getEncContenu();
const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet
const placeDisponible = Misc.keepDecimals(dest.system.capacite - encContenu - newEnc, 4)
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
if (placeDisponible < 0) {
ui.notifications.warn(
`Le conteneur ${dest.name} a une capacité de ${dest.system.capacite}, et contient déjà ${encContenu}.
Impossible d'y ranger: ${moved.name} d'encombrement ${newEnc}!`); Impossible d'y ranger: ${moved.name} d'encombrement ${newEnc}!`);
return false; return false;
}
return true;
} }
return true;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/** Ajoute un item dans un conteneur, sur la base de leurs ID */ /** Ajoute un item dans un conteneur, sur la base de leurs ID */
async ajouterDansConteneur(item, conteneur, onAjouterDansConteneur) { async ajouterDansConteneur(item, conteneur, onAjouterDansConteneur) {
if (conteneur?.isConteneur()) { if (conteneur?.isConteneur()) {
item.estContenu = true; item.estContenu = true;
const nouveauContenu = [...conteneur.system.contenu, item.id]; const nouveauContenu = [...conteneur.system.contenu, item.id];
await conteneur.update({ 'system.contenu': nouveauContenu }); await conteneur.update({ 'system.contenu': nouveauContenu });
onAjouterDansConteneur(item.id, conteneur.id) onAjouterDansConteneur(item.id, conteneur.id)
}
else {
item.estContenu = false;
await conteneur?.update({ 'system.-=contenu': undefined })
}
} }
else {
item.estContenu = false;
await conteneur?.update({ 'system.-=contenu': undefined })
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */ /** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */
async nettoyerConteneurs() { async nettoyerConteneurs() {
RdDConfirm.confirmer({ RdDConfirm.confirmer({
settingConfirmer: "confirmation-vider", settingConfirmer: "confirmation-vider",
content: `<p>Etes vous certain de vouloir vider tous les conteneurs ?</p>`, content: `<p>Etes vous certain de vouloir vider tous les conteneurs ?</p>`,
title: 'Vider les conteneurs', title: 'Vider les conteneurs',
buttonLabel: 'Vider', buttonLabel: 'Vider',
onAction: async () => { onAction: async () => {
const corrections = []; const corrections = [];
for (let item of this.items) { for (let item of this.items) {
if (item.estContenu) { if (item.estContenu) {
item.estContenu = undefined; item.estContenu = undefined;
}
if (item.system.contenu != undefined) {
if (item.type == 'conteneur') {
corrections.push({ _id: item.id, 'system.contenu': [] });
}
else {
corrections.push({ _id: item.id, 'system.-=contenu': undefined });
}
}
} }
if (corrections.length > 0) { if (item.system.contenu != undefined) {
await this.updateEmbeddedDocuments('Item', corrections); if (item.type == 'conteneur') {
corrections.push({ _id: item.id, 'system.contenu': [] });
}
else {
corrections.push({ _id: item.id, 'system.-=contenu': undefined });
}
} }
} }
}); if (corrections.length > 0) {
} await this.updateEmbeddedDocuments('Item', corrections);
}
}
});
}
/* -------------------------------------------- */ /* -------------------------------------------- */
buildSubConteneurObjetList(conteneurId, deleteList) { buildSubConteneurObjetList(conteneurId, deleteList) {
let conteneur = this.getItem(conteneurId); let conteneur = this.getItem(conteneurId);
if (conteneur?.type == 'conteneur') { // Si c'est un conteneur if (conteneur?.type == 'conteneur') { // Si c'est un conteneur
for (let subId of conteneur.system.contenu) { for (let subId of conteneur.system.contenu) {
let subObj = this.getItem(subId); let subObj = this.getItem(subId);
if (subObj) { if (subObj) {
if (subObj.type == 'conteneur') { if (subObj.type == 'conteneur') {
this.buildSubConteneurObjetList(subId, deleteList); this.buildSubConteneurObjetList(subId, deleteList);
}
deleteList.push({ id: subId, conteneurId: conteneurId });
} }
deleteList.push({ id: subId, conteneurId: conteneurId });
} }
} }
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async deleteAllConteneur(itemId, options) { async deleteAllConteneur(itemId, options) {
let list = []; let list = [];
list.push({ id: itemId, conteneurId: undefined }); // Init list list.push({ id: itemId, conteneurId: undefined }); // Init list
this.buildSubConteneurObjetList(itemId, list); this.buildSubConteneurObjetList(itemId, list);
await this.deleteEmbeddedDocuments('Item', list.map(it => it.id), options); await this.deleteEmbeddedDocuments('Item', list.map(it => it.id), options);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/** /**
* Supprime un item d'un conteneur, sur la base de leurs ID * Supprime un item d'un conteneur, sur la base de leurs ID
*/ */
async enleverDeConteneur(item, conteneur, onEnleverDeConteneur) { async enleverDeConteneur(item, conteneur, onEnleverDeConteneur) {
if (conteneur) { if (conteneur) {
if (conteneur.isConteneur()) { if (conteneur.isConteneur()) {
const contenu = conteneur.system.contenu.filter(id => id != item.id); const contenu = conteneur.system.contenu.filter(id => id != item.id);
await conteneur.update({ 'system.contenu': contenu }); await conteneur.update({ 'system.contenu': contenu });
onEnleverDeConteneur(); onEnleverDeConteneur();
} }
else { else {
await conteneur.update({ 'system.-=contenu': undefined }) await conteneur.update({ 'system.-=contenu': undefined })
}
} }
item.estContenu = false;
} }
item.estContenu = false;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async moveItemsBetweenActors(itemId, sourceActorId, sourceTokenId) { async moveItemsBetweenActors(itemId, sourceActorId, sourceTokenId) {
let sourceActor = RdDBaseActor.getRealActor(sourceActorId, sourceTokenId) let sourceActor = RdDBaseActor.getRealActor(sourceActorId, sourceTokenId)
let itemsList = [{ id: itemId, conteneurId: undefined }] let itemsList = [{ id: itemId, conteneurId: undefined }]
sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list
const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id)) const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id))
.map(it => foundry.utils.duplicate(it)) .map(it => foundry.utils.duplicate(it))
.map(it => { it.system.contenu = []; return it; }); .map(it => { it.system.contenu = []; return it; });
let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate); let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate);
let itemMap = this._buildMapOldNewId(itemsList, newItems); let itemMap = this._buildMapOldNewId(itemsList, newItems);
for (let item of itemsList) { // Second boucle pour traiter la remise en conteneurs for (let item of itemsList) { // Second boucle pour traiter la remise en conteneurs
// gestion conteneur/contenu // gestion conteneur/contenu
if (item.conteneurId) { // l'Objet était dans un conteneur if (item.conteneurId) { // l'Objet était dans un conteneur
const newConteneurId = itemMap[item.conteneurId]; const newConteneurId = itemMap[item.conteneurId];
const newConteneur = this.getItem(newConteneurId); const newConteneur = this.getItem(newConteneurId);
const newItemId = itemMap[item.id]; // Get newItem const newItemId = itemMap[item.id]; // Get newItem
console.log('New conteneur filling!', newConteneur, newItemId, item); console.log('New conteneur filling!', newConteneur, newItemId, item);
const nouveauContenu = [...newConteneur.system.contenu, newItemId] const nouveauContenu = [...newConteneur.system.contenu, newItemId]
await newConteneur.update({ 'system.contenu': nouveauContenu }) await newConteneur.update({ 'system.contenu': nouveauContenu })
}
} }
const deletedItemIds = itemsList.map(it => it.id)
await sourceActor.deleteEmbeddedDocuments('Item', deletedItemIds);
} }
const deletedItemIds = itemsList.map(it => it.id)
await sourceActor.deleteEmbeddedDocuments('Item', deletedItemIds);
}
_buildMapOldNewId(itemsList, newItems) { _buildMapOldNewId(itemsList, newItems) {
let itemMap = {}; let itemMap = {};
for (let i = 0; i < itemsList.length; i++) { for (let i = 0; i < itemsList.length; i++) {
itemMap[itemsList[i].id] = newItems[i].id; // Pour garder le lien ancien / nouveau itemMap[itemsList[i].id] = newItems[i].id; // Pour garder le lien ancien / nouveau
}
return itemMap;
} }
return itemMap;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async postActorToChat(modeOverride) { async postActorToChat(modeOverride) {
let chatData = { let chatData = {
doctype: 'Actor', doctype: 'Actor',
id: this.id, id: this.id,
type: this.type, type: this.type,
img: this.img, img: this.img,
pack: this.pack, pack: this.pack,
name: this.getAlias(), name: this.getAlias(),
system: { description: this.system.description } system: { description: this.system.description }
}
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.hbs', chatData)
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
} }
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.hbs', chatData)
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
}
actionImpossible(action) { actionImpossible(action) {
ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`) ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`)
} }
isAlcoolise() { return false } isAlcoolise() { return false }
async jetEthylisme() { this.actionImpossible("jet d'éthylisme") } async jetEthylisme() { this.actionImpossible("jet d'éthylisme") }
async rollAppelChance() { this.actionImpossible("appel à la chance") } async rollAppelChance() { this.actionImpossible("appel à la chance") }
async jetDeMoral() { this.actionImpossible("jet de moral") } async jetDeMoral() { this.actionImpossible("jet de moral") }
async resetItemUse() { } async resetItemUse() { }
async incDecItemUse(itemId, shouldIncrease = true) { } async incDecItemUse(itemId, shouldIncrease = true) { }
getItemUse(itemId) { return 0; } getItemUse(itemId) { return 0; }
async finDeRound(options = { terminer: false }) { } async finDeRound(options = { terminer: false }) { }
isActorCombat() { return false } isActorCombat() { return false }
getCaracInit(competence) { return 0 } getCaracInit(competence) { return 0 }
listAttaques() { listAttaques() {
return this.listActions({ isAttaque: true, isEquipe: false }) return this.listActions({ isAttaque: true, isEquipe: false })
} }
listActions({ isAttaque = false, isEquipe = false }) { return [] } listActions({ isAttaque = false, isEquipe = false }) { return [] }
listActionsPossessions() { listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession] return this.itemTypes[ITEM_TYPES.possession]
.filter(it => !it.system.possede) .filter(it => !it.system.possede)
.map(p => { .map(p => {
return { return {
label: p.name, label: p.name,
action: 'possession', action: 'possession',
possessionid: p.system.possessionid, possessionid: p.system.possessionid,
} }
}) })
} }
} }
+2 -2
View File
@@ -28,11 +28,11 @@ export class RdDCommerce extends RdDBaseActor {
await super.depenserSols(cout) await super.depenserSols(cout)
} }
async decrementerQuantiteItem(item, quantite) { async decrementerQuantiteItem(itemId, quantite) {
if (this.system.illimite) { if (this.system.illimite) {
return; return;
} }
await super.decrementerQuantiteItem(item, quantite, { supprimerSiZero: false }); await super.decrementerQuantiteItem(itemId, quantite, { supprimerSiZero: false });
} }
calculerPrix(item) { calculerPrix(item) {
+1 -1
View File
@@ -104,7 +104,7 @@ export class Apprecier {
apprecier(callbacks = []) { apprecier(callbacks = []) {
if (this.qualite <= 0) { if (this.qualite <= 0) {
this.raisons.push(`la qualité ${this.qualite} est négative.`) this.raisons.push(`la qualité ${this.qualite} est insuffisante.`)
} }
if (this.qualite <= this.actor.getMoralTotal()) { if (this.qualite <= this.actor.getMoralTotal()) {
this.raisons.push(`la qualité de ${this.qualite} est inférieure au moral de ${this.actor.getMoralTotal()}.`) this.raisons.push(`la qualité de ${this.qualite} est inférieure au moral de ${this.actor.getMoralTotal()}.`)
+4 -4
View File
@@ -8,9 +8,9 @@
<hr> <hr>
<span> <span>
{{#if jetVie.rolled.isSuccess}} {{#if jetVie.rolled.isSuccess}}
{{alias}} a réussi son jet d'éthylisme, il a consommé {{doses}} doses sans effet. {{alias}} a réussi son jet d'éthylisme, {{doses}} doses ont été consommées sans effet.
{{else}} {{else}}
{{alias}} a échoué son jet d'éthylisme, il est maintenant {{nomEthylisme}} ({{ajustementEthylique}}). {{alias}} a échoué son jet d'éthylisme et est maintenant {{nomEthylisme}} ({{ajustementEthylique}}).
{{/if}} {{/if}}
</span> </span>
{{#if jetVie.rolled.isEchec}} {{#if jetVie.rolled.isEchec}}
@@ -19,8 +19,8 @@
{{alias}} perd {{perteEndurance.perte}} points d'endurance. {{#if perteEndurance.perteVie}}<br/>Il tombe inconscient et perd un point de vie.{{/if}} {{alias}} perd {{perteEndurance.perte}} points d'endurance. {{#if perteEndurance.perteVie}}<br/>Il tombe inconscient et perd un point de vie.{{/if}}
{{#if jetMoral}} {{#if jetMoral}}
<br/>Jet de moral {{#if jetMoral.succes}}réussi{{else}}manqué{{/if}} en situation heureuse ({{jetMoral.jet}}/{{jetMoral.difficulte}}). <br/>Jet de moral {{#if jetMoral.succes}}réussi{{else}}manqué{{/if}} en situation heureuse ({{jetMoral.jet}}/{{jetMoral.difficulte}}).
{{#if (gt jetMoral.ajustement 0)}}L'alcool met {{alias}} en joie. Il gagne un point de moral. {{#if (gt jetMoral.ajustement 0)}}L'alcool met en joie {{alias}} qui gagne un point de moral.
{{else if (lt jetMoral.ajustement 0)}}{{alias}} a l'alcool triste. Il perd un point de moral. {{else if (lt jetMoral.ajustement 0)}}{{alias}} a l'alcool triste et perd un point de moral.
{{else}}{{alias}} garde son moral.{{/if}} {{else}}{{alias}} garde son moral.{{/if}}
{{/if}} {{/if}}
</span> </span>