Compare commits

...

27 Commits

Author SHA1 Message Date
49d7c4f71d Merge pull request '12.0.2 - Les pluies d'Astrobazzarh' (#703) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #703
2024-06-14 08:04:23 +02:00
23582984cf Version 12.0.2 - Les pluies d'Astrobazzarh 2024-06-14 00:25:10 +02:00
638459049d Fix: dé draconique et rencontre
Le dé draconique donnait toujours un total de 0
2024-06-14 00:03:06 +02:00
366ca981ca Fix message de log de journaux 2024-06-13 22:46:35 +02:00
c0e54c2369 Fix warning sur test de version 2024-06-13 22:06:23 +02:00
f95f5b2b81 Fix calendrier in v12 2024-06-13 22:00:09 +02:00
d30226cb33 Fix game.users for v12 2024-06-13 21:52:48 +02:00
5cf7dda76c Fix game.users for v12 2024-06-13 21:51:31 +02:00
9bc2593b8c Sync version to v12 2024-06-12 08:21:03 +02:00
efd02b40a9 Merge pull request 'Version 11.2.22 - Le futur d'Akarlikarlikar' (#702) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #702
2024-06-12 08:16:17 +02:00
feb3116c47 Version 11.2.22 2024-06-12 01:02:03 +02:00
91a870ad91 Merge pull request 'Fix User ... lacks permission to update' (#701) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #701
2024-06-11 07:52:59 +02:00
2bbf606f30 Fix User ... lacks permission to update
Correction de l'erreur qui était affichée chez les joueurs lors de
hooks utilisés pour effectuer des modifications sur des
documents:

- ChatMessage, ajout de flags pour l'heure
- Item au sein d'un Actor pour mettre à jour certains éléments
2024-06-11 02:49:18 +02:00
a385b98126 Various fixes for v12 2024-06-07 11:12:00 +02:00
8775df5285 Merge pull request 'Corrections v12' (#700) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #700
2024-06-01 09:11:18 +02:00
a103239288 Passe de vérification mergeObject
Quand mergeObject est utilisé pour retourner une valeur, faire très
attention à ne pas passer un Item/Actor, ou une de ses sous parties
en premier paramètre sans préciser l'option { inplace: false }

Sinon, le premier paramètre subit une mutation!
2024-06-01 01:53:14 +02:00
0b1c5d0a3d Fix again achatVente
- remplacement des données/JSON dans le html par des Flags sur
  le ChatMessage
- extraction de la gestion des infos de ventes pour rassembler la
  génération du ChatMessage
- on ne perd plus la quantité ou le vendeur
- attention au mergeObject: il modifie le premier parametre, ce
  qui modifiait parfois l'acteur (!!!) et toujours la quantité de
  l'objet du vendeur lors de la création de l'objet de l'acheteur!
2024-06-01 01:50:48 +02:00
e19577eab2 Fix for v12 2024-05-31 21:48:19 +02:00
c3b502ff6c Fix V12 Fenêtre de recherche 2024-05-31 21:42:09 +02:00
db2ca2453e Foundry v11/v12 support 2024-05-27 08:53:57 +02:00
915283a674 Merge pull request '11.2.21 - Le questionnement d'Akarlikarlikar' (#699) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #699
2024-05-27 07:17:09 +02:00
621bb4ebc3 Version 11.2.21 2024-05-27 00:57:12 +02:00
26e805cf46 Ajout de la date/heure aux messages 2024-05-27 00:55:18 +02:00
657566fb11 Les effets s'appliquent aux créatures 2024-05-26 22:43:07 +02:00
26e8853a94 Passage v12 2024-05-26 22:16:42 +02:00
4f69d3cf78 Expérience sur rêve et chance actuels
L'expérience en caractéristique sur les jets de
2024-05-26 22:15:10 +02:00
dfe4b47452 Message de confirmation rencontre TMR
Quand un haut-rêvant monte dans les TMR avec une rencontre en attente,
un message est affiché pour demander confirmation
2024-05-26 22:13:47 +02:00
64 changed files with 484 additions and 362 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -1,11 +1,32 @@
# 11.2
## 11.2.20 - Le soulagement d'Akarlikarlikar
# 12.0
- L'option 'ajout de la difficulté d'attaque à l'encaissement est affichée comme un modificateur d'encaissement
- Les options d'encaissement alternative fonctionnent avec la validation du gardien
## 12.0.2 - Les pluies d'Astrobazzarh
- **Support V12**
- correction des actions techniques déleguées au MJ qui bloquaient les fenêtre de lancer de dés des joueurs (et plein d'autres)
- la fenêtre de calendrier s'ouvre correctement
- les dés draconiques peuvent de nouveau faire plus que 0
- adaptation de la fenêtre de recherche
- correction des comparaisons de version pour les migrations automatiques
- correction des roll.eveluate: l'option async est maintenant standard
- correction des templates liés aux selections
- correction de l'ajustement de luminosité de la scène selon l'heure
- correction des images d'effets sur les tokens
- correction de la vente par le tchat: seul le premier acheteur pouvait acheter
- correction d'erreurs intempestives 'User ... lacks permission to update ...'
# 11.2
## 11.2.21 - Le questionnement d'Akarlikarlikar
- Une confirmation spécifique est demandée pour monter dans les terres médianes en cas de rencontre en attente
- L'expérience en caractéristique sur les jets de chance et rêve actuels est mise dans la caractéristique correspondante
- Les effets s'appliquent correctement sur les créatures
- La date et l'heure (draconiques) sont affichées dans les messages du tchat
## 11.2.20 - Le soulagement d'Akarlikarlikar
- L'option "ajout de la difficulté d'attaque à l'encaissement" est affichée comme un modificateur d'encaissement
- Les options d'encaissement alternatives fonctionnent avec la validation de l'encaissement par le gardien
- La fenêtre d'astrologie du gardien affiche toutes les heures lues par un personnage
- Si aucune expérience n'est gagnée, les autres effets à appliquer (comme la récupération de seuil après avoir vaincu un rêve de Dragon) s'appliquent normalement
- Les tooltips de Foundry sont maintenant lisibles
- Les tooltips de Foundry sont lisibles
- On n'accorde plus les entités de cauchemar deux fois quand le gardien valide les encaissements
- Les messages de récupération de rêve en cas de Rêve de Dragon sont clarifiés

4
icons/heures/.directory Normal file
View File

@ -0,0 +1,4 @@
[Dolphin]
Timestamp=2024,5,29,20,57,41.954
Version=4
VisibleRoles=Details_text,Details_size,Details_modificationtime,Details_creationtime,CustomizedDetails

View File

@ -0,0 +1,65 @@
import { SYSTEM_RDD } from "../constants.js";
import { RdDUtility } from "../rdd-utility.js";
const DETAIL_VENTE = 'detailVente';
const NB_LOTS = 'nbLotss';
export class ChatVente {
static getDetailVente(chatMessageId) {
const chatMessage = game.messages.get(chatMessageId)
if (!chatMessage) {
return undefined;
}
const nbLots = chatMessage.getFlag(SYSTEM_RDD, NB_LOTS)
const detail = foundry.utils.duplicate(chatMessage.getFlag(SYSTEM_RDD, DETAIL_VENTE))
if (!detail.item) {
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
return undefined;
}
const vendeur = detail.vendeurId ? game.actors.get(detail.vendeurId) : undefined;
return foundry.utils.mergeObject(detail,
{
alias: vendeur?.name ?? game.user.name,
vendeur,
nbLots: nbLots,
chatMessageIdVente: chatMessageId
})
}
static getDetailAchatVente(chatMessageId) {
const acheteur = RdDUtility.getSelectedActor()
const detail = ChatVente.getDetailVente(chatMessageId)
if (!acheteur && !detail.vendeur) {
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
return undefined;
}
return foundry.utils.mergeObject(detail, { acheteur })
}
static async diminuerQuantiteAchatVente(chatMessageId, quantite) {
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.html', vente);
chatMessage.update({ content: html });
chatMessage.render(true);
}
static async displayAchatVente(vente) {
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html))
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
await chatMessage.setFlag(SYSTEM_RDD, DETAIL_VENTE, {
item: vente.item,
properties: vente.item.getProprietes(),
vendeurId: vente.vendeurId,
tailleLot: vente.tailleLot,
quantiteIllimite: vente.quantiteIllimite,
prixLot: vente.prixLot
})
}
}

View File

@ -1,35 +1,13 @@
import { Misc } from "./misc.js";
import { RdDUtility } from "./rdd-utility.js";
import { Misc } from "../misc.js";
import { RdDUtility } from "../rdd-utility.js";
import { ChatVente } from "./chat-vente.js";
export class DialogItemAchat extends Dialog {
static preparerAchat(chatButton) {
const vendeurId = chatButton.attributes['data-vendeurId']?.value;
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
const acheteur = RdDUtility.getSelectedActor();
const json = chatButton.attributes['data-jsondata']?.value;
if (!acheteur && !vendeur) {
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
return undefined;
}
if (!json) {
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
return undefined;
}
return {
item: JSON.parse(json),
vendeur,
acheteur,
nbLots: parseInt(chatButton.attributes['data-quantiteNbLots']?.value),
tailleLot: parseInt(chatButton.attributes['data-tailleLot']?.value ?? 1),
prixLot: Number(chatButton.attributes['data-prixLot']?.value ?? 0),
quantiteIllimite: chatButton.attributes['data-quantiteIllimite']?.value == 'true',
chatMessageIdVente: RdDUtility.findChatMessageId(chatButton),
};
return ChatVente.getDetailAchatVente(RdDUtility.findChatMessageId(chatButton))
}
static async onAcheter({ item, vendeur, acheteur, tailleLot, prixLot, nbLots, quantiteIllimite, chatMessageIdVente }) {
const venteData = {
item,
@ -38,17 +16,21 @@ export class DialogItemAchat extends Dialog {
acheteur,
tailleLot,
quantiteIllimite,
quantiteNbLots: nbLots,
nbLots,
choix: { seForcer: false, supprimerSiZero: true },
prixLot,
isVente: prixLot > 0,
isConsommable: item.type == 'nourritureboisson' && acheteur?.isPersonnage(),
chatMessageIdVente
};
}
if (venteData.vendeur?.id == venteData.acheteur?.id) {
ui.notifications.info("Inutile de se vendre à soi-même")
return
}
DialogItemAchat.changeNombreLots(venteData, 1);
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
new DialogItemAchat(html, venteData).render(true);
DialogItemAchat.changeNombreLots(venteData, 1)
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData)
new DialogItemAchat(html, venteData).render(true)
}
static changeNombreLots(venteData, nombreLots) {
@ -116,18 +98,18 @@ export class DialogItemAchat extends Dialog {
this.venteData.choix.seForcer = event.currentTarget.checked;
}
setNombreLots(nombreLots) {
setNombreLots(nbLots) {
if (!this.venteData.quantiteIllimite) {
if (!this.venteData.quantiteIllimite && nombreLots > this.venteData.quantiteNbLots) {
ui.notifications.warn(`Seulement ${this.venteData.quantiteNbLots} lots disponibles, vous ne pouvez pas en prendre ${nombreLots}`)
if (!this.venteData.quantiteIllimite && nbLots > this.venteData.nbLots) {
ui.notifications.warn(`Seulement ${this.venteData.nbLots} lots disponibles, vous ne pouvez pas en prendre ${nbLots}`)
}
nombreLots = Math.min(nombreLots, this.venteData.quantiteNbLots);
nbLots = Math.min(nbLots, this.venteData.nbLots);
}
DialogItemAchat.changeNombreLots(this.venteData, nombreLots);
DialogItemAchat.changeNombreLots(this.venteData, nbLots);
this.html.find(".nombreLots").val(nombreLots);
this.html.find(".nombreLots").val(nbLots);
this.html.find(".prixTotal").text(this.venteData.prixTotal);
this.html.find("span.total-sust").text(this.venteData.totalSust);
this.html.find("span.total-desaltere").text(this.venteData.totalDesaltere);

View File

@ -1,29 +1,30 @@
import { HtmlUtility } from "./html-utility.js";
import { HtmlUtility } from "../html-utility.js";
import { RdDUtility } from "../rdd-utility.js";
import { ChatVente } from "./chat-vente.js";
export class DialogItemVente extends Dialog {
static async display({ item, callback, quantiteMax = undefined }) {
static async display({ item, quantiteMax = undefined }) {
const quantite = quantiteMax ?? item.getQuantite() ?? 1;
const isOwned = item.parent;
const venteData = {
item: item,
alias: item.actor?.name ?? game.user.name,
vendeurId: item.actor?.id,
vendeurId: item.actor.id,
prixOrigine: item.calculerPrixCommercant(),
prixUnitaire: item.calculerPrixCommercant(),
prixLot: item.calculerPrixCommercant(),
tailleLot: 1,
quantiteNbLots: quantite,
quantiteMaxLots: quantite,
nbLots: quantite,
maxLots: quantite,
quantiteMax: quantite,
quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !isOwned,
isOwned: isOwned,
};
quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !item.parent,
isOwned: item.parent,
}
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
return new DialogItemVente(venteData, html, callback).render(true);
return new DialogItemVente(venteData, html).render(true);
}
constructor(venteData, html, callback) {
constructor(venteData, html) {
let options = { classes: ["dialogvente"], width: 400, height: 'fit-content', 'z-index': 99999 };
let conf = {
@ -34,7 +35,6 @@ export class DialogItemVente extends Dialog {
};
super(conf, options);
this.callback = callback;
this.venteData = venteData;
}
@ -43,7 +43,7 @@ export class DialogItemVente extends Dialog {
this.html = html;
this.html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
this.html.find(".quantiteNbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
this.html.find(".nbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
this.html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked));
this.html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value)));
@ -52,7 +52,15 @@ export class DialogItemVente extends Dialog {
async onProposer(it) {
this.updateVente(this.getChoixVente());
this.callback(this.venteData);
this.venteData["properties"] = this.venteData.item.getProprietes();
if (this.venteData.isOwned) {
if (this.venteData.nbLots * this.venteData.tailleLot > this.venteData.quantiteMax) {
ui.notifications.warn(`Vous avez ${this.venteData.quantiteMax} ${this.venteData.item.name}, ce n'est pas suffisant pour vendre ${this.venteData.nbLots} de ${this.venteData.tailleLot}`)
return;
}
}
await ChatVente.displayAchatVente(this.venteData)
}
updateVente(update) {
@ -61,7 +69,7 @@ export class DialogItemVente extends Dialog {
getChoixVente() {
return {
quantiteNbLots: Number(this.html.find(".quantiteNbLots").val()),
nbLots: Number(this.html.find(".nbLots").val()),
tailleLot: Number(this.html.find(".tailleLot").val()),
quantiteIllimite: this.html.find(".quantiteIllimite").is(':checked'),
prixLot: Number(this.html.find(".prixLot").val())
@ -77,26 +85,26 @@ export class DialogItemVente extends Dialog {
const maxLots = Math.floor(this.venteData.quantiteMax / tailleLot);
this.updateVente({
tailleLot,
quantiteNbLots: Math.min(maxLots, this.venteData.quantiteNbLots),
quantiteMaxLots: maxLots,
nbLots: Math.min(maxLots, this.venteData.nbLots),
maxLots: maxLots,
prixLot: (tailleLot * this.venteData.prixOrigine).toFixed(2)
});
this.html.find(".prixLot").val(this.venteData.prixLot);
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
this.html.find(".quantiteNbLots").attr("max", this.venteData.quantiteMaxLots)
this.html.find(".nbLots").val(this.venteData.nbLots);
this.html.find(".nbLots").attr("max", this.venteData.maxLots)
}
setNbLots(nbLots) {
this.updateVente({
quantiteNbLots: this.venteData.isOwned ? Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots)) : nbLots
nbLots: this.venteData.isOwned ? Math.max(0, Math.min(nbLots, this.venteData.maxLots)) : nbLots
})
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
this.html.find(".nbLots").val(this.venteData.nbLots);
}
setQuantiteIllimite(checked) {
this.updateVente({ quantiteIllimite: checked })
this.html.find(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles");
HtmlUtility.showControlWhen(this.html.find(".quantiteNbLots"), !this.venteData.quantiteIllimite)
HtmlUtility.showControlWhen(this.html.find(".nbLots"), !this.venteData.quantiteIllimite)
}
}

View File

@ -16,7 +16,6 @@ import { RdDItem } from "./item.js";
import { RdDItemBlessure } from "./item/blessure.js";
import { RdDEmpoignade } from "./rdd-empoignade.js";
import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js";
import { ChatUtility } from "./chat-utility.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js";
/* -------------------------------------------- */
@ -33,22 +32,20 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
width: 550,
showCompNiveauBase: false,
vueArchetype: false,
});
}, { inplace: false });
}
/* -------------------------------------------- */
async getData() {
let formData = await super.getData();
foundry.utils.mergeObject(formData,
{
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
limited: this.actor.limited,
owner: this.actor.isOwner,
biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }),
notes: await TextEditor.enrichHTML(this.actor.system.notes, { async: true }),
});
foundry.utils.mergeObject(formData, {
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
limited: this.actor.limited,
owner: this.actor.isOwner,
biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }),
notes: await TextEditor.enrichHTML(this.actor.system.notes, { async: true }),
});
foundry.utils.mergeObject(formData.calc, {
surenc: this.actor.computeMalusSurEncombrement(),
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
@ -213,7 +210,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
const key = Number(li.data("key") ?? -1);
await this.actor.deleteExperienceLog(0, key + 1);
});
// Boutons spéciaux MJs
// Boutons spéciaux MJs
this.html.find('.forcer-tmr-aleatoire').click(async event => this.actor.reinsertionAleatoire("Action MJ"))
this.html.find('.afficher-tmr').click(async event => this.actor.changeTMRVisible())
}

View File

@ -902,7 +902,7 @@ export class RdDActor extends RdDBaseActorSang {
async ajouterRefoulement(value = 1, refouler) {
let refoulement = this.system.reve.refoulement.value + value;
const roll = new Roll("1d20");
await roll.evaluate({ async: true });
await roll.evaluate();
await roll.toMessage({ flavor: `${this.name} refoule ${refouler} pour ${value} points de refoulement (total: ${refoulement})` });
if (roll.total <= refoulement) {
refoulement = 0;
@ -991,25 +991,31 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
buildTMRInnaccessible() {
const tmrInnaccessibles = this.filterItems(it => Draconique.isCaseTMR(it) &&
EffetsDraconiques.isInnaccessible(it));
return tmrInnaccessibles.map(it => it.system.coord);
return this.items.filter(it => it.type == TYPES.casetmr).filter(it => EffetsDraconiques.isInnaccessible(it)).map(it => it.system.coord)
}
/* -------------------------------------------- */
getTMRRencontres() {
return this.itemTypes['rencontre'];
getRencontresTMR() {
return this.itemTypes[TYPES.rencontre];
}
/* -------------------------------------------- */
async deleteTMRRencontreAtPosition() {
const demiReve = this.getDemiReve()
let rencontreIds = this.items.filter(it => it.type == 'rencontre' && it.system.coord == demiReve).map(it => it.id);
async deleteRencontreTMRAtPosition() {
const rencontreIds = this.itemTypes[TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id)
if (rencontreIds.length > 0) {
await this.deleteEmbeddedDocuments('Item', rencontreIds);
await this.deleteEmbeddedDocuments('Item', rencontreIds)
}
}
getRencontreTMREnAttente() {
return this.itemTypes[TYPES.rencontre].find(this.filterRencontreTMRDemiReve())
}
filterRencontreTMRDemiReve() {
const position = this.getDemiReve()
return it => it.system.coord == position
}
/* -------------------------------------------- */
async addTMRRencontre(currentRencontre) {
const toCreate = currentRencontre.toObject();
@ -1141,6 +1147,7 @@ export class RdDActor extends RdDBaseActorSang {
finalLevel: 0,
diffConditions: 0,
ajustementsForce: CONFIG.RDD.difficultesLibres,
config: game.system.rdd.config
}
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ethylisme.html', rollData);
new RdDRollDialogEthylisme(html, rollData, this, r => this.saouler(r.forceAlcool)).render(true);
@ -2337,7 +2344,7 @@ export class RdDActor extends RdDBaseActorSang {
async _xpCaracDerivee(xpData) {
const caracs = RdDActor._getComposantsCaracDerivee(xpData.caracName)
.map(c => foundry.utils.mergeObject(this.system.carac[c], { isMax: this.isCaracMax(c) }))
.map(c => foundry.utils.mergeObject(this.system.carac[c], { isMax: this.isCaracMax(c) }, { inplace: false }))
switch (caracs.filter(it => !it.isMax).length) {
case 0:
xpData.caracRepartitionManuelle = true;
@ -2353,6 +2360,8 @@ export class RdDActor extends RdDBaseActorSang {
static _getComposantsCaracDerivee(caracName) {
switch (Grammar.toLowerCaseNoAccent(caracName)) {
case 'reve-actuel': case 'reve actuel': return ['reve']
case 'chance-actuelle': case 'chance actuelle': return ['chance']
case 'vie': return ['constitution']
case 'tir': return ['vue', 'dexterite']
case 'lancer': return ['force', 'dexterite', 'vue']
@ -2423,22 +2432,29 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async displayTMR(mode = "normal") {
if (this.tmrApp) {
ui.notifications.warn("Vous êtes déja dans les TMR....");
this.tmrApp.forceTMRDisplay();
ui.notifications.warn("Vous êtes déja dans les TMR....")
this.tmrApp.forceTMRDisplay()
return
}
if (mode != 'visu' && this.getEffect(STATUSES.StatusDemiReve)) {
ui.notifications.warn("Le joueur ou le MJ est déja dans les Terres Médianes avec ce personnage ! Visualisation uniquement");
ui.notifications.warn("Les personnage est déjà dans les Terres Médianes, elles s'affichent en visualisation")
mode = "visu"; // bascule le mode en visu automatiquement
}
RdDConfirm.confirmer({
bypass: mode == 'visu',
settingConfirmer: "confirmation-tmr",
content: `<p>Voulez vous monter dans les TMR en mode ${mode}?</p>`,
title: 'Confirmer la montée dans les TMR',
buttonLabel: 'Monter dans les TMR',
onAction: async () => await this._doDisplayTMR(mode)
});
if (mode == 'visu') {
await this._doDisplayTMR(mode)
}
else {
const rencontre = this.getRencontreTMREnAttente();
const settingConfirmer = rencontre ? "confirmation-tmr-rencontre" : "confirmation-tmr";
const messageRencontre = rencontre ? `<p>Vous devrez combattre ${rencontre.system.genre == 'f' ? 'la' : 'le'} ${rencontre.name} de ${rencontre.system.force} points de Rêve</p>` : '';
RdDConfirm.confirmer({
settingConfirmer: settingConfirmer,
content: `<p>Voulez vous monter dans les TMR en mode ${mode}?</p>` + messageRencontre,
title: 'Confirmer la montée dans les TMR',
buttonLabel: 'Monter dans les TMR',
onAction: async () => await this._doDisplayTMR(mode)
})
}
}
async _doDisplayTMR(mode) {
@ -2610,13 +2626,13 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async resetItemUse() {
await this.unsetFlag(SYSTEM_RDD, 'itemUse');
await this.setFlag(SYSTEM_RDD, 'itemUse', {});
}
/* -------------------------------------------- */
async incDecItemUse(itemId, inc = 1) {
let itemUse = foundry.utils.duplicate(this.getFlag(SYSTEM_RDD, 'itemUse') ?? {});
const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse');
let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {};
itemUse[itemId] = (itemUse[itemId] ?? 0) + inc;
await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse);
console.log("ITEM USE INC", inc, itemUse);
@ -2967,9 +2983,6 @@ export class RdDActor extends RdDBaseActorSang {
}
}
/* -------------------------------------------- */
isEffectAllowed(effectId) { return true }
/* -------------------------------------------- */
async onPreUpdateItem(item, change, options, id) {
if (item.isCompetencePersonnage() && item.system.defaut_carac && item.system.xp) {

View File

@ -180,7 +180,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
}
/* -------------------------------------------- */
isEffectAllowed(effectId) { return true }
isEffectAllowed(effectId) { return false }
getEffects(filter = e => true) {
return this.getEmbeddedCollection("ActiveEffect").filter(filter);
@ -286,12 +286,12 @@ export class RdDBaseActorReve extends RdDBaseActor {
getCarac() {
// TODO: le niveau d'une entité de cauchemar devrait être exclu...
const carac = foundry.utils.mergeObject(foundry.utils.duplicate(this.system.carac),
return foundry.utils.mergeObject(this.system.carac,
{
'reve-actuel': this.getCaracReveActuel(),
'chance-actuelle': this.getCaracChanceActuelle()
});
return carac;
},
{ inplace: false })
}
/* -------------------------------------------- */

View File

@ -269,6 +269,8 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return this.getEffect(STATUSES.StatusStunned);
}
isEffectAllowed(effectId) { return true }
/* -------------------------------------------- */
async computeEtatGeneral() { this.system.compteurs.etat.value = this.malusVie() + this.malusFatigue() + this.malusEthylisme() }
getEtatGeneral(options = { ethylisme: false }) { return this.system.compteurs.etat.value }

View File

@ -20,7 +20,7 @@ export class RdDBaseActorSheet extends ActorSheet {
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
vueDetaillee: false
});
}, { inplace: false })
}
/* -------------------------------------------- */
@ -37,7 +37,9 @@ export class RdDBaseActorSheet extends ActorSheet {
system: this.actor.system,
description: await TextEditor.enrichHTML(this.actor.system.description, { async: true }),
notesmj: await TextEditor.enrichHTML(this.actor.system.notesmj, { async: true }),
options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable)
options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable),
effects: this.actor.effects,
config: game.system.rdd.config
}
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);

View File

@ -1,3 +1,4 @@
import { ChatVente } from "../achat-vente/chat-vente.js";
import { ChatUtility } from "../chat-utility.js";
import { SYSTEM_SOCKET_ID } from "../constants.js";
import { Grammar } from "../grammar.js";
@ -8,7 +9,6 @@ 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 {
@ -16,7 +16,7 @@ export class RdDBaseActor extends Actor {
return Object.entries(carac)
.filter(it => Grammar.equalsInsensitive(it[1].label, name))
.map(it => it[0])
.find(it => it);
.find(it => it)
}
static $findCaracByName(carac, name) {
const caracList = Object.entries(carac);
@ -32,10 +32,10 @@ export class RdDBaseActor extends Actor {
}
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));
Hooks.on("preUpdateItem", (item, change, options, id) => Misc.documentIfResponsible(item.parent)?.onPreUpdateItem(item, change, options, id))
Hooks.on("createItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onCreateItem(item, options, id))
Hooks.on("deleteItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onDeleteItem(item, options, id))
Hooks.on("updateActor", (actor, change, options, actorId) => Misc.documentIfResponsible(actor)?.onUpdateActor(change, options, actorId))
}
static onSocketMessage(sockmsg) {
@ -82,10 +82,6 @@ export class RdDBaseActor extends Actor {
static extractActorMin = (actor) => { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img }; };
static getParentActor(document) {
return document?.parent instanceof Actor ? document.parent : undefined
}
/**
* Cette methode surcharge Actor.create() pour ajouter si besoin des Items par défaut:
* compétences et monnaies.
@ -361,12 +357,9 @@ export class RdDBaseActor extends Actor {
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);
}
await vendeur?.vendre(itemVendu, quantite, cout);
await acheteur?.acheter(itemVendu, quantite, cout, achat)
if (cout > 0) {
RdDAudio.PlayContextAudio("argent");
}
@ -380,24 +373,26 @@ export class RdDBaseActor extends Actor {
});
if (!achat.vente.quantiteIllimite) {
if (achat.vente.quantiteNbLots <= achat.choix.nombreLots) {
if (achat.vente.nbLots <= 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);
await ChatVente.diminuerQuantiteAchatVente(achat.chatMessageIdVente, achat.choix.nombreLots)
}
}
}
async decrementerVente(vendeur, itemVendu, quantite, cout) {
if (vendeur) {
await vendeur.ajouterSols(cout);
await vendeur.decrementerQuantiteItem(itemVendu, quantite);
async vendre(item, quantite, cout) {
await this.ajouterSols(cout);
await this.decrementerQuantiteItem(item, quantite);
}
async acheter(item, quantite, cout, achat) {
await this.depenserSols(cout)
const createdItemId = await this.creerQuantiteItem(item, quantite)
if (achat.choix.consommer && item.type == 'nourritureboisson' && createdItemId != undefined) {
achat.choix.doses = achat.choix.nombreLots;
await this.consommerNourritureboisson(createdItemId, achat.choix, achat.vente.actingUserId);
}
}
@ -410,31 +405,28 @@ export class RdDBaseActor extends Actor {
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 consommerNourritureboisson(itemId, choix, userId) { }
async decrementerQuantiteItem(item, quantite, options = { supprimerSiZero: true }) {
if (item.isService()) {
return;
}
const itemId = item.id;
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 }]);
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)
realItem.update({ 'system.quantite': resteQuantite });
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': resteQuantite }]);
}
}
@ -446,7 +438,7 @@ export class RdDBaseActor extends Actor {
type: item.type,
img: item.img,
name: item.name,
system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined })
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);

View File

@ -1,4 +1,4 @@
import { DialogItemAchat } from "../dialog-item-achat.js";
import { DialogItemAchat } from "../achat-vente/dialog-item-achat.js";
import { RdDItem } from "../item.js";
import { RdDUtility } from "../rdd-utility.js";
import { RdDBaseActorSheet } from "./base-actor-sheet.js";
@ -15,7 +15,7 @@ export class RdDCommerceSheet extends RdDBaseActorSheet {
template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html",
width: 600, height: 720,
tabs: []
});
}, { inplace: false })
}
get title() {
if (this.actor.token && this.actor.token != this.actor.prototypeToken) {

View File

@ -25,8 +25,7 @@ export class RdDCommerce extends RdDBaseActor {
}
await super.depenserSols(cout)
}
async consommerNourritureAchetee(achat, vente, createdItemId) {
async consommerNourritureboisson(itemId, choix, userId) {
// ne pas consommer pour un commerce
}

View File

@ -12,7 +12,7 @@ export class RdDCreatureSheet extends RdDBaseActorSangSheet {
return foundry.utils.mergeObject(RdDBaseActorSangSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html",
width: 640, height: 720
});
}, { inplace: false })
}
/* -------------------------------------------- */

View File

@ -33,10 +33,6 @@ export class RdDCreature extends RdDBaseActorSang {
}
}
isEffectAllowed(effectId) {
return [STATUSES.StatusComma].includes(effectId);
}
isEntiteAccordee(attacker) {
if (this.isEntite([ENTITE_INCARNE])) {
let resonnance = this.system.sante.resonnance

View File

@ -9,7 +9,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html",
width: 640, height: 720,
});
}, { inplace: false })
}
async getData() {

View File

@ -9,7 +9,7 @@ export class RdDActorVehiculeSheet extends RdDBaseActorSheet {
return foundry.utils.mergeObject(RdDBaseActorSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html",
width: 640, height: 720,
});
}, { inplace: false })
}
/* -------------------------------------------- */

View File

@ -1,5 +1,6 @@
import { Misc } from "./misc.js";
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
/**
@ -148,14 +149,13 @@ export class ChatUtility {
}
static async setMessageData(chatMessage, key, flag) {
if (flag) {
await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(flag));
if (flag && chatMessage.isAuthor) {
await chatMessage.setFlag(SYSTEM_RDD, key, flag)
}
}
static getMessageData(chatMessage, key) {
const json = chatMessage.getFlag(SYSTEM_RDD, key);
return json ? JSON.parse(json) : undefined;
return chatMessage.getFlag(SYSTEM_RDD, key);
}
static getChatMessage(event) {
@ -163,4 +163,19 @@ export class ChatUtility {
return game.messages.get(chatMessageId);
}
static async onRenderChatMessage(chatMessage, html, data) {
const rddTimestamp = chatMessage.getFlag(SYSTEM_RDD, 'rdd-timestamp')
if (rddTimestamp) {
const timestamp = new RdDTimestamp(rddTimestamp);
const timestampData = timestamp.toCalendrier();
const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData);
html.find('header.message-header .message-sender').after(dateHeure)
}
}
static async onCreateChatMessage(chatMessage, options, id) {
if (chatMessage.isAuthor) {
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
}
}
}

View File

@ -117,8 +117,8 @@ export class RdDCoeur {
}
ChatUtility.removeChatMessageId(infoCoeur.chatMessageId)
infoCoeur.target.jetTendre = (await (new Roll('1d6').evaluate({ async: true }))).total
infoCoeur.source.jetTendre = (await (new Roll('1d6').evaluate({ async: true }))).total
infoCoeur.target.jetTendre = (await (new Roll('1d6').evaluate())).total
infoCoeur.source.jetTendre = (await (new Roll('1d6').evaluate())).total
const diff = Math.abs(infoCoeur.source.jetTendre - infoCoeur.target.jetTendre)
for (let amoureux of [infoCoeur.source, infoCoeur.target]) {
const actorAmoureux = game.actors.get(amoureux.actor.id);

View File

@ -8,3 +8,46 @@ export const SHOW_DICE = 'show';
export const ENTITE_INCARNE = 'incarne';
export const ENTITE_NONINCARNE = 'nonincarne';
export const ENTITE_BLURETTE = 'blurette';
export const RDD_CONFIG = {
niveauEthylisme : [
{value: "1", label: "Aucun"},
{value: "0", label: "Eméché (0)"},
{value: "-1", label: "Gris (-1)"},
{value: "-2", label: "Pinté (-2)"},
{value: "-3", label: "Pas Frais (-3)"},
{value: "-4", label: "Ivre (-4)"},
{value: "-5", label: "Bu (-5)"},
{value: "-6", label: "Complètement fait (-6)"},
{value: "-7", label: "Ivre mort (-7)"}
],
categorieEntite: {
"cauchemar": "Cauchemar",
"reve": "Rêve"
},
typeEntite: {
"incarne": "Incarnée",
"nonincarne": "Non Incarnée",
"blurette": "Blurette"
},
heuresRdD : [
{value : "vaisseau", label: "Vaisseau", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd01.webp"},
{value : "sirene", label: "Sirène", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd02.webp"},
{value : "faucon", label: "Faucon", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd03.webp"},
{value : "couronne", label: "Couronne", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd04.webp"},
{value : "dragon", label: "Dragon", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd05.webp"},
{value : "epees", label: "Epées", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd06.webp"},
{value : "lyre", label: "Lyre", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd07.webp"},
{value : "serpent", label: "Serpent", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd08.webp"},
{value : "poissonacrobate", label: "Poisson Acrobate", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd09.webp"},
{value : "araignee", label: "Araignée", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd10.webp"},
{value : "roseau", label: "Roseau", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd11.webp"},
{value : "chateaudormant", label: "Chateau Dormant", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd12.webp"}
],
raretes: [
{value: "Commune", label: "Commune"},
{value: "Frequente", label: "Fréquente"},
{value: "Rare", label: "Rare"},
{value: "Rarissime", label: "Rarissime"}
]
}

View File

@ -25,6 +25,7 @@ export class DialogChronologie extends Dialog {
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
timestamp: game.system.rdd.calendrier.timestamp,
config: game.system.rdd.config,
dateReel: game.system.rdd.calendrier.dateReel()
};
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.html", dialogData);

View File

@ -199,7 +199,7 @@ export class RdDItemCompetence extends Item {
if (idOrName == undefined || idOrName == "") {
return RdDItemCompetence.sansCompetence();
}
options = foundry.utils.mergeObject(options, { preFilter: it => it.isCompetence(), description: 'compétence' }, { overwrite: false });
options = foundry.utils.mergeObject(options, { preFilter: it => it.isCompetence(), description: 'compétence' }, { overwrite: false, inplace: false });
return RdDItemCompetence.findFirstItem(list, idOrName, options);
}

View File

@ -33,8 +33,7 @@ export class RdDItemCompetenceCreature extends Item {
if (categorieAttaque != undefined) {
// si c'est un Item compétence: cloner pour ne pas modifier la compétence
let arme = item.clone();
foundry.utils.mergeObject(arme,
{
return foundry.utils.mergeObject(arme, {
action: item.isCompetencePossession() ? 'possession' : 'attaque',
system: {
competence: arme.name,
@ -48,8 +47,7 @@ export class RdDItemCompetenceCreature extends Item {
force: 0,
rapide: true,
}
});
return arme;
}, { inplace: false });
}
return undefined;
}

View File

@ -44,7 +44,7 @@ export class RdDItemSheet extends ItemSheet {
template: RdDItemSheet.defaultTemplate(RdDItemSheet.ITEM_TYPE),
width: 550,
height: 550
});
}, { inplace: false });
}
/* -------------------------------------------- */
@ -108,8 +108,8 @@ export class RdDItemSheet extends ItemSheet {
const competences = await SystemCompendiums.getCompetences('personnage');
formData.categories = this.item.getCategories()
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
formData.caracList = foundry.utils.duplicate(game.system.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.system.model.Actor.personnage.reve.reve)
formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve)
formData.competences = competences;
}
if (this.item.type == 'arme') {

View File

@ -1,4 +1,4 @@
import { DialogItemVente } from "./dialog-item-vente.js";
import { DialogItemVente } from "./achat-vente/dialog-item-vente.js";
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { RdDHerbes } from "./rdd-herbes.js";
@ -177,7 +177,7 @@ export class RdDItem extends Item {
constructor(docData, context = {}) {
if (!context.rdd?.ready) {
mergeObject(context, { rdd: { ready: true } });
foundry.utils.mergeObject(context, { rdd: { ready: true } });
const ItemConstructor = game.system.rdd.itemClasses[docData.type];
if (ItemConstructor) {
if (!docData.img) {
@ -233,7 +233,7 @@ export class RdDItem extends Item {
}
isCompetenceArme() {
return this.isCompetence() && [ 'melee','tir', 'lancer'].includes(this.system.categorie)
return this.isCompetence() && ['melee', 'tir', 'lancer'].includes(this.system.categorie)
}
isCompetencePossession() { return TYPES.competencecreature == this.type && this.system.categorie == "possession" }
@ -538,7 +538,7 @@ export class RdDItem extends Item {
_id: this.id,
'system.quantite': this.system.quantite * sust,
'system.encombrement': Misc.keepDecimals(this.system.encombrement / sust, 2),
'system.cout': Misc.keepDecimals(this.system.cout / sust, 2),
'system.cout': Math.max(0, Misc.keepDecimals(this.system.cout / sust, 2)),
'system.sust': 1
}])
}
@ -621,23 +621,7 @@ export class RdDItem extends Item {
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`);
return;
}
await DialogItemVente.display({
item: this,
quantiteMax,
callback: async (vente) => {
vente["properties"] = this.getProprietes();
if (vente.isOwned) {
if (vente.quantiteNbLots * vente.tailleLot > vente.quantiteMax) {
ui.notifications.warn(`Vous avez ${vente.quantiteMax} ${vente.item.name}, ce n'est pas suffisant pour vendre ${vente.quantiteNbLots} de ${vente.tailleLot}`)
return;
}
}
vente.jsondata = JSON.stringify(vente.item);
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
ChatMessage.create(RdDUtility.chatDataSetup(html));
}
});
await DialogItemVente.display({ item: this, quantiteMax })
}
/* -------------------------------------------- */

View File

@ -39,7 +39,7 @@ export class RdDItemBlessure extends RdDItem {
ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`)
return undefined;
}
return foundry.utils.mergeObject(foundry.utils.duplicate(BASE_TACHE_SOIN_BLESSURE), tache)
return foundry.utils.mergeObject(BASE_TACHE_SOIN_BLESSURE, tache, { inplace: false })
}
static async applyFullBlessure(actor, gravite) {
@ -48,7 +48,7 @@ export class RdDItemBlessure extends RdDItem {
let lostEndurance = 0
let lostVie = 0
if (definition.endurance) {
lostEndurance = new Roll(definition.endurance).roll({async: false}).total;
lostEndurance = await new Roll(definition.endurance).roll().total;
actor.santeIncDec("endurance", -Number(lostEndurance));
}
if (definition.vie) {
@ -106,12 +106,12 @@ export class RdDItemBlessure extends RdDItem {
}
async setSoinsBlessure(systemUpdate = {}) {
systemUpdate = foundry.utils.mergeObject(systemUpdate, this.system, { overwrite: false }),
systemUpdate.soinscomplets.done = systemUpdate.premierssoins.done && systemUpdate.soinscomplets.done
systemUpdate = foundry.utils.mergeObject(systemUpdate, this.system, { overwrite: false })
systemUpdate.soinscomplets.done = systemUpdate.premierssoins.done && systemUpdate.soinscomplets.done
await this.update({
img: this.getImgSoins(systemUpdate.gravite, systemUpdate.soinscomplets.done),
system: systemUpdate
});
})
}
async recuperationBlessure({ actor, timestamp, message, isMaladeEmpoisonne, blessures }) {

View File

@ -10,7 +10,7 @@ export class RdDItemInventaireSheet extends RdDItemSheet {
static get defaultOptions() {
return foundry.utils.mergeObject(RdDItemSheet.defaultOptions, {
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
});
}, { inplace: false })
}
setPosition(options = {}) {
@ -23,9 +23,10 @@ export class RdDItemInventaireSheet extends RdDItemSheet {
async getData() {
const formData = await super.getData();
return foundry.utils.mergeObject(formData, {
foundry.utils.mergeObject(formData, {
milieux: await game.system.rdd.environnement.autresMilieux(this.item)
});
})
return formData
}
activateListeners(html) {

View File

@ -8,7 +8,7 @@ export class RdDRencontreItemSheet extends RdDItemSheet {
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }]
});
}, { inplace: false })
}
/* -------------------------------------------- */
@ -35,7 +35,7 @@ export class RdDRencontreItemSheet extends RdDItemSheet {
select: RdDRencontre.mapEffets(this.item.system.echec.effets)
}
}
});
})
return formData;
}

View File

@ -567,9 +567,9 @@ export class Migrations {
if (currentVersion.startsWith("v")) {
currentVersion = currentVersion.substring(1)
}
if (isNewerVersion(game.system.version, currentVersion)) {
if (foundry.utils.isNewerVersion(game.system.version, currentVersion)) {
// if (true) { /* comment previous and uncomment here to test before upgrade */
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
const migrations = Migrations.getMigrations().filter(m => foundry.utils.isNewerVersion(m.version, currentVersion));
if (migrations.length > 0) {
migrations.sort((a, b) => this.compareVersions(a, b));
migrations.forEach(async (m) => {

View File

@ -166,15 +166,42 @@ export class Misc {
}
static firstConnectedGM() {
return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
if (game.users?.activeGM) {
return game.users.activeGM
}
return game.users.sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
}
static connectedGMs() {
return game.users.filter(u => u.isGM && u.active);
}
static isOwnerPlayer(actor, user = undefined) {
return actor.testUserPermission(user ?? game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER)
/**
* This helper method allows to get the docuument, for a single user (either first connected GM, or the owner
* if there is no connected GMs), or else return undefined.
*
* This allows for example update hooks that should apply modifications to actors to be called only for one
* user (preventing the "User ... lacks permission to update Item" that was occuring on hooks when Item updates
* were triggering other changes)
*
* @param {*} document the Document with is potentially an Actor
* @returns the actor if either the game.user is the first connected GM, or if the game.user is the owner
* and there is no connected GM
*/
static documentIfResponsible(document) {
if (document instanceof Document) {
if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) {
return document
}
}
return undefined
}
static isOwnerPlayerOrUniqueConnectedGM(actor, user = undefined) {
return Misc.isOwnerPlayer(actor, user) ?? Misc.isUniqueConnectedGM();
static isOwnerPlayer(actor) {
return actor.testUserPermission(game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER)
}
static isOwnerPlayerOrUniqueConnectedGM(actor) {
return Misc.isOwnerPlayer(actor) ?? Misc.isUniqueConnectedGM();
}
/**

View File

@ -119,7 +119,7 @@ export class RdDCombatManager extends Combat {
//console.log("Combatat", c);
const roll = combatant.getInitiativeRoll(rollFormula);
if (!roll.total) {
roll.evaluate({ async: false });
await roll.evaluate();
}
const total = Math.max(roll.total, 0.00);
console.log("Compute init for", rollFormula, roll, total, combatant);
@ -128,21 +128,17 @@ export class RdDCombatManager extends Combat {
// Send a chat message
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
let messageData = foundry.utils.mergeObject(
{
speaker: {
scene: canvas.scene._id,
actor: combatant.actor?._id,
token: combatant.token._id,
alias: combatant.token.name,
sound: CONFIG.sounds.dice,
},
flavor: `${combatant.token.name} a fait son jet d'Initiative (${messageOptions.initInfo})
<br>
`,
let messageData = foundry.utils.mergeObject({
speaker: {
scene: canvas.scene._id,
actor: combatant.actor?._id,
token: combatant.token._id,
alias: combatant.token.name,
sound: CONFIG.sounds.dice,
},
messageOptions
);
flavor: `${combatant.token.name} a fait son jet d'Initiative (${messageOptions.initInfo})<br>`,
},
messageOptions);
roll.toMessage(messageData, { rollMode, create: true });
RdDCombatManager.processPremierRoundInit();

View File

@ -4,29 +4,23 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
export class RdDConfirm {
/* -------------------------------------------- */
static confirmer(options, autresActions) {
options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionnelles.isUsing(options.settingConfirmer));
if (options.bypass) {
options.onAction();
let buttons = {
"action": RdDConfirm._createButtonAction(options),
"cancel": RdDConfirm._createButtonCancel()
};
if (options.settingConfirmer) {
buttons = foundry.utils.mergeObject(RdDConfirm._createButtonActionSave(options), buttons);
}
else {
let buttons = {
"action": RdDConfirm._createButtonAction(options),
"cancel": RdDConfirm._createButtonCancel()
};
if (options.settingConfirmer) {
buttons = foundry.utils.mergeObject(RdDConfirm._createButtonActionSave(options), buttons);
}
if (autresActions) {
buttons = foundry.utils.mergeObject(autresActions, buttons);
}
const dialogDetails = {
title: options.title,
content: options.content,
default: "cancel",
buttons: buttons
};
new Dialog(dialogDetails, { width: 150 * Object.keys(buttons).length }).render(true);
if (autresActions) {
buttons = foundry.utils.mergeObject(autresActions, buttons, { inplace: false });
}
const dialogDetails = {
title: options.title,
content: options.content,
default: "cancel",
buttons: buttons
};
new Dialog(dialogDetails, { width: 150 * Object.keys(buttons).length }).render(true);
}
static _createButtonCancel() {

View File

@ -36,8 +36,8 @@ export class DeTMR extends Die {
super(termData);
}
async evaluate() {
super.evaluate();
async evaluate(options) {
await super.evaluate(options);
this.explode("x=8");
return this;
}
@ -73,8 +73,8 @@ export class DeDraconique extends Die {
super(termData);
}
async evaluate() {
super.evaluate();
async evaluate(options) {
await super.evaluate(options);
this.explode("x=7");
return this;
}
@ -138,7 +138,7 @@ export class RdDDice {
static async roll(formula, options = { showDice: SHOW_DICE, rollMode: undefined }) {
const roll = new Roll(RdDDice._formulaOrFake(formula, options));
await roll.evaluate({ async: true });
await roll.evaluate();
await this.showDiceSoNice(roll, options);
return roll;
}
@ -216,7 +216,7 @@ export class RdDDice {
static async fakeD10(faces) {
let roll = new Roll(`1d${faces}`);
await roll.evaluate({ async: true });
await roll.evaluate();
return roll.total;
}

View File

@ -1,4 +1,4 @@
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { SYSTEM_RDD, SYSTEM_SOCKET_ID, RDD_CONFIG } from "./constants.js";
import { Migrations } from './migrations.js';
import { RdDUtility } from "./rdd-utility.js";
@ -108,7 +108,8 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */
async onInit() {
game.system.rdd = this;
this.AppAstrologie = AppAstrologie;
game.system.rdd.config = RDD_CONFIG;
this.AppAstrologie = AppAstrologie;
console.log(`Initializing Reve de Dragon System`);

View File

@ -56,7 +56,7 @@ const temperatures = [
export class RdDMeteo {
static async getForce() {
const roll = new Roll(`1dr`);
await roll.evaluate({ async: true });
await roll.evaluate();
return roll.total;
}
@ -67,14 +67,14 @@ export class RdDMeteo {
static async getTemperature() {
const degre = await RdDMeteo.getForce();
const rollChaudFroid = new Roll('1d2');
await rollChaudFroid.evaluate({ async: true });
await rollChaudFroid.evaluate();
const chaudFroid = rollChaudFroid.total == 1;
return chaudFroid.total ? degre : -degre;
}
static async getDirection(direction) {
const roll = new Roll(`1d16`);
await roll.evaluate({ async: true });
await roll.evaluate();
switch (roll.total % 16) {
case 0: return 'Nord';
case 1: return 'Nord Nord Est';

View File

@ -212,7 +212,7 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
loadRencontres() {
this.rencontresExistantes = this.actor.getTMRRencontres();
this.rencontresExistantes = this.actor.getRencontresTMR();
}
/* -------------------------------------------- */
@ -382,7 +382,7 @@ export class RdDTMRDialog extends Dialog {
async refouler() {
console.log("-> refouler", this.currentRencontre);
await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
await this.actor.deleteRencontreTMRAtPosition()
this.updateTokens();
this.updateValuesDisplay();
this.nettoyerRencontre();
@ -392,7 +392,7 @@ export class RdDTMRDialog extends Dialog {
async ignorerRencontre() {
console.log("-> ignorer", this.currentRencontre);
this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
await this.actor.deleteRencontreTMRAtPosition()
this.updateTokens();
this.updateValuesDisplay();
this.nettoyerRencontre();
@ -446,7 +446,7 @@ export class RdDTMRDialog extends Dialog {
async maitriserRencontre() {
console.log("-> maitriser", this.currentRencontre);
await this.actor.deleteTMRRencontreAtPosition();
await this.actor.deleteRencontreTMRAtPosition()
this.updateTokens();
let rencontreData = {

View File

@ -4,7 +4,7 @@ import { RdDCombat } from "./rdd-combat.js";
import { Misc } from "./misc.js";
import { Grammar } from "./grammar.js";
import { TMRUtility } from "./tmr-utility.js";
import { DialogItemAchat } from "./dialog-item-achat.js";
import { DialogItemAchat } from "./achat-vente/dialog-item-achat.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { RdDDice } from "./rdd-dice.js";
import { RdDItem } from "./item.js";
@ -99,8 +99,9 @@ export class RdDUtility {
static afficheContenu = {}
/* -------------------------------------------- */
static async init() {
Hooks.on("renderChatMessage", async (app, html, msg) => RdDUtility.onRenderChatMessage(app, html, msg));
Hooks.on('renderChatLog', (log, html, chatLog) => RdDUtility.chatListeners(html));
Hooks.on("renderChatMessage", async (app, html, msg) => await ChatUtility.onRenderChatMessage(app, html, msg))
Hooks.on("createChatMessage", async (chatMessage, options, id) => await ChatUtility.onCreateChatMessage(chatMessage, options, id))
Hooks.on('renderChatLog', (log, html, chatLog) => RdDUtility.chatListeners(html))
}
/* -------------------------------------------- */
@ -206,6 +207,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs',
'systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs',
@ -298,6 +300,14 @@ export class RdDUtility {
Handlebars.registerHelper('plusMoins', diff => (diff > 0 ? '+' : '') + Math.round(diff))
Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
// Handle v12 removal of this helper
Handlebars.registerHelper('select', function (selected, options) {
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']');
const html = options.fn(this);
return html.replace(rgx, "$& selected");
});
return loadTemplates(templatePaths);
}
@ -622,7 +632,7 @@ export class RdDUtility {
/* -------------------------------------------- */
static async _evaluatePerte(formula, over20) {
let perte = new Roll(formula, { over20: over20 });
await perte.evaluate({ async: true });
await perte.evaluate();
return perte.total;
}
@ -890,10 +900,4 @@ export class RdDUtility {
}
}
/*-------------------------------------------- */
static async onRenderChatMessage(app, html, msg) {
// TODO
//console.log(app, html, msg);
}
}

View File

@ -26,6 +26,7 @@ const listeReglesOptionnelles = [
{ group: 'Confirmations', name: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-tmr-rencontre', descr: "Confirmer pour monter dans les TMR avec rencontre en attente", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},
@ -70,8 +71,7 @@ export class ReglesOptionnelles extends FormApplication {
}
static get defaultOptions() {
const options = super.defaultOptions;
foundry.utils.mergeObject(options, {
return foundry.utils.mergeObject(super.defaultOptions, {
id: "regles-optionnelles",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.html",
height: 650,
@ -79,8 +79,7 @@ export class ReglesOptionnelles extends FormApplication {
minimizable: false,
closeOnSubmit: true,
title: "Règles optionnelles"
});
return options;
}, { inplace: false })
}
getData() {

View File

@ -18,8 +18,8 @@ const rddStatusEffects = [
{ rdd: true, id: STATUSES.StatusStunned, label: 'EFFECT.StatusStunned', icon: 'icons/svg/stoned.svg', "duration.rounds": 1 },
{ rdd: true, id: STATUSES.StatusBleeding, label: 'EFFECT.StatusBleeding', icon: 'icons/svg/blood.svg' },
{ rdd: true, id: STATUSES.StatusProne, label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg' },
{ rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.svg' },
{ rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.svg' },
{ rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp' },
{ rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp' },
{ rdd: true, id: STATUSES.StatusRestrained, label: 'EFFECT.StatusRestrained', icon: 'icons/svg/net.svg' },
{ rdd: true, id: STATUSES.StatusUnconscious, label: 'EFFECT.StatusUnconscious', icon: 'icons/svg/unconscious.svg' },
{ rdd: true, id: STATUSES.StatusBlind, label: 'EFFECT.StatusBlind', icon: 'icons/svg/blind.svg' },
@ -65,7 +65,7 @@ export class StatusEffects extends FormApplication {
static valeurSurprise(effect, isCombat) {
if (statusSurpriseTotale.intersects(effect.statuses)) {
return 2;
return 2
}
if (statusDemiSurprise.intersects(effect.statuses)) {
return 1
@ -110,7 +110,7 @@ export class StatusEffects extends FormApplication {
static get defaultOptions() {
const options = super.defaultOptions;
mergeObject(options, {
foundry.utils.mergeObject(options, {
id: "status-effects",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/status-effects.html",
height: 800,

View File

@ -152,7 +152,7 @@ export class SystemCompendiums extends FormApplication {
getData() {
const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS)
.map(it => foundry.utils.mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) }));
.map(it => foundry.utils.mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) }, { inplace: false }))
const availableCompendiums = game.packs.map(pack => {
return {
name: pack.collection,
@ -163,7 +163,7 @@ export class SystemCompendiums extends FormApplication {
return foundry.utils.mergeObject(super.getData(), {
systemCompendiums: systemCompendiums,
availableCompendiums: availableCompendiums
});
}, { inplace: false })
}
activateListeners(html) {

View File

@ -25,7 +25,7 @@ export class AppAstrologie extends Application {
classes: ['calendar-astrologie'],
popOut: true,
resizable: false
});
}, { inplace: false })
}
constructor(actor, options = {}) {
@ -49,7 +49,7 @@ export class AppAstrologie extends Application {
signeNaissance: RdDTimestamp.definition(0)
}
})
return this.appData;
return this.appData
}
getActorAstrologie() {

View File

@ -17,7 +17,7 @@ export class AutoAdjustDarkness {
static async adjust(darkness) {
if (AutoAdjustDarkness.isAuto()) {
const scene = game.scenes.viewed;
if (scene?.globalLight && scene?.tokenVision) {
if (scene?.environment?.globalLight?.enabled && scene?.tokenVision) {
await scene.update({ darkness });
}
}

View File

@ -43,7 +43,7 @@ export class RdDCalendrier extends Application {
resizable: false,
width: 'fit-content',
height: 'fit-content',
});
}, { inplace: false })
}
constructor() {

View File

@ -231,6 +231,7 @@ export class RdDTimestamp {
get annee() { return Math.floor(this.indexDate / RDD_JOURS_PAR_AN) }
get mois() { return Math.floor(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
get nomMois() { return Math.floor(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
get jour() { return Misc.modulo(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN), RDD_JOURS_PAR_MOIS) }
get heure() { return Math.floor(this.indexMinute / RDD_MINUTES_PAR_HEURES) }
get minute() { return Misc.modulo(this.indexMinute, RDD_MINUTES_PAR_HEURES) }

View File

@ -125,7 +125,7 @@ export class FenetreRechercheTirage extends Application {
popOut: true,
dragDrop: [{ dragSelector: "a.content-link" }],
resizable: true
});
}, { inplace: false })
}
static async create() {

View File

@ -16,7 +16,7 @@ export class Rencontre extends Draconique {
return pixiTMR.sprite(this.code(), {
zIndex: tmrTokenZIndex.rencontre,
decallage: pixiTMR.sizes.decallage(0, 0),
taille: () => pixiTMR.sizes.twoThird,
taille: () => pixiTMR.sizes.full,
})
}
}

View File

@ -142,18 +142,19 @@ export class DialogFatigueVoyage extends Dialog {
it => this.$extractActor(this.html.find(it))
)
actors.filter(it => it.selected)
.forEach(async it => {
.forEach(async it => {
const perteFatigue = fatigueBase + it.ajustement
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(it.actor.name),
content: await renderTemplate(
'systems/foundryvtt-reve-de-dragon/templates/voyage/chat-fatigue_voyage.hbs', foundry.utils.mergeObject(it,
'systems/foundryvtt-reve-de-dragon/templates/voyage/chat-fatigue_voyage.hbs',
foundry.utils.mergeObject(it,
{
parameters: this.parameters,
fatigueBase: fatigueBase,
perteFatigue: perteFatigue,
isVoyage: fatigueBase == this.parameters.nombreHeures * this.parameters.fatigueHoraire
})
}, { inplace: false })
),
})
await it.actor.santeIncDec("fatigue", perteFatigue)

View File

@ -1527,6 +1527,11 @@ div.control-icon.token-hud-icon {
font-size: 1rem;
}
.chat-message header.message-header .heure-rdd {
font-size: 0.7rem;
flex-grow: 3;
}
.chat-message.whisper {
background: rgba(220,220,210,0.75);
border: 2px solid #545469;

View File

@ -1,13 +1,13 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "11.2.20",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.2.20.zip",
"version": "12.0.2",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.2.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json",
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": {
"minimum": "11",
"verified": "11"
"verified": "12"
},
"description": "Rêve de Dragon RPG for FoundryVTT",
"authors": [

View File

@ -55,9 +55,7 @@
<li class="caracteristique flexrow list-item" data-tooltip="Niveau d'éthylisme">
<label class="derivee-label" for="system.compteurs.ethylisme.value">{{system.compteurs.ethylisme.label}}</label>
<select class="derivee-value" name="system.compteurs.ethylisme.value" data-dtype="Number">
{{#select system.compteurs.ethylisme.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html"}}
{{/select}}
{{selectOptions @root.config.niveauEthylisme selected=system.compteurs.ethylisme.value valueAttr="value" nameAttr="value" labelAttr="label"}}
</select>
</li>

View File

@ -2,20 +2,13 @@
<li class="caracteristique flexrow list-item">
<span class="carac-label" name="catEntite">Catégorie : </span>
<select name="system.definition.categorieentite" value="{{system.definition.categorieentite}}" data-dtype="String" {{#unless @root.options.vueDetaillee}}disabled{{/unless}}>
{{#select system.definition.categorieentite}}
<option value="cauchemar">Cauchemar</option>
<option value="reve">Rêve</option>
{{/select}}
{{selectOptions @root.config.categorieEntite selected=system.definition.categorieentite}}
</select>
</li>
<li class="caracteristique flexrow list-item">
<span class="carac-label" name="typeEntite">Type d'entité : </span>
<select name="system.definition.typeentite" value="{{system.definition.typeentite}}" data-dtype="String" {{#unless @root.options.vueDetaillee}}disabled{{/unless}}>
{{#select system.definition.typeentite}}
<option value="incarne">Incarnée</option>
<option value="nonincarne">Non Incarnée</option>
<option value="blurette">Blurette</option>
{{/select}}
{{selectOptions @root.config.typeEntite selected=system.definition.typeentite}}
</select>
</li>
{{#each system.attributs as |attr key|}}

View File

@ -2,7 +2,7 @@
{{#if effects}}
{{#each effects as |effect key|}}
<span class="active-effect" data-effect="{{effect.id}}">
<img class="button-effect-img {{#if @root.options.isGM}}delete-active-effect{{/if}}" src="{{effect.icon}}" data-tooltip="{{localize effect.name}}" width="24" height="24" />
<img class="button-effect-img {{#if @root.options.isGM}}delete-active-effect{{/if}}" src="{{effect.img}}" data-tooltip="{{localize effect.name}}" width="24" height="24" />
</span>
{{/each}}
{{#if calc.surprise}}<span>{{calc.surprise}}!</span>{{/if}}

View File

@ -1,3 +1,4 @@
{{log 'chat-vente-item' this}}
<div class="post-item" data-transfer="{{transfer}}">
<h3>{{#if alias}}{{alias}} propose: {{else}}Acheter {{/if}}{{item.name}}</h3>
{{#if item.img}}
@ -12,7 +13,7 @@
<hr>
<p>
{{#unless quantiteIllimite}}
<span>Lots disponibles: <span class="quantiteNbLots">{{quantiteNbLots}}</span></span><br>
<span>Lots disponibles: {{nbLots}}</span><br>
{{/unless}}
{{#if (gt tailleLot 1)}}
<span>Lots de: <span class="tailleLot">{{tailleLot}}</span></span><br>
@ -22,15 +23,9 @@
<span class="prixLot">{{numberFormat prixLot decimals=2 sign=false}}</span> Sols</strong></span><br>
{{/if}}
</p>
{{#if (or (gt quantiteNbLots 0) quantiteIllimite)}}
{{#if (or (gt nbLots 0) quantiteIllimite)}}
<span class="chat-card-button-area">
<a class="button-acheter chat-card-button"
data-jsondata='{{jsondata}}'
{{#if vendeurId}}data-vendeurId='{{vendeurId}}'{{/if}}
data-tailleLot="{{tailleLot}}"
data-quantiteNbLots="{{quantiteNbLots}}"
data-quantiteIllimite="{{#if quantiteIllimite}}true{{else}}false{{/if}}"
data-prixLot="{{prixLot}}">
<a class="button-acheter chat-card-button">
{{#if (eq prixLot 0)}}Prendre{{else}}Acheter{{/if}}</a>
</span>
{{/if}}

View File

@ -1,22 +1,20 @@
<span draggable="true">
{{#if pack}}
{{!-- draggable="true" --}}
<a class="content-link"
<span draggable="true">
<a class="{{#if pack}}content-link{{else}}rdd-world-content-link{{/if}}"
data-id="{{id}}"
data-link=""
{{#if doctype}}
data-doctype="{{doctype}}"
data-type="{{doctype}}"
{{/if}}
{{#if pack}}
data-pack="{{pack}}"
data-uuid="Compendium.{{pack}}.{{id}}"
data-pack="{{pack}}"
{{#if doctype}}data-doctype="{{doctype}}"{{/if}}
data-id="{{id}}"
>
{{else}}
<a class="rdd-world-content-link"
{{#if doctype}}data-doctype="{{doctype}}"{{/if}}
data-id="{{id}}"
>
{{/if}}
{{#if img}}
<img class="in-text-img" src="{{img}}" data-tooltip="{{name}}" />
{{else}}
<i class="fas fa-suitcase"></i>
{{/if}}
{{name}}</a>
{{/if}} >
{{#if img}}
<img class="in-text-img" src="{{img}}" data-tooltip="{{name}}" />
{{else}}
<i class="fas fa-suitcase"></i>
{{/if}}
{{name}}
</a>
</span>

View File

@ -0,0 +1,3 @@
<span class="message-metadata heure-rdd">
{{this.jourDuMois}} {{this.mois.label}} - {{timestamp-imgSigne this.heure}}
</span>

View File

@ -2,8 +2,6 @@
<div class="flexrow">
<input type="number" name="{{path}}.nombre" value="{{nombre}}" data-dtype="Number"/>
<select name="{{path}}.unite" data-dtype="String" >
{{#select unite}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-periode.html"}}
{{/select}}
{{selectOptions (timestamp-formulesPeriode) selected=unite labelAttr="label" nameAttr="code" valueAttr="code"}}
</select>
</div>

View File

@ -6,9 +6,7 @@
type="number" data-dtype="Number" min="1" max="28"
name="{{path}}.jourDuMois" value="{{jourDuMois}}" />
<select {{#if disabled}}{{disabled}}{{/if}} name="{{path}}.mois" class="calendar-signe-heure" data-dtype="String">
{{#select mois.key}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-heures.html"}}
{{/select}}
{{selectOptions @root.config.heuresRdD selected=mois.key labelAttr="label" nameAttr="value" valueAttr="value"}}
</select>
{{timestamp-imgSigne mois}}
<input {{#if disabled}}{{disabled}}{{/if}} type="number" class="number-x2" name="{{path}}.annee" value="{{annee}}" data-dtype="Number"/>
@ -17,9 +15,7 @@
<label></label>
<label>heure</label>
<select {{#if disabled}}{{disabled}}{{/if}} name="{{path}}.heure" class="calendar-signe-heure" data-dtype="String">
{{#select heure.key}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-heures.html"}}
{{/select}}
{{selectOptions @root.config.heuresRdD selected=heure.key labelAttr="label" nameAttr="value" valueAttr="value"}}
</select>
{{timestamp-imgSigne heure}}
<input {{#if disabled}}{{disabled}}{{/if}} type="number" class="number-x2" name="{{path}}.minute" value="{{minute}}" data-dtype="Number"/>

View File

@ -31,7 +31,7 @@
<label>{{#if quantiteIllimite}}
pas de limite
{{else}}
{{quantiteNbLots}}
{{nbLots}}
{{/if}}</label>
</div>
<div class="flexrow flex-group-left">
@ -41,7 +41,7 @@
</label>
<div class="flexrow">
<input name="nombreLots" class="nombreLots flex-shrink number-x2" type="number" min="1"
{{#unless quantiteIllimite}} max="{{quantiteNbLots}}" {{/unless}}
{{#unless quantiteIllimite}} max="{{nbLots}}" {{/unless}}
value="{{choix.nombreLots}}"
data-dtype="Number" />
</div>

View File

@ -18,8 +18,8 @@
quantiteIllimite}}checked{{/if}} />
<label class="label-quantiteIllimite flex-shrink">disponibles</label>
{{/unless}}
<input name="quantiteNbLots" class="quantiteNbLots flex-shrink number-x2" type="number" min="1"
max="{{quantiteMaxLots}}" value="{{quantiteNbLots}}" data-dtype="Number" />
<input name="nbLots" class="nbLots flex-shrink number-x2" type="number" min="1"
max="{{maxLots}}" value="{{nbLots}}" data-dtype="Number" />
</div>
</div>
<div class="flexrow flex-group-left">

View File

@ -26,9 +26,7 @@
</label>
<span class="flexrow">
<select name="milieu-{{key}}-rarete" class="environnement-rarete flex-shrink" data-dtype="String">
{{#select env.rarete}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}}
{{/select}}
{{selectOptions config.rarete selected=env.rarete labelAttr="label" valueAttr="value" nameAttr="value"}}
</select>
{{rangePicker name="milieu-{{key}}-frequence" value=env.frequence min=(rarete-getChamp env.rarete 'min') max=(rarete-getChamp env.rarete 'max') step=1}}
<label>[{{rarete-getChamp env.rarete 'min'}}-{{rarete-getChamp env.rarete 'max'}}]</label>

View File

@ -7,7 +7,7 @@
{{else}}
<input class="resource-content select-effect" type="checkbox" name="{{effect.id}}" {{#if effect.active}}checked{{/if}}/>
{{/if}}
<img class="button-effect-img" height="16" width="16" src="{{effect.icon}}" data-tooltip="{{localize effect.name}}" />
<img class="button-effect-img" height="16" width="16" src="{{effect.img}}" data-tooltip="{{localize effect.name}}" />
<label>{{localize effect.name}}</label>
</li>
{{/each}}

View File

@ -3,7 +3,7 @@
{{#each systemCompendiums as |definition key|}}
<li class="flexrow">
<label>{{definition.label}}</label>
<select data-dtype="String" class="system-compendium-setting flex-grow-2" data-compendium="{{definition.compendium}}" >
<select data-dtype="String" class="system-compendium-setting flex-grow-2" data-compendium="{{definition.compendium}}" >
{{#select definition.value}}
{{#each @root.availableCompendiums as |available key|}}
{{#if (eq available.type definition.type)}}

View File

@ -1,19 +1,11 @@
<div>
<label>Conditions</label>
<select name="diffConditions" data-dtype="Number">
{{#select '0'}}
{{#each actorAstrologie.ajustements as |ajustement|}}
<option value={{ajustement}}>{{ajustement}}</option>
{{/each}}
{{/select}}
{{selectOptions actorAstrologie.ajustements selected='0'}}
</select>
<label>&nbsp;&nbsp;Jours</label>
<select name="joursAstrologie" data-dtype="Number">
{{#select ''}}
{{#each dates as |date|}}
<option value={{date.index}}>{{date.label}}</option>
{{/each}}
{{/select}}
{{selectOptions dates selected='' labelAttr='label' valueAttr='index' nameAttr='index'}}
</select>
<label>
&nbsp;&nbsp;Etat Général: {{actorAstrologie.etat}}