Compare commits

..

39 Commits

Author SHA1 Message Date
6b0c7f4d38 Merge Vincent fixes + carquois en double 2022-11-17 10:38:11 +01:00
dd2109735d Merge pull request 'Fix de régressions, stabilisation' (#575) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: public/foundryvtt-reve-de-dragon#575
2022-11-17 10:34:57 +01:00
Vincent Vandemeulebrouck
0b192d66c3 Fix commandes et aides
- corrections de commandes sans paramêtre pour proposer l'aide
- correction de l'aide /tmrr (qui peut lancer des dés différents si les
  compendiums sont changés)
2022-11-17 01:57:36 +01:00
Vincent Vandemeulebrouck
472cbb372e Fix du calcul des données calendrier
- Utilisation de la méthode getDefSigne pour obtenir le détail
du signe de l'heure / du mois

- fix d'une initialisation du mois qui faussait le calendrier
2022-11-17 01:25:50 +01:00
Vincent Vandemeulebrouck
8d2e7fd0c8 Fit content pour dialog chronologie/calendrier
Suppression de l'espace perdu
2022-11-17 01:25:50 +01:00
Vincent Vandemeulebrouck
c8526a2270 Amélioration /tmrr
- support des mauvaises rencontres avec /tmrr Mauvaise
- recherche "intelligente": /tmrr ci pour lancer une rencontre en cité
2022-11-17 01:25:50 +01:00
Vincent Vandemeulebrouck
8b6abcc8bb Suppression bouton default
Pour éviter qu'un dialog ouvert depuis le tchat se valide tout seul
aux ouvertures suivantes
2022-11-17 01:25:50 +01:00
Vincent Vandemeulebrouck
468982b07b Fix décrément qty ChatMessage vente
Régression suite aux fix sur les achat-vente
2022-11-17 01:25:50 +01:00
Vincent Vandemeulebrouck
95179ffff2 Cleanup 2022-11-17 01:25:50 +01:00
Vincent Vandemeulebrouck
884733e54b Suppression de modèle non utlisé
Sans doute rémanensce d'un état intermédiare de l'extraction des
Item rencontres
2022-11-17 01:25:49 +01:00
a2d4b1049e Inc release 2022-11-16 21:48:41 +01:00
3ce3898326 Merge pull request 'Amélioration esthétique' (#574) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: public/foundryvtt-reve-de-dragon#574
2022-11-16 20:59:24 +01:00
Vincent Vandemeulebrouck
32fc0019d5 Compendium d'extraits poétiques
Permet de surcharger le compendium. Un compendium vide permet de
ne plus avoir d'extraits. D'autres textes peuvent être utilisés avec
un compendium personalisé.
2022-11-16 03:00:55 +01:00
Vincent Vandemeulebrouck
f3f928e43f Cleanup 2022-11-16 03:00:55 +01:00
Vincent Vandemeulebrouck
374a0e1846 Fix: Affichage de l'heure plutôt que du code
Dans le message de déclenchement de sorts en réserve
2022-11-16 03:00:55 +01:00
Vincent Vandemeulebrouck
1e5a99e009 Hauteur des fenêtre 'fit-content'
Evite d'avoir tout le temps des tailles mal ajustées
2022-11-16 03:00:55 +01:00
64320fc260 Merge Vincent fixes pour la boisson 2022-11-13 23:16:39 +01:00
ff923ebab2 Merge pull request '10.0.2.1' (#573) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: public/foundryvtt-reve-de-dragon#573
2022-11-13 23:15:44 +01:00
Vincent Vandemeulebrouck
bcd25dd0ed Affichage de dialog en 2 temps
Sinon, la touche entrée est appliqué sur une commande et ferme
le dialogue
2022-11-13 21:57:48 +01:00
Vincent Vandemeulebrouck
ccb6709f5b Fix: Nourriture consommée par le bon user 2022-11-13 21:57:48 +01:00
2fe6b472a2 Upgrade version to 10.2.0 2022-11-10 07:25:42 +01:00
01642ba495 Merge pull request 'Les rencontres sont configurables' (#572) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: public/foundryvtt-reve-de-dragon#572
2022-11-10 07:24:52 +01:00
Vincent Vandemeulebrouck
191d23e903 Nouveaux effets de rencontre
Gain de 1 point de rêve
Perte de (force) points de vie
Gain de 1 point de moral
Perte de 1 point de moral
Gain de (force) xp sort
Perte de 1 point d'endurance
Perte de (force) points d'endurance
Coup de fatigue de 1 point
Coup de fatigue de (force) points
Récupération de 1 point de fatigue
Récupération de (force) points de fatigue
Perte de chance actuelle
Perte de 1 point de chance actuelle
Gain de 1 point de stress
2022-11-10 02:05:16 +01:00
Vincent Vandemeulebrouck
be57a52f61 Suppression du jet de rencontre de test 2022-11-10 00:59:25 +01:00
Vincent Vandemeulebrouck
c2e8621405 Idées de nouvelles rencontres 2022-11-10 00:42:01 +01:00
Vincent Vandemeulebrouck
d3533f5627 Fix description mauvaise rencontre
Le tirage est fait automatiquement
2022-11-10 00:42:01 +01:00
Vincent Vandemeulebrouck
db448028f9 Gestion de la tête Augmentation de seuil 2022-11-10 00:42:01 +01:00
Vincent Vandemeulebrouck
f659a7508a Remplacement progressif rencontres 2022-11-10 00:42:01 +01:00
Vincent Vandemeulebrouck
d20a6a1506 Suppression de setForceRencontre
On pourra se créer des rencontres et les placer sur la feuille du
personnage
2022-11-10 00:42:00 +01:00
Vincent Vandemeulebrouck
d724e9eb17 Affichage des Items rencontres sur Actor 2022-11-10 00:42:00 +01:00
Vincent Vandemeulebrouck
2106e6ebef Table de rencontre sur une TMR
Au lieu de passer le type de TMR, passer la TMR {type,
coordonnées}

Ce qui permettra de créer une rencontre avec les coordonnées
si disponible
2022-11-10 00:42:00 +01:00
Vincent Vandemeulebrouck
dc07b60acf Compendium de rencontres 2022-11-10 00:42:00 +01:00
Vincent Vandemeulebrouck
d77f046a6a Ajout d'Item rencontre
Pour l'instant, pas utilisée. Une rencontre permettra de
définir les différents effets de la rencontre.

Un compendium dédié donnera les rencontres possibles.
2022-11-10 00:41:47 +01:00
Vincent Vandemeulebrouck
73c490a91d Compendiums paramétrables 2022-11-10 00:41:47 +01:00
Vincent Vandemeulebrouck
ce562b6b8a Déplacement des différents settings 2022-11-10 00:41:47 +01:00
Vincent Vandemeulebrouck
9ea4c05199 Compendiums privés par défaut
Pour que le Gardien n'ait pas à configurer tout en privé à la main
2022-11-10 00:41:47 +01:00
Vincent Vandemeulebrouck
e198cb60b1 Cleanup & Reformatage 2022-11-10 00:41:47 +01:00
Vincent Vandemeulebrouck
d183ce505a gitignore dossier "ignored"
Pour stocker des fichiers temporaires/intermédiaires
2022-11-07 00:05:55 +01:00
Vincent Vandemeulebrouck
9d1dec4179 Amélioration de l'apparence de recherche 2022-11-05 18:20:24 +01:00
70 changed files with 2553 additions and 2148 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,5 @@
.vscode/settings.json
.idea
todo.txt
todo.md
/.vscode
/ignored/

View File

@@ -15,7 +15,7 @@
"TypeNombreastral": "Nombre astral",
"TypeTarot": "Carte de tarot",
"TypeCasetmr": "TMR spéciale",
"TypeRencontrestmr": "Rencontre TMR",
"TypeRencontre": "Rencontre TMR",
"TypeMunition": "Munition",
"TypeMonnaie": "Monnaie",
"TypeHerbe": "Herbe ou plante",
@@ -42,7 +42,8 @@
"TypeSouffle": "Souffle de Dragon",
"TypeTete": "Tête de Dragon",
"TypePossession": "Possession",
"TypeSortreserve": "Sort en réserve"
"TypeSortreserve": "Sort en réserve",
"TypeExtraitpoetique": "Extrait poetique"
},
"EFFECT": {
"StatusStunned": "Sonné",

View File

@@ -1,14 +1,9 @@
import { RdDActorSheet } from "./actor-sheet.js";
/**
* Extend the basic ActorSheet with some very simple modifications
* @extends {ActorSheet}
*/
import { RdDUtility } from "./rdd-utility.js";
import { RdDActorSheet } from "./actor-sheet.js";
import { RdDCarac } from "./rdd-carac.js";
/* -------------------------------------------- */
export class RdDActorCreatureSheet extends RdDActorSheet {
/** @override */
@@ -19,7 +14,7 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
width: 640,
height: 720,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }]
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
});
}

View File

@@ -1,6 +1,4 @@
import { RdDActorSheet } from "./actor-sheet.js";
import { HtmlUtility } from "./html-utility.js";
import { RdDUtility } from "./rdd-utility.js";
export class RdDActorEntiteSheet extends RdDActorSheet {
@@ -12,7 +10,7 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
width: 640,
height: 720,
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac"}],
dragDrop: [{dragSelector: ".item-list .item", dropSelector: null}]
dragDrop: [{dragSelector: ".item-list .item", dropSelector: undefined}]
});
}

View File

@@ -1,8 +1,3 @@
/**
* Extend the basic ActorSheet with some very simple modifications
* @extends {ActorSheet}
*/
import { RdDUtility } from "./rdd-utility.js";
import { HtmlUtility } from "./html-utility.js";
import { RdDItemArme } from "./item-arme.js";
@@ -12,12 +7,16 @@ import { Misc } from "./misc.js";
import { RdDCombatManager } from "./rdd-combat.js";
import { RdDCarac } from "./rdd-carac.js";
import { DialogSplitItem } from "./dialog-split-item.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { DialogRepos } from "./dialog-repos.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { STATUSES } from "./status-effects.js";
import { STATUSES } from "./settings/status-effects.js";
/* -------------------------------------------- */
/**
* Extend the basic ActorSheet with some very simple modifications
* @extends {ActorSheet}
*/
export class RdDActorSheet extends ActorSheet {
/** @override */
@@ -28,7 +27,7 @@ export class RdDActorSheet extends ActorSheet {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html",
width: 640,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
showCompNiveauBase: false,
vueDetaillee: false
});
@@ -102,7 +101,6 @@ export class RdDActorSheet extends ActorSheet {
formData.hautreve = {
isDemiReve: this.actor.getEffect(STATUSES.StatusDemiReve),
rencontres: duplicate(formData.system.reve.rencontre.list),
cacheTMR: this.actor.isTMRCache()
}
@@ -171,9 +169,6 @@ export class RdDActorSheet extends ActorSheet {
const item = RdDSheetUtility.getItem(event, this.actor);
item.sheet.render(true);
});
html.find('.rencontre-delete').click(async event => {
this.actor.deleteTMRRencontre(RdDSheetUtility.getItemId(event));
});
html.find('.item-delete').click(async event => {
const li = RdDSheetUtility.getEventElement(event);
const item = this.actor.getObjet(li.data("item-id"));

View File

@@ -1,5 +1,4 @@
import { RdDUtility } from "./rdd-utility.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { RdDActorSheet } from "./actor-sheet.js";
/* -------------------------------------------- */
@@ -15,7 +14,7 @@ export class RdDActorVehiculeSheet extends RdDActorSheet {
width: 640,
height: 720,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }]
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
});
}

View File

@@ -17,12 +17,11 @@ import { RdDAudio } from "./rdd-audio.js";
import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemArme } from "./item-arme.js";
import { RdDAlchimie } from "./rdd-alchimie.js";
import { STATUSES, StatusEffects } from "./status-effects.js";
import { STATUSES, StatusEffects } from "./settings/status-effects.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { TMRRencontres } from "./tmr-rencontres.js";
import { Poetique } from "./poetique.js";
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { Draconique } from "./tmr/draconique.js";
import { RdDCarac } from "./rdd-carac.js";
@@ -30,12 +29,12 @@ import { Monnaie } from "./item-monnaie.js";
import { DialogConsommer } from "./dialog-item-consommer.js";
import { DialogFabriquerPotion } from "./dialog-fabriquer-potion.js";
import { RollDataAjustements } from "./rolldata-ajustements.js";
import { DialogItemAchat } from "./dialog-item-achat.js";
import { RdDItem } from "./item.js";
import { RdDPossession } from "./rdd-possession.js";
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { RdDConfirm } from "./rdd-confirm.js";
import { DialogValidationEncaissement } from "./dialog-validation-encaissement.js";
import { RdDRencontre } from "./item-rencontre.js";
const POSSESSION_SANS_DRACONIC = {
img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp',
@@ -56,6 +55,7 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
static init() {
Hooks.on("preUpdateItem", (item, change, options, id) => RdDActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id));
// TODO: replace with pre-hooks?
Hooks.on("createItem", (item, options, id) => RdDActor.getParentActor(item)?.onCreateItem(item, options, id));
Hooks.on("deleteItem", (item, options, id) => RdDActor.getParentActor(item)?.onDeleteItem(item, options, id));
Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId));
@@ -64,7 +64,7 @@ export class RdDActor extends Actor {
static onSocketMessage(sockmsg) {
switch (sockmsg.msg) {
case "msg_remote_actor_call":
return RdDActor.onRemoteActorCall(sockmsg.data);
return RdDActor.onRemoteActorCall(sockmsg.data, sockmsg.userId);
case "msg_reset_nombre_astral":
console.log("RESET ASTRAL", game.user.character);
game.user.character.resetNombreAstral();
@@ -72,23 +72,26 @@ export class RdDActor extends Actor {
}
}
static remoteActorCall(callData, canExecuteLocally = () => Misc.isUniqueConnectedGM()) {
if (canExecuteLocally()) {
RdDActor.onRemoteActorCall(callData);
static remoteActorCall(callData, userId = undefined) {
userId = userId ?? Misc.firstConnectedGMId();
if (userId == game.user.id) {
RdDActor.onRemoteActorCall(callData, userId);
return false;
}
else {
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_remote_actor_call", data: callData });
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_remote_actor_call", data: callData, userId: userId });
return true;
}
}
static onRemoteActorCall(callData) {
const actor = game.actors.get(callData?.actorId);
if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
const args = callData.args;
console.info(`RdDActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDActor.${callData.method}(`, ...args, ')');
actor[callData.method](...args);
static onRemoteActorCall(callData, userId) {
if (userId == game.user.id) {
const actor = game.actors.get(callData?.actorId);
if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
const args = callData.args;
console.info(`RdDActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDActor.${callData.method}(`, ...args, ')');
actor[callData.method](...args);
}
}
}
@@ -298,7 +301,7 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
getObjet(id) {
return id ? this.items.find(it => it.id == id) : undefined;
return this.getEmbeddedDocument('Item', id);
}
listItemsData(type) {
@@ -756,25 +759,24 @@ export class RdDActor extends Actor {
actor: this,
competence: duplicate(this.getDraconicOuPossession()),
canClose: false,
rencontre: duplicate(TMRRencontres.getRencontre('rdd')),
rencontre: await TMRRencontres.getReveDeDragon(force),
tmr: true,
use: { libre: false, conditions: false },
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.getReveActuel() } }
}
rollData.rencontre.force = force;
rollData.competence.system.defaut_carac = 'reve-actuel';
const dialog = await RdDRoll.create(this, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-reve-de-dragon.html',
options: { height: 400 }
options: { height: 'fit-content' }
},
{
name: 'maitrise',
label: 'Maîtriser le Rêve de Dragon',
callbacks: [
this.createCallbackExperience(),
{ action: async r => this.resultCombatReveDeDragon(r) }
{ action: async r =>
this.resultCombatReveDeDragon(r) }
]
}
);
@@ -783,27 +785,11 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
async resultCombatReveDeDragon(rollData) {
rollData.queues = [];
if (rollData.rolled.isEchec) {
rollData.queues.push(await this.ajouterQueue());
}
if (rollData.rolled.isETotal) {
rollData.queues.push(await this.ajouterQueue());
}
if (rollData.rolled.isSuccess) {
await this.updatePointDeSeuil();
await this.reveActuelIncDec(rollData.rencontre.force);
}
if (rollData.rolled.isPart) {
// TODO: un dialogue pour demander le type de tête?
rollData.tete = true;
}
rollData.poesie = await Poetique.getExtrait();
const result = rollData.rolled.isSuccess
? rollData.rencontre.system.succes
: rollData.rencontre.system.echec;
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, rollData)
});
RdDRencontre.appliquer(result.effets, {}, rollData)
}
/* -------------------------------------------- */
@@ -1540,42 +1526,27 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
getTMRRencontres() {
return this.system.reve.rencontre.list;
return this.itemTypes['rencontre'];
}
/* -------------------------------------------- */
async deleteTMRRencontreAtPosition() {
let rencontres = this.getTMRRencontres();
let newRencontres = rencontres.filter(it => it.coord != this.getDemiReve());
if (newRencontres.length != rencontres.length) {
await this.update({ "system.reve.rencontre.list": newRencontres });
const demiReve = this.getDemiReve()
let rencontreIds = this.items.filter(it => it.type == 'rencontre' && it.system.coord == demiReve).map(it => it.id);
if (rencontreIds.length>0) {
await this.deleteEmbeddedDocuments('Item', rencontreIds);
}
}
/* -------------------------------------------- */
async addTMRRencontre(currentRencontre) {
let rencontres = this.getTMRRencontres();
let newRencontres = rencontres.filter(it => it.coord != this.getDemiReve());
if (newRencontres.length == rencontres.length) {
newRencontres.push(currentRencontre);
await this.update({ "system.reve.rencontre.list": newRencontres });
}
}
/* -------------------------------------------- */
async deleteTMRRencontre(rencontreKey) {
let list = duplicate(this.system.reve.rencontre.list);
let newList = [];
for (let i = 0; i < list.length; i++) {
if (i != rencontreKey)
newList.push(list[i]);
}
await this.update({ "system.reve.rencontre.list": newList });
const toCreate = currentRencontre.toObject();
console.log('actor.addTMRRencontre(', toCreate,')');
this.createEmbeddedDocuments('Item', [toCreate]);
}
/* -------------------------------------------- */
async updateCoordTMR(coord) {
//console.log("UPDATE TMR", coord);
await this.update({ "system.reve.tmrpos.coord": coord });
}
@@ -1586,11 +1557,13 @@ export class RdDActor extends Actor {
}
/* -------------------------------------------- */
async updatePointDeSeuil(value = 1) {
async regainPointDeSeuil() {
const seuil = Misc.toInt(this.system.reve.seuil.value);
const reve = Misc.toInt(this.system.carac.reve.value);
if (seuil < reve) {
await this.setPointsDeSeuil(Math.min(seuil + value, reve));
const seuilMax = Misc.toInt(this.system.carac.reve.value)
+ 2 * EffetsDraconiques.countAugmentationSeuil(this);
if (seuil < seuilMax) {
await this.setPointsDeSeuil(Math.min(seuil + 1, seuilMax));
}
}
@@ -1961,15 +1934,24 @@ export class RdDActor extends Actor {
async consommer(item, choix) {
switch (item.type) {
case 'nourritureboisson':
return await this.consommerNourritureboisson(item, choix);
return await this.consommerNourritureboisson(item.id, choix);
case 'potion':
return await this.consommerPotion(item)
}
}
/* -------------------------------------------- */
async consommerNourritureboisson(item, choix = { doses: 1, seForcer: false, supprimerSiZero: false }) {
async consommerNourritureboisson(itemId, choix = { doses: 1, seForcer: false, supprimerSiZero: false}, userId = undefined) {
if (userId != undefined && userId != game.user.id) {
RdDActor.remoteActorCall({
actorId: this.id,
method: 'consommerNourritureboisson',
args: [itemId, choix, userId]
},
userId)
return;
}
const item = this.getObjet(itemId)
if (item.type != 'nourritureboisson') {
return;
}
@@ -2366,7 +2348,7 @@ export class RdDActor extends Actor {
const dialog = await RdDRoll.create(this, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html',
options: { height: 600 },
options: { height: 'fit-content' },
close: html => { this.currentTMR.maximize() } // Re-display TMR
},
{
@@ -2382,7 +2364,7 @@ export class RdDActor extends Actor {
}
/* -------------------------------------------- */
isRencontreSpeciale() { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective'
isMauvaiseRencontre() { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective'
let addMsg = "";
let rencSpecial = EffetsDraconiques.mauvaiseRencontre(this);
if (rencSpecial) {
@@ -2691,7 +2673,7 @@ export class RdDActor extends Actor {
const dialog = await RdDRoll.create(this, artData,
{
html: `systems/foundryvtt-reve-de-dragon/templates/dialog-roll-${oeuvre.type}.html`,
options: { height: 500, }
options: { height: 'fit-content', }
},
{
name: `jet-${artData.art}`,
@@ -2831,7 +2813,7 @@ export class RdDActor extends Actor {
const dialog = await RdDRoll.create(this, meditationData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html',
options: { height: 575, }
options: { height: 'fit-content', }
},
{
name: 'jet-meditation',
@@ -2908,7 +2890,7 @@ export class RdDActor extends Actor {
const dialog = await RdDRoll.create(this, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-signedraconique.html',
options: { height: 600 },
options: { height: 'fit-content' },
close: html => { this.currentTMR.maximize() } // Re-display TMR
},
{
@@ -3675,13 +3657,9 @@ export class RdDActor extends Actor {
});
return;
}
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined;
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
const messageVente = game.messages.get(achat.chatMessageIdVente);
const html = await messageVente.getHTML();
const button = html.find(".button-acheter")[0];
const vente = DialogItemAchat.venteData(button);
const vente = achat.vente;
const itemId = vente.item._id;
const isItemEmpilable = "quantite" in vente.item.system;
@@ -3721,7 +3699,7 @@ export class RdDActor extends Actor {
let items = await acheteur.createEmbeddedDocuments("Item", listeAchat);
if (achat.choix.consommer && vente.item.type == 'nourritureboisson') {
achat.choix.doses = achat.choix.nombreLots;
await acheteur.consommerNourritureboisson(items[0], achat.choix);
await acheteur.consommerNourritureboisson(items[0].id, achat.choix, vente.actingUserId);
}
}
if (coutDeniers > 0) {
@@ -3744,6 +3722,7 @@ export class RdDActor extends Actor {
vente["properties"] = new RdDItem(vente.item).getProprietes();
vente.quantiteNbLots -= achat.choix.nombreLots;
vente.jsondata = JSON.stringify(vente.item);
const messageVente = game.messages.get(achat.chatMessageIdVente);
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente) });
messageVente.render(true);
}
@@ -3824,7 +3803,7 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */
_buildActorLinksList(links, actorTransformation = it => RdDActor._buildActorData(it)) {
return links.map(link => game.actors.get(link.id))
.filter(it => it != null)
.filter(it => it != undefined)
.map(actorTransformation);
}

View File

@@ -6,7 +6,7 @@ const LATEST_USED_JOURNAL_ID = "chronologie-dernier-journal";
export class DialogChronologie extends Dialog {
static onInit() {
static init() {
game.settings.register(SYSTEM_RDD, LATEST_USED_JOURNAL_ID, {
name: "Dernier article de journal utilisé pour enregistrer la chronologie",
scope: "client",
@@ -27,14 +27,15 @@ export class DialogChronologie extends Dialog {
dateReel: DialogChronologie.getCurrentDateTime()
};
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.html", dialogData);
new DialogChronologie(html).render(true);
const dialog = new DialogChronologie(html);
dialog.render(true);
}
constructor(html) {
const options = {
classes: ["DialogChronologie"],
width: 500,
height: 350,
height: 'fit-content',
'z-index': 99999
};
const conf = {
@@ -42,8 +43,7 @@ export class DialogChronologie extends Dialog {
content: html,
buttons: {
ajout: { label: "Ajouter", callback: it => this.ajouter() },
},
default: "ajout"
}
};
super(conf, options);
}

View File

@@ -22,6 +22,7 @@ export class DialogItemAchat extends Dialog {
const prixLot = Monnaie.arrondiDeniers(button.attributes['data-prixLot']?.value ?? 0);
return {
item: json ? JSON.parse(json) : undefined,
actingUserId: game.user.id,
vendeurId: vendeurId,
vendeur: vendeur,
acheteur: acheteur,
@@ -39,6 +40,7 @@ export class DialogItemAchat extends Dialog {
chatMessageIdVente: RdDUtility.findChatMessageId(button)
};
}
static async onAcheter(venteData) {
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
const dialog = new DialogItemAchat(html, venteData);
@@ -47,12 +49,12 @@ export class DialogItemAchat extends Dialog {
constructor(html, venteData) {
const isConsommable = venteData.item.type == 'nourritureboisson' && venteData.acheteur?.isPersonnage();
let options = { classes: ["dialogachat"], width: 400, height: isConsommable ? 450 : 350, 'z-index': 99999 };
let options = { classes: ["dialogachat"], width: 400, height: 'fit-content', 'z-index': 99999 };
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
const buttons = {};
if (isConsommable) {
buttons["consommer"] = { label: venteData.item.system.boisson ? "Boire" : "Manger", callback: it => { this.onAchatConsommer(); } }
buttons["consommer"] = { label: venteData.item.system.boisson ? "Boire" : "Manger", callback: it => this.onAchatConsommer() }
}
buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
buttons["decliner"] = { label: "Décliner", callback: it => { } };
@@ -76,7 +78,8 @@ export class DialogItemAchat extends Dialog {
acheteurId: this.venteData.acheteur?.id,
prixTotal: this.venteData.prixTotal,
chatMessageIdVente: this.venteData.chatMessageIdVente,
choix: this.venteData.choix
choix: this.venteData.choix,
vente: this.venteData
});
}

View File

@@ -9,7 +9,7 @@ export class DialogConsommer extends Dialog {
}
constructor(actor, item, consommerData, html, onActionItem = async ()=>{}) {
const options = { classes: ["dialogconsommer"], width: 350, height: 450, 'z-index': 99999 };
const options = { classes: ["dialogconsommer"], width: 350, height: 'fit-content', 'z-index': 99999 };
let conf = {
title: consommerData.title,
content: html,

View File

@@ -24,7 +24,7 @@ export class DialogItemVente extends Dialog {
}
constructor(venteData, html, callback) {
let options = { classes: ["dialogvente"], width: 400, height: 300, 'z-index': 99999 };
let options = { classes: ["dialogvente"], width: 400, height: 'fit-content', 'z-index': 99999 };
let conf = {
title: "Proposer",

View File

@@ -3,9 +3,9 @@ import { Misc } from "./misc.js";
export class DialogRepos extends Dialog {
static async create(actor) {
let actorData = actor
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-repos.html", actorData);
new DialogRepos(html, actor).render(true);
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-repos.html", actor);
const dialog = new DialogRepos(html, actor);
dialog.render(true);
}
constructor(html, actor) {

View File

@@ -23,7 +23,7 @@ export class DialogStress extends Dialog {
constructor(dialogData, html) {
const options = { classes: ["DialogStress"],
width: 400,
height: 205+dialogData.actors.length*25,
height: 'fit-content',
'z-index': 99999
};
const conf = {
@@ -31,8 +31,7 @@ export class DialogStress extends Dialog {
content: html,
buttons: {
stress: { label: "Stress !", callback: it => { this.onStress(); } }
},
default: "stress"
}
};
super(conf, options);
this.dialogData = dialogData;

137
module/effets-rencontres.js Normal file
View File

@@ -0,0 +1,137 @@
import { ChatUtility } from "./chat-utility.js";
import { Poetique } from "./poetique.js";
import { RdDDice } from "./rdd-dice.js";
import { TMRUtility } from "./tmr-utility.js";
export class EffetsRencontre {
static messager = async (dialog, context) => {
dialog.setRencontreState('messager', TMRUtility.getTMRPortee(context.tmr.coord, context.rencontre.system.force));
}
static passeur = async (dialog, context) => {
dialog.setRencontreState('passeur', TMRUtility.getTMRPortee(context.tmr.coord, context.rencontre.system.force));
}
static teleportation_typecase = async (dialog, context) => {
dialog.setRencontreState('changeur', TMRUtility.getCasesType(context.tmr.type));
}
static rencontre_persistante = async (dialog, context) => {
dialog.setRencontreState('persistant', []);
}
static reve_plus_force = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, context.rencontre.system.force) }
static reve_plus_1 = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, 1) }
static reve_moins_force = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, -context.rencontre.system.force) }
static reve_moins_1 = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, -1) }
static $reve_plus = async (actor, valeur) => { await actor.reveActuelIncDec(valeur) }
static vie_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
static vie_moins_force = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -context.rencontre.system.force) }
static $vie_plus = async (actor, valeur) => { await actor.santeIncDec("vie", valeur) }
static moral_plus_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, 1) }
static moral_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
static $moral_plus = async (actor, valeur) => { await actor.moralIncDec(valeur) }
static end_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
static end_moins_force = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -context.rencontre.system.force) }
static $end_plus = async (actor, valeur) => { await actor.santeIncDec("endurance", valeur) }
static fatigue_plus_1 = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, 1) }
static fatigue_plus_force = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, context.rencontre.system.force) }
static fatigue_moins_1 = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, -1) }
static fatigue_moins_force = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, -context.rencontre.system.force) }
static $fatigue_plus = async (actor, valeur) => { await actor.santeIncDec("fatigue", valeur) }
static perte_chance = async (dialog, context) => {
const perte = context.rolled.isETotal ? context.rencontre.system.force : 1;
await context.actor.chanceActuelleIncDec("fatigue", -perte);
}
static xp_sort_force = async (dialog, context) => {
let competence = context.competence;
if (competence) {
const xpSort = Misc.toInt(competence.system.xp_sort) + context.rencontre.system.force;
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': xpSort }]);
await this.updateExperienceLog("XP Sort", xpSort, `Rencontre d'un ${context.rencontre.name} en TMR`);
}
}
static stress_plus_1 = async (dialog, context) => {
await context.actor.addCompteurValue('stress', 1, `Rencontre d'un ${context.rencontre.name} en TMR`);
}
static reinsertion = async (dialog, context) => {
await EffetsRencontre.$reinsertion(dialog, context.actor, it => true)
}
static teleportation_aleatoire_typecase = async (dialog, context) => {
await EffetsRencontre.$reinsertion(dialog, context.actor, it => it.type == context.tmr.type && it.coord != context.tmr.coord)
}
static demireve_rompu = async (dialog, context) => {
dialog.close()
}
static sort_aleatoire = async (dialog, context) => {
context.sortReserve = await RdDDice.rollOneOf(context.actor.itemTypes['sortreserve']);
if (context.sortReserve) {
context.newTMR = TMRUtility.getTMR(context.sortReserve.system.coord);
await dialog.positionnerDemiReve(context.newTMR.coord);
await dialog.processSortReserve(context.sortReserve);
dialog.close();
}
else {
await EffetsRencontre.$reinsertion(dialog, context.actor, it => true);
}
}
static deplacement_aleatoire = async (dialog, context) => {
const oldCoord = context.actor.system.reve.tmrpos.coord;
const newTmr = await TMRUtility.deplaceTMRAleatoire(context.actor, oldCoord);
await dialog.positionnerDemiReve(newTmr.coord)
}
static rdd_part_tete = async (dialog, context) => {
mergeObject(context, {
tete: context.rolled.isPart,
poesie: await Poetique.getExtrait()
})
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(context.actor.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, context)
});
}
static rdd_echec_queue = async (dialog, context) => {
mergeObject(context, {
queues: [await context.actor.ajouterQueue()],
poesie: await Poetique.getExtrait()
})
if (context.rolled.isETotal) {
context.queues.push(await context.actor.ajouterQueue());
}
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, context)
});
}
static experience_particuliere = async (dialog, context) => {
await context.actor.appliquerAjoutExperience(context)
}
static regain_seuil = async (dialog, context) => {
await context.actor.regainPointDeSeuil()
}
static async $reinsertion(dialog, actor, filter) {
const newTMR = await TMRUtility.getTMRAleatoire(filter);
await actor.forcerPositionTMRInconnue(newTMR);
await dialog.positionnerDemiReve(newTMR.coord);
}
}

View File

@@ -72,19 +72,19 @@ export class Monnaie {
let parValeur = Misc.classifyFirst(monnaies, it => it.system.valeur_deniers);
for (let valeur of [1000, 100, 10, 1]) {
const itemPiece = parValeur[valeur];
const piecesDeCetteValeur = Math.floor(reste / valeur);
if (itemPiece) {
if (piecesDeCetteValeur != itemPiece.system.quantite) {
updates.push({ _id: parValeur[valeur].id, 'system.quantite': piecesDeCetteValeur });
const quantite = Math.floor(reste / valeur);
if (quantite != itemPiece.system.quantite) {
updates.push({ _id: parValeur[valeur].id, 'system.quantite': quantite });
}
reste -= piecesDeCetteValeur*valeur;
reste -= quantite*valeur;
}
}
console.log('Monnaie.optimiser', actor.name, 'total', fortune, 'parValeur', parValeur, 'updates', updates, 'reste', reste);
if (updates.length > 0) {
await actor.updateEmbeddedDocuments('Item', updates);
}
if (reste>0){
if (reste > 0){
// créer le reste en deniers fortune en deniers
await Monnaie.creerMonnaiesDeniers(actor, reste);
}

View File

@@ -0,0 +1,108 @@
import { RdDRencontre } from "./item-rencontre.js";
/**
* Item sheet pour configurer les rencontres
* @extends {ItemSheet}
*/
export class RdDRencontreItemSheet extends ItemSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["rdd", "sheet", "item"],
template: "systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html",
width: 500,
height: 500,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }]
});
}
/* -------------------------------------------- */
_getHeaderButtons() {
let buttons = super._getHeaderButtons();
buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => this.item.postItem() });
return buttons;
}
/* -------------------------------------------- */
/** @override */
setPosition(options = {}) {
const position = super.setPosition(options);
const sheetHeader = this.element.find(".sheet-header");
const sheetBody = this.element.find(".sheet-body");
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
return position;
}
/* -------------------------------------------- */
async getData() {
const formData = duplicate(this.item);
mergeObject(formData, {
title: formData.name,
isGM: game.user.isGM,
owner: this.actor?.isOwner,
isOwned: this.actor ? true : false,
actorId: this.actor?.id,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
effets: {
succes: {
liste: RdDRencontre.getEffetsSucces(),
select: RdDRencontre.mapEffets(this.item.system.succes.effets)
},
echec: {
liste: RdDRencontre.getEffetsEchec(),
select: RdDRencontre.mapEffets(this.item.system.echec.effets)
}
}
});
return formData;
}
/* -------------------------------------------- */
/** @override */
activateListeners(html) {
super.activateListeners(html);
if (!this.options.editable) return;
html.find("a.effet-add").click(event => this.onAddEffet(event));
html.find("a.effet-delete").click(event => this.onDeleteEffet(event));
}
async onAddEffet(event) {
const resultat = $(event.currentTarget)?.data("effet-resultat");
const keyEffets = `system.${resultat}.effets`;
const code = $(event.currentTarget)?.data("effet-code");
const liste = RdDRencontre.getListeEffets(this.item, resultat);
liste.push(code);
await this._updateEffetsRencontre(keyEffets, liste);
}
async onDeleteEffet(event) {
const resultat = $(event.currentTarget)?.data("effet-resultat");
const keyEffets = `system.${resultat}.effets`;
const pos = $(event.currentTarget)?.data("effet-pos");
const liste = RdDRencontre.getListeEffets(this.item, resultat);
liste.splice(pos, 1);
await this._updateEffetsRencontre(keyEffets, liste);
}
async _updateEffetsRencontre(key, liste) {
const updates = {};
updates[key] = liste;
this.item.update(updates);
}
get template() {
/* -------------------------------------------- */
return `systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html`;
}
get title() {
return `Rencontre: ${this.object.name}`;
}
}

71
module/item-rencontre.js Normal file
View File

@@ -0,0 +1,71 @@
import { EffetsRencontre } from "./effets-rencontres.js";
const tableEffets = [
{ code: "messager", resultat: "succes", description: "Envoie un message à (force) cases", method: EffetsRencontre.messager },
{ code: "passeur", resultat: "succes", description: "Déplacer le demi-rêve à (force) cases", method: EffetsRencontre.passeur},
{ code: "reve+f", resultat: "succes", description: "Gain de (force) points de rêve" , method: EffetsRencontre.reve_plus_force},
{ code: "teleport", resultat: "succes", description: "Déplacer le demi-rêve (même type)", method: EffetsRencontre.teleportation_typecase },
{ code: "part+tete", resultat: "succes", description: "Tête de dragon sur réussite particulière", method: EffetsRencontre.rdd_part_tete },
{ code: "part+xp", resultat: "succes", description: "Expérience sur réussite particulière", method: EffetsRencontre.experience_particuliere },
{ code: "seuil", resultat: "succes", description: "Récupération de seuil de rêve", method: EffetsRencontre.regain_seuil },
{ code: "reve-1", resultat: "echec", description: "Perte de 1 point de rêve", method: EffetsRencontre.reve_moins_1 },
{ code: "reve-f", resultat: "echec", description: "Perte de (force) points de rêve", method: EffetsRencontre.reve_moins_force },
{ code: "vie-1", resultat: "echec", description: "Perte de 1 point de vie", method: EffetsRencontre.vie_moins_1 },
{ code: "reinsere", resultat: "echec", description: "Réinsertion aléatoire", method: EffetsRencontre.reinsertion },
{ code: "persistant", resultat: "echec", description: "Bloque le demi-rêve", method: EffetsRencontre.rencontre_persistante },
{ code: "teleport-aleatoire", resultat: "echec", description: "Déplacement aléatoire (même type)", method: EffetsRencontre.teleportation_aleatoire_typecase },
{ code: "aleatoire", resultat: "echec", description: "Déplacement aléatoire", method: EffetsRencontre.deplacement_aleatoire },
{ code: "sort-aleatoire", resultat: "echec", description: "Déclenche un sort en réserve aléatoire", method: EffetsRencontre.sort_aleatoire },
{ code: "rompu", resultat: "echec", description: "Demi-rêve interrompu", method: EffetsRencontre.demireve_rompu },
{ code: "echec-queue", resultat: "echec", description: "Queue(s) de dragon sur échec", method: EffetsRencontre.rdd_echec_queue },
{ code: "reve+1", resultat: "succes", description: "Gain de 1 point de rêve", method: EffetsRencontre.reve_plus_1 },
{ code: "vie-f", resultat: "echec", description: "Perte de (force) points de vie", method: EffetsRencontre.vie_moins_force },
{ code: "moral+1", resultat: "succes", description: "Gain de 1 point de moral", method: EffetsRencontre.moral_plus_1 },
{ code: "moral-1", resultat: "echec", description: "Perte de 1 point de moral", method: EffetsRencontre.moral_moins_1 },
{ code: "xpsort+f", resultat: "succes", description: "Gain de (force) xp sort", method: EffetsRencontre.xp_sort_force },
{ code: "endurance-1", resultat: "echec", description: "Perte de 1 point d'endurance", method: EffetsRencontre.end_moins_1 },
{ code: "endurance-f", resultat: "echec", description: "Perte de (force) points d'endurance", method: EffetsRencontre.end_moins_force },
{ code: "fatigue+1", resultat: "echec", description: "Coup de fatigue de 1 point", method: EffetsRencontre.fatigue_plus_1},
{ code: "fatigue+f", resultat: "echec", description: "Coup de fatigue de 1 (force) points", method: EffetsRencontre.fatigue_plus_force },
{ code: "fatigue-1", resultat: "succes", description: "Récupération de 1 point de fatigue", method: EffetsRencontre.fatigue_moins_1},
{ code: "fatigue-f", resultat: "succes", description: "Récupération de 1 (force) points de fatigue", method: EffetsRencontre.fatigue_moins_force },
{ code: "perte-chance", resultat: "echec", description: "Perte de chance actuelle", method: EffetsRencontre.perte_chance },
{ code: "stress+1", resultat: "succes", description: "Gain de 1 point de stress", method: EffetsRencontre.stress_plus_1 },
// { code: "epart-souffle", resultat: "echec", description: "Souffle de dragon sur échec particulier" },
];
export class RdDRencontre {
static getEffetsSucces() { return RdDRencontre.getEffets("succes"); }
static getEffetsEchec() { return RdDRencontre.getEffets("echec"); }
static getEffets(resultat) {
return tableEffets.filter(e => resultat == e.resultat);
}
static mapEffets(liste) {
return liste.map(it => RdDRencontre.getEffet(it));
}
static getListeEffets(item, reussite) {
if (reussite == 'echec') {
return [...item.system.echec.effets];
}
if (reussite == 'succes') {
return [...item.system.succes.effets];
}
return [];
}
static getEffet(code) {
return tableEffets.find(it => code == it.code)
}
static async appliquer(codes, tmrDialog, rencData) {
for(const effet of RdDRencontre.mapEffets(codes)){
await effet.method(tmrDialog, rencData);
}
}
}

View File

@@ -4,9 +4,8 @@ import { RdDAlchimie } from "./rdd-alchimie.js";
import { RdDItemCompetence } from "./item-competence.js";
import { RdDHerbes } from "./rdd-herbes.js";
import { RdDGemme } from "./rdd-gemme.js";
import { Misc } from "./misc.js";
import { HtmlUtility } from "./html-utility.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { SYSTEM_RDD } from "./constants.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
@@ -67,8 +66,6 @@ export class RdDItemSheet extends ItemSheet {
img: this.item.img,
name: this.item.name,
system: this.item.system,
// TODO: v10 remove
data: this.item.system,
isGM: game.user.isGM,
actorId: this.actor?.id,
owner: this.item.isOwner,
@@ -99,14 +96,18 @@ export class RdDItemSheet extends ItemSheet {
formData.competences = await RdDUtility.loadItems(it => RdDItemCompetence.isDraconic(it), RdDItemCompetence.actorCompendium(this.actor?.type))
}
if (this.item.type == 'recettecuisine') {
formData.ingredients = await TextEditor.enrichHTML(this.object.system.ingredients, {async: true})
formData.ingredients = await TextEditor.enrichHTML(this.object.system.ingredients, {async: true})
}
if (this.item.type == 'extraitpoetique') {
formData.extrait = await TextEditor.enrichHTML(this.object.system.extrait, {async: true})
formData.texte = await TextEditor.enrichHTML(this.object.system.texte, {async: true})
}
if (this.item.type == 'recettealchimique') {
RdDAlchimie.processManipulation(this.item, this.actor && this.actor.id);
formData.manipulation_update = await TextEditor.enrichHTML(this.object.system.manipulation_update, {async: true})
formData.utilisation = await TextEditor.enrichHTML(this.object.system.utilisation, {async: true})
formData.enchantement = await TextEditor.enrichHTML(this.object.system.enchantement, {async: true})
formData.sureffet = await TextEditor.enrichHTML(this.object.system.sureffet, {async: true})
formData.manipulation_update = await TextEditor.enrichHTML(this.object.system.manipulation_update, {async: true})
formData.utilisation = await TextEditor.enrichHTML(this.object.system.utilisation, {async: true})
formData.enchantement = await TextEditor.enrichHTML(this.object.system.enchantement, {async: true})
formData.sureffet = await TextEditor.enrichHTML(this.object.system.sureffet, {async: true})
}
if (this.item.type == 'gemme') {
formData.gemmeTypeList = RdDGemme.getGemmeTypeOptionList();

View File

@@ -1,7 +1,6 @@
import { SYSTEM_RDD } from "./constants.js";
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
import { Misc } from "./misc.js";
import { TMRType, TMRUtility } from "./tmr-utility.js";
import { TMRUtility } from "./tmr-utility.js";
/**
* Item sheet pour signes draconiques

View File

@@ -18,7 +18,7 @@ const typesObjetsEquipement = [
"potion",
]
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve"]
const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"]
const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"]
const typesObjetsEffet = ["possession", "poison", "maladie"]
const typesObjetsCompetence = ["competence", "competencecreature"]
@@ -38,6 +38,7 @@ export const defaultItemImg = {
ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp",
livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp",
potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp",
rencontre: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp",
queue: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
ombre: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp",
@@ -57,6 +58,7 @@ export const defaultItemImg = {
gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp",
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
}
/* -------------------------------------------- */
@@ -301,8 +303,7 @@ export class RdDItem extends Item {
async postItem(modeOverride) {
console.log(this);
let chatData = duplicate(this);
const properties = this.getProprietes();
chatData["properties"] = properties
chatData["properties"] = this.getProprietes();
if (this.actor) {
chatData.actor = { id: this.actor.id };
}
@@ -325,254 +326,218 @@ export class RdDItem extends Item {
/* -------------------------------------------- */
_objetChatData() {
const tplData = this.system
let properties = [].concat(
RdDItem.propertyIfDefined('Résistance', tplData.resistance, tplData.resistance),
RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
RdDItem.propertyIfDefined('Encombrement', tplData.encombrement),
return [].concat(
RdDItem.propertyIfDefined('Résistance', this.system.resistance, this.system.resistance),
RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite),
RdDItem.propertyIfDefined('Encombrement', this.system.encombrement),
);
return properties;
}
/* -------------------------------------------- */
_nourritureboissonChatData() {
const tplData = this.system
let properties = [].concat(
RdDItem.propertyIfDefined('Sustentation', tplData.sust, tplData.sust > 0),
RdDItem.propertyIfDefined('Désaltère', tplData.desaltere, tplData.boisson),
RdDItem.propertyIfDefined('Force alcool', tplData.force, tplData.boisson && tplData.alcoolise),
RdDItem.propertyIfDefined('Exotisme', tplData.exotisme, tplData.exotisme < 0),
RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
RdDItem.propertyIfDefined('Encombrement', tplData.encombrement),
return [].concat(
RdDItem.propertyIfDefined('Sustentation', this.system.sust, this.system.sust > 0),
RdDItem.propertyIfDefined('Désaltère', this.system.desaltere, this.system.boisson),
RdDItem.propertyIfDefined('Force alcool', this.system.force, this.system.boisson && this.system.alcoolise),
RdDItem.propertyIfDefined('Exotisme', this.system.exotisme, this.system.exotisme < 0),
RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite),
RdDItem.propertyIfDefined('Encombrement', this.system.encombrement),
);
return properties;
}
/* -------------------------------------------- */
_armeChatData() {
const tplData = this.system
let properties = [
`<b>Compétence</b>: ${tplData.competence}`,
`<b>Dommages</b>: ${tplData.dommages}`,
`<b>Force minimum</b>: ${tplData.force}`,
`<b>Resistance</b>: ${tplData.resistance}`,
`<b>Encombrement</b>: ${tplData.encombrement}`
return [
`<b>Compétence</b>: ${this.system.competence}`,
`<b>Dommages</b>: ${this.system.dommages}`,
`<b>Force minimum</b>: ${this.system.force}`,
`<b>Resistance</b>: ${this.system.resistance}`,
`<b>Encombrement</b>: ${this.system.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_conteneurChatData() {
const tplData = this.system
let properties = [
`<b>Capacité</b>: ${tplData.capacite} Enc.`,
`<b>Encombrement</b>: ${tplData.encombrement}`
return [
`<b>Capacité</b>: ${this.system.capacite} Enc.`,
`<b>Encombrement</b>: ${this.system.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_munitionChatData() {
const tplData = this.system
let properties = [
`<b>Encombrement</b>: ${tplData.encombrement}`
return [
`<b>Encombrement</b>: ${this.system.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_armureChatData() {
const tplData = this.system
let properties = [
`<b>Protection</b>: ${tplData.protection}`,
`<b>Détérioration</b>: ${tplData.deterioration}`,
`<b>Malus armure</b>: ${tplData.malus}`,
`<b>Encombrement</b>: ${tplData.encombrement}`
return [
`<b>Protection</b>: ${this.system.protection}`,
`<b>Détérioration</b>: ${this.system.deterioration}`,
`<b>Malus armure</b>: ${this.system.malus}`,
`<b>Encombrement</b>: ${this.system.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_competenceChatData() {
const tplData = this.system
let properties = [
`<b>Catégorie</b>: ${tplData.categorie}`,
`<b>Niveau</b>: ${tplData.niveau}`,
`<b>Caractéristique par défaut</b>: ${tplData.carac_defaut}`,
`<b>XP</b>: ${tplData.xp}`
return [
`<b>Catégorie</b>: ${this.system.categorie}`,
`<b>Niveau</b>: ${this.system.niveau}`,
`<b>Caractéristique par défaut</b>: ${this.system.carac_defaut}`,
`<b>XP</b>: ${this.system.xp}`
]
return properties;
}
/* -------------------------------------------- */
_competencecreatureChatData() {
const tplData = this.system
let properties = [
`<b>Catégorie</b>: ${tplData.categorie}`,
`<b>Niveau</b>: ${tplData.niveau}`,
`<b>Caractéristique</b>: ${tplData.carac_value}`,
`<b>XP</b>: ${tplData.xp}`
return [
`<b>Catégorie</b>: ${this.system.categorie}`,
`<b>Niveau</b>: ${this.system.niveau}`,
`<b>Caractéristique</b>: ${this.system.carac_value}`,
`<b>XP</b>: ${this.system.xp}`
]
return properties;
}
/* -------------------------------------------- */
_sortChatData() {
const tplData = this.system
let properties = [
`<b>Draconic</b>: ${tplData.draconic}`,
`<b>Difficulté</b>: ${tplData.difficulte}`,
`<b>Case TMR</b>: ${tplData.caseTMR}`,
`<b>Points de Rêve</b>: ${tplData.ptreve}`
return [
`<b>Draconic</b>: ${this.system.draconic}`,
`<b>Difficulté</b>: ${this.system.difficulte}`,
`<b>Case TMR</b>: ${this.system.caseTMR}`,
`<b>Points de Rêve</b>: ${this.system.ptreve}`
]
return properties;
}
/* -------------------------------------------- */
_herbeChatData() {
const tplData = this.system
let properties = [
`<b>Milieu</b>: ${tplData.milieu}`,
`<b>Rareté</b>: ${tplData.rarete}`,
`<b>Catégorie</b>: ${tplData.categorie}`,
return [
`<b>Milieu</b>: ${this.system.milieu}`,
`<b>Rareté</b>: ${this.system.rarete}`,
`<b>Catégorie</b>: ${this.system.categorie}`,
]
return properties;
}
/* -------------------------------------------- */
_ingredientChatData() {
const tplData = this.system
let properties = [
`<b>Milieu</b>: ${tplData.milieu}`,
`<b>Rareté</b>: ${tplData.rarete}`,
`<b>Catégorie</b>: ${tplData.categorie}`,
return [
`<b>Milieu</b>: ${this.system.milieu}`,
`<b>Rareté</b>: ${this.system.rarete}`,
`<b>Catégorie</b>: ${this.system.categorie}`,
]
return properties;
}
/* -------------------------------------------- */
_tacheChatData() {
const tplData = this.system
let properties = [
`<b>Caractéristique</b>: ${tplData.carac}`,
`<b>Compétence</b>: ${tplData.competence}`,
`<b>Périodicité</b>: ${tplData.periodicite}`,
`<b>Fatigue</b>: ${tplData.fatigue}`,
`<b>Difficulté</b>: ${tplData.difficulte}`
return [
`<b>Caractéristique</b>: ${this.system.carac}`,
`<b>Compétence</b>: ${this.system.competence}`,
`<b>Périodicité</b>: ${this.system.periodicite}`,
`<b>Fatigue</b>: ${this.system.fatigue}`,
`<b>Difficulté</b>: ${this.system.difficulte}`
].concat([
tplData.cacher_points_de_tache ? [] :`<b>Points de Tâche</b>: ${tplData.points_de_tache}`
this.system.cacher_points_de_tache ? [] :`<b>Points de Tâche</b>: ${this.system.points_de_tache}`
]).concat([
`<b>Points de Tâche atteints</b>: ${tplData.points_de_tache_courant}`]
`<b>Points de Tâche atteints</b>: ${this.system.points_de_tache_courant}`]
);
return properties;
}
/* -------------------------------------------- */
_livreChatData() {
const tplData = this.system
let properties = [
`<b>Compétence</b>: ${tplData.competence}`,
`<b>Auteur</b>: ${tplData.auteur}`,
`<b>Difficulté</b>: ${tplData.difficulte}`,
`<b>Points de Tâche</b>: ${tplData.points_de_tache}`,
`<b>Encombrement</b>: ${tplData.encombrement}`
return [
`<b>Compétence</b>: ${this.system.competence}`,
`<b>Auteur</b>: ${this.system.auteur}`,
`<b>Difficulté</b>: ${this.system.difficulte}`,
`<b>Points de Tâche</b>: ${this.system.points_de_tache}`,
`<b>Encombrement</b>: ${this.system.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_potionChatData() {
const tplData = this.system
let properties = [
`<b>Rareté</b>: ${tplData.rarete}`,
`<b>Catégorie</b>: ${tplData.categorie}`,
`<b>Encombrement</b>: ${tplData.encombrement}`,
return [
`<b>Rareté</b>: ${this.system.rarete}`,
`<b>Catégorie</b>: ${this.system.categorie}`,
`<b>Encombrement</b>: ${this.system.encombrement}`,
]
return properties;
}
/* -------------------------------------------- */
_queueChatData() {
const tplData = this.system
let properties = [
`<b>Refoulement</b>: ${tplData.refoulement}`
return [
`<b>Refoulement</b>: ${this.system.refoulement}`
]
return properties;
}
/* -------------------------------------------- */
_ombreChatData() {
const tplData = this.system
let properties = [
`<b>Refoulement</b>: ${tplData.refoulement}`
return [
`<b>Refoulement</b>: ${this.system.refoulement}`
]
return properties;
}
/* -------------------------------------------- */
_souffleChatData() {
const tplData = this.system
let properties = [];
return properties;
return [];
}
/* -------------------------------------------- */
_teteChatData() {
const tplData = this.system
let properties = [];
return properties;
return [];
}
/* -------------------------------------------- */
_tarotChatData() {
const tplData = this.system
let properties = [
`<b>Concept</b>: ${tplData.concept}`,
`<b>Aspect</b>: ${tplData.aspect}`,
return [
`<b>Concept</b>: ${this.system.concept}`,
`<b>Aspect</b>: ${this.system.aspect}`,
]
return properties;
}
/* -------------------------------------------- */
_nombreastralChatData() {
const tplData = this.system
let properties = [
`<b>Valeur</b>: ${tplData.value}`,
`<b>Jour</b>: ${tplData.jourlabel}`,
return [
`<b>Valeur</b>: ${this.system.value}`,
`<b>Jour</b>: ${this.system.jourlabel}`,
]
return properties;
}
/* -------------------------------------------- */
_monnaieChatData() {
const tplData = this.system
let properties = [
`<b>Valeur en Deniers</b>: ${tplData.valeur_deniers}`,
`<b>Encombrement</b>: ${tplData.encombrement}`
return [
`<b>Valeur en Deniers</b>: ${this.system.valeur_deniers}`,
`<b>Encombrement</b>: ${this.system.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_meditationChatData() {
const tplData = this.system
let properties = [
`<b>Thème</b>: ${tplData.theme}`,
`<b>Compétence</b>: ${tplData.competence}`,
`<b>Support</b>: ${tplData.support}`,
`<b>Heure</b>: ${tplData.heure}`,
`<b>Purification</b>: ${tplData.purification}`,
`<b>Vêture</b>: ${tplData.veture}`,
`<b>Comportement</b>: ${tplData.comportement}`,
`<b>Case TMR</b>: ${tplData.tmr}`
return [
`<b>Thème</b>: ${this.system.theme}`,
`<b>Compétence</b>: ${this.system.competence}`,
`<b>Support</b>: ${this.system.support}`,
`<b>Heure</b>: ${this.system.heure}`,
`<b>Purification</b>: ${this.system.purification}`,
`<b>Vêture</b>: ${this.system.veture}`,
`<b>Comportement</b>: ${this.system.comportement}`,
`<b>Case TMR</b>: ${this.system.tmr}`
]
}
/* -------------------------------------------- */
_rencontreChatData() {
if (this.system.coord) {
return [
`<b>Force</b>: ${this.system.force}`,
`<b>Coordonnées</b>: ${this.system.coord}`,
]
}
return [
`<b>Force</b>: ${this.system.force}`,
`<b>Refoulement</b>: ${this.system.refoulement}`,
`<b>Présent de cités</b>: ${this.system.presentCite}`,
]
return properties;
}
/* -------------------------------------------- */
_casetmrChatData() {
const tplData = this.system
let properties = [
`<b>Coordonnée</b>: ${tplData.coord}`,
`<b>Spécificité</b>: ${tplData.specific}`
return [
`<b>Coordonnée</b>: ${this.system.coord}`,
`<b>Spécificité</b>: ${this.system.specific}`
]
return properties;
}
/* -------------------------------------------- */
_maladieChatData() {
const tplData = this.system
let properties
if (tplData.identifie) {
properties = [
`<b>Malignité</b>: ${tplData.malignite}`,
`<b>Périodicité</b>: ${tplData.periodicite}`,
`<b>Dommages</b>: ${tplData.dommages}`
if (!this.system.identifie) {
return [`<b>Inconnue</b>`]
}
let properties = [
`<b>Malignité</b>: ${this.system.malignite}`,
`<b>Périodicité</b>: ${this.system.periodicite}`,
`<b>Dommages</b>: ${this.system.dommages}`
]
if (tplData.remedesconnus) {
properties.push(`<b>Remedes</b>: ${tplData.remedes}`)
}
} else {
properties = [
`<b>Inconnue</b>`]
if (this.system.remedesconnus) {
properties.push(`<b>Remedes</b>: ${this.system.remedes}`)
}
return properties;
}
@@ -584,15 +549,13 @@ export class RdDItem extends Item {
/* -------------------------------------------- */
_gemmeChatData() {
const tplData = this.system
let properties = [
`<b>Pureté</b>: ${tplData.purete}`,
`<b>Taille</b>: ${tplData.taille}`,
`<b>Inertie</b>: ${tplData.inertie}`,
`<b>Enchantabilité</b>: ${tplData.enchantabilite}`,
`<b>Prix</b>: ${tplData.cout}`,
return [
`<b>Pureté</b>: ${this.system.purete}`,
`<b>Taille</b>: ${this.system.taille}`,
`<b>Inertie</b>: ${this.system.inertie}`,
`<b>Enchantabilité</b>: ${this.system.enchantabilite}`,
`<b>Prix</b>: ${this.system.cout}`,
]
return properties;
}

View File

@@ -43,7 +43,7 @@ class _10_0_16_MigrationSortsReserve extends Migration {
await actor.createEmbeddedDocuments("Item", sortsReserve, {
renderSheet: false,
});
await actor.update({ 'system.reve.reserve.list': [] })
await actor.update({ 'system.reve.reserve': undefined })
});
}

View File

@@ -102,7 +102,7 @@ export class Misc {
}
static join(params, separator = '') {
return params.reduce((a, b) => a + separator + b);
return params?.reduce((a, b) => a + separator + b) ?? '';
}
static connectedGMOrUser(ownerId = undefined) {
@@ -133,7 +133,11 @@ export class Misc {
* @returns true pour un seul utilisateur: le premier GM connecté par ordre d'id
*/
static isUniqueConnectedGM() {
return game.user.id == Misc.firstConnectedGM()?.id;
return game.user.id == Misc.firstConnectedGMId();
}
static firstConnectedGMId() {
return Misc.firstConnectedGM()?.id;
}
/* -------------------------------------------- */
@@ -191,4 +195,4 @@ export class Misc {
}
return subset;
}
}
}

View File

@@ -1,72 +1,13 @@
import { Misc } from "./misc.js"
import { RdDDice } from "./rdd-dice.js";
const poesieHautReve = [
{
reference: 'Le Ratier Bretonien',
extrait: `Le courant du Fleuve
<br>Te domine et te Porte
<br>Avant que tu te moeuves
<br>Combat le, ou il t'emporte`
},
{
reference: 'Incompatibilité, Charles Beaudelaire',
extrait: `Et lorsque par hasard une nuée errante
<br>Assombrit dans son vol le lac silencieux,
<br>On croirait voir la robe ou l'ombre transparente
<br>D'un esprit qui voyage et passe dans les cieux.`
},
{
reference: 'Au fleuve de Loire, Joachim du Bellay',
extrait: `Ô de qui la vive course
<br>Prend sa bienheureuse source,
<br>Dune argentine fontaine,
<br>Qui dune fuite lointaine,
<br>Te rends au sein fluctueux
<br>De lOcéan monstrueux`
},
{
reference: 'Denis Gerfaud',
extrait: `Et l'on peut savoir qui est le maître d'Oniros, c'est le Fleuve de l'Oubli.
Et l'on sait qui est le créateur du Fleuve de l'Oubli, c'est Hypnos et Narcos.
Mais l'on ne sait pas qui est le maître du Fleuve de l'Oubli,
sinon peut-être lui-même, ou peut-être Thanatos` },
{
reference: 'Denis Gerfaud',
extrait: `Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure
Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir.
Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli`
},
{
reference: 'Denis Gerfaud',
extrait: `Narcos engendre le fils dont il est la mère à l'heure du Vaisseau,
car Oniros s'embarque pour redescendre le Fleuve
vers son père Hypnos sur la Voie de l'Oubli`
},
{
reference: 'Denis Gerfaud',
extrait: `Hypnos engendre le fils dont il est la mère à l'heure du Serpent, car
tel les serpents, Oniros commence à remonter le Fleuve
sur le Voie du Souvenir vers son père Narcos`
},
{
reference: 'Denis Gerfaud',
extrait: `Ainsi se succèdent les Jours et les Ages.
<br>Les jours des Dragons sont les Ages des Hommes.`
},
{
reference: 'Denis Gerfaud',
extrait: `Ainsi parlent les sages:
&laquo;Les Dragons sont créateurs de leurs rêves, mais ils ne sont pas créateurs d'Oniros
Les Dragons ne sont pas les maîtres de leurs rêvezs, car ils ne sont pas maîtres d'Oniros.
Nul ne sait qui est le créateur des Dragons, ni qui est leur maître.
Mais l'on peut supposer qui est le maître du Rêve des Dragons, c'est Oniros&raquo;`
},
]
import { SystemCompendiums } from "./settings/system-compendiums.js";
export class Poetique {
static async getExtrait(){
return await RdDDice.rollOneOf(poesieHautReve);
static async getExtrait() {
const items = await SystemCompendiums.getItems('extrait-poetique', 'extraitpoetique')
const selected = await RdDDice.rollOneOf(items);
return {
reference: selected?.name,
extrait: selected?.system.extrait
}
}
}
}

View File

@@ -8,18 +8,19 @@ export class RdDCalendrierEditeur extends Dialog {
/* -------------------------------------------- */
constructor(html, calendrier, calendrierData) {
let myButtons = {
saveButton: { label: "Enregistrer", callback: html => this.fillData() }
};
// Common conf
let dialogConf = { content: html, title: "Editeur de date/heure", buttons: myButtons, default: "saveButton" };
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 300, 'z-index': 99999 }
let dialogConf = {
content: html,
title: "Editeur de date/heure",
buttons: {
save: { label: "Enregistrer", callback: html => this.fillData() }
},
default: "save"
};
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 'fit-content', 'z-index': 99999 }
super(dialogConf, dialogOptions)
this.calendrier = calendrier;
this.calendrierData = calendrierData; //duplicate(calendrierData);
this.calendrierData = calendrierData;
}
/* -------------------------------------------- */

View File

@@ -14,7 +14,7 @@ import { DialogChronologie } from "./dialog-chronologie.js";
const dossierIconesHeures = 'systems/foundryvtt-reve-de-dragon/icons/heures/'
const heuresList = ["vaisseau", "sirene", "faucon", "couronne", "dragon", "epees", "lyre", "serpent", "poissonacrobate", "araignee", "roseau", "chateaudormant"];
const heuresDef = {
"vaisseau": {key:"vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "printemps", heure: 0, icon: 'hd01.svg' },
"vaisseau": {key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "printemps", heure: 0, icon: 'hd01.svg' },
"sirene": { key: "sirene", label: "Sirène", lettreFont: 'i', saison: "printemps", heure: 1, icon: 'hd02.svg' },
"faucon": { key: "faucon", label: "Faucon", lettreFont: 'f', saison: "printemps", heure: 2, icon: 'hd03.svg' },
"couronne": { key: "couronne", label: "Couronne", lettreFont: '', saison: "ete", heure: 3, icon: 'hd04.svg' },
@@ -86,14 +86,14 @@ export class RdDCalendrier extends Application {
getCalendrier(index) {
index = index ?? this.getCurrentDayIndex();
const moisRdD = Math.floor(index / RDD_JOUR_PAR_MOIS) % RDD_MOIS_PAR_AN;
const mois = Math.floor(index / RDD_JOUR_PAR_MOIS) % RDD_MOIS_PAR_AN;
return {
heureRdD: 0, // Index dans heuresList / heuresDef[x].heure
minutesRelative: 0,
indexJour: index,
annee: Math.floor(index / (RDD_JOUR_PAR_MOIS * RDD_MOIS_PAR_AN)),
moisRdD: RdDCalendrier.getDefSigne(moisRdD),
moisLabel: RdDCalendrier.getDefSigne(moisRdD).label,
moisRdD: RdDCalendrier.getDefSigne(mois).heure,
moisLabel: RdDCalendrier.getDefSigne(mois).label,
jour: (index % RDD_JOUR_PAR_MOIS) // Le calendrier stocke le jour en 0-27, mais en 1-28 à l'affichage
}
}
@@ -138,7 +138,7 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */
getDateFromIndex(index) {
const dateRdD = this.getCalendrier(index);
return (dateRdD.jour + 1) + ' ' + RdDCalendrier.getDefSigne(dateRdD.moisRdD).label;
return (dateRdD.jour + 1) + ' ' + dateRdD.moisLabel;
}
/* -------------------------------------------- */
@@ -316,16 +316,12 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */
fillCalendrierData(formData = {}) {
console.log(this.calendrier);
let moisKey = heuresList[this.calendrier.moisRdD];
let heureKey = heuresList[this.calendrier.heureRdD];
console.log(moisKey, heureKey);
const mois = RdDCalendrier.getDefSigne(this.calendrier.moisRdD);
const heure = RdDCalendrier.getDefSigne(this.calendrier.heureRdD);
console.log('fillCalendrierData', this.calendrier, mois, heure);
const mois = heuresDef[moisKey];
const heure = heuresDef[heureKey];
formData.heureKey = heureKey;
formData.moisKey = moisKey;
formData.heureKey = heure.key;
formData.moisKey = mois.key;
formData.jourMois = this.calendrier.jour + 1;
formData.nomMois = mois.label; // heures et mois nommés identiques
formData.iconMois = dossierIconesHeures + mois.icon;
@@ -458,7 +454,7 @@ export class RdDCalendrier extends Application {
function check() {
let elmnt = document.getElementById("calendar-time-container");
if (elmnt) {
elmnt.style.bottom = null;
elmnt.style.bottom = undefined;
let xPos = (pos.left) > window.innerWidth ? window.innerWidth - 200 : pos.left;
let yPos = (pos.top) > window.innerHeight - 20 ? window.innerHeight - 100 : pos.top;
elmnt.style.top = (yPos) + "px";
@@ -615,16 +611,16 @@ export class RdDCalendrier extends Application {
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
elmnt.style.bottom = null
elmnt.style.bottom = undefined
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
elmnt.onmousedown = null;
document.onmouseup = null;
document.onmousemove = null;
elmnt.onmousedown = undefined;
document.onmouseup = undefined;
document.onmousemove = undefined;
let xPos = (elmnt.offsetLeft - pos1) > window.innerWidth ? window.innerWidth - 200 : (elmnt.offsetLeft - pos1);
let yPos = (elmnt.offsetTop - pos2) > window.innerHeight - 20 ? window.innerHeight - 100 : (elmnt.offsetTop - pos2)
xPos = xPos < 0 ? 0 : xPos;

View File

@@ -9,8 +9,8 @@ import { RdDBonus } from "./rdd-bonus.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDRoll } from "./rdd-roll.js";
import { RdDRollTables } from "./rdd-rolltables.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { STATUSES } from "./status-effects.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { STATUSES } from "./settings/status-effects.js";
/* -------------------------------------------- */
const premierRoundInit = [
@@ -121,7 +121,7 @@ export class RdDCombatManager extends Combat {
{
speaker: {
scene: canvas.scene._id,
actor: combatant.actor ? combatant.actor._id : null,
actor: combatant.actor?._id,
token: combatant.token._id,
alias: combatant.token.name,
sound: CONFIG.sounds.dice,
@@ -498,7 +498,7 @@ export class RdDCombat {
let defender = canvas.tokens.get(msg.defenderTokenId).actor;
if (Misc.isOwnerPlayerOrUniqueConnectedGM()) {
let attackerRoll = msg.attackerRoll;
let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : null;
let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined;
defender.encaisserDommages(attackerRoll, attacker);
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);

View File

@@ -39,21 +39,22 @@ export class RdDCommands {
rddCommands.registerCommand({ path: ["/meteo"], func: (content, msg, params) => rddCommands.getMeteo(msg, params), descr: "Propose une météo marine" });
rddCommands.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
rddCommands.registerCommand({
path: ["/tmr"], func: (content, msg, params) => rddCommands.findTMR(msg, params),
descr: `Cherche où se trouve une case des Terres médianes
<br><strong>/tmr sord</strong> indique que la cité Sordide est en D13
<br><strong>/tmr foret</strong> donne la liste des TMR dont le nom contient "foret" (donc, toutes les forêts)` });
rddCommands.registerCommand({
path: ["/tmra"], func: (content, msg, params) => rddCommands.getTMRAleatoire(msg, params),
descr: `Tire une case aléatoire des Terres médianes
<br><strong>/tmra forêt</strong> détermine une 'forêt' aléatoire
<br><strong>/tmra</strong> détermine une case aléatoire dans toutes les TMR` });
rddCommands.registerCommand({
path: ["/tmr"], func: (content, msg, params) => rddCommands.findTMR(msg, params),
descr: `Cherche où se trouve une case des Terres médianes
<br><strong>/tmr? sordide</strong> indique que la cité Sordide est en D13
<br><strong>/tmr? foret</strong> donne la liste des TMR dont le nom contient "foret" (donc, toutes les forêts)` });
rddCommands.registerCommand({
path: ["/tmrr"], func: (content, msg, params) => rddCommands.getRencontreTMR(params),
descr: `Détermine une rencontre dans un type de case
<br><strong>/tmrr foret</strong> lance un d100 et détermine la rencontre correspondante en 'forêt'
<br><strong>/tmrr forêt 47</strong> détermine la rencontre en 'forêt' pour un jet de dé de 47`
<br><strong>/tmrr forêt</strong> détermine une rencontre aléatoire en 'forêt'
<br><strong>/tmrr mauvaise</strong> détermine une mauvaise rencontre aléatoire
<br><strong>/tmrr for 47</strong> détermine la rencontre en 'forêt' pour un jet de dé de 47`
});
rddCommands.registerCommand({
@@ -84,7 +85,7 @@ export class RdDCommands {
rddCommands.registerCommand({
path: ["/payer"], func: (content, msg, params) => RdDUtility.afficherDemandePayer(params[0], params[1]),
descr: `Permet de payer un montant. Exemples:
descr: `Demande aux joueurs de payer un montant. Exemples:
<br><strong>/payer 5s 10d</strong> permet d'envoyer un message pour payer 5 sols et 10 deniers
<br><strong>/payer 10d</strong> permet d'envoyer un message pour payer 10 deniers`
});
@@ -180,7 +181,7 @@ export class RdDCommands {
return this._processCommand(this.commandsTable, command, params, content, msg);
}
_processCommand(commandsTable, name, params, content = '', msg = {}, path = "") {
async _processCommand(commandsTable, name, params, content = '', msg = {}, path = "") {
let command = commandsTable[name];
path = path + name + " ";
if (command && command.subTable) {
@@ -193,7 +194,7 @@ export class RdDCommands {
}
}
if (command && command.func) {
const result = command.func(content, msg, params);
const result = await command.func(content, msg, params);
if (result == false) {
RdDCommands._chatAnswer(msg, command.descr);
}
@@ -218,7 +219,7 @@ export class RdDCommands {
buttons: {},
},
{
width: 600, height: 500,
width: 600, height: 600,
});
d.render(true);
@@ -250,9 +251,7 @@ export class RdDCommands {
if (params.length == 1 || params.length == 2) {
return TMRRencontres.rollRencontre(params[0], params[1])
}
else {
return false;
}
return false;
}
/* -------------------------------------------- */
@@ -305,20 +304,20 @@ export class RdDCommands {
show: { title: "Table de résolution" }
};
await RdDResolutionTable.rollData(rollData);
RdDCommands._chatAnswer(msg, await RdDResolutionTable.buildRollDataHtml(rollData));
return RdDCommands._chatAnswer(msg, await RdDResolutionTable.buildRollDataHtml(rollData));
}
/* -------------------------------------------- */
async rollDeDraconique(msg) {
let ddr = await RdDDice.rollTotal("1dr + 7");
RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr}`);
return RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr}`);
}
async getTMRAleatoire(msg, params) {
if (params.length < 2) {
let type = params[0];
const tmr = await TMRUtility.getTMRAleatoire(type ? (it => it.type == type) : (it => true));
RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`);
return RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`);
}
else {
return false;
@@ -326,12 +325,15 @@ export class RdDCommands {
}
async findTMR(msg, params) {
const search = Misc.join(params, ' ');
const found = TMRUtility.findTMR(search);
if (found?.length > 0) {
return RdDCommands._chatAnswer(msg, `Les TMRs correspondant à '${search}' sont:` + Misc.join(found.map(it => `<br>${it.coord}: ${it.label}`)));
if (params && params.length > 0) {
const search = Misc.join(params, ' ');
const found = TMRUtility.findTMR(search);
if (found?.length > 0) {
return RdDCommands._chatAnswer(msg, `Les TMRs correspondant à '${search}' sont:` + Misc.join(found.map(it => `<br>${it.coord}: ${it.label}`)));
}
return RdDCommands._chatAnswer(msg, 'Aucune TMR correspondant à ' + search);
}
return RdDCommands._chatAnswer(msg, 'Aucune TMR correspondant à ' + search);
return false;
}
/* -------------------------------------------- */
@@ -339,7 +341,7 @@ export class RdDCommands {
if (params && (params.length == 1 || params.length == 2)) {
let to = params.length == 1 ? Number(params[0]) : Number(params[1]);
let from = params.length == 1 ? to - 1 : Number(params[0]);
RdDCommands._chatAnswer(msg, `Coût pour passer une compétence de ${from} à ${to}: ${RdDItemCompetence.getDeltaXp(from, to)}`);
return RdDCommands._chatAnswer(msg, `Coût pour passer une compétence de ${from} à ${to}: ${RdDItemCompetence.getDeltaXp(from, to)}`);
}
else {
return false;
@@ -350,7 +352,7 @@ export class RdDCommands {
getCoutXpCarac(msg, params) {
if (params && params.length == 1) {
let to = Number(params[0]);
RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to)}`);
return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to)}`);
}
else {
return false;

View File

@@ -29,13 +29,14 @@ export class RddCompendiumOrganiser {
static getEntityTypeLabel(entity) {
const documentName = entity?.documentName
const type = entity?.type
const type = entity?.type
if (documentName === 'Actor' || documentName === 'Item') {
const label = CONFIG[documentName]?.typeLabels?.[type] ?? type;
return game.i18n.has(label) ? game.i18n.localize(label) : t;
if (game.i18n.has(label)) {
return game.i18n.localize(label);
}
}
return type;
}
}

View File

@@ -1,5 +1,5 @@
import { Grammar } from "./grammar.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
export class RdDConfirm {
/* -------------------------------------------- */

View File

@@ -144,6 +144,9 @@ export class RdDDice {
}
static async rollOneOf(array) {
if (array == undefined || array.length == 0) {
return undefined;
}
const roll = await RdDDice.rollTotal(`1d${array.length}`);
return array[roll - 1];
}
@@ -241,7 +244,7 @@ export class RdDDice {
}
static _getWhisperBlind(options) {
let whisper = null;
let whisper = undefined;
let blind = false;
let rollMode = options.rollMode ?? game.settings.get("core", "rollMode");
switch (rollMode) {

View File

@@ -23,9 +23,9 @@ import { RdDTokenHud } from "./rdd-token-hud.js";
import { RdDCommands } from "./rdd-commands.js";
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
import { ChatUtility } from "./chat-utility.js";
import { StatusEffects } from "./status-effects.js";
import { StatusEffects } from "./settings/status-effects.js";
import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { TMRRencontres } from "./tmr-rencontres.js";
import { RdDHotbar } from "./rdd-hotbar-drop.js"
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
@@ -37,6 +37,8 @@ import { RdDSigneDraconiqueItemSheet } from "./item-signedraconique-sheet.js";
import { Misc } from "./misc.js";
import { Migrations } from './migrations.js';
import { DialogChronologie } from "./dialog-chronologie.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
import { RdDRencontreItemSheet } from "./item-rencontre-sheet.js";
/* -------------------------------------------- */
/* Foundry VTT Initialization */
@@ -143,8 +145,6 @@ Hooks.once("init", async function () {
default: "aucun"
});
DialogChronologie.onInit();
/* -------------------------------------------- */
// Set an initiative formula for the system
CONFIG.Combat.initiative = {
@@ -189,14 +189,27 @@ Hooks.once("init", async function () {
types: ["signedraconique"],
makeDefault: true
});
Items.registerSheet(SYSTEM_RDD, RdDRencontreItemSheet, {
label: "Rencontre",
types: ["rencontre"],
makeDefault: true
});
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
types: ["arme", "armure", "objet", "arme", "armure", "conteneur", "competence", "sort", "herbe", "ingredient", "livre", "potion", "munition", "rencontresTMR", "queue", "ombre", "souffle",
"tete", "competencecreature", "tarot", "monnaie", "nombreastral", "tache", "meditation", "casetmr", "recettealchimique", "gemme",
"musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre", "nourritureboisson", "possession", "sortreserve"], makeDefault: true
types: [
"competence", "competencecreature",
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
"objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition",
"monnaie", "nourritureboisson", "gemme",
"meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
"nombreastral", "tache", "maladie", "poison", "possession",
"tarot", "extraitpoetique"
], makeDefault: true
});
CONFIG.Combat.documentClass = RdDCombatManager;
// préparation des différents modules
SystemCompendiums.init();
DialogChronologie.init();
ReglesOptionelles.init();
RdDUtility.init();
RdDDice.init();
@@ -208,7 +221,6 @@ Hooks.once("init", async function () {
RddCompendiumOrganiser.init();
EffetsDraconiques.init()
TMRUtility.init();
TMRRencontres.init();
RdDHotbar.initDropbar();
RdDPossession.init();
});

View File

@@ -92,8 +92,7 @@ export class RdDPossession {
const dialog = await RdDRoll.create(defender, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html',
options: { height: 450 }
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html'
},
{
name: 'conjurer',
@@ -134,8 +133,7 @@ export class RdDPossession {
const dialog = await RdDRoll.create(attacker, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
options: { height: 540 }
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html'
}, {
name: 'jet-possession',
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',

View File

@@ -1,7 +1,7 @@
import { ChatUtility } from "./chat-utility.js";
import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
/**
* difficultés au delà de -10
@@ -54,7 +54,7 @@ export class RdDResolutionTable {
/* -------------------------------------------- */
static explain(rolled) {
let message = "<br>Jet : <strong>" + rolled.roll + "</strong> sur " + rolled.score + "% ";
if (rolled.caracValue != null && rolled.finalLevel != null) {
if (rolled.caracValue != undefined && rolled.finalLevel != undefined) {
message += (rolled.diviseurSignificative > 1 ? `(1/${rolled.diviseurSignificative} de ` : "(")
+ rolled.caracValue + " à " + Misc.toSignedString(rolled.finalLevel) + ") ";
}
@@ -116,7 +116,7 @@ export class RdDResolutionTable {
static _updateChancesFactor(chances, diviseur) {
if (chances.level > -11 && diviseur && diviseur > 1) {
let newScore = Math.floor(chances.score / diviseur);
mergeObject(chances, this._computeCell(null, newScore), { overwrite: true });
mergeObject(chances, this._computeCell(undefined, newScore), { overwrite: true });
}
}
@@ -124,7 +124,7 @@ export class RdDResolutionTable {
static _updateChancesWithBonus(chances, bonus, finalLevel) {
if (bonus && finalLevel>-11) {
let newScore = Number(chances.score) + bonus;
mergeObject(chances, this._computeCell(null, newScore), { overwrite: true });
mergeObject(chances, this._computeCell(undefined, newScore), { overwrite: true });
}
}

View File

@@ -33,7 +33,7 @@ export class RdDEncaisser extends Dialog {
let dialogOptions = {
classes: ["rdddialog"],
width: 320,
height: 260
height: 'fit-content'
}
// Select proper roll dialog template and stuff

View File

@@ -15,7 +15,7 @@ export class RdDRollDialogEthylisme extends Dialog {
default: "rollButton",
buttons: { "rollButton": { label: "Test d'éthylisme", callback: html => this.onButton(html) } }
};
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 270, 'z-index': 99999 }
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 'fit-content', 'z-index': 99999 }
super(dialogConf, dialogOptions)
//console.log("ETH", rollData);

View File

@@ -53,7 +53,7 @@ export class RdDRollResolutionTable extends Dialog {
'lancer-fermer': { label: 'Lancer les dés et fermer', callback: html => this.onLancerFermer() }
}
};
super(conf, { classes: ["rdddialog"], width: 800, height: 800, 'z-index': 99999 });
super(conf, { classes: ["rdddialog"], width: 800, height: 'fit-content', 'z-index': 99999 });
this.rollData = rollData;
}

View File

@@ -6,7 +6,7 @@ import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js";
import { RdDCarac } from "./rdd-carac.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
/**
* Extend the base Dialog entity to select roll parameters
@@ -29,7 +29,7 @@ export class RdDRoll extends Dialog {
const html = await renderTemplate(dialogConfig.html, rollData);
let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 };
let options = { classes: ["rdddialog"], width: 600, height: 'fit-content', 'z-index': 99999 };
if (dialogConfig.options) {
mergeObject(options, dialogConfig.options, { overwrite: true })
}

View File

@@ -1,3 +1,5 @@
import { SystemCompendiums } from "./settings/system-compendiums.js";
export class RdDRollTables {
/* -------------------------------------------- */
@@ -14,7 +16,7 @@ export class RdDRollTables {
}
static async getSystemTable(tableName) {
const pack = game.packs.get("foundryvtt-reve-de-dragon.tables-diverses");
const pack = SystemCompendiums.getPack("tables-diverses");
const index = await pack.getIndex();
const entry = index.find(e => e.name === tableName);
return await pack.getDocument(entry._id);
@@ -24,8 +26,7 @@ export class RdDRollTables {
static async drawItemFromRollTable(tableName, toChat = false) {
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
const pack = game.packs.get(drawResult.documentCollection)
let doc = await pack.getDocument(drawResult.documentId)
return doc
return await pack.getDocument(drawResult.documentId)
}
/* -------------------------------------------- */

View File

@@ -1,3 +1,4 @@
import { SHOW_DICE } from "./constants.js";
import { RollDataAjustements } from "./rolldata-ajustements.js";
import { RdDUtility } from "./rdd-utility.js";
import { TMRUtility } from "./tmr-utility.js";
@@ -11,11 +12,13 @@ import { Poetique } from "./poetique.js";
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { PixiTMR } from "./tmr/pixi-tmr.js";
import { Draconique } from "./tmr/draconique.js";
import { Misc } from "./misc.js";
import { HtmlUtility } from "./html-utility.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { RdDDice } from "./rdd-dice.js";
import { STATUSES } from "./status-effects.js";
import { STATUSES } from "./settings/status-effects.js";
import { RdDRencontre } from "./item-rencontre.js";
import { RdDCalendrier } from "./rdd-calendrier.js";
/* -------------------------------------------- */
export class RdDTMRDialog extends Dialog {
@@ -89,7 +92,7 @@ export class RdDTMRDialog extends Dialog {
TMRUtility.getTMR(coord).type == 'fleuve'
? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve'
: it => it.system.coord == coord
);
);
}
/* -------------------------------------------- */
@@ -146,7 +149,7 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
_tokenRencontre(rencontre) {
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord);
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.system.coord);
}
_tokenCaseSpeciale(casetmr) {
const caseData = casetmr;
@@ -248,7 +251,7 @@ export class RdDTMRDialog extends Dialog {
let tmrpos = document.getElementById("tmr-pos");
if (this.isDemiReveCache()) {
tmrpos.innerHTML = `?? ( ${ TMRUtility.getTMRType(coord)})`;
tmrpos.innerHTML = `?? ( ${TMRUtility.getTMRType(coord)})`;
} else {
tmrpos.innerHTML = `${coord} ( ${TMRUtility.getTMRLabel(coord)})`;
}
@@ -280,25 +283,44 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
async onActionRencontre(action, tmr) {
switch (action) {
case 'derober':
await this.derober();
return;
case 'refouler':
await this.refouler();
break;
case 'maitriser':
await this.maitriserRencontre();
break;
case 'ignorer':
await this.ignorerRencontre();
break;
}
await this.postRencontre(tmr);
}
async derober() {
await this.actor.addTMRRencontre(this.currentRencontre);
console.log("-> derober", this.currentRencontre);
await this.actor.addTMRRencontre(this.currentRencontre);
this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR.");
this.close();
}
/* -------------------------------------------- */
async refouler() {
await this.actor.ajouterRefoulement(this.currentRencontre.refoulement ?? 1, `une rencontre ${this.currentRencontre.name}`);
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
this.updateTokens();
console.log("-> refouler", this.currentRencontre)
this.updateValuesDisplay();
this.nettoyerRencontre();
}
/* -------------------------------------------- */
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
this.updateTokens();
@@ -307,7 +329,14 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
colorierZoneRencontre(listCoordTMR) {
// garder la trace de l'état en cours
setRencontreState(state, listCoordTMR) {
this.rencontreState = state;
this.$marquerCasesTMR(listCoordTMR ?? []);
}
/* -------------------------------------------- */
$marquerCasesTMR(listCoordTMR) {
this.currentRencontre.graphics = []; // Keep track of rectangles to delete it
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location
for (let coordTMR of listCoordTMR) {
@@ -323,23 +352,6 @@ export class RdDTMRDialog extends Dialog {
}
}
/* -------------------------------------------- */
// garder la trace de l'état en cours
setStateRencontre(state) {
this.rencontreState = state;
}
/* -------------------------------------------- */
async choisirCasePortee(coord, portee) {
// Récupère la liste des cases à portées
this.colorierZoneRencontre(TMRUtility.getTMRPortee(coord, portee));
}
/* -------------------------------------------- */
async choisirCaseType(type) {
this.colorierZoneRencontre(TMRUtility.filterTMR(it => it.type == type).map(it => it.coord));
}
/* -------------------------------------------- */
checkQuitterTMR() {
@@ -364,15 +376,15 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async quitterLesTMRInconscient() {
if (this.currentRencontre?.isPersistant) {
await this.refouler();
}
await this.refouler();
this.close();
}
/* -------------------------------------------- */
async maitriserRencontre() {
this.actor.deleteTMRRencontreAtPosition();
console.log("-> maitriser", this.currentRencontre);
await this.actor.deleteTMRRencontreAtPosition();
this.updateTokens();
let rencontreData = {
@@ -383,7 +395,7 @@ export class RdDTMRDialog extends Dialog {
rencontre: this.currentRencontre,
nbRounds: 1,
canClose: false,
selectedCarac: {label: "reve-actuel"},
selectedCarac: { label: "reve-actuel" },
tmr: TMRUtility.getTMR(this._getActorCoord())
}
@@ -392,8 +404,6 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async _tentativeMaitrise(rencData) {
console.log("-> matriser", rencData);
rencData.reve = this.actor.getReveActuel();
rencData.etat = this.actor.getEtatGeneral();
@@ -403,41 +413,67 @@ export class RdDTMRDialog extends Dialog {
? this._rollPresentCite(rencData)
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
let postProcess = await TMRRencontres.gererRencontre(this, rencData);
const result = rencData.rolled.isSuccess
? rencData.rencontre.system.succes
: rencData.rencontre.system.echec;
await RdDRencontre.appliquer(result.effets, this, rencData);
rencData.poesie = { extrait: result.poesie, reference: result.reference };
rencData.message = this.formatMessageRencontre(rencData, result.message);
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencData)
});
if (postProcess) {
/** Gère les rencontres avec du post-processing (passeur, messagers, tourbillons, ...) */
await postProcess(this, rencData);
}
else {
this.currentRencontre = undefined;
}
this.updateValuesDisplay();
if (this.checkQuitterTMR()) {
return;
}
else if (rencData.rolled.isEchec && rencData.rencontre.isPersistant) {
setTimeout(() => {
rencData.nbRounds++;
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase;
}
this._tentativeMaitrise(rencData);
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
}, 2000);
if (this.rencontreState == 'persistant') {
this._nouvelleTentativeMaitrise(rencData);
}
else if (!this.isRencontreDeplacement()) {
this.nettoyerRencontre();
}
}
_nouvelleTentativeMaitrise(rencData) {
setTimeout(() => {
// TODO: remplacer par une boucle while(this.currentRencontre) ?
rencData.nbRounds++;
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase;
}
this._tentativeMaitrise(rencData);
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
}, 2000);
this.rencontreState == 'normal';
}
formatMessageRencontre(rencData, template) {
let messageDuree = ''
if (rencData.nbRounds > 1) {
if (rencData.rolled.isSuccess) {
messageDuree = ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
}
else {
messageDuree = ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
}
}
try {
const compiled = Handlebars.compile(template);
return compiled(rencData) + messageDuree ;
} catch (error) {
return template + messageDuree ;
}
}
/* -------------------------------------------- */
_rollPresentCite(rencontreData) {
let rolled = RdDResolutionTable.computeChances(rencontreData.reve, 0);
mergeObject(rolled, { caracValue: rencontreData.reve, finalLevel: 0, roll: rolled.score });
_rollPresentCite(rencData) {
let rolled = RdDResolutionTable.computeChances(rencData.reve, 0);
mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score });
RdDResolutionTable.succesRequis(rolled);
return rolled;
}
@@ -481,15 +517,16 @@ export class RdDTMRDialog extends Dialog {
if (this._presentCite(tmr)) {
return;
}
let rencontre = await this._jetDeRencontre(tmr);
if (rencontre) { // Manages it
if (rencontre.rencontre) rencontre = rencontre.rencontre; // Manage stored rencontres
console.log("manageRencontre", rencontre);
this.currentRencontre = duplicate(rencontre);
let dialog = new RdDTMRRencontreDialog(this, this.currentRencontre, () => this.postRencontre(tmr));
dialog.render(true);
this.currentRencontre = await this._jetDeRencontre(tmr);
if (this.currentRencontre) {
if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)){
// rencontre en attente suite à dérobade
await this.maitriserRencontre();
}
else {
let dialog = new RdDTMRRencontreDialog(this, this.currentRencontre, tmr);
dialog.render(true);
}
}
else {
this.postRencontre(tmr);
@@ -502,15 +539,18 @@ export class RdDTMRDialog extends Dialog {
if (presentCite) {
this.minimize();
const caseData = presentCite;
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (type => this._utiliserPresentCite(presentCite, type, tmr)));
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (present => this._utiliserPresentCite(presentCite, present, tmr)));
}
return presentCite;
}
/* -------------------------------------------- */
async _utiliserPresentCite(presentCite, typeRencontre, tmr) {
this.currentRencontre = TMRRencontres.getRencontre(typeRencontre);
await TMRRencontres.evaluerForceRencontre(this.currentRencontre);
async _utiliserPresentCite(presentCite, present, tmr) {
this.currentRencontre = present.clone({
'system.force': await RdDDice.rollTotal(present.system.formule),
'system.coord': tmr.coord
}, {save: false});
await EffetsDraconiques.presentCites.ouvrirLePresent(this.actor, presentCite);
this.removeToken(tmr, presentCite);
@@ -532,33 +572,26 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async _jetDeRencontre(tmr) {
let rencontre = this.rencontresExistantes.find(prev => prev.coord == tmr.coord);
let rencontre = this.lookupRencontreExistente(tmr);
if (rencontre) {
return rencontre;
return TMRRencontres.calculRencontre(rencontre, tmr);
}
let locTMR = (this.isDemiReveCache()
? Misc.upperFirst(tmr.type) + " ??"
? TMRUtility.getTMRType(tmr.coord) + " ??"
: tmr.label + " (" + tmr.coord + ")");
let myRoll = await RdDDice.rollTotal("1dt");
if (TMRUtility.isForceRencontre() || myRoll == 7) {
let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
if (myRoll == 7) {
this._tellToUser(myRoll + ": Rencontre en " + locTMR);
return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale());
return await TMRRencontres.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
} else {
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
}
}
/* -------------------------------------------- */
async rencontreTMRRoll(tmr, isMauvaise = false) {
let rencontre = TMRUtility.utiliseForceRencontre() ??
(isMauvaise
? await TMRRencontres.getMauvaiseRencontre()
: await TMRRencontres.getRencontreAleatoire(tmr.type));
rencontre.coord = tmr.coord;
rencontre.date = game.system.rdd.calendrier.getDateFromIndex();
rencontre.heure = game.system.rdd.calendrier.getCurrentHeure();
return rencontre;
lookupRencontreExistente(tmr) {
return this.rencontresExistantes.find(it => it.system.coord == tmr.coord)
?? this.rencontresExistantes.find(it => it.system.coord == "");
}
/* -------------------------------------------- */
@@ -586,7 +619,7 @@ export class RdDTMRDialog extends Dialog {
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
}
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined,
rollData.competence.system.defaut_carac = 'reve-actuel';
rollData.competence.system.defaut_carac = 'reve-actuel';
await this._rollMaitriseCaseHumide(rollData);
}
}
@@ -741,7 +774,7 @@ export class RdDTMRDialog extends Dialog {
const dialog = await RdDRoll.create(this.actor, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
options: { height: 420 },
options: { height: 'fit-content' },
close: html => { this.maximize(); } // Re-display TMR
},
{
@@ -806,12 +839,13 @@ export class RdDTMRDialog extends Dialog {
async processSortReserve(sortReserve) {
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
console.log("declencheSortEnReserve", sortReserve);
const heureCible = RdDCalendrier.getSigneAs('label', sortReserve.system.heurecible);
this._tellToUserAndGM(`Vous avez déclenché
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"}
en réserve <strong>${sortReserve.name}</strong>
avec ${sortReserve.system.ptreve} points de Rêve
en ${sortReserve.system.coord} (${TMRUtility.getTMRLabel(sortReserve.system.coord)}).
L'heure ciblée est ${sortReserve.system.heurecible}`);
L'heure ciblée est ${heureCible}`);
this.close();
}
@@ -877,16 +911,14 @@ export class RdDTMRDialog extends Dialog {
if (this.isDemiReveCache()) {
if (this.isTerreAttache(targetCoord)
|| this.isConnaissanceFleuve(currentCoord, targetCoord)
|| deplacementType == 'changeur')
{
|| this.isConnaissanceFleuve(currentCoord, targetCoord)
|| deplacementType == 'changeur') {
// déplacement possible
await this.actor.setTMRVisible(true);
this.demiReve = this._tokenDemiReve();
this._trackToken(this.demiReve);
}
else
{
else {
ui.notifications.error(`Vous ne connaissez plus votre position dans les TMR.
Vous devez utiliser les boutons de direction pour vous déplacer.
Une fois que vous aurez retrouvé votre demi-rêve, demandez au gardien de vérifier et rendre les TMR visibles.
@@ -895,20 +927,18 @@ export class RdDTMRDialog extends Dialog {
}
}
switch (deplacementType){
switch (deplacementType) {
case 'normal':
case 'changeur':
case 'passeur':
await this._deplacerDemiReve(targetCoord, deplacementType);
break;
case 'messager':
await this._messagerDemiReve(targetCoord);
break;
case 'changeur':
case 'passeur':
await this._deplacerDemiReve(targetCoord, deplacementType);
break;
default:
ui.notifications.error("Vous ne pouvez pas vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
console.log("STATUS :", this.rencontreState, this.currentRencontre);
ui.notifications.error("Vous ne pouvez pas vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
console.log("STATUS :", this.rencontreState, this.currentRencontre);
}
this.checkQuitterTMR();
@@ -916,19 +946,23 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
_calculDeplacement(targetCoord, currentCoord, fromOddq, toOddq) {
const isInArea = this.rencontreState == 'aucune'
? (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || TMRUtility.distanceOddq(fromOddq, toOddq) <= 1)
: this.currentRencontre?.locList?.find(coord => coord == targetCoord) ?? false
if (isInArea) {
switch (this.rencontreState) {
case 'aucune': return 'normal';
case 'passeur': case 'changeur': case 'messager': return this.rencontreState;
if (this.isRencontreDeplacement()) {
if (this.currentRencontre?.locList?.find(coord => coord == targetCoord)) {
return this.rencontreState;
}
}
else {
if (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || TMRUtility.distanceOddq(fromOddq, toOddq) <= 1) {
return 'normal'
}
}
return 'erreur';
}
isRencontreDeplacement() {
return ['passeur', 'changeur', 'messager'].includes(this.rencontreState);
}
/* -------------------------------------------- */
async _messagerDemiReve(targetCoord) {
/*

View File

@@ -2,46 +2,41 @@
export class RdDTMRRencontreDialog extends Dialog {
/* -------------------------------------------- */
constructor(tmrApp, rencontre, postRencontre) {
constructor(tmrApp, rencontre, tmr) {
const dialogConf = {
title: "Rencontre en TMR!",
content: "Vous rencontrez un " + rencontre.name + " de force " + rencontre.force + "<br>",
content: "Vous rencontrez un " + rencontre.name + " de force " + rencontre.system.force + "<br>",
buttons: {
derober: { icon: '<i class="fas fa-check"></i>', label: "Se dérober", callback: () => { this.onButtonFuir(() => tmrApp.derober()); } },
refouler: { icon: '<i class="fas fa-check"></i>', label: "Refouler", callback: () => this.onButtonAction(() => tmrApp.refouler()) },
maitiser: { icon: '<i class="fas fa-check"></i>', label: "Maîtriser", callback: () => this.onButtonAction(() => tmrApp.maitriserRencontre()) }
derober: { icon: '<i class="fas fa-check"></i>', label: "Se dérober", callback: () => this.onButtonAction('derober') },
maitiser: { icon: '<i class="fas fa-check"></i>', label: "Maîtriser", callback: () => this.onButtonAction('maitriser') }
},
default: "derober"
};
if (rencontre.ignorer) {
dialogConf.buttons.ignorer = { icon: '<i class="fas fa-check"></i>', label: "Ignorer", callback: () => this.onButtonAction(() => tmrApp.ignorerRencontre()) }
};
}
if ((rencontre.system.refoulement ?? 0) == 0) {
dialogConf.buttons.ignorer = { icon: '<i class="fas fa-check"></i>', label: "Ignorer", callback: () => this.onButtonAction('ignorer') }
}
else {
dialogConf.buttons.refouler = { icon: '<i class="fas fa-check"></i>', label: "Refouler", callback: () => this.onButtonAction('refouler') }
}
const dialogOptions = {
classes: ["tmrrencdialog"],
width: 320, height: 240,
width: 320, height: 'fit-content',
'z-index': 50
}
super(dialogConf, dialogOptions);
this.toClose = false;
this.rencontreData = duplicate(rencontre);
this.postRencontre = postRencontre;
this.tmr = tmr;
this.tmrApp = tmrApp;
this.tmrApp.minimize();
}
async onButtonAction(action) {
this.toClose = true;
await action();
this.postRencontre();
this.tmrApp.onActionRencontre(action, this.tmr)
}
async onButtonFuir(action) {
this.toClose = true;
await action();
}
/* -------------------------------------------- */
close() {
if (this.toClose) {

View File

@@ -6,14 +6,13 @@ import { Misc } from "./misc.js";
import { Grammar } from "./grammar.js";
import { TMRUtility } from "./tmr-utility.js";
import { DialogItemAchat } from "./dialog-item-achat.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { RdDDice } from "./rdd-dice.js";
import { RdDItem } from "./item.js";
import { Monnaie } from "./item-monnaie.js";
import { RdDPossession } from "./rdd-possession.js";
import { RdDNameGen } from "./rdd-namegen.js";
import { RdDConfirm } from "./rdd-confirm.js";
import { RdDActor } from "./actor.js";
import { RdDCalendrier } from "./rdd-calendrier.js";
/* -------------------------------------------- */
@@ -182,7 +181,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/item-livre-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-tache-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-potion-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-rencontresTMR-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-souffle-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-tarot-sheet.html',
@@ -193,6 +192,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/item-nourritureboisson-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-possession-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-extraitpoetique-sheet.html',
// partial enums
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
@@ -280,6 +280,7 @@ export class RdDUtility {
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
Handlebars.registerHelper('typeTmr-name', coord => TMRUtility.typeTmrName(coord));
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
Handlebars.registerHelper('signeHeure', (key, heure) => RdDCalendrier.getSigneAs(key, heure));
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
@@ -415,6 +416,7 @@ export class RdDUtility {
RdDUtility.filterEquipementParType(formData, itemTypes);
formData.sorts = this.arrayOrEmpty(itemTypes['sort']);
formData.rencontres = this.arrayOrEmpty(itemTypes['rencontre']);
formData.casestmr = this.arrayOrEmpty(itemTypes['casetmr']);
formData.signesdraconiques = this.arrayOrEmpty(itemTypes['signedraconique']);
formData.queues = this.arrayOrEmpty(itemTypes['queue']);

View File

@@ -6,7 +6,7 @@ import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js";
import { RdDCarac } from "./rdd-carac.js";
import { RdDUtility } from "./rdd-utility.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
/**
* tous les ajustements pouvant s'appliquer.
@@ -120,7 +120,7 @@ export const referenceAjustements = {
isVisible: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
isUsed: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
getLabel: (rollData, actor) => rollData.rencontre?.name,
getValue: (rollData, actor) => - (rollData.rencontre?.force ?? 0)
getValue: (rollData, actor) => - (rollData.rencontre?.system.force ?? 0)
},
ethylismeAlcool: {
isVisible: (rollData, actor) => rollData.nbDoses != undefined,

View File

@@ -1,5 +1,5 @@
import { SYSTEM_RDD } from "./constants.js";
import { Misc } from "./misc.js";
import { SYSTEM_RDD } from "../constants.js";
import { Misc } from "../misc.js";
const listeReglesOptionelles = [
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
@@ -43,7 +43,7 @@ export class ReglesOptionelles extends FormApplication {
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
name: "Choisir les règles optionelles",
label: "Choix des règles optionelles",
label: "Règles optionelles",
hint: "Ouvre la fenêtre de sélection des règles optionelles",
icon: "fas fa-bars",
type: ReglesOptionelles
@@ -61,8 +61,8 @@ export class ReglesOptionelles extends FormApplication {
static get defaultOptions() {
const options = super.defaultOptions;
mergeObject(options, {
id: "optional-settings",
template: "systems/foundryvtt-reve-de-dragon/templates/regles-optionelles.html",
id: "regles-optionelles",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionelles.html",
height: 600,
width: 450,
minimizable: false,

View File

@@ -1,4 +1,4 @@
import { SYSTEM_RDD } from "./constants.js";
import { SYSTEM_RDD } from "../constants.js";
export const STATUSES = {
StatusStunned : 'stun',
@@ -32,7 +32,7 @@ const demiReveStatusEffect = rddStatusEffects.find(it => it.id == STATUSES.Statu
const statusDemiSurprise = [STATUSES.StatusStunned, STATUSES.StatusProne, STATUSES.StatusRestrained];
const statusSurpriseTotale = [STATUSES.StatusUnconscious, STATUSES.StatusBlind, STATUSES.StatusComma];
export class StatusEffects {
export class StatusEffects extends FormApplication {
static onReady() {
const rddStatusIds = rddStatusEffects.map(it => it.id);
rddStatusEffects.forEach(it => it.flags = { core: { statusId: it.id } });
@@ -50,7 +50,7 @@ export class StatusEffects {
label: "Choix des effets",
hint: "Ouvre la fenêtre de sélection des effets/status appliqués aux acteurs",
icon: "fas fa-bars",
type: StatusEffectsSettings,
type: StatusEffects,
restricted: true
});
@@ -69,13 +69,12 @@ export class StatusEffects {
}
static _getUseStatusEffects() {
const setting = game.settings.get(SYSTEM_RDD, "use-status-effects");
return setting ? setting.split(',') : [];
return game.settings.get(SYSTEM_RDD, "use-status-effects")?.split(',') ?? [];
}
static _setUseStatusEffects(statusIds) {
if (game.user.isGM) {
game.settings.set(SYSTEM_RDD, "use-status-effects", StatusEffects._toSetting(statusIds));
game.settings.set(SYSTEM_RDD, "use-status-effects", statusIds.join());
}
for (let effect of CONFIG.RDD.allEffects) {
@@ -84,10 +83,6 @@ export class StatusEffects {
CONFIG.statusEffects = CONFIG.RDD.allEffects.filter(it => it.active);
}
static _toSetting(statusIds) {
return statusIds.join();
}
static status(statusId) {
return rddStatusEffects.find(it => it.flags?.core?.statusId == statusId);
}
@@ -95,9 +90,7 @@ export class StatusEffects {
static demiReve() {
return demiReveStatusEffect;
}
}
class StatusEffectsSettings extends FormApplication {
constructor(...args) {
super(...args);
}
@@ -105,9 +98,9 @@ class StatusEffectsSettings extends FormApplication {
static get defaultOptions() {
const options = super.defaultOptions;
mergeObject(options, {
id: "status-effects-settings",
template: "systems/foundryvtt-reve-de-dragon/templates/status-effects-settings.html",
height: "800",
id: "status-effects",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/status-effects.html",
height: 800,
width: 350,
minimizable: false,
closeOnSubmit: true,

View File

@@ -0,0 +1,126 @@
import { SYSTEM_RDD } from "../constants.js";
const COMPENDIUM_SETTING_PREFIX = 'compendium-';
const CONFIGURABLE_COMPENDIUMS = {
'tables-diverses': { label: "Tables aléatoires", type: "RollTable" },
'competences': { label: "Compétences", type: "Item" },
'extrait-poetique': { label: "Extraits poetiques", type: "Item" },
'queues-de-dragon': { label: "Queues de dragon", type: "Item" },
'ombres-de-thanatos': { label: "Ombres de Thanatos", type: "Item" },
'souffles-de-dragon': { label: "Souffles de Dragon", type: "Item" },
'tarot-draconique': { label: "Tarots draconiques", type: "Item" },
'rencontres': { label: "Rencontres dans les TMR", type: "Item" },
'tetes-de-dragon-pour-haut-revants': { label: "Têtes de dragons (haut-rêvant)", type: "Item" },
'tetes-de-dragon-pour-tous-personnages': { label: "Têtes de dragons (tous)", type: "Item" },
}
export class SystemCompendiums extends FormApplication {
static init() {
Object.keys(CONFIGURABLE_COMPENDIUMS).forEach(compendium => {
const definition = CONFIGURABLE_COMPENDIUMS[compendium];
mergeObject(definition, {
compendium: compendium,
default: SystemCompendiums._getDefaultCompendium(compendium),
setting: SystemCompendiums._getSettingCompendium(compendium)
});
game.settings.register(SYSTEM_RDD, definition.setting, {
name: definition.label,
default: definition.default,
scope: "world",
config: false,
type: String
});
});
game.settings.registerMenu(SYSTEM_RDD, "compendium-settings", {
name: "Choisir les compendiums système",
label: "Compendiums système",
hint: "Ouvre la fenêtre de sélection des compendiums système",
icon: "fas fa-bars",
type: SystemCompendiums
})
}
static getPack(compendium) {
return game.packs.get(SystemCompendiums.getCompendium(compendium));
}
static async getContent(compendium, docType) {
const pack = SystemCompendiums.getPack(compendium);
if (pack.metadata.type == docType) {
return await pack.getDocuments();
}
return [];
}
static async getItems(compendium, itemType = undefined) {
const items = await SystemCompendiums.getContent(compendium, 'Item');
return itemType ? items.filter(it => it.type == itemType) : items;
}
static async getDefaultItems(compendium) {
const pack = game.packs.get(SystemCompendiums._getDefaultCompendium(compendium));
if (pack.metadata.type == 'Item') {
return await pack.getDocuments();
}
return [];
}
static getCompendium(compendium) {
const setting = CONFIGURABLE_COMPENDIUMS[compendium]?.setting;
return setting ? game.settings.get(SYSTEM_RDD, setting) : SystemCompendiums._getDefaultCompendium(compendium);
}
static _getSettingCompendium(compendium) {
return COMPENDIUM_SETTING_PREFIX + compendium;
}
static _getDefaultCompendium(compendium) {
return `${SYSTEM_RDD}.${compendium}`;
}
constructor(...args) {
super(...args);
}
static get defaultOptions() {
const options = super.defaultOptions;
mergeObject(options, {
id: "system-compendiums",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/system-compendiums.html",
height: 'fit-content',
width: 600,
minimizable: false,
closeOnSubmit: true,
title: "Compendiums système"
});
return options;
}
getData() {
const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS)
.map(it => mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) }));
const availableCompendiums = game.packs.map(pack => { return {
name: pack.collection,
path: pack.collection.replace('.', " / "),
type: pack.metadata.type
} });
return mergeObject(super.getData(), {
systemCompendiums: systemCompendiums,
availableCompendiums: availableCompendiums
});
}
activateListeners(html) {
html.find("select.system-compendium-setting").change((event) => {
const compendium = $(event.currentTarget).data('compendium')
const value = $(event.currentTarget).val();
const systemCompendium = CONFIGURABLE_COMPENDIUMS[compendium];
game.settings.set(SYSTEM_RDD, systemCompendium.setting, value);
});
}
}

View File

@@ -1,500 +1,136 @@
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
import { TMRUtility } from "./tmr-utility.js";
import { TMRType } from "./tmr-utility.js";
/* -------------------------------------------- */
const typeRencontres = {
messager: {
msgSucces: async (rencData) => {
if (rencData.actor.isTMRCache()){
return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort, mais vous ne savez pas où vous êtes.`;
}
return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`;
},
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`,
postSucces: async (tmrDialog, rencData) => {
tmrDialog.setStateRencontre(rencData.rencontre.type);
tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
},
poesieSucces: {
reference: "La chevelure, Charles Baudelaire",
extrait: `J'irai là-bas où l'arbre et l'homme, pleins de sève,
<br>Se pâment longuement sous l'ardeur des climats ;
<br>Fortes tresses, soyez la houle qui m'enlève !`
},
poesieEchec: {
reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `En réalité, tous les éléments du rêve des Dragons expriment
le Draconic : chaque pierre, chaque fleur, chaque goutte d'eau,
chaque nuage est porteur d'un message dans la langue des Dragons`}
},
passeur: {
msgSucces: async (rencData) => {
if (rencData.actor.isTMRCache()){
return `Le ${rencData.rencontre.name} vous propose de vous transporter, mais vous ne savez pas où vous êtes.`;
}
return `Le ${rencData.rencontre.name} vous propose de vous transporter à ${rencData.rencontre.force} cases des ${rencData.tmr.label}.`;
},
msgEchec: async (rencData)=> `Le prix que demande le ${rencData.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`,
postSucces: async (tmrDialog, rencData) => {
tmrDialog.setStateRencontre(rencData.rencontre.type);
tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
},
poesieSucces: {
reference: "Femmes damnées (2), Charles Baudelaire",
extrait: `Comme je descendais des Fleuves impassibles,
<br>Je ne me sentis plus guidé par les haleurs :
<br>Des Peaux-Rouges criards les avaient pris pour cibles,
<br>Les ayant cloués nus aux poteaux de couleurs.`},
poesieEchec: {
reference: "Le bateau ivre, Arthur Rimbaud",
extrait: `Loin des peuples vivants, errantes, condamnées,
<br>A travers les déserts courez comme les loups ;
<br>Faites votre destin, âmes désordonnées,
<br>Et fuyez l'infini que vous portez en vous !`}
},
fleur: {
msgSucces: async (rencData) => `Vous cueillez la ${rencData.rencontre.name}, son parfum vous apporte ${rencData.rencontre.force} points de Rêve.`,
msgEchec: async (rencData)=> `La ${rencData.rencontre.name} se fâne et disparaît entre vos doigts.`,
postSucces: async (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(rencData.rencontre.force),
poesieSucces: {
reference: "L'Ennemi, Charles Baudelaire",
extrait: `Et qui sait si les fleurs nouvelles que je rêve
<br>Trouveront dans ce sol lavé comme une grève
<br>Le mystique aliment qui ferait leur vigueur ?`},
poesieEchec: {
reference: "Une charogne, Charles Baudelaire",
extrait: `Et le ciel regardait la carcasse superbe
<br>Comme une fleur s'épanouir.
<br>La puanteur était si forte, que sur l'herbe
<br>Vous crûtes vous évanouir.`},
},
mangeur: {
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} claque de sa machoire dans le vide avant de fuir.`,
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} croque votre Rêve ! Il emporte ${rencData.rencontre.force} de vos points de rêve actuels`,
postEchec: async (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(-rencData.rencontre.force),
poesieSucces: {
reference: "Conseil, Victor Hugo",
extrait: `Rois ! la bure est souvent jalouse du velours.
<br>Le peuple a froid l'hiver, le peuple a faim toujours.
<br>Rendez-lui son sort plus facile.
<br>Le peuple souvent porte un bien rude collier.
<br>Ouvrez l'école aux fils, aux pères l'atelier,
<br>À tous vos bras, auguste asile !`},
poesieEchec: {
reference: "El Desdichado, Gérard de Nerval",
extrait: `Suis-je Amour ou Phébus ?... Lusignan ou Biron ?
<br>Mon front est rouge encor du baiser de la Reine ;
<br>J'ai rêvé dans la Grotte où nage la sirène...`}
},
changeur: {
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[rencData.tmr.type].name} de votre choix en échange de sa liberté.`,
msgEchec: async (rencData) => `Le ${rencData.rencontre.name} vous embobine avec des promesses, et vous transporte sur une autre ${TMRType[rencData.tmr.type].name} sans attendre votre avis.`,
postSucces: async (tmrDialog, rencData) => {
tmrDialog.setStateRencontre(rencData.rencontre.type);
tmrDialog.choisirCaseType(rencData.tmr.type);
},
postEchec: async (tmrDialog, rencData) => {
const newTMR = await TMRUtility.getTMRAleatoire(it => it.type == rencData.tmr.type && it.coord != rencData.tmr.coord);
await tmrDialog.actor.forcerPositionTMRInconnue(newTMR);
tmrDialog.positionnerDemiReve(newTMR.coord);
},
poesieSucces: {
reference: "Caligula - IIIème chant, Gérard de Nerval",
extrait: `Allez, que le caprice emporte
<br>Chaque âme selon son désir,
<br>Et que, close après vous, la porte
<br>Ne se rouvre plus qu'au plaisir.`},
poesieEchec: {
reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `Les sages ont encore coutume de dire :
<br>&laquo; Mais comment les Dragons peuvent-ils
être influencés par une créature qui, tout
bien considéré, n'existe pas vraiment pour eux,
qui n'est que le fantasme de leur activité nocturne ? &raquo;`}
},
briseur: {
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`,
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`,
postEchec: async (tmrDialog, rencData) => tmrDialog.close(),
poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `La légende affirme que ce sont les Gnomes qui furent
les premiers haut-rêvants. En observant les pierres précieuses,
les gemmes qui sont les larmes de joie des Dragons, ils parvinrent à
en comprendre la langue. Et l'ayant comprise, ils purent s'en servir
pour influencer le cours du rêve`},
poesieEchec: {
reference: "Quand le rêve se brise, Cypora Sebagh",
extrait: `Quand le rêve se brise,
<br>Dans la plainte du jour,
<br>Ma mémoire devient grise
<br>Et sombre, tour à tour,
<br>Dans le puits du silence
<br>Et de la solitude ;
<br>Elle reprend son errance
<br>Parmi la multitude.`}
},
reflet: {
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} s'estompe dans l'oubli.`,
msgEchec: async (rencData)=> `Vous êtes submergé par un ${rencData.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`,
poesieSucces: {
reference: "Une charogne, Charles Baudelaire",
extrait: `Les formes s'effaçaient et n'étaient plus qu'un rêve,
<br>Une ébauche lente à venir
<br>Sur la toile oubliée, et que l'artiste achève
<br>Seulement par le souvenir.`},
poesieEchec: {
reference: "La chevelure, Charles Baudelaire",
extrait: `Longtemps ! toujours ! ma main dans ta crinière lourde
<br>Sèmera le rubis, la perle et le saphir,
<br>Afin qu'à mon désir tu ne sois jamais sourde !
<br>N'es-tu pas l'oasis où je rêve, et la gourde
<br>Où je hume à longs traits le vin du souvenir`}
},
passeurfou: {
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`,
msgEchec: async (rencData)=> TMRRencontres.msgEchecPasseurFou(rencData),
postEchec: async (tmrDialog, rencData) => TMRRencontres.postEchecPasseurFou(tmrDialog, rencData),
poesieSucces: {
reference: "Un Fou et un Sage, Jean de La Fontaine",
extrait: `Certain Fou poursuivait à coups de pierre un Sage.
<br>Le Sage se retourne et lui dit : Mon ami,
<br>C'est fort bien fait à toi ; reçois cet écu-ci :
<br>Tu fatigues assez pour gagner davantage.`},
poesieEchec: {
reference: "Guitare, Victor Hugo",
extrait: `Je la voyais passer de ma demeure,
<br>Et c'était tout.
<br>Mais à présent je m'ennuie à toute heure,
<br>Plein de dégoût,
<br>Rêveur oisif, l'âme dans la campagne,
<br>La dague au clou ...
<br>Le vent qui vient à travers la montagne
<br>M'a rendu fou !`}
},
tbblanc: {
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`,
msgEchec: async (rencData)=> `Le souffle du ${rencData.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`,
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 1),
poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement
des temps, le commencement des rêves. Durant cette période plus mythique
que réellement historique, les Dragons aimaient à se rêver eux-mêmes.`},
poesieEchec: {
reference: "Les Djinns, Victor Hugo",
extrait: `C'est l'essaim des Djinns qui passe,
<br>Et tourbillonne en sifflant !
<br>Les ifs, que leur vol fracasse,
<br>Craquent comme un pin brûlant.`},
},
tbnoir: {
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`,
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`,
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 2),
poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les
Gnomes s'enfoncèrent profondément sous les montagnes et la magie passa aux
mains des Humains qui en usèrent et abusèrent, se croyant devenus les maîtres du monde`},
poesieEchec: {
reference: "Lily, Pierre Perret",
extrait: `Elle aurait pas cru sans le voir
<br>Que la couleur du désespoir
<br>Là-bas aussi ce fût le noir.`},
},
tbrouge: {
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`,
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`,
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, rencData),
poesieSucces: {
reference: "Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet",
extrait: `Qu'est-ce de votre vie ? un tourbillon rouant
<br>De fumière à flot gris, parmi l'air se jouant,
<br>Qui passe plus soudain que foudre meurtrière.`},
poesieEchec: {
reference: "Les Djinns, poème Victor Hugo",
extrait: `Cris de l'enfer! voix qui hurle et qui pleure !
<br>L'horrible essaim, poussé par l'aquilon,
<br>Sans doute, ô ciel ! s'abat sur ma demeure.
<br>Le mur fléchit sous le noir bataillon.
<br>La maison crie et chancelle penchée,
<br>Et l'on dirait que, du sol arrachée,
<br>Ainsi qu'il chasse une feuille séchée,
<br>Le vent la roule avec leur tourbillon !`},
},
rdd: {
msgSucces: async (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${rencData.rencontre.force} points de rêve`,
msgEchec: async (rencData)=> `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${rencData.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`,
postSucces: async (tmrDialog, rencData) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, rencData),
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, rencData),
poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `Le monde est Rêve de Dragons, mais nous ne savons
<br>ni leur apparence ni qui sont les dragons.
<br>En dépit de l'iconographie qui les clame
<br>immenses créatures ailées crachant des flammes`},
poesieEchec: {
reference: "El Desdichado, Gérard de Nerval",
extrait: `Je suis le Ténébreux, le Veuf, l'Inconsolé,
<br>Le Prince d'Aquitaine à la Tour abolie :
<br>Ma seule Etoile est morte, et mon luth constellé
<br>Porte le Soleil noir de la Mélancolie.`}
},
}
/* -------------------------------------------- */
const mauvaisesRencontres = [
{ code: "mangeur", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6", refoulement: 2, isMauvaise: true },
{ code: "mangeur2d6", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "2d6", refoulement: 2, isMauvaise: true },
{ code: "reflet+4", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true },
{ code: "tbblanc+4", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true },
{ code: "tbnoir+4", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8+4", refoulement: 2, isPersistant: true, isMauvaise: true },
{ code: "passfou", name: "Passeur fou", type: "passeurfou", genre: "m", force: "2d8", refoulement: 2, isMauvaise: true },
{ code: "tbrouge", name: "Tourbillon rouge", type: "tbrouge", genre: "m", force: "2d8", refoulement: 3, isPersistant: true, isMauvaise: true }
]
/* -------------------------------------------- */
const rencontresStandard = [
{ code: "messager", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d4", ignorer: true },
{ code: "passeur", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d4", ignorer: true },
{ code: "fleur", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "1d6", ignorer: true },
{ code: "mangeur", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6" },
{ code: "changeur", name: "Changeur de Rêve", type: "changeur", genre: "m", force: "2d6" },
{ code: "briseur", name: "Briseur de Rêve", type: "briseur", genre: "m", force: "2d6", quitterTMR: true },
{ code: "reflet", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6", isPersistant: true },
{ code: "tbblanc", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6", isPersistant: true },
{ code: "tbnoir", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8", isPersistant: true },
{ code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1dr + 7", refoulement: 2, quitterTMR: true }
];
const rencontresPresentCite = [
{ code: "messager2d6", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d6", ignorer: true },
{ code: "passeur2d6", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d6", ignorer: true },
{ code: "fleur2d6", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "2d6", ignorer: true }
]
const rencontresAll = [].concat(rencontresStandard).concat(mauvaisesRencontres).concat(rencontresPresentCite);
const tableRencontres = {
cite: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }],
sanctuaire: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }],
plaines: [{ code: 'messager', range: [1, 20] }, { code: 'passeur', range: [21, 40] }, { code: 'fleur', range: [41, 55] }, { code: 'mangeur', range: [56, 60] }, { code: 'changeur', range: [61, 75] }, { code: 'briseur', range: [76, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
pont: [{ code: 'messager', range: [1, 20] }, { code: 'passeur', range: [21, 40] }, { code: 'fleur', range: [41, 55] }, { code: 'mangeur', range: [56, 60] }, { code: 'changeur', range: [61, 75] }, { code: 'briseur', range: [76, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
collines: [{ code: 'messager', range: [1, 15] }, { code: 'passeur', range: [16, 30] }, { code: 'fleur', range: [31, 42] }, { code: 'mangeur', range: [43, 54] }, { code: 'changeur', range: [55, 69] }, { code: 'briseur', range: [70, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
foret: [{ code: 'messager', range: [1, 15] }, { code: 'passeur', range: [16, 30] }, { code: 'fleur', range: [31, 42] }, { code: 'mangeur', range: [43, 54] }, { code: 'changeur', range: [55, 69] }, { code: 'briseur', range: [70, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
monts: [{ code: 'messager', range: [1, 10] }, { code: 'passeur', range: [11, 20] }, { code: 'fleur', range: [21, 26] }, { code: 'mangeur', range: [27, 44] }, { code: 'changeur', range: [45, 59] }, { code: 'briseur', range: [60, 75] }, { code: 'reflet', range: [76, 85] }, { code: 'tbblanc', range: [86, 92] }, { code: 'tbnoir', range: [93, 97] }, { code: 'rdd', range: [98, 100] }],
desert: [{ code: 'messager', range: [1, 10] }, { code: 'passeur', range: [11, 20] }, { code: 'fleur', range: [21, 26] }, { code: 'mangeur', range: [27, 44] }, { code: 'changeur', range: [45, 59] }, { code: 'briseur', range: [60, 75] }, { code: 'reflet', range: [76, 85] }, { code: 'tbblanc', range: [86, 92] }, { code: 'tbnoir', range: [93, 97] }, { code: 'rdd', range: [98, 100] }],
fleuve: [{ code: 'messager', range: [1, 5] }, { code: 'passeur', range: [6, 10] }, { code: 'fleur', range: [11, 13] }, { code: 'mangeur', range: [14, 37] }, { code: 'changeur', range: [38, 49] }, { code: 'briseur', range: [50, 65] }, { code: 'reflet', range: [66, 79] }, { code: 'tbblanc', range: [80, 89] }, { code: 'tbnoir', range: [90, 97] }, { code: 'rdd', range: [98, 100] }],
lac: [{ code: 'messager', range: [1, 5] }, { code: 'passeur', range: [6, 10] }, { code: 'fleur', range: [11, 13] }, { code: 'mangeur', range: [14, 37] }, { code: 'changeur', range: [38, 49] }, { code: 'briseur', range: [50, 65] }, { code: 'reflet', range: [66, 79] }, { code: 'tbblanc', range: [80, 89] }, { code: 'tbnoir', range: [90, 97] }, { code: 'rdd', range: [98, 100] }],
marais: [{ code: 'messager', range: [1, 2] }, { code: 'passeur', range: [3, 4] }, { code: 'fleur', range: [5, 5] }, { code: 'mangeur', range: [6, 29] }, { code: 'changeur', range: [30, 39] }, { code: 'briseur', range: [40, 60] }, { code: 'reflet', range: [61, 75] }, { code: 'tbblanc', range: [76, 86] }, { code: 'tbnoir', range: [87, 97] }, { code: 'rdd', range: [98, 100] }],
gouffre: [{ code: 'messager', range: [1, 2] }, { code: 'passeur', range: [3, 4] }, { code: 'fleur', range: [5, 5] }, { code: 'mangeur', range: [6, 29] }, { code: 'changeur', range: [30, 39] }, { code: 'briseur', range: [40, 60] }, { code: 'reflet', range: [61, 75] }, { code: 'tbblanc', range: [76, 86] }, { code: 'tbnoir', range: [87, 97] }, { code: 'rdd', range: [98, 100] }],
necropole: [{ code: 'mangeur', range: [1, 20] }, { code: 'changeur', range: [21, 30] }, { code: 'briseur', range: [31, 50] }, { code: 'reflet', range: [51, 65] }, { code: 'tbblanc', range: [66, 80] }, { code: 'tbnoir', range: [81, 97] }, { code: 'rdd', range: [98, 100] }],
desolation: [{ code: 'mangeur', range: [1, 20] }, { code: 'changeur', range: [21, 30] }, { code: 'briseur', range: [31, 50] }, { code: 'reflet', range: [51, 65] }, { code: 'tbblanc', range: [66, 80] }, { code: 'tbnoir', range: [81, 97] }, { code: 'rdd', range: [98, 100] }]
}
/* -------------------------------------------- */
export class TMRRencontres {
static gestionRencontre = {}
/* -------------------------------------------- */
static init() {
for (let type in typeRencontres) {
TMRRencontres.register(type, typeRencontres[type]);
}
}
/* -------------------------------------------- */
static register(type, rencontre) {
TMRRencontres.gestionRencontre[type] = rencontre;
}
/* -------------------------------------------- */
/**
* Retourne une recontre en fonction de la case et du tirage
* @param {*} terrain
* @param {*} roll
* @param {*} forcedRoll
*/
static async rollRencontre(terrain, roll = undefined) {
if (!terrain) {
ChatMessage.create({ content: "Un type de case doit être indiqué (par exemple sanctuaire, desert ou cité)" });
return false;
static async rollRencontre(terrain, forcedRoll) {
terrain = TMRUtility.findTMRLike(terrain);
if (terrain == undefined) {
return undefined;
}
if (!roll || roll <= 0 || roll > 100) {
roll = await RdDDice.rollTotal("1d100");
if (forcedRoll && (forcedRoll <= 0 || forcedRoll > 100)) {
forcedRoll = undefined;
}
let rencontre = await TMRRencontres.getRencontreAleatoire(terrain, roll);
const codeTerrain = Grammar.toLowerCaseNoAccent(terrain)
const table = await TMRRencontres.$buildTableRencontre(codeTerrain);
const [selected, roll] = await TMRRencontres.$selectRencontre(codeTerrain, table, forcedRoll);
const rencontre = await TMRRencontres.createRencontre(selected.rencontre);
TMRRencontres.$chatRolledRencontre(rencontre, terrain, table, roll, true);
return false;
}
/* -------------------------------------------- */
static async $buildTableRencontre(codeTerrain) {
let max = 0;
const items = await SystemCompendiums.getItems('rencontres', 'rencontre');
const filtreMauvaise = codeTerrain == 'mauvaise' ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
const rencontres = items.filter(it => it.type == 'rencontre')
.filter(filtreMauvaise)
.filter(it => it.system.frequence[codeTerrain] > 0)
.sort(Misc.ascending(it => it.system.ordreTri))
.map(it => {
const frequence = it.system.frequence[codeTerrain];
max += frequence;
return { rencontre: it, min: max - frequence + 1, max: max,frequence: frequence };
});
return rencontres;
}
/* -------------------------------------------- */
static async $selectRencontre(terrain, table, roll = undefined) {
const total = table.map(it => it.frequence).reduce(Misc.sum(), 0);
if (total == 0){
ui.notifications.warn(`Pas de rencontres définies pour ${terrain}`);
return undefined;
}
if (roll != undefined && (roll > total || roll <= 0)) {
ui.notifications.warn(`Jet de rencontre ${roll} en dehors de la table [1..${total}], le jet est relancé`);
roll = undefined;
}
if (!roll) {
roll = await RdDDice.rollTotal(`1d${total}`);
}
return [table.find(it => it.min <= roll && roll <= it.max), roll];
}
/* -------------------------------------------- */
static async createRencontre(rencontre, tmr = undefined) {
return rencontre.clone({
'system.force': await RdDDice.rollTotal(rencontre.system.formule),
'system.coord': tmr?.coord,
'system.date': game.system.rdd.calendrier.getDateFromIndex(),
'system.heure': game.system.rdd.calendrier.getCurrentHeure()
}, {save: false});
}
static async calculRencontre(rencontre, tmr = undefined) {
if (rencontre.system.coord == ""){
rencontre.system.coord = tmr?.coord;
}
if (rencontre.system.force == 0){
rencontre.system.force = await RdDDice.rollTotal(rencontre.system.formule);
}
if (rencontre.system.date == "" ) {
rencontre.system.date = game.system.rdd.calendrier.getDateFromIndex();
}
if (rencontre.system.heure == "") {
rencontre.system.heure = game.system.rdd.calendrier.getCurrentHeure();
}
return rencontre;
}
/* -------------------------------------------- */
static $chatRolledRencontre(rencontre, terrain, table, roll = 0, displayTable=false){
const total = table.map(it => it.frequence).reduce(Misc.sum(), 0);
const namesPercent = displayTable ?
table.map(it => `<br>${it.rencontre.name} : ${it.frequence}${total == 100 ? '%' : ''} (${it.min} - ${it.max})`).reduce((a, b) => a + b, '<hr>')
: '';
const chances = game.user.isGM
? (roll ? `Jet: ${roll} / ${total}` : `Valeurs: [1..${total}]`)
: (roll ? `Jet: ${Math.ceil(roll*100/total)} / 100` : '');
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: `Rencontre en ${terrain} (jet : ${roll}%)<br>Vous rencontrez un ${rencontre.name} de ${rencontre.force} Points de Rêve`
content: `Compendium: ${SystemCompendiums.getCompendium('rencontres')}
<br>Rencontre en ${terrain}:
${namesPercent}<hr>
<br>${chances}
<br>Rencontre: ${rencontre.name} ${rencontre.system.force} (${rencontre.system.formule})`
});
return false;
}
static async getPresentsCite() {
const rencontres = await SystemCompendiums.getDefaultItems('rencontres');
return rencontres.filter(it => !it.system.mauvaiseRencontre && it.system.presentCite).map(it =>
it.clone({ 'system.formule': "2d6" }, {save: false}));
}
static async getReveDeDragon(force) {
const rencontres = await SystemCompendiums.getDefaultItems('rencontres');
const reveDeDragon = rencontres.find(it => Grammar.equalsInsensitive(it.name, 'Rêve de Dragon'));
return reveDeDragon?.clone({ 'system.force': force }, {save: false});
}
/* -------------------------------------------- */
static getRencontre(index) {
let rencontre;
if (isNaN(index)) {
rencontre = rencontresAll.find(r => r.type == index) ?? rencontresAll.find(r => r.code == index)
}
else if (0 <= index && index < rencontresAll.length) {
rencontre = rencontresAll[index];
}
if (rencontre) {
return duplicate(rencontre);
}
else {
ui.notifications.info(`Pas de rencontre pour ${index}, seulement ${rencontresAll.length} rencontres sont connues.<br>Vous pouvez aussi essayer par type (ie: mangeur, fleur, fleur2d6, ...)`)
}
return undefined;
}
/* -------------------------------------------- */
static async getRencontreAleatoire(terrain, roll = undefined) {
if (!roll || roll <= 0 || roll > 100) {
roll = await RdDDice.rollTotal("1d100");
}
terrain = Grammar.toLowerCaseNoAccent(terrain);
const code = tableRencontres[terrain].find(it => it.range[0] <= roll && roll <= it.range[1]).code;
const rencontre = duplicate(rencontresStandard.find(it => it.code == code));
rencontre.roll = roll;
await TMRRencontres.evaluerForceRencontre(rencontre);
static async getRencontreAleatoire(tmr, mauvaise) {
const codeTerrain = mauvaise ? 'mauvaise' : tmr.type;
const table = await TMRRencontres.$buildTableRencontre(codeTerrain);
const [selected, roll] = await TMRRencontres.$selectRencontre(codeTerrain, table);
const rencontre = await TMRRencontres.createRencontre(selected.rencontre, tmr);
TMRRencontres.$chatRolledRencontre(rencontre, TMRUtility.getTMRType(tmr.coord), table, roll);
return rencontre;
}
/* -------------------------------------------- */
static async getMauvaiseRencontre(index = undefined) {
const rencontre = duplicate(
(index && index >= 0 && index < mauvaisesRencontres.length)
? mauvaisesRencontres[index]
: await RdDDice.rollOneOf(mauvaisesRencontres));
await TMRRencontres.evaluerForceRencontre(rencontre);
return rencontre;
}
/* -------------------------------------------- */
static async evaluerForceRencontre(rencontre) {
const rollForce = new Roll(rencontre.force);
await rollForce.evaluate();
rencontre.force = rollForce.total;
return rencontre.force;
}
/* -------------------------------------------- */
static isReveDeDragon(rencontre) {
return rencontre.type == "rdd";
}
/* -------------------------------------------- */
static getGestionRencontre(name) {
let gestion = TMRRencontres.gestionRencontre[name];
if (!gestion) {
ui.notifications.error(`La rencontre ${name} est inconnue, pas de méthode de gestion associée`)
gestion = TMRRencontres.gestionRencontre['messager'];
}
return gestion;
}
/* -------------------------------------------- */
static async gererRencontre(tmrDialog, rencData) {
let gestion = TMRRencontres.getGestionRencontre(rencData.rencontre.type);
if (rencData.rolled.isSuccess) {
rencData.message = await gestion.msgSucces(rencData);
if (rencData.nbRounds > 1) {
rencData.message += ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
}
rencData.poesie = gestion.poesieSucces;
return gestion.postSucces;
}
rencData.message = await gestion.msgEchec(rencData);
if (rencData.nbRounds > 1) {
rencData.message += ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
}
rencData.poesie = gestion.poesieEchec;
return gestion.postEchec;
}
/* -------------------------------------------- */
static async msgEchecPasseurFou(tmrData) {
tmrData.sortReserve = RdDDice.rollOneOf(tmrData.actor.itemTypes['sortreserve']);
if (tmrData.sortReserve) {
// Passeur fou positionne sur la case d'un sort en réserve
tmrData.newTMR = TMRUtility.getTMR(tmrData.sortReserve.coord);
} else {
// Déplacement aléatoire de la force du Passeur Fou
const newCoord = await RdDDice.rollOneOf(TMRUtility.getTMRPortee(tmrData.tmr.coord, tmrData.rencontre.force));
tmrData.newTMR = TMRUtility.getTMR(newCoord);
}
if (tmrData.sortReserve) {
return `Le ${tmrData.rencontre.name} vous dérobe la clé de vos sorts. Vous vous saisissez de lui, mais dans un nuage violet, il vous emporte en ${tmrData.newTMR.label} déclencher votre sort en réserve de ${tmrData.sortReserve.name}.`;
}
else {
return `Le ${tmrData.rencontre.name} tente de vous dérober la clé de vos sorts. Ne la trouvant pas, il déclenche un nuage violet et vous emporte en ${tmrData.newTMR.label}`;
}
}
/* -------------------------------------------- */
static async postEchecPasseurFou(tmrDialog, tmrData) {
if (tmrData.sortReserve) {
await tmrDialog.processSortReserve(tmrData.sortReserve);
}
await tmrDialog.positionnerDemiReve(tmrData.newTMR.coord);
if (tmrData.sortReserve) {
tmrDialog.close();
}
}
/* -------------------------------------------- */
static async onPostEchecTourbillon(tmrDialog, tmrData, cases) {
await tmrData.actor.reveActuelIncDec(-cases);
await TMRRencontres._toubillonner(tmrDialog, tmrData.actor, cases);
}
/* -------------------------------------------- */
static async onPostEchecTourbillonRouge(tmrDialog, rencontre) {
await rencontre.actor.reveActuelIncDec(-2); // -2 pts de Reve a chaque itération
TMRRencontres._toubillonner(tmrDialog, rencontre.actor, 4);
await rencontre.actor.santeIncDec("vie", -1); // Et -1 PV
}
/* -------------------------------------------- */
static async _toubillonner(tmrDialog, actor, cases) {
let coord = actor.system.reve.tmrpos.coord;
for (let i = 0; i < cases; i++) {
coord = await TMRUtility.deplaceTMRAleatoire(actor, coord).coord;
}
await tmrDialog.positionnerDemiReve(coord)
}
/* -------------------------------------------- */
static async onPostSuccessReveDeDragon(tmrDialog, tmrData) {
if (tmrData.rolled.isPart) {
await tmrData.actor.appliquerAjoutExperience(tmrData);
}
await tmrData.actor.resultCombatReveDeDragon(tmrData);
}
/* -------------------------------------------- */
static async onPostEchecReveDeDragon(tmrDialog, tmrData) {
await tmrData.actor.resultCombatReveDeDragon(tmrData);
tmrDialog.close();
}
}

View File

@@ -1,4 +1,3 @@
import { TMRRencontres } from "./tmr-rencontres.js";
import { Misc } from "./misc.js";
import { Grammar } from "./grammar.js";
import { RdDDice } from "./rdd-dice.js";
@@ -287,13 +286,30 @@ export class TMRUtility {
const tmr = TMRMapping[coord];
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
}
static findTMRLike(type, options = {inclusMauvaise:true}) {
const choix = [...Object.values(TMRType)]
if (options.inclusMauvaise){
choix.push({name: 'Mauvaise'});
}
const selection = Misc.findAllLike(type, choix).map(it => it.name);
if (selection.length == 0) {
ui.notifications.warn(`Un type de TMR doit être indiqué, '${type}' n'est pas trouvé dans ${choix}`);
return undefined;
}
if (selection.length > 1) {
ui.notifications.warn(`Plusieurs types de TMR pourraient correspondre à '${type}': ${selection}`);
return undefined;
}
return selection[0];
}
static typeTmrName(type) {
return Misc.upperFirst(TMRType[Grammar.toLowerCaseNoAccent(type)].name);
}
static buildSelectionTypesTMR(typesTMR) {
typesTMR= typesTMR?? [];
typesTMR = typesTMR?? [];
return Object.values(TMRType).map(value => Misc.upperFirst(value.name))
.sort()
.map(name => { return { name: name, selected: typesTMR.includes(name) } });
@@ -307,35 +323,6 @@ export class TMRUtility {
return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais';
}
/* -------------------------------------------- */
/** Some debug functions */
static async setForceRencontre(index, force = undefined) {
this.prochaineRencontre = TMRRencontres.getRencontre(index);
if (this.prochaineRencontre) {
if (force) {
this.prochaineRencontre.force = force;
}
else {
await TMRRencontres.evaluerForceRencontre(this.prochaineRencontre);
}
console.log("La prochaine rencontre sera:", this.prochaineRencontre.name, " force:", this.prochaineRencontre.force);
}
else {
ui.notifications.warn("Pas de prochaine rencontre valide pour " + index);
}
}
/* -------------------------------------------- */
static isForceRencontre() {
return this.prochaineRencontre;
}
/* -------------------------------------------- */
static utiliseForceRencontre() {
const rencontre = this.prochaineRencontre;
this.prochaineRencontre = undefined;
return rencontre;
}
/* -------------------------------------------- */
static async getDirectionPattern() {
return await RdDDice.rollOneOf(tmrRandomMovePatten);
@@ -343,24 +330,15 @@ export class TMRUtility {
/* -------------------------------------------- */
static async deplaceTMRAleatoire(actor, coord) {
return TMRUtility.deplaceTMRSelonPattern(actor, coord, await TMRUtility.getDirectionPattern(), 1);
}
/* -------------------------------------------- */
static async deplaceTMRSelonPattern(actor, coordTMR, direction, nTime) {
let coord;
for (let i = 0; i < nTime; i++) {
let currentOddq = TMRUtility.coordTMRToOddq(coordTMR);
currentOddq.col = currentOddq.col + direction.col;
currentOddq.row = currentOddq.row + direction.row;
if (this.isOddqInTMR(currentOddq)) { // Sortie de carte ! Ré-insertion aléatoire
coord = TMRUtility.getTMR(TMRUtility.oddqToCoordTMR(currentOddq));
} else {
coord = await actor.reinsertionAleatoire('Sortie de carte');
}
console.log("Nouvelle case iteration !!!", i, coord);
const currentOddq = TMRUtility.coordTMRToOddq(coord);
const direction = await TMRUtility.getDirectionPattern();
currentOddq.col = currentOddq.col + direction.col;
currentOddq.row = currentOddq.row + direction.row;
if (this.isOddqInTMR(currentOddq)) { // Sortie de carte ! Ré-insertion aléatoire
return TMRUtility.getTMR(TMRUtility.oddqToCoordTMR(currentOddq));
} else {
return await actor.reinsertionAleatoire('Sortie de carte');
}
return coord;
}
/* -------------------------------------------- */
@@ -372,9 +350,12 @@ export class TMRUtility {
return Object.values(TMRMapping).filter(filter);
}
static getCasesType(type) {
return TMRUtility.filterTMR(it => it.type == type).map(it => it.coord);
}
static findTMR(search) {
const labelSearch = Grammar.toLowerCaseNoAccent(search)
return TMRUtility.filterTMR(it => Grammar.toLowerCaseNoAccent(it.label).match(labelSearch) || it.coord == search);
return TMRUtility.filterTMR(it => Grammar.includesLowerCaseNoAccent(it.label, search) || it.coord == search);
}
static filterTMRCoord(filter) {

View File

@@ -0,0 +1,18 @@
import { Grammar } from "../grammar.js";
import { Draconique } from "./draconique.js";
import { Misc } from "../misc.js";
export class AugmentationSeuil extends Draconique {
constructor() {
super();
}
type() { return 'tete' }
match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('augmentation du seuil de reve'); }
manualMessage() { return false }
async onActorCreateOwned(actor, tete) {
const seuil = Misc.toInt(actor.system.reve.seuil.value) + 2;
await actor.update({ "system.reve.seuil.value": seuil })
}
}

View File

@@ -17,6 +17,7 @@ import { Pelerinage } from "./pelerinage.js";
import { Periple } from "./periple.js";
import { UrgenceDraconique } from "./urgence-draconique.js";
import { Grammar } from "../grammar.js";
import { AugmentationSeuil } from "./augmentation-seuil.js";
export class EffetsDraconiques {
@@ -37,6 +38,7 @@ export class EffetsDraconiques {
static pelerinage = new Pelerinage();
static periple = new Periple();
static urgenceDraconique = new UrgenceDraconique();
static augmentationSeuil = new AugmentationSeuil();
static init() {
Draconique.register(EffetsDraconiques.carteTmr);
@@ -56,6 +58,7 @@ export class EffetsDraconiques {
Draconique.register(EffetsDraconiques.pelerinage);
Draconique.register(EffetsDraconiques.periple);
Draconique.register(EffetsDraconiques.urgenceDraconique);
Draconique.register(EffetsDraconiques.augmentationSeuil)
}
/* -------------------------------------------- */
@@ -116,6 +119,10 @@ export class EffetsDraconiques {
.filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
}
static countAugmentationSeuil(actor) {
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Augmentation du seuil de rêve').length;
}
static isDonDoubleReve(actor) {
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Don de double-rêve').length>0;
}

View File

@@ -3,6 +3,7 @@ import { Grammar } from "../grammar.js";
import { TMRUtility } from "../tmr-utility.js";
import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js";
import { Draconique } from "./draconique.js";
import { TMRRencontres } from "../tmr-rencontres.js";
export class PresentCites extends Draconique {
@@ -46,15 +47,13 @@ export class PresentCites extends Draconique {
}
async choisirUnPresent(casetmr, onChoixPresent) {
const presents = await TMRRencontres.getPresentsCite()
const buttons = {};
presents.forEach(r => buttons['present'+r.id] = { icon: '<i class="fas fa-check"></i>', label: r.name, callback: async () => onChoixPresent(r) });
let d = new Dialog({
title: "Présent des cités",
content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faite votre choix`,
buttons: {
messager: { icon: '<i class="fas fa-check"></i>', label: "Un Messager des rêves", callback: () => onChoixPresent('messager2d6') },
passeur: { icon: '<i class="fas fa-check"></i>', label: "Un Passeur des rêves", callback: () => onChoixPresent('passeur2d6') },
fleur: { icon: '<i class="fas fa-check"></i>', label: "Une Fleur des rêves", callback: () => onChoixPresent('fleur2d6') },
},
default: "fleur"
content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faites votre choix`,
buttons: buttons
});
d.render(true);
}

View File

@@ -13,7 +13,7 @@ export class Rencontre extends Draconique {
async onActorCreateOwned(actor, item) { }
code() { return 'rencontre' }
tooltip(rencontre) { return `${rencontre.name} de force ${rencontre.force}` }
tooltip(rencontre) { return `${rencontre.name} de force ${rencontre.system.force}` }
img() { return 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp' }
createSprite(pixiTMR) {

View File

@@ -136,7 +136,6 @@
{"_id":"fLKFTvLWoj7juxQE","name":"Flèche, carreau","type":"objet","img":"systems/foundryvtt-reve-de-dragon/icons/objets/fleche.webp","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"rYShh2P1DNavdoBD":3},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.fLKFTvLWoj7juxQE"}}}
{"_id":"fOfVLKBacNEsDBn1","name":"Brandevin","type":"nourritureboisson","img":"systems/foundryvtt-reve-de-dragon/icons/liquides/liquide_sang.webp","data":{"description":"<p>Dose de 10cl de Brandevin</p>","sust":0,"boisson":true,"desaltere":0.2,"alcoolise":true,"force":-5,"qualite":0,"exotisme":0,"encombrement":0.05,"quantite":1,"cout":0.1},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"wYnBx3HmLfGzsj7P":3},"flags":{}}
{"name":"Etain (1 denier)","type":"monnaie","img":"systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp","data":{"quantite":0,"valeur_deniers":1,"encombrement":0.01,"description":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"jtRmvSuwkwMmIMf0":3},"flags":{"core":{"sourceId":"Item.UFCII7LUClrCWElV"}},"_id":"fhP2azbUBfmpF441"}
{"_id":"gYFprGGUUVG1Apcf","name":"Carquois","type":"conteneur","img":"systems/foundryvtt-reve-de-dragon/icons/objets/carquois.webp","data":{"description":"","capacite":2,"encombrement":0.1,"equipe":false,"qualite":0,"contenu":[],"cout":0.5},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"rYShh2P1DNavdoBD":3},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.zYI8mDiysWtmsSyy"}}}
{"_id":"gfU7oZL1JYqF3lAW","name":"Robe de lin","type":"objet","img":"systems/foundryvtt-reve-de-dragon/icons/objets/robe_lin.webp","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.6},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"jOzRscDxoXZWpGS6":3},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.gfU7oZL1JYqF3lAW"}}}
{"_id":"gmBC6SO3F5d64Vpl","name":"Miroir en cuivre poli 20 cm","type":"objet","img":"systems/foundryvtt-reve-de-dragon/icons/objets/miroir.webp","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":1},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"rYShh2P1DNavdoBD":3},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.equipement.gmBC6SO3F5d64Vpl"}}}
{"name":"Or (10 sols)","type":"monnaie","img":"systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp","data":{"quantite":0,"valeur_deniers":1000,"encombrement":0.01,"description":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"jtRmvSuwkwMmIMf0":3},"flags":{"core":{"sourceId":"Item.CmqfrDQgL61XIAqt"}},"_id":"gmbvvEx7hPrAy3zh"}

View File

@@ -0,0 +1,9 @@
{"name":"Au fleuve de Loire, Joachim du Bellay","type":"extraitpoetique","img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","system":{"extrait":"<p>&Ocirc; de qui la vive course <br>Prend sa bienheureuse source, <br>D&rsquo;une argentine fontaine, <br>Qui d&rsquo;une fuite lointaine, <br>Te rends au sein fluctueux <br>De l&rsquo;Oc&eacute;an monstrueux</p>","texte":""},"effects":[],"flags":{},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.2.0","coreVersion":"10.288"},"_id":"1xzVPsfnO3uukbc4","ownership":{"default":0}}
{"name":"Le Fleuve, Le Ratier Bretonien","type":"extraitpoetique","img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","system":{"extrait":"<p>Le courant du Fleuve<br>Te domine et te Porte<br>Avant que tu te moeuves<br>Combats le, ou il t'emporte</p>","texte":""},"effects":[],"flags":{},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.2.0","coreVersion":"10.288"},"_id":"4dPfQh9ovWa90M9o","ownership":{"default":0}}
{"name":"Des voies du Rêve (4), Denis Gerfaud","type":"extraitpoetique","img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","system":{"extrait":"<p>&laquo;Narcos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Vaisseau, <br>car Oniros s'embarque pour redescendre le Fleuve <br>vers son p&egrave;re Hypnos sur la Voie de l'Oubli&raquo;</p>","texte":"<p>Ainsi parlent les sages: <br>&laquo;Les Dragons sont cr&eacute;ateurs de leurs r&ecirc;ves, mais ils ne sont pas cr&eacute;ateurs d'Oniros <br>Les Dragons ne sont pas les ma&icirc;tres de leurs r&ecirc;ves, car ils ne sont pas ma&icirc;tres d'Oniros. <br>Nul ne sait qui est le cr&eacute;ateur des Dragons, ni qui est leur ma&icirc;tre. <br>Mais l'on peut supposer qui est le ma&icirc;tre du R&ecirc;ve des Dragons, c'est Oniros&raquo;</p>\n<p>&laquo;Et l'on peut savoir qui est le ma&icirc;tre d'Oniros, c'est le Fleuve de l'Oubli. <br>Et l'on sait qui est le cr&eacute;ateur du Fleuve de l'Oubli, c'est Hypnos et Narcos. <br>Mais l'on ne sait pas qui est le ma&icirc;tre du Fleuve de l'Oubli, <br>sinon peut-&ecirc;tre lui-m&ecirc;me, ou peut-&ecirc;tre Thanatos&raquo;</p>\n<p>&laquo;Hypnos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Serpent, car <br>tel les serpents, Oniros commence &agrave; remonter le Fleuve <br>sur le Voie du Souvenir vers son p&egrave;re Narcos&raquo;</p>\n<p>&laquo;Narcos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Vaisseau, <br>car Oniros s'embarque pour redescendre le Fleuve <br>vers son p&egrave;re Hypnos sur la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure <br>Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir. <br>Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Ainsi se succ&egrave;dent les Jours et les Ages. <br>Les jours des Dragons sont les Ages des Hommes.&raquo;</p>"},"effects":[],"flags":{},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.2.0","coreVersion":"10.288"},"_id":"7DNOC40NKHog49rb","ownership":{"default":0}}
{"name":"Des voies du Rêve (5), Denis Gerfaud","type":"extraitpoetique","img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","system":{"extrait":"<p>&laquo;Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure <br>Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir. <br>Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli&raquo;</p>","texte":"<p>Ainsi parlent les sages: <br>&laquo;Les Dragons sont cr&eacute;ateurs de leurs r&ecirc;ves, mais ils ne sont pas cr&eacute;ateurs d'Oniros <br>Les Dragons ne sont pas les ma&icirc;tres de leurs r&ecirc;ves, car ils ne sont pas ma&icirc;tres d'Oniros. <br>Nul ne sait qui est le cr&eacute;ateur des Dragons, ni qui est leur ma&icirc;tre. <br>Mais l'on peut supposer qui est le ma&icirc;tre du R&ecirc;ve des Dragons, c'est Oniros&raquo;</p>\n<p>&laquo;Et l'on peut savoir qui est le ma&icirc;tre d'Oniros, c'est le Fleuve de l'Oubli. <br>Et l'on sait qui est le cr&eacute;ateur du Fleuve de l'Oubli, c'est Hypnos et Narcos. <br>Mais l'on ne sait pas qui est le ma&icirc;tre du Fleuve de l'Oubli, <br>sinon peut-&ecirc;tre lui-m&ecirc;me, ou peut-&ecirc;tre Thanatos&raquo;</p>\n<p>&laquo;Hypnos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Serpent, car <br>tel les serpents, Oniros commence &agrave; remonter le Fleuve <br>sur le Voie du Souvenir vers son p&egrave;re Narcos&raquo;</p>\n<p>&laquo;Narcos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Vaisseau, <br>car Oniros s'embarque pour redescendre le Fleuve <br>vers son p&egrave;re Hypnos sur la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure <br>Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir. <br>Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Ainsi se succ&egrave;dent les Jours et les Ages. <br>Les jours des Dragons sont les Ages des Hommes.&raquo;</p>"},"effects":[],"flags":{},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.2.0","coreVersion":"10.288"},"_id":"Ym0pweWHr8CIZFIR","ownership":{"default":0}}
{"name":"Des voies du Rêve (1), Denis Gerfaud (Copy)","type":"extraitpoetique","img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","system":{"extrait":"<p>Ainsi parlent les sages: <br>&laquo;Les Dragons sont cr&eacute;ateurs de leurs r&ecirc;ves, mais ils ne sont pas cr&eacute;ateurs d'Oniros <br>Les Dragons ne sont pas les ma&icirc;tres de leurs r&ecirc;ves, car ils ne sont pas ma&icirc;tres d'Oniros. <br>Nul ne sait qui est le cr&eacute;ateur des Dragons, ni qui est leur ma&icirc;tre. <br>Mais l'on peut supposer qui est le ma&icirc;tre du R&ecirc;ve des Dragons, c'est Oniros&raquo;</p>","texte":"<p>Ainsi parlent les sages: <br>&laquo;Les Dragons sont cr&eacute;ateurs de leurs r&ecirc;ves, mais ils ne sont pas cr&eacute;ateurs d'Oniros <br>Les Dragons ne sont pas les ma&icirc;tres de leurs r&ecirc;ves, car ils ne sont pas ma&icirc;tres d'Oniros. <br>Nul ne sait qui est le cr&eacute;ateur des Dragons, ni qui est leur ma&icirc;tre. <br>Mais l'on peut supposer qui est le ma&icirc;tre du R&ecirc;ve des Dragons, c'est Oniros&raquo;</p>\n<p>&laquo;Et l'on peut savoir qui est le ma&icirc;tre d'Oniros, c'est le Fleuve de l'Oubli. <br>Et l'on sait qui est le cr&eacute;ateur du Fleuve de l'Oubli, c'est Hypnos et Narcos. <br>Mais l'on ne sait pas qui est le ma&icirc;tre du Fleuve de l'Oubli, <br>sinon peut-&ecirc;tre lui-m&ecirc;me, ou peut-&ecirc;tre Thanatos&raquo;</p>\n<p>&laquo;Hypnos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Serpent, car <br>tel les serpents, Oniros commence &agrave; remonter le Fleuve <br>sur le Voie du Souvenir vers son p&egrave;re Narcos&raquo;</p>\n<p>&laquo;Narcos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Vaisseau, <br>car Oniros s'embarque pour redescendre le Fleuve <br>vers son p&egrave;re Hypnos sur la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure <br>Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir. <br>Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Ainsi se succ&egrave;dent les Jours et les Ages. <br>Les jours des Dragons sont les Ages des Hommes.&raquo;</p>"},"effects":[],"flags":{},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.2.0","coreVersion":"10.288"},"_id":"fXBZ0YjF12LRtSOp","ownership":{"default":0}}
{"name":"Des voies du Rêve (6), Denis Gerfaud","type":"extraitpoetique","img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","system":{"extrait":"<p>&laquo;Ainsi se succ&egrave;dent les Jours et les Ages. <br>Les jours des Dragons sont les Ages des Hommes.&raquo;</p>","texte":"<p>Ainsi parlent les sages: <br>&laquo;Les Dragons sont cr&eacute;ateurs de leurs r&ecirc;ves, mais ils ne sont pas cr&eacute;ateurs d'Oniros <br>Les Dragons ne sont pas les ma&icirc;tres de leurs r&ecirc;ves, car ils ne sont pas ma&icirc;tres d'Oniros. <br>Nul ne sait qui est le cr&eacute;ateur des Dragons, ni qui est leur ma&icirc;tre. <br>Mais l'on peut supposer qui est le ma&icirc;tre du R&ecirc;ve des Dragons, c'est Oniros&raquo;</p>\n<p>&laquo;Et l'on peut savoir qui est le ma&icirc;tre d'Oniros, c'est le Fleuve de l'Oubli. <br>Et l'on sait qui est le cr&eacute;ateur du Fleuve de l'Oubli, c'est Hypnos et Narcos. <br>Mais l'on ne sait pas qui est le ma&icirc;tre du Fleuve de l'Oubli, <br>sinon peut-&ecirc;tre lui-m&ecirc;me, ou peut-&ecirc;tre Thanatos&raquo;</p>\n<p>&laquo;Hypnos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Serpent, car <br>tel les serpents, Oniros commence &agrave; remonter le Fleuve <br>sur le Voie du Souvenir vers son p&egrave;re Narcos&raquo;</p>\n<p>&laquo;Narcos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Vaisseau, <br>car Oniros s'embarque pour redescendre le Fleuve <br>vers son p&egrave;re Hypnos sur la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure <br>Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir. <br>Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Ainsi se succ&egrave;dent les Jours et les Ages. <br>Les jours des Dragons sont les Ages des Hommes.&raquo;</p>"},"effects":[],"flags":{},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.2.0","coreVersion":"10.288"},"_id":"k55zGYj5cTis14Cw","ownership":{"default":0}}
{"name":"Des voies du Rêve (2), Denis Gerfaud","type":"extraitpoetique","img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","system":{"extrait":"<p>&laquo;Et l'on peut savoir qui est le ma&icirc;tre d'Oniros, c'est le Fleuve de l'Oubli. <br>Et l'on sait qui est le cr&eacute;ateur du Fleuve de l'Oubli, c'est Hypnos et Narcos. <br>Mais l'on ne sait pas qui est le ma&icirc;tre du Fleuve de l'Oubli, <br>sinon peut-&ecirc;tre lui-m&ecirc;me, ou peut-&ecirc;tre Thanatos&raquo;</p>","texte":"<p>Ainsi parlent les sages: <br>&laquo;Les Dragons sont cr&eacute;ateurs de leurs r&ecirc;ves, mais ils ne sont pas cr&eacute;ateurs d'Oniros <br>Les Dragons ne sont pas les ma&icirc;tres de leurs r&ecirc;ves, car ils ne sont pas ma&icirc;tres d'Oniros. <br>Nul ne sait qui est le cr&eacute;ateur des Dragons, ni qui est leur ma&icirc;tre. <br>Mais l'on peut supposer qui est le ma&icirc;tre du R&ecirc;ve des Dragons, c'est Oniros&raquo;</p>\n<p>&laquo;Et l'on peut savoir qui est le ma&icirc;tre d'Oniros, c'est le Fleuve de l'Oubli. <br>Et l'on sait qui est le cr&eacute;ateur du Fleuve de l'Oubli, c'est Hypnos et Narcos. <br>Mais l'on ne sait pas qui est le ma&icirc;tre du Fleuve de l'Oubli, <br>sinon peut-&ecirc;tre lui-m&ecirc;me, ou peut-&ecirc;tre Thanatos&raquo;</p>\n<p>&laquo;Hypnos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Serpent, car <br>tel les serpents, Oniros commence &agrave; remonter le Fleuve <br>sur le Voie du Souvenir vers son p&egrave;re Narcos&raquo;</p>\n<p>&laquo;Narcos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Vaisseau, <br>car Oniros s'embarque pour redescendre le Fleuve <br>vers son p&egrave;re Hypnos sur la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure <br>Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir. <br>Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Ainsi se succ&egrave;dent les Jours et les Ages. <br>Les jours des Dragons sont les Ages des Hommes.&raquo;</p>"},"effects":[],"flags":{},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.2.0","coreVersion":"10.288"},"_id":"rjlGncoP26PljA2G","ownership":{"default":0}}
{"name":"Des voies du Rêve (3), Denis Gerfaud","type":"extraitpoetique","img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","system":{"extrait":"<p>&laquo;Hypnos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Serpent, car <br>tel les serpents, Oniros commence &agrave; remonter le Fleuve <br>sur le Voie du Souvenir vers son p&egrave;re Narcos&raquo;</p>","texte":"<p>Ainsi parlent les sages: <br>&laquo;Les Dragons sont cr&eacute;ateurs de leurs r&ecirc;ves, mais ils ne sont pas cr&eacute;ateurs d'Oniros <br>Les Dragons ne sont pas les ma&icirc;tres de leurs r&ecirc;ves, car ils ne sont pas ma&icirc;tres d'Oniros. <br>Nul ne sait qui est le cr&eacute;ateur des Dragons, ni qui est leur ma&icirc;tre. <br>Mais l'on peut supposer qui est le ma&icirc;tre du R&ecirc;ve des Dragons, c'est Oniros&raquo;</p>\n<p>&laquo;Et l'on peut savoir qui est le ma&icirc;tre d'Oniros, c'est le Fleuve de l'Oubli. <br>Et l'on sait qui est le cr&eacute;ateur du Fleuve de l'Oubli, c'est Hypnos et Narcos. <br>Mais l'on ne sait pas qui est le ma&icirc;tre du Fleuve de l'Oubli, <br>sinon peut-&ecirc;tre lui-m&ecirc;me, ou peut-&ecirc;tre Thanatos&raquo;</p>\n<p>&laquo;Hypnos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Serpent, car <br>tel les serpents, Oniros commence &agrave; remonter le Fleuve <br>sur le Voie du Souvenir vers son p&egrave;re Narcos&raquo;</p>\n<p>&laquo;Narcos engendre le fils dont il est la m&egrave;re &agrave; l'heure du Vaisseau, <br>car Oniros s'embarque pour redescendre le Fleuve <br>vers son p&egrave;re Hypnos sur la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure <br>Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir. <br>Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli&raquo;</p>\n<p>&laquo;Ainsi se succ&egrave;dent les Jours et les Ages. <br>Les jours des Dragons sont les Ages des Hommes.&raquo;</p>"},"effects":[],"flags":{},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.2.0","coreVersion":"10.288"},"_id":"xMigGwI39BORZ82r","ownership":{"default":0}}
{"name":"Incompatibilité, Charles Beaudelaire","type":"extraitpoetique","img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","system":{"extrait":"<p>Et lorsque par hasard une nu&eacute;e errante <br>Assombrit dans son vol le lac silencieux, <br>On croirait voir la robe ou l'ombre transparente <br>D'un esprit qui voyage et passe dans les cieux.</p>","texte":""},"effects":[],"flags":{},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.2.0","coreVersion":"10.288"},"_id":"yJ3m3fheGJluiGDx","ownership":{"default":0}}

View File

@@ -1,4 +1,4 @@
{"_id":"0jrEZ62Q2Jz4kBGf","name":"Mauvaise rencontre en perspective","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Tirer la prochaine rencontre dans les TMR sur la @Compendium[foundryvtt-reve-de-dragon.tables-diverses.66ye0OOxBO9LEjdd]{Table spéciale de rencontres}</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[]}
{"_id":"0jrEZ62Q2Jz4kBGf","name":"Mauvaise rencontre en perspective","type":"queue","flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>La prochaine rencontre dans les TMR sera tir&eacute;e de la @Compendium[foundryvtt-reve-de-dragon.tables-diverses.66ye0OOxBO9LEjdd]{Table sp&eacute;ciale de rencontres}</p>","descriptionmj":"","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":null,"modifiedTime":1668033514731,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"0uc2pMIGL03Hq2Hn","name":"Idée fixe : Anorexie. Ne rien avaler, ni solide, ni liquide, pas même une potion","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","data":{"description":"<p>Prend effet imm&eacute;diatement et dure jusqu'&agrave; la <strong>fin de l'heure du Ch&acirc;teau Dormant </strong>du <strong>lendemain.<br /></strong>Si pass&eacute; ce d&eacute;lai, l'occasion de la manifester ne s'est pas pr&eacute;sent&eacute;e, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","refoulement":1,"duree":"","restant":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"rYShh2P1DNavdoBD":3},"flags":{}}
{"_id":"1gGVlZM0UyifL6RK","name":"Souvenir obsessionnel de l'archétype","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"queue","data":{"description":"<p>Les prochains points dexpérience dus au stress doivent être mis dans une compétence déterminée aléatoirement par la table de @Compendium[foundryvtt-reve-de-dragon.tables-diverses.E0WLgjn6LA9WsvKJ]{Détermination aléatoire de compétence}.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[]}
{"_id":"1l59lWbtvYp74OTb","name":"Désir lancinant : Briser un objet de verre","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'exp&eacute;rience ne peut plus &ecirc;tre gagn&eacute; par l'exercice en cas de particuli&egrave;re et d'ajustement final n&eacute;gatif.<br />Les points d'exp&eacute;rience dus au stress ne sont pas affect&eacute;s.</p>","descriptionmj":"","refoulement":1,"duree":"","restant":0},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"rYShh2P1DNavdoBD":3},"flags":{}}

17
packs/rencontres.db Normal file
View File

@@ -0,0 +1,17 @@
{"name":"Passeur des Rêves","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","system":{"genre":"m","formule":"2d4","refoulement":0,"presentCite":true,"mauvaiseRencontre":false,"ordreTri":2,"force":0,"coord":"","date":"","heure":"","succes":{"effets":["passeur"],"message":"Le Passeur des Rêves propose de vous transporter{{#if actor.system.reve.tmrpos.cache}}, mais vous ne savez pas où vous êtes{{else}} à {{rencontre.system.force}} cases de {{tmr.label}}{{/if}}.","poesie":"<p>Comme je descendais des Fleuves impassibles,<br>Je ne me sentis plus guid&eacute; par les haleurs :<br>Des Peaux-Rouges criards les avaient pris pour cibles,<br>Les ayant clou&eacute;s nus aux poteaux de couleurs.</p>","reference":"Le bateau ivre, Arthur Rimbaud"},"echec":{"effets":[],"message":"Le prix que demande le Passeur des Rêves est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.","poesie":"<p>Loin des peuples vivants, errantes, condamn&eacute;es,<br>A travers les d&eacute;serts courez comme les loups ;<br>Faites votre destin, &acirc;mes d&eacute;sordonn&eacute;es,<br>Et fuyez l'infini que vous portez en vous !</p>","reference":"Femmes damnées (2), Charles Baudelaire"},"frequence":{"cite":25,"sanctuaire":25,"plaines":20,"pont":20,"collines":15,"foret":15,"monts":10,"desert":10,"fleuve":5,"lac":5,"marais":2,"gouffre":2,"necropole":0,"desolation":0,"mauvaise":0},"description":""},"effects":[],"flags":{"core":{"sourceId":"Item.Ffk9pio1qy4Z28Lc"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036337,"modifiedTime":1668036933995,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"0IQLIYklxPIGjHT8","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Messager des Rêves","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","system":{"genre":"m","formule":"2d4","refoulement":0,"presentCite":true,"mauvaiseRencontre":false,"ordreTri":1,"force":0,"coord":"","date":"","heure":"","succes":{"effets":["messager"],"message":"Le Messager des rêves propose d'emmener votre message {{#if actor.system.reve.tmrpos.cache}}, mais vous ne savez pas où vous êtes{{else}} à {{rencontre.system.force}} cases de {{tmr.label}}{{/if}}.","poesie":"<p>J'irai l&agrave;-bas o&ugrave; l'arbre et l'homme, pleins de s&egrave;ve,<br>Se p&acirc;ment longuement sous l'ardeur des climats ;<br>Fortes tresses, soyez la houle qui m'enl&egrave;ve !</p>","reference":"La chevelure, Charles Baudelaire"},"echec":{"effets":[],"message":"Le Messager des Rêves est pressé et continue son chemin d'une traite sans vous accorder un regard.","poesie":"<p>En r&eacute;alit&eacute;, tous les &eacute;l&eacute;ments du r&ecirc;ve des Dragons expriment<br>le Draconic : chaque pierre, chaque fleur, chaque goutte d'eau,<br>chaque nuage est porteur d'un message dans la langue des Dragons</p>","reference":"Rêve de Dragon, Denis Gerfaud"},"frequence":{"cite":25,"sanctuaire":25,"plaines":20,"pont":20,"collines":15,"foret":15,"monts":10,"desert":10,"fleuve":5,"lac":5,"marais":2,"gouffre":2,"necropole":0,"desolation":0,"mauvaise":0},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.Ffk9pio1qy4Z28Lc"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036337,"modifiedTime":1668036933994,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"0MwHtPpFV2lTeCtt","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Briseur de Rêve","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","system":{"genre":"m","formule":"2d6","refoulement":1,"presentCite":false,"mauvaiseRencontre":false,"ordreTri":6,"force":0,"coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.","poesie":"<p>La l&eacute;gende affirme que ce sont les Gnomes qui furent les premiers haut-r&ecirc;vants. En observant les pierres pr&eacute;cieuses, les gemmes qui sont les larmes de joie des Dragons, ils parvinrent &agrave; en comprendre la langue. Et l'ayant comprise, ils purent s'en servir pour influencer le cours du r&ecirc;ve.</p>","reference":"Rêve de Dragon, Denis Gerfaud"},"echec":{"effets":["rompu"],"message":"Le {{rencontre.name}} vous déconcentre au point de briser votre demi-rêve.","poesie":"<p>Quand le r&ecirc;ve se brise,<br>Dans la plainte du jour,<br>Ma m&eacute;moire devient grise<br>Et sombre, tour &agrave; tour,<br>Dans le puits du silence<br>Et de la solitude ;<br>Elle reprend son errance<br>Parmi la multitude.</p>","reference":"Quand le rêve se brise, Cypora Sebagh"},"frequence":{"cite":5,"sanctuaire":5,"plaines":7,"pont":7,"collines":13,"foret":13,"monts":16,"desert":16,"fleuve":16,"lac":16,"marais":21,"gouffre":21,"necropole":20,"desolation":20,"mauvaise":0},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.dvEiIk0HFGsvyb5F"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036340,"modifiedTime":1668036933993,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"3e6jIvyy1e7OzYcB","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Reflet d'ancien Rêve","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","system":{"genre":"m","formule":"2d6","refoulement":1,"presentCite":false,"mauvaiseRencontre":false,"ordreTri":7,"force":"0","coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} s'estompe dans l'oubli.","poesie":"<p>Les formes s'effa&ccedil;aient et n'&eacute;taient plus qu'un r&ecirc;ve,<br>Une &eacute;bauche lente &agrave; venir<br>Sur la toile oubli&eacute;e, et que l'artiste ach&egrave;ve<br>Seulement par le souvenir.</p>","reference":"Une charogne, Charles Baudelaire"},"echec":{"effets":["persistant"],"message":"Vous êtes submergé par un {{rencontre.name}}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!","poesie":"<p>Longtemps ! toujours ! ma main dans ta crini&egrave;re lourde<br>S&egrave;mera le rubis, la perle et le saphir,<br>Afin qu'&agrave; mon d&eacute;sir tu ne sois jamais sourde !<br>N'es-tu pas l'oasis o&ugrave; je r&ecirc;ve, et la gourde<br>O&ugrave; je hume &agrave; longs traits le vin du souvenir</p>","reference":"La chevelure, Charles Baudelaire"},"frequence":{"cite":5,"sanctuaire":5,"plaines":6,"pont":6,"collines":6,"foret":6,"monts":10,"desert":10,"fleuve":14,"lac":14,"marais":15,"gouffre":15,"necropole":15,"desolation":15,"mauvaise":0},"description":""},"effects":[],"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3},"flags":{"core":{"sourceId":"Item.drXUmMGrrY9jyJPp"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667773074055,"modifiedTime":1668036933995,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"folder":null,"sort":0,"_id":"5IEjrkpQ2YNFiUP4"}
{"name":"Tourbillon noir","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","system":{"genre":"m","formule":"2d8","refoulement":1,"presentCite":false,"mauvaiseRencontre":false,"ordreTri":9,"force":0,"coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.","poesie":"<p>Car le Second &Acirc;ge fut bel et bien celui des Magiciens. Durant cette p&eacute;riode, les Gnomes s'enfonc&egrave;rent profond&eacute;ment sous les montagnes et la magie passa aux mains des Humains qui en us&egrave;rent et abus&egrave;rent, se croyant devenus les ma&icirc;tres du monde</p>","reference":"Rêve de Dragon, Denis Gerfaud"},"echec":{"effets":["reve-1","reve-1","aleatoire","aleatoire","persistant"],"message":"Le {{rencontre.name}} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.","poesie":"<p>Elle aurait pas cru sans le voir<br>Que la couleur du d&eacute;sespoir<br>L&agrave;-bas aussi ce f&ucirc;t le noir.</p>","reference":"Lily, Pierre Perret"},"frequence":{"cite":3,"sanctuaire":3,"plaines":4,"pont":4,"collines":4,"foret":4,"monts":5,"desert":5,"fleuve":8,"lac":8,"marais":11,"gouffre":11,"necropole":17,"desolation":17,"mauvaise":0},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.81b2cjAzl9hfK7Zt"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036336,"modifiedTime":1668036933995,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"89NtInRn4uWArlct","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Reflet d'ancien Rêve","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","system":{"genre":"m","formule":"2d6+4","refoulement":2,"presentCite":false,"mauvaiseRencontre":true,"ordreTri":3,"force":0,"coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} s'estompe dans l'oubli.","poesie":"<p>Les formes s'effa&ccedil;aient et n'&eacute;taient plus qu'un r&ecirc;ve,<br>Une &eacute;bauche lente &agrave; venir<br>Sur la toile oubli&eacute;e, et que l'artiste ach&egrave;ve<br>Seulement par le souvenir.</p>","reference":"Une charogne, Charles Baudelaire"},"echec":{"effets":["persistant"],"message":"Vous êtes submergé par un {{rencontre.name}}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!","poesie":"<p>Longtemps ! toujours ! ma main dans ta crini&egrave;re lourde<br>S&egrave;mera le rubis, la perle et le saphir,<br>Afin qu'&agrave; mon d&eacute;sir tu ne sois jamais sourde !<br>N'es-tu pas l'oasis o&ugrave; je r&ecirc;ve, et la gourde<br>O&ugrave; je hume &agrave; longs traits le vin du souvenir</p>","reference":"La chevelure, Charles Baudelaire"},"frequence":{"cite":5,"sanctuaire":5,"plaines":6,"pont":6,"collines":6,"foret":6,"monts":10,"desert":10,"fleuve":14,"lac":14,"marais":15,"gouffre":15,"necropole":15,"desolation":15,"mauvaise":23},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.MB2qOlTsEUTQkRVL"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036338,"modifiedTime":1668036933995,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"U6WoTkHRwC4DicuZ","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Changeur de Rêve","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","system":{"genre":"m","formule":"2d6","refoulement":1,"presentCite":false,"mauvaiseRencontre":false,"ordreTri":5,"force":0,"coord":"","date":"","heure":"","succes":{"effets":["teleport"],"message":"Le {{rencontre.name}} vaincu accepte de vous déplacer sur une autre case {{caseTmr-type tmr.coord}} de votre choix en échange de sa liberté.","poesie":"<p>Allez, que le caprice emporte<br>Chaque &acirc;me selon son d&eacute;sir,<br>Et que, close apr&egrave;s vous, la porte<br>Ne se rouvre plus qu'au plaisir.</p>","reference":"Caligula - IIIème chant, Gérard de Nerval"},"echec":{"effets":["teleport-aleatoire"],"message":"Le {{rencontre.name}} vous embobine avec des promesses, et vous transporte sur une autre case {{caseTmr-type tmr.coord}} sans attendre votre avis.","poesie":"<p>Les sages ont encore coutume de dire : <br>&laquo; Mais comment les Dragons peuvent-ils &ecirc;tre influenc&eacute;s par une cr&eacute;ature qui, tout bien consid&eacute;r&eacute;, n'existe pas vraiment pour eux, qui n'est que le fantasme de leur activit&eacute; nocturne ? &raquo;</p>","reference":"Rêve de Dragon, Denis Gerfaud"},"frequence":{"cite":10,"sanctuaire":10,"plaines":15,"pont":15,"collines":15,"foret":15,"monts":15,"desert":15,"fleuve":12,"lac":12,"marais":10,"gouffre":10,"necropole":10,"desolation":10,"mauvaise":0},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.q4uyAZoFPyc4x8XI"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036340,"modifiedTime":1668036933994,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"WeCnQirDR1r3TUFw","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Rêve de Dragon","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/styles/img/rdd_pause.webp","system":{"genre":"m","formule":"1dr+7","refoulement":2,"presentCite":false,"mauvaiseRencontre":false,"ordreTri":10,"force":0,"coord":"","date":"","heure":"","succes":{"effets":["reve+f","part+tete","part+xp","seuil"],"message":"A tout seigneur, tout honneur, vous faites face à un {{rencontre.name}}. Vous le maîtrisez et gagnez ses {{rencontre.system.force}} points de rêve.","poesie":"<p>Le monde est R&ecirc;ve de Dragons, mais nous ne savons <br>Ni leur apparence ni qui sont les dragons. <br>En d&eacute;pit de l'iconographie qui les clame <br>Immenses cr&eacute;atures ail&eacute;es crachant des flammes</p>","reference":"Rêve de Dragon, Denis Gerfaud"},"echec":{"effets":["echec-queue"],"message":"A tout seigneur, tout honneur, vous faites face à un {{rencontre.name}}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez {{#if rolled.isETotal}}deux queues{{else}}une queue{{/if}} de dragon!","poesie":"<p>Je suis le T&eacute;n&eacute;breux, &ndash; le Veuf, &ndash; l'Inconsol&eacute;, <br>Le Prince d'Aquitaine &agrave; la Tour abolie : <br>Ma seule Etoile est morte, &ndash; et mon luth constell&eacute; <br>Porte le Soleil noir de la M&eacute;lancolie.</p>","reference":"El Desdichado, Gérard de Nerval"},"frequence":{"cite":3,"sanctuaire":3,"plaines":3,"pont":3,"collines":3,"foret":3,"monts":3,"desert":3,"fleuve":3,"lac":3,"marais":3,"gouffre":3,"necropole":3,"desolation":3,"mauvaise":0},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.Hw40Q8jS9wmukgU4"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036338,"modifiedTime":1668036933995,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"dWKuUc29ysrlPZFg","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Passeur fou","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","system":{"genre":"m","formule":"2d8","refoulement":2,"presentCite":false,"mauvaiseRencontre":true,"ordreTri":26,"force":0,"coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le Passeur fou tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.","poesie":"<p>Certain Fou poursuivait &agrave; coups de pierre un Sage.<br>Le Sage se retourne et lui dit : Mon ami,<br>C'est fort bien fait &agrave; toi ; re&ccedil;ois cet &eacute;cu-ci :<br>Tu fatigues assez pour gagner davantage.</p>","reference":"Un Fou et un Sage, Jean de La Fontaine"},"echec":{"effets":["sort-aleatoire"],"message":"{{#if sortReserve}}Le Passeur fou dérobe la clé de vos sorts. Vous vous saisissez de lui, mais dans un nuage violet, il vous emporte {{newTMR.label}} déclencher votre sort en réserve de {{sortReserve.name}}.{{else}}Le Passeur fou tente de vous dérober la clé de vos sorts. Ne la trouvant pas, il déclenche un nuage violet et vous emporte en {{newTMR.label}}.{{/if}}","poesie":"<p>Je la voyais passer de ma demeure,<br>Et c'&eacute;tait tout.<br>Mais &agrave; pr&eacute;sent je m'ennuie &agrave; toute heure,<br>Plein de d&eacute;go&ucirc;t,<br>R&ecirc;veur oisif, l'&acirc;me dans la campagne,<br>La dague au clou ... &ndash;<br>Le vent qui vient &agrave; travers la montagne<br>M'a rendu fou !</p>","reference":"Guitare, Victor Hugo"},"frequence":{"cite":0,"sanctuaire":0,"plaines":0,"pont":0,"collines":0,"foret":0,"monts":0,"desert":0,"fleuve":0,"lac":0,"marais":0,"gouffre":0,"necropole":0,"desolation":0,"mauvaise":1},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.HkYBb3Ls4W15tKwo"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036338,"modifiedTime":1668036933995,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"eVxv2FMRZOo7aTWB","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Mangeur de Rêve","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","system":{"genre":"m","formule":"1d6","refoulement":1,"presentCite":false,"mauvaiseRencontre":false,"ordreTri":4,"force":0,"coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} claque de sa machoire dans le vide avant de fuir.","poesie":"<p>Rois ! la bure est souvent jalouse du velours.<br>Le peuple a froid l'hiver, le peuple a faim toujours.<br>Rendez-lui son sort plus facile.<br>Le peuple souvent porte un bien rude collier.<br>Ouvrez l'&eacute;cole aux fils, aux p&egrave;res l'atelier,<br>&Agrave; tous vos bras, auguste asile !</p>","reference":"Conseil, Victor Hugo"},"echec":{"effets":["reve-f"],"message":"Le {{rencontre.name}} croque votre Rêve ! Il emporte {{rencontre.system.force}} de vos points de rêve actuels","poesie":"<div>\n<div>Suis-je Amour ou Ph&eacute;bus ?... Lusignan ou Biron ?</div>\n<div>Mon front est rouge encor du baiser de la Reine ;</div>\n<div>J'ai r&ecirc;v&eacute; dans la Grotte o&ugrave; nage la sir&egrave;ne...</div>\n</div>","reference":"El Desdichado, Gérard de Nerval"},"frequence":{"cite":5,"sanctuaire":5,"plaines":5,"pont":5,"collines":12,"foret":12,"monts":18,"desert":18,"fleuve":24,"lac":24,"marais":24,"gouffre":24,"necropole":20,"desolation":20,"mauvaise":1},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.3SA5An6kPlpcDEIj"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036336,"modifiedTime":1668036933994,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"fd89RWxlO8BF1FFJ","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Tourbillon noir","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","system":{"genre":"m","formule":"2d8+4","refoulement":2,"presentCite":false,"mauvaiseRencontre":true,"ordreTri":25,"force":0,"coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.","poesie":"<p>Car le Second &Acirc;ge fut bel et bien celui des Magiciens. Durant cette p&eacute;riode, les Gnomes s'enfonc&egrave;rent profond&eacute;ment sous les montagnes et la magie passa aux mains des Humains qui en us&egrave;rent et abus&egrave;rent, se croyant devenus les ma&icirc;tres du monde</p>","reference":"Rêve de Dragon, Denis Gerfaud"},"echec":{"effets":["reve-1","reve-1","aleatoire","aleatoire","persistant"],"message":"Le {{rencontre.name}} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.","poesie":"<p>Elle aurait pas cru sans le voir<br>Que la couleur du d&eacute;sespoir<br>L&agrave;-bas aussi ce f&ucirc;t le noir.</p>","reference":"Lily, Pierre Perret"},"frequence":{"cite":3,"sanctuaire":3,"plaines":4,"pont":4,"collines":4,"foret":4,"monts":5,"desert":5,"fleuve":8,"lac":8,"marais":11,"gouffre":11,"necropole":17,"desolation":17,"mauvaise":1},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.D0gbC3plAesQx3uq"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036336,"modifiedTime":1668036933995,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"hmeuLiLh5nkuQ4eD","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Fleur des rêves","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","system":{"genre":"f","formule":"1d6","refoulement":0,"presentCite":true,"mauvaiseRencontre":false,"ordreTri":3,"force":"0","coord":"","date":"","heure":"","succes":{"effets":["reve+f"],"message":"Vous cueillez la {{rencontre.name}}, son parfum vous apporte {{rencontre.system.force}} points de Rêve.","poesie":"<p>Et qui sait si les fleurs nouvelles que je r&ecirc;ve<br>Trouveront dans ce sol lav&eacute; comme une gr&egrave;ve<br>Le mystique aliment qui ferait leur vigueur ?</p>","reference":"L'Ennemi, Charles Baudelaire","effet":["reve+f"]},"echec":{"effets":[],"message":"La {{rencontre.name}} se fane et disparaît entre vos doigts.","poesie":"<p>Et le ciel regardait la carcasse superbe<br>Comme une fleur s'&eacute;panouir.<br>La puanteur &eacute;tait si forte, que sur l'herbe<br>Vous cr&ucirc;tes vous &eacute;vanouir.</p>","reference":"Une charogne, Charles Baudelaire"},"frequence":{"cite":15,"sanctuaire":15,"plaines":15,"pont":15,"collines":12,"foret":12,"monts":6,"desert":6,"fleuve":3,"lac":3,"marais":1,"gouffre":1,"necropole":0,"desolation":0,"mauvaise":0},"description":"","onSucces":{"effets":[],"message":"","poesie":"","reference":""},"onEchec":{"effets":[],"message":"","poesie":"","reference":""},"descriptionmj":"","code":"","onSuccess":{"effets":[],"message":"","poesie":"","reference":""}},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.2ywduc2BHGpVvUbz"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036335,"modifiedTime":1668036933994,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"jtJk1ptJXsdsGZHA","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Tourbillon rouge","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","system":{"genre":"m","formule":"2d8","refoulement":3,"presentCite":false,"mauvaiseRencontre":true,"ordreTri":27,"force":0,"coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.","poesie":"<p>Qu'est-ce de votre vie ? un tourbillon rouant<br>De fumi&egrave;re &agrave; flot gris, parmi l'air se jouant,<br>Qui passe plus soudain que foudre meurtri&egrave;re.</p>","reference":"Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet"},"echec":{"effets":["aleatoire","aleatoire","aleatoire","aleatoire","reve-1","reve-1","vie-1","persistant"],"message":"Le {{rencontre.name}} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.","poesie":"<p>Cris de l'enfer! voix qui hurle et qui pleure !<br>L'horrible essaim, pouss&eacute; par l'aquilon,<br>Sans doute, &ocirc; ciel ! s'abat sur ma demeure.<br>Le mur fl&eacute;chit sous le noir bataillon.<br>La maison crie et chancelle pench&eacute;e,<br>Et l'on dirait que, du sol arrach&eacute;e,<br>Ainsi qu'il chasse une feuille s&eacute;ch&eacute;e,<br>Le vent la roule avec leur tourbillon !</p>","reference":"Les Djinns, poème Victor Hugo"},"frequence":{"cite":0,"sanctuaire":0,"plaines":0,"pont":0,"collines":0,"foret":0,"monts":0,"desert":0,"fleuve":0,"lac":0,"marais":0,"gouffre":0,"necropole":0,"desolation":0,"mauvaise":1},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.WiyUvZX4oTAd82s3"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036339,"modifiedTime":1668036933996,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"nD7p8ROloR6ElTpW","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Tourbillon blanc","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","system":{"genre":"m","formule":"2d6","refoulement":1,"presentCite":false,"mauvaiseRencontre":false,"ordreTri":8,"force":"0","coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.","poesie":"<p>Le Premier &Acirc;ge fut appel&eacute; l'&Acirc;ge des Dragons. Ce fut le commencement<br>des temps, le commencement des r&ecirc;ves. Durant cette p&eacute;riode plus mythique<br>que r&eacute;ellement historique, les Dragons aimaient &agrave; se r&ecirc;ver eux-m&ecirc;mes.</p>","reference":"Rêve de Dragon, Denis Gerfaud"},"echec":{"effets":["reve-1","aleatoire","persistant"],"message":"Le souffle du {{rencontre.name}} vous déstabilise et vous emmène dans un nuage de poussière.","poesie":"<p>C'est l'essaim des Djinns qui passe,<br>Et tourbillonne en sifflant !<br>Les ifs, que leur vol fracasse,<br>Craquent comme un pin br&ucirc;lant.</p>","reference":"Les Djinns, Victor Hugo"},"frequence":{"cite":4,"sanctuaire":4,"plaines":5,"pont":5,"collines":5,"foret":5,"monts":7,"desert":7,"fleuve":10,"lac":10,"marais":11,"gouffre":11,"necropole":15,"desolation":15,"mauvaise":0},"description":""},"effects":[],"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3},"flags":{"core":{"sourceId":"Item.GIG8SbYrl60p50u3"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667773090153,"modifiedTime":1668036933995,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"folder":null,"sort":0,"_id":"ph6qZi1yDgh68Y5l"}
{"name":"Mangeur de Rêve","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","system":{"genre":"m","formule":"1d6","refoulement":2,"presentCite":false,"mauvaiseRencontre":true,"ordreTri":21,"force":0,"coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} claque de sa machoire dans le vide avant de fuir.","poesie":"<p>Rois ! la bure est souvent jalouse du velours.<br>Le peuple a froid l'hiver, le peuple a faim toujours.<br>Rendez-lui son sort plus facile.<br>Le peuple souvent porte un bien rude collier.<br>Ouvrez l'&eacute;cole aux fils, aux p&egrave;res l'atelier,<br>&Agrave; tous vos bras, auguste asile !</p>","reference":"Conseil, Victor Hugo"},"echec":{"effets":["reve-f"],"message":"Le {{rencontre.name}} croque votre Rêve ! Il emporte {{rencontre.system.force}} de vos points de rêve actuels","poesie":"<div>\n<div>Suis-je Amour ou Ph&eacute;bus ?... Lusignan ou Biron ?</div>\n<div>Mon front est rouge encor du baiser de la Reine ;</div>\n<div>J'ai r&ecirc;v&eacute; dans la Grotte o&ugrave; nage la sir&egrave;ne...</div>\n</div>","reference":"El Desdichado, Gérard de Nerval"},"frequence":{"cite":5,"sanctuaire":5,"plaines":5,"pont":5,"collines":12,"foret":12,"monts":18,"desert":18,"fleuve":24,"lac":24,"marais":24,"gouffre":24,"necropole":20,"desolation":20,"mauvaise":1},"description":""},"effects":[],"flags":{"core":{"sourceId":"Item.3SA5An6kPlpcDEIj"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036340,"modifiedTime":1668036933994,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"uhdiBoim26qSmVJ7","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Mangeur de Rêve","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","system":{"genre":"m","formule":"2d6","refoulement":2,"presentCite":false,"mauvaiseRencontre":true,"ordreTri":22,"force":0,"coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} claque de sa machoire dans le vide avant de fuir.","poesie":"<p>Rois ! la bure est souvent jalouse du velours.<br>Le peuple a froid l'hiver, le peuple a faim toujours.<br>Rendez-lui son sort plus facile.<br>Le peuple souvent porte un bien rude collier.<br>Ouvrez l'&eacute;cole aux fils, aux p&egrave;res l'atelier,<br>&Agrave; tous vos bras, auguste asile !</p>","reference":"Conseil, Victor Hugo"},"echec":{"effets":["reve-f"],"message":"Le {{rencontre.name}} croque votre Rêve ! Il emporte {{rencontre.system.force}} de vos points de rêve actuels","poesie":"<div>\n<div>Suis-je Amour ou Ph&eacute;bus ?... Lusignan ou Biron ?</div>\n<div>Mon front est rouge encor du baiser de la Reine ;</div>\n<div>J'ai r&ecirc;v&eacute; dans la Grotte o&ugrave; nage la sir&egrave;ne...</div>\n</div>","reference":"El Desdichado, Gérard de Nerval"},"frequence":{"cite":5,"sanctuaire":5,"plaines":5,"pont":5,"collines":12,"foret":12,"monts":18,"desert":18,"fleuve":24,"lac":24,"marais":24,"gouffre":24,"necropole":20,"desolation":20,"mauvaise":1},"description":""},"effects":[],"flags":{"core":{"sourceId":"Item.3SA5An6kPlpcDEIj"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036340,"modifiedTime":1668036933994,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"yHm1Rqa8CP5qhg69","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"name":"Tourbillon blanc","type":"rencontre","img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","system":{"genre":"m","formule":"2d6+4","refoulement":2,"presentCite":false,"mauvaiseRencontre":true,"ordreTri":24,"force":0,"coord":"","date":"","heure":"","succes":{"effets":[],"message":"Le {{rencontre.name}} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.","poesie":"<p>Le Premier &Acirc;ge fut appel&eacute; l'&Acirc;ge des Dragons. Ce fut le commencement<br>des temps, le commencement des r&ecirc;ves. Durant cette p&eacute;riode plus mythique<br>que r&eacute;ellement historique, les Dragons aimaient &agrave; se r&ecirc;ver eux-m&ecirc;mes.</p>","reference":"Rêve de Dragon, Denis Gerfaud"},"echec":{"effets":["reve-1","aleatoire","persistant"],"message":"Le souffle du {{rencontre.name}} vous déstabilise et vous emmène dans un nuage de poussière.","poesie":"<p>C'est l'essaim des Djinns qui passe,<br>Et tourbillonne en sifflant !<br>Les ifs, que leur vol fracasse,<br>Craquent comme un pin br&ucirc;lant.</p>","reference":"Les Djinns, Victor Hugo"},"frequence":{"cite":4,"sanctuaire":4,"plaines":5,"pont":5,"collines":5,"foret":5,"monts":7,"desert":7,"fleuve":10,"lac":10,"marais":11,"gouffre":11,"necropole":15,"desolation":15,"mauvaise":1},"description":""},"effects":[],"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.rencontres.GIG8SbYrl60p50u3"}},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.1.0","coreVersion":"10.288","createdTime":1667846036337,"modifiedTime":1668036933995,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"yXZW5cDrGoZxD9lK","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}

View File

@@ -77,6 +77,10 @@
--gradient-violet: linear-gradient(150deg, rgba(100, 45, 124, 0.6), rgba(216, 157, 192, 0.3), rgba(177, 157, 216, 0.5), rgba(107, 62, 121, 0.3), rgba(100, 45, 124, 0.6));
--gradient-purple-black: linear-gradient(150deg, rgba(0, 0, 0, 0.7), rgba(100, 45, 124, 0.4), rgba(82, 17, 131, 0.3),rgba(100, 45, 124, 0.4), rgba(0, 0, 0, 0.7));
--gradient-silver-light: linear-gradient(30deg, rgba(61, 55, 93, 0.2), rgba(178, 179, 196, 0.1), rgba(59, 62, 63, 0.2), rgba(206, 204, 199, 0.1), rgba(61, 46, 49, 0.2));
--background-custom-button: linear-gradient(to bottom, rgba(33, 55, 74, 0.988) 5%, rgba(21, 40, 51, 0.671) 100%);
--background-custom-button-hover: linear-gradient(to bottom, rgb(128, 0, 0) 5%, rgb(62, 1, 1) 100%);
--background-tooltip: rgba(220,220,210,0.95);
}
/*@import url("https://fonts.googleapis.com/css2?family=Martel:wght@400;800&family=Roboto:wght@300;400;500&display=swap");*/
@@ -316,7 +320,6 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) {
-webkit-box-pack: start;
-ms-flex-pack: start;
justify-content: flex-start;
margin-bottom: 10px;
}
.foundryvtt-reve-de-dragon .sheet-header .profile-img {
@@ -806,8 +809,12 @@ ul, li {
padding: 0;
}
.sheet input.recherche {
background: url("img/ui/icon-search.svg") no-repeat right;
background-image: url("img/ui/icon-search.svg");
background-position: 0.1rem 0.1rem;
background-size: 1rem;
background-repeat: no-repeat;
padding: 0.1rem 0.1rem 0.1rem 1.2rem;
max-height: 1.2rem;
}
.alterne-list > .list-item:hover {
@@ -1592,7 +1599,7 @@ display: inline-flex;
.tooltip .ttt-ajustements {
width: 150px;
background: rgba(220,220,210,0.95);
background: var(--background-tooltip);
border-radius: 6px;
font-size: 0.9rem;
padding: 3px 0;
@@ -1602,7 +1609,7 @@ display: inline-flex;
text-align: justify;
width: 100%;
top: 30px;
background: rgba(220,220,210,0.95);
background: var(--background-tooltip);
border-radius: 6px;
font-size: 0.9rem;
padding: 3px;
@@ -1610,7 +1617,7 @@ display: inline-flex;
.tooltip :is(.ttt-xp,.ttt-levelup) {
width: 250px;
background: rgba(220,220,210,0.95) !important;
background: var(--background-tooltip) !important;
border-radius: 6px;
font-size: 0.9rem;
padding: 3px 0;
@@ -1624,7 +1631,7 @@ display: inline-flex;
.chat-card-button {
box-shadow: inset 0px 1px 0px 0px #a6827e;
background: linear-gradient(to bottom, #21374afc 5%, #152833ab 100%);
background: var(--background-custom-button);
background-color: #7d5d3b00;
border-radius: 3px;
border: 2px ridge #846109;
@@ -1640,14 +1647,51 @@ display: inline-flex;
margin:5px;
}
.chat-card-button:hover {
background: linear-gradient(to bottom, #800000 5%, #3e0101 100%);
background: var(--background-custom-button-hover);
background-color: red;
}
.chat-card-button:active {
position:relative;
top:1px;
}
/* Dropdown Content (Hidden by Default) */
.button-dropdown-content {
display: none;
position: absolute;
width: max-content;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
background: var(--background-tooltip) ;
overflow-y: scroll;
max-height: 14rem;
z-index: 10;
}
.button-dropdown {
position: relative;
display: inline-block;
}
/* Change the background color of the dropdown button when the dropdown content is shown */
.button-dropdown:hover .button-dropbutton {
text-shadow: 1px 0px 0px #ff6600;
}
/* Show the dropdown menu on hover */
.button-dropdown:hover .button-dropdown-content {display: block;}
/* Links inside the dropdown */
.button-dropdown-content a {
color: black;
padding: 0.2rem 0.4rem;
text-decoration: none;
display: block;
}
/* Change color of dropdown links on hover */
.button-dropdown-content a:hover {background-color: #ddd;}
/*************************************************************/
#pause

View File

@@ -1,8 +1,8 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "10.1.0",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.1.0.zip",
"version": "10.2.3",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.2.3.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json",
"compatibility": {
"minimum": "10",
@@ -69,7 +69,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/competences.db",
"type": "Item",
"private": false,
"private": true,
"flags": {}
},
{
@@ -87,7 +87,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/competences-creatures.db",
"type": "Item",
"private": false,
"private": true,
"flags": {}
},
{
@@ -96,7 +96,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/competences-entites.db",
"type": "Item",
"private": false,
"private": true,
"flags": {}
},
{
@@ -150,7 +150,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/maladies-et-poisons.db",
"type": "Item",
"private": false,
"private": true,
"flags": {}
},
{
@@ -168,7 +168,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/queues-de-dragon.db",
"type": "Item",
"private": false,
"private": true,
"flags": {}
},
{
@@ -177,7 +177,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/ombres-de-thanatos.db",
"type": "Item",
"private": false,
"private": true,
"flags": {}
},
{
@@ -186,7 +186,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/souffles-de-dragon.db",
"type": "Item",
"private": false,
"private": true,
"flags": {}
},
{
@@ -198,13 +198,22 @@
"private": false,
"flags": {}
},
{
"name": "extrait-poetique",
"label": "Extraits poétiques",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/extrait-poetique.db",
"type": "Item",
"private": false,
"flags": {}
},
{
"name": "tetes-de-dragon-pour-haut-revants",
"label": "Têtes de Dragon (Hauts-Rêvants)",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/tetes-de-dragon-pour-haut-revants.db",
"type": "Item",
"private": false,
"private": true,
"flags": {}
},
{
@@ -213,7 +222,16 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/tetes-de-dragon-pour-tous-personnages.db",
"type": "Item",
"private": false,
"private": true,
"flags": {}
},
{
"name": "rencontres",
"label": "Rencontres",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/rencontres.db",
"type": "Item",
"private": true,
"flags": {}
},
{
@@ -222,7 +240,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/tables-diverses.db",
"type": "RollTable",
"private": false,
"private": true,
"flags": {}
},
{
@@ -231,7 +249,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/animaux.db",
"type": "Actor",
"private": false,
"private": true,
"flags": {}
},
{
@@ -249,7 +267,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/vehicules.db",
"type": "Actor",
"private": false,
"private": true,
"flags": {}
},
{
@@ -258,7 +276,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/archetypes.db",
"type": "Actor",
"private": false,
"private": true,
"flags": {}
},
{
@@ -267,7 +285,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/humanoides.db",
"type": "Actor",
"private": false,
"private": true,
"flags": {}
},
{
@@ -276,7 +294,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/entites-de-cauchemar.db",
"type": "Actor",
"private": false,
"private": true,
"flags": {}
},
{
@@ -285,7 +303,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/invocations.db",
"type": "Actor",
"private": false,
"private": true,
"flags": {}
},
{
@@ -294,7 +312,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/botanique.db",
"type": "Item",
"private": false,
"private": true,
"flags": {}
},
{
@@ -330,7 +348,7 @@
"system": "foundryvtt-reve-de-dragon",
"path": "packs/scenes-rdd.db",
"type": "Scene",
"private": false,
"private": true,
"flags": {}
}
],

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +1,17 @@
{{#if hautreve.rencontres.length}}
{{#if rencontres.length}}
<h3>Rencontres en attente dans les TMR</h3>
<ul class="item-list">
{{#each hautreve.rencontres as |rencontre key|}}
<li class="item flexrow" data-item-id="{{key}}" data-attribute="{{key}}">
<span class="display-label"><a data-item-id="{{key}}">{{rencontre.name}} r{{rencontre.force}}</a></span>
<span class="flex-shrink">{{rencontre.coord}} - {{caseTmr-label rencontre.coord}}</span>
{{#if rencontre.date}}
<span>{{upperFirst rencontre.heure}}, le {{rencontre.date}}</span>
{{#each rencontres as |rencontre key|}}
<li class="item flexrow" data-item-id="{{rencontre._id}}" data-attribute="{{key}}">
<img class="sheet-competence-img" src="{{rencontre.img}}" />
<span class="display-label flex-grow"><a>
{{rencontre.name}} r{{rencontre.system.force}} ({{rencontre.system.coord}} - {{caseTmr-label rencontre.system.coord}})
</a></span>
{{#if rencontre.system.date}}
<span class="flex-shrink">{{upperFirst rencontre.system.heure}}, le {{rencontre.system.date}}</span>
{{/if}}
<div class="item-controls flex-shrink">
<a class="rencontre-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
<a class="item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}

View File

@@ -1,6 +1,6 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{competence.name}}"/>
<h4 data-categorie="tmr" data-actor-id="{{actor._id}}" data-rencontre-round="{{nbRounds}}">
{{alias}} rencontre {{#if (eq genre 'f')}}une{{else}}un{{/if}} {{rencontre.name}} de force {{rencontre.force}}
{{alias}} rencontre {{#if (eq rencontre.system.genre 'f')}}une{{else}}un{{/if}} {{rencontre.name}} de force {{rencontre.system.force}}
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>

View File

@@ -6,7 +6,7 @@
<hr>
<span>
{{#if rolled.isSuccess}}
{{alias}} maîtrise le Rêve de Dragon! ll gagne {{rencontre.force}} points de Rêve.
{{alias}} maîtrise le Rêve de Dragon! ll gagne {{rencontre.system.force}} points de Rêve.
{{#if tete}}
<br>{{alias}} doit <strong>demander au Gardien des Rêves</strong> de faire un tirage sur une des
tables des têtes de dragon (Haut-rêvant ou Tous personnages).

View File

@@ -6,7 +6,7 @@
</header>
<label>&nbsp;&nbsp;Conditions</label>
<select name="diffConditions" id="diffConditions" data-dtype="number">
<select name="diffConditions" id="diffConditions" data-dtype="Number">
{{#select diffConditions}}
{{#each ajustementsConditions as |key|}}
<option value={{key}}>{{numberFormat key decimals=0 sign=true}}</option>
@@ -14,7 +14,7 @@
{{/select}}
</select>
<label>&nbsp;&nbsp;Jours</label>
<select name="joursAstrologie" id="joursAstrologie" data-dtype="number">
<select name="joursAstrologie" id="joursAstrologie" data-dtype="Number">
{{#select joursSuivants}}
{{#each dates as |date key|}}
<option value={{date.index}}>{{date.label}}</option>

View File

@@ -1,5 +1,5 @@
<form class="skill-roll-dialog">
<h2>Rêve de Dragon de force {{rencontre.force}}!</h2>
<h2>{{rencontre.name}} de force {{rencontre.system.force}}!</h2>
<div class="grid grid-2col">
<div class="flex-group-left">
<img class="chat-icon" src="{{competence.img}}" alt="{{competence.name}}"/>

View File

@@ -0,0 +1,25 @@
<form class="{{cssClass}}" autocomplete="off">
<header class="sheet-header">
<img class="chat-icon" src="{{img}}" data-edit="img" title="{{name}}"/>
<div class="header-fields">
<h1 class="charname">
<input name="name" type="text" value="{{name}}" placeholder="Name"/>
</h1>
<p class="poesie-reference">Référence</p>
</div>
</header>
<section class="sheet-body">
<div class="flexcol">
<label>Extrait</label>
<div class="form-group editor">
{{editor extrait target="system.extrait" button=true owner=owner editable=editable}}
</div>
</div>
<div class="flexcol">
<label>Texte complet</label>
<div class="form-group editor">
{{editor texte target="system.texte" button=true owner=owner editable=editable}}
</div>
</div>
</section>
</form>

View File

@@ -0,0 +1,232 @@
<form class="{{cssClass}}" autocomplete="off">
{{>"systems/foundryvtt-reve-de-dragon/templates/header-item.html"}}
{{!-- Sheet Body --}}
<nav class="sheet-tabs tabs" data-group="primary">
<a class="item" data-tab="rencontre">Rencontre</a>
<a class="item" data-tab="succes">Victoire</a>
<a class="item" data-tab="echec">Défaite</a>
{{#unless system.mauvaiseRencontre}}
<a class="item" data-tab="frequence">Fréquences</a>
{{/unless}}
</nav>
<section class="sheet-body">
<div class="tab items" data-group="primary" data-tab="rencontre">
{{#if isOwned}}
<div class="form-group">
<label for="system.force">Rêve</label>
<input type="text" name="system.force" value="{{system.force}}" data-dtype="Number"/>
</div>
<div class="form-group">
<label for="system.coord">Case TMR - {{caseTmr-label system.coord}}</label>
<input class="attribute-value" type="text" name="system.coord" value="{{system.coord}}" data-dtype="String" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.date">Date/heure</label>
<div class="flexrow">
<input class="attribute-value" type="text" name="system.date" value="{{system.date}}" data-dtype="String" {{#unless isGM}}disabled{{/unless}}/>
<input class="attribute-value" type="text" name="system.heure" value="{{system.heure}}" data-dtype="String" {{#unless isGM}}disabled{{/unless}}/>
</div>
</div>
{{else}}
<div class="form-group">
<label for="system.formule">Rêve</label>
<input type="text" name="system.formule" value="{{system.formule}}" data-dtype="String" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.genre">Genre</label>
<select type="text" name="system.genre" data-dtype="String" {{#unless isGM}}disabled{{/unless}}>
{{#select system.genre}}
<option value=""></option>
<option value="f">Féminin</option>
<option value="m">Masculin</option>
{{/select}}
</select>
</div>
<div class="form-group">
<label for="system.ordreTri">Position dans la table</label>
<input type="number" name="system.ordreTri" value="{{system.ordreTri}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.presentCite">Offert par les Présents des cités</label>
<input type="checkbox" name="system.presentCite" data-dtype="Boolean" {{#if system.presentCite}}checked{{/if}} {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.refoulement">Refoulement</label>
<input type="number" name="system.refoulement" value="{{system.refoulement}}" min="0" max="4" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
{{/if}}
<div class="form-group">
<label for="system.mauvaiseRencontre">Mauvaise rencontre</label>
<input type="checkbox" name="system.mauvaiseRencontre" data-dtype="Boolean" {{#if system.mauvaiseRencontre}}checked{{/if}} {{#unless isGM}}disabled{{/unless}}/>
</div>
{{#unless isOwned}}
{{#if system.mauvaiseRencontre}}
<div class="form-group">
<label for="system.frequence.mauvaise">Fréquence mauvaise rencontre</label>
<input type="number" name="system.frequence.mauvaise" value="{{system.frequence.mauvaise}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
{{/if}}
{{/unless}}
<div class="flexcol">
<span><label>Description : </label></span>
<div class="form-group editor">
{{editor description target="system.description" button=true owner=owner editable=editable}}
</div>
</div>
</div>
<div class="tab items" data-group="primary" data-tab="succes">
<div class="form-group">
<label for="system.succes.message">Message</label>
<textarea autocomplete="off" title="Message en cas de succès" name="system.succes.message" {{#unless isGM}}disabled{{/unless}}/>{{system.succes.message}}</textarea>
</div>
<div class="form-group">
<div class="button-dropdown">
{{#if isGM}}
<label class="button-dropbutton" title="Ajouter">Effets <i class="fas fa-plus-circle"></i></label>
<div class="button-dropdown-content">
{{#each effets.succes.liste as |effet|}}
<a class="effet-add" data-effet-code="{{effet.code}}" data-effet-resultat="{{effet.resultat}}">{{effet.description}}</a>
{{/each}}
</div>
{{else}}
<label>Effets</label>
{{/if}}
</div>
</div>
<div class="form-group">
<label></label>
<div class="flexcol">
{{#each effets.succes.select as |effet pos|}}
<label>
{{effet.description}}
{{#if @root.isGM}}
<a class="effet-delete" data-effet-code="{{effet.code}}" data-effet-resultat="{{effet.resultat}}" data-effet-pos="{{pos}}" title="Supprimer"><i class="fas fa-trash"></i></a>
{{/if}}
</label>
{{/each}}
</div>
</div>
<hr>
<div class="form-group">
<label for="system.succes.reference">Réference</label>
<input type="text" name="system.succes.reference" value="{{system.succes.reference}}" data-dtype="String" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="flexcol">
<label for="system.succes.poesie">Poésie</label>
<div class="form-group editor">
{{editor system.succes.poesie target="system.succes.poesie" button=true owner=owner editable=editable}}
</div>
</div>
</div>
<div class="tab items" data-group="primary" data-tab="echec">
<div class="form-group">
<label for="system.echec.message">Message</label>
<textarea autocomplete="off" title="Message en cas d'échec" name="system.echec.message" {{#unless isGM}}disabled{{/unless}}/>{{system.echec.message}}</textarea>
</div>
<div class="form-group">
<div class="button-dropdown">
{{#if isGM}}
<label class="button-dropbutton" title="Ajouter">Effets <i class="fas fa-plus-circle"></i></label>
<div class="button-dropdown-content">
{{#each effets.echec.liste as |effet|}}
<a class="effet-add" data-effet-code="{{effet.code}}" data-effet-resultat="{{effet.resultat}}">{{effet.description}}</a>
{{/each}}
</div>
{{else}}
<label>Effets</label>
{{/if}}
</div>
</div>
<div class="form-group">
<label></label>
<div class="flexcol">
{{#each effets.echec.select as |effet pos|}}
<label>
{{effet.description}}
{{#if @root.isGM}}
<a class="effet-delete" data-effet-code="{{effet.code}}" data-effet-resultat="{{effet.resultat}}" data-effet-pos="{{pos}}" title="Supprimer"><i class="fas fa-trash"></i></a>
{{/if}}
</label>
{{/each}}
</div>
</div>
<hr>
<div class="form-group">
<label for="system.echec.reference">Réference</label>
<input type="text" name="system.echec.reference" value="{{system.echec.reference}}" data-dtype="String" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="flexcol">
<label for="system.echec.poesie">Poésie</label>
<div class="form-group editor">
{{editor system.echec.poesie target="system.echec.poesie" button=true owner=owner editable=editable}}
</div>
</div>
</div>
{{#unless system.mauvaiseRencontre}}
<div class="tab items" data-group="primary" data-tab="frequence">
<hr>
<div class="form-group">
<label for="system.frequence.cite">Fréquence en Cité</label>
<input type="number" name="system.frequence.cite" value="{{system.frequence.cite}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.sanctuaire">Fréquence en Sanctuaire</label>
<input type="number" name="system.frequence.sanctuaire" value="{{system.frequence.sanctuaire}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.plaines">Fréquence en Plaines</label>
<input type="number" name="system.frequence.plaines" value="{{system.frequence.plaines}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.pont">Fréquence en Pont</label>
<input type="number" name="system.frequence.pont" value="{{system.frequence.pont}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.collines">Fréquence en Collines</label>
<input type="number" name="system.frequence.collines" value="{{system.frequence.collines}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.foret">Fréquence en Forêt</label>
<input type="number" name="system.frequence.foret" value="{{system.frequence.foret}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.monts">Fréquence en Monts</label>
<input type="number" name="system.frequence.monts" value="{{system.frequence.monts}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.desert">Fréquence en Désert</label>
<input type="number" name="system.frequence.desert" value="{{system.frequence.desert}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.fleuve">Fréquence en Fleuve</label>
<input type="number" name="system.frequence.fleuve" value="{{system.frequence.fleuve}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.lac">Fréquence en Lac</label>
<input type="number" name="system.frequence.lac" value="{{system.frequence.lac}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.marais">Fréquence en Marais</label>
<input type="number" name="system.frequence.marais" value="{{system.frequence.marais}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.gouffre">Fréquence en Gouffre</label>
<input type="number" name="system.frequence.gouffre" value="{{system.frequence.gouffre}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.necropole">Fréquence en Nécropole</label>
<input type="number" name="system.frequence.necropole" value="{{system.frequence.necropole}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
<div class="form-group">
<label for="system.frequence.desolation">Fréquence en Désolation</label>
<input type="number" name="system.frequence.desolation" value="{{system.frequence.desolation}}" min="0" max="100" data-dtype="Number" {{#unless isGM}}disabled{{/unless}}/>
</div>
</div>
{{/unless}}
</section>
</form>

View File

@@ -2,7 +2,6 @@
{{>"systems/foundryvtt-reve-de-dragon/templates/header-item.html"}}
<section class="sheet-body">
{{log 'sortreserve' this}}
{{#if (and system.sortid sort)}}
<div class="form-group">
<label>Sort</label>

View File

@@ -0,0 +1,21 @@
<form autocomplete="off" onsubmit="event.preventDefault();">
{{log 'systemCompendiums'systemCompendiums}}
{{log 'availableCompendiums' availableCompendiums}}
<ul>
{{#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 definition.value}}
{{#each @root.availableCompendiums as |available key|}}
{{#if (eq available.type definition.type)}}
<option value="{{available.name}}">{{available.path }}</option>
{{/if}}
{{/each}}
{{/select}}
</select>
</li>
{{/each}}
</ul>
</form>

View File

@@ -5,4 +5,4 @@
Dans la console dans les "devtools" de Chrome, quelques commandes sont utiles:
* `CONFIG.debug.hooks = true` permet de logger les appels des hooks et les objets passés
* `game.system.rdd.TMRUtility.setForceRencontre('changeur', 3)` pour forcer une rencontre avec un changeur de rêves