Compare commits
225 Commits
foundryvtt
...
foundryvtt
| Author | SHA1 | Date | |
|---|---|---|---|
| 9bdde92d61 | |||
| 74313b7fd3 | |||
| 9a9399a581 | |||
| 95a7ac73d0 | |||
| ab4c118d12 | |||
| 681358238d | |||
| 5511acc876 | |||
| 2e144851d4 | |||
| 9f24aee1f3 | |||
| e605ab405a | |||
| 86f69566a6 | |||
| 2561a658f2 | |||
| 8a1d1fd253 | |||
| e42f384d7f | |||
| d381191692 | |||
| 53a7230f1d | |||
| 4d5651c2d3 | |||
| 61474172a7 | |||
| 083806612b | |||
| 1c417d02a1 | |||
| ee9e7d2adb | |||
| fa3334273d | |||
| 05b73a41a5 | |||
| 842243485a | |||
| 1e53f2d9e8 | |||
| 792fcc1b39 | |||
| 3d914a29c3 | |||
| 7fe7c1e9bd | |||
| d86b81fbbc | |||
| 22da2807d8 | |||
| 76e03b07ed | |||
| e4098c813b | |||
| 90aecd6cc0 | |||
| 254709f55b | |||
| 064472dc11 | |||
| 7a67cb7cea | |||
| 7f051e76be | |||
| 38db7fb7c8 | |||
| c448f32bb8 | |||
| e194514965 | |||
| a790c36618 | |||
| f221bb31eb | |||
| bdc2d8db3a | |||
| 782dc38268 | |||
| 024e355586 | |||
| 37704558e0 | |||
| d816490839 | |||
| a4186da540 | |||
| b8b4a1ff14 | |||
| 8925a4979d | |||
| 851a208aee | |||
| 4df04fe06f | |||
| f4d074fa31 | |||
| f7595a1bfe | |||
| 86feb12811 | |||
| 2383094254 | |||
| 2a72f6ffea | |||
| 3cc56c615c | |||
| 948309bb4f | |||
| 40fdff4057 | |||
| c972913a67 | |||
| 0d5c8e5304 | |||
| 0aba6d2f0a | |||
| df3e181d7f | |||
| 8877939b9f | |||
| 7334f2d8e6 | |||
| ceff3d1b50 | |||
| a4802d1113 | |||
| 162a6a04b8 | |||
| 0c36cf3c47 | |||
| 969e5f6b2d | |||
| 306ecacc98 | |||
| 2dc86e6679 | |||
| 484530d67d | |||
| a08890dcb0 | |||
| 1956fdd755 | |||
| 651356159a | |||
| ca304109d5 | |||
| 9c0d08cb6f | |||
| f9fd8a1e24 | |||
| 03f84eb3f7 | |||
| 05e48b61ff | |||
| f20788d6d9 | |||
| 009639dd5f | |||
| 14542cf7cd | |||
| f4f2db68e0 | |||
| 7e75715d88 | |||
| d62d1c45bc | |||
| 62914c343f | |||
| 9349e81580 | |||
| 404539a004 | |||
| 9eaeceafc4 | |||
| 1cd3bdef25 | |||
| fa356bd7f8 | |||
| 771c8c9c8e | |||
| ca860a0243 | |||
| 2e36221018 | |||
| 07e203513a | |||
| 31960ce940 | |||
| 19118911b9 | |||
| 652ae4cf51 | |||
| cf340f73f1 | |||
| 3782ed9055 | |||
| c3076fdbfc | |||
| 739fcbdf09 | |||
| 19b3adc222 | |||
| 388629d36e | |||
| 912b1d3df3 | |||
| 11e4ad09d3 | |||
| 8844f76b65 | |||
| ec24126e75 | |||
| b3c6845e68 | |||
| cf8df182ba | |||
|
|
30cc8419c5 | ||
|
|
5ab6c5989e | ||
|
|
46df3d9f11 | ||
| 6a6759087c | |||
| a7ce1db7c5 | |||
| a0efefad3f | |||
| 8e0825b6b9 | |||
| 39d14c8496 | |||
| 89442ea6c6 | |||
| a66fe122c4 | |||
|
|
2e0abaa284 | ||
|
|
5bddc548de | ||
| 4acd0879b0 | |||
| 060943ee53 | |||
| 80be0490eb | |||
| ceacee8e6c | |||
| d5453c9b04 | |||
| 7ca3306c6f | |||
| aa5d175027 | |||
| d4ddc4e940 | |||
| 87f12019ac | |||
| 128d7adf89 | |||
| ee42bdcf83 | |||
| 5972db035d | |||
| 92388df5c7 | |||
| 274009d3fa | |||
| d7e5a09540 | |||
| 7f5b2e0abf | |||
| fbd3aa7121 | |||
| 2ca601b5f8 | |||
|
|
d77ecee9bd | ||
| c2a3b5e246 | |||
| 09bf28eed1 | |||
| 33c20dd2b7 | |||
|
|
c933810b6b | ||
|
|
df92a65f5d | ||
|
|
dbcab12f24 | ||
|
|
454193490d | ||
|
|
c79298b60a | ||
|
|
26808d7b49 | ||
|
|
2062ff0777 | ||
|
|
6adeb790a0 | ||
|
|
2546b89b44 | ||
| 84f4a152a8 | |||
| d6f8698189 | |||
| 4f80c719c2 | |||
| 7d8b5c9549 | |||
|
|
ec58317b35 | ||
|
|
7c70e944b1 | ||
|
|
f397c82c6d | ||
|
|
81e3ceb4dc | ||
|
|
7bec249e8d | ||
|
|
70b30b545b | ||
|
|
ed2eebf99d | ||
|
|
4ba2c384d7 | ||
|
|
7f27399f3c | ||
|
|
61389e117b | ||
|
|
46cc245abf | ||
|
|
a372531849 | ||
|
|
8a8323ac8d | ||
|
|
8e6d4fbb89 | ||
|
|
886307f24c | ||
| f40dbd5d7b | |||
|
|
66da7d5eb4 | ||
|
|
b2d8c2439a | ||
|
|
ceb4095c31 | ||
|
|
2af37cf98f | ||
|
|
fd156960a7 | ||
|
|
80a904e533 | ||
|
|
c9dc847440 | ||
| 4e382d405e | |||
|
|
6a12dc97f6 | ||
|
|
e0b6957bc6 | ||
|
|
944120b524 | ||
|
|
bb6bf3387e | ||
|
|
467a4d53a4 | ||
|
|
d5635b27fe | ||
| 3a33f7c4fc | |||
| d2e77dc61c | |||
|
|
320bc471e3 | ||
|
|
090241f0f5 | ||
|
|
ddc37c6969 | ||
|
|
6af6e41bc9 | ||
|
|
0f7f609a2a | ||
|
|
a58f701ca6 | ||
|
|
757b46080a | ||
|
|
df44cd66c7 | ||
|
|
1040ec1be2 | ||
|
|
92643d1c46 | ||
|
|
31c4aa32d9 | ||
| f5431b58fb | |||
|
|
bd32e1039a | ||
|
|
6b8f0ed51e | ||
|
|
10681b3f61 | ||
|
|
bbde3b73fe | ||
| 57d52c1966 | |||
| e3a29cdab5 | |||
|
|
10e4f14eb2 | ||
| 04273dfcf1 | |||
| 8c5c01114e | |||
|
|
19e6124330 | ||
|
|
1c908b50cb | ||
|
|
969cedfc3d | ||
|
|
830e66749d | ||
|
|
df26e654ae | ||
|
|
153bfe2e75 | ||
|
|
f6d42875ae | ||
|
|
450cb8e899 | ||
| 0202938910 | |||
| 512a056e59 | |||
|
|
214377c66d | ||
| 752e534350 |
4
.gitignore
vendored
@@ -3,3 +3,7 @@
|
|||||||
todo.md
|
todo.md
|
||||||
/.vscode
|
/.vscode
|
||||||
/ignored/
|
/ignored/
|
||||||
|
/node_modules/
|
||||||
|
/jsconfig.json
|
||||||
|
/package.json
|
||||||
|
/package-lock.json
|
||||||
|
|||||||
BIN
icons/faune/Escargot.webp
Normal file
|
After Width: | Height: | Size: 8.2 KiB |
BIN
icons/faune/barbon.webp
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
icons/faune/brocart.webp
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
icons/faune/cancre.webp
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
icons/faune/cancrelas.webp
Normal file
|
After Width: | Height: | Size: 8.5 KiB |
BIN
icons/faune/colimace.webp
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
icons/faune/coquillage-pointe.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
icons/faune/coquille.webp
Normal file
|
After Width: | Height: | Size: 7.3 KiB |
BIN
icons/faune/fretin.webp
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
icons/faune/soldieze.webp
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
icons/faune/ver.webp
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
icons/services/bacquet-eau.webp
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
icons/services/biere.webp
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
icons/services/brandevin.webp
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
icons/services/commerce.webp
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
icons/services/compagnie.webp
Normal file
|
After Width: | Height: | Size: 6.4 KiB |
BIN
icons/services/lit.webp
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
icons/services/paiement.webp
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
icons/services/repas.webp
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
icons/services/verre.webp
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
icons/services/vin.webp
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
@@ -3,6 +3,7 @@
|
|||||||
"TypePersonnage": "Personnage",
|
"TypePersonnage": "Personnage",
|
||||||
"TypeCreature": "Créature",
|
"TypeCreature": "Créature",
|
||||||
"TypeEntite": "Entité de cauchemar",
|
"TypeEntite": "Entité de cauchemar",
|
||||||
|
"TypeCommerce": "Commerce",
|
||||||
"TypeVehicule": "Véhicule"
|
"TypeVehicule": "Véhicule"
|
||||||
},
|
},
|
||||||
"ITEM": {
|
"ITEM": {
|
||||||
@@ -18,7 +19,8 @@
|
|||||||
"TypeRencontre": "Rencontre TMR",
|
"TypeRencontre": "Rencontre TMR",
|
||||||
"TypeMunition": "Munition",
|
"TypeMunition": "Munition",
|
||||||
"TypeMonnaie": "Monnaie",
|
"TypeMonnaie": "Monnaie",
|
||||||
"TypeHerbe": "Herbe ou plante",
|
"TypeHerbe": "Herbe",
|
||||||
|
"TypePlante": "Plante",
|
||||||
"TypeIngredient": "Ingrédient",
|
"TypeIngredient": "Ingrédient",
|
||||||
"TypeFaune": "Faune",
|
"TypeFaune": "Faune",
|
||||||
"TypeLivre": "Livre",
|
"TypeLivre": "Livre",
|
||||||
@@ -27,6 +29,7 @@
|
|||||||
"TypeArmure": "Armure",
|
"TypeArmure": "Armure",
|
||||||
"TypeConteneur": "Conteneur",
|
"TypeConteneur": "Conteneur",
|
||||||
"TypeNourritureboisson": "Nourriture & boisson",
|
"TypeNourritureboisson": "Nourriture & boisson",
|
||||||
|
"TypeService": "Service",
|
||||||
"TypeChant": "Chant",
|
"TypeChant": "Chant",
|
||||||
"TypeDanse": "Danse",
|
"TypeDanse": "Danse",
|
||||||
"TypeMusique": "Musique",
|
"TypeMusique": "Musique",
|
||||||
|
|||||||
@@ -40,11 +40,4 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
|
|||||||
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
|
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** @override */
|
|
||||||
_updateObject(event, formData) {
|
|
||||||
// Update the Actor
|
|
||||||
return this.object.update(formData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,20 +3,20 @@ import { RdDActorSheet } from "./actor-sheet.js";
|
|||||||
export class RdDActorEntiteSheet extends RdDActorSheet {
|
export class RdDActorEntiteSheet extends RdDActorSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
return mergeObject(super.defaultOptions, {
|
return mergeObject(super.defaultOptions, {
|
||||||
classes: ["rdd", "sheet", "actor"],
|
classes: ["rdd", "sheet", "actor"],
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html",
|
template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html",
|
||||||
width: 640,
|
width: 640,
|
||||||
height: 720,
|
height: 720,
|
||||||
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac"}],
|
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
||||||
dragDrop: [{dragSelector: ".item-list .item", dropSelector: undefined}]
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/** @override */
|
/** @override */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
// Everything below here is only needed if the sheet is editable
|
||||||
@@ -24,17 +24,17 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
|
|||||||
|
|
||||||
// On competence change
|
// On competence change
|
||||||
this.html.find('.creature-carac').change(async event => {
|
this.html.find('.creature-carac').change(async event => {
|
||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
this.actor.updateCreatureCompetence( compName, "carac_value", parseInt(event.target.value) );
|
this.actor.updateCreatureCompetence(compName, "carac_value", parseInt(event.target.value));
|
||||||
} );
|
});
|
||||||
this.html.find('.creature-niveau').change(async event => {
|
this.html.find('.creature-niveau').change(async event => {
|
||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
this.actor.updateCreatureCompetence( compName, "niveau", parseInt(event.target.value) );
|
this.actor.updateCreatureCompetence(compName, "niveau", parseInt(event.target.value));
|
||||||
} );
|
});
|
||||||
this.html.find('.creature-dommages').change(async event => {
|
this.html.find('.creature-dommages').change(async event => {
|
||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
this.actor.updateCreatureCompetence( compName, "dommages", parseInt(event.target.value) );
|
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
|
||||||
} );
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,16 +8,18 @@ import { RdDCombatManager } from "./rdd-combat.js";
|
|||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
import { DialogSplitItem } from "./dialog-split-item.js";
|
import { DialogSplitItem } from "./dialog-split-item.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||||
import { DialogRepos } from "./dialog-repos.js";
|
|
||||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
import { STATUSES } from "./settings/status-effects.js";
|
||||||
|
import { MAINS_DIRECTRICES } from "./actor.js";
|
||||||
|
import { RdDBaseActorSheet } from "./actor/base-actor-sheet.js";
|
||||||
|
import { RdDItem } from "./item.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/**
|
/**
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
* @extends {ActorSheet}
|
* @extends {ActorSheet}
|
||||||
*/
|
*/
|
||||||
export class RdDActorSheet extends ActorSheet {
|
export class RdDActorSheet extends RdDBaseActorSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
@@ -35,51 +37,38 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getData() {
|
async getData() {
|
||||||
|
let formData = await super.getData();
|
||||||
|
mergeObject(formData,
|
||||||
|
{
|
||||||
|
editable: this.isEditable,
|
||||||
|
cssClass: this.isEditable ? "editable" : "locked",
|
||||||
|
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
|
||||||
|
limited: this.actor.limited,
|
||||||
|
owner: this.actor.isOwner,
|
||||||
|
biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }),
|
||||||
|
notes: await TextEditor.enrichHTML(this.actor.system.notes, { async: true }),
|
||||||
|
});
|
||||||
|
mergeObject(formData.calc, {
|
||||||
|
surenc: this.actor.computeMalusSurEncombrement(),
|
||||||
|
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
|
||||||
|
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
|
||||||
|
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
|
||||||
|
surEncombrementMessage: this.actor.getMessageSurEncombrement(),
|
||||||
|
})
|
||||||
|
|
||||||
this.timerRecherche = undefined;
|
this.timerRecherche = undefined;
|
||||||
this.actor.computeEtatGeneral();
|
|
||||||
|
|
||||||
let formData = {
|
|
||||||
title: this.title,
|
|
||||||
id: this.actor.id,
|
|
||||||
type: this.actor.type,
|
|
||||||
img: this.actor.img,
|
|
||||||
name: this.actor.name,
|
|
||||||
editable: this.isEditable,
|
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
|
||||||
system: foundry.utils.deepClone(this.actor.system),
|
|
||||||
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
|
|
||||||
limited: this.actor.limited,
|
|
||||||
options: this.options,
|
|
||||||
owner: this.actor.isOwner,
|
|
||||||
description: await TextEditor.enrichHTML(this.object.system.description, {async: true}),
|
|
||||||
biographie: await TextEditor.enrichHTML(this.object.system.biographie, {async: true}),
|
|
||||||
notes: await TextEditor.enrichHTML(this.object.system.notes, {async: true}),
|
|
||||||
notesmj: await TextEditor.enrichHTML(this.object.system.notesmj, {async: true}),
|
|
||||||
calc: {
|
|
||||||
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
|
||||||
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
|
||||||
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
|
|
||||||
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
|
|
||||||
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
|
|
||||||
surEncombrementMessage: this.actor.getMessageSurEncombrement(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
formData.options.isGM = game.user.isGM;
|
|
||||||
|
|
||||||
RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
|
||||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
|
||||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
|
||||||
|
|
||||||
if (formData.type == 'personnage') {
|
if (formData.type == 'personnage') {
|
||||||
|
formData.options.mainsDirectrices = MAINS_DIRECTRICES;
|
||||||
formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie)
|
formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie)
|
||||||
formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences);
|
formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences);
|
||||||
formData.calc.competenceXPTotal= RdDItemCompetence.computeTotalXP(formData.competences);
|
formData.calc.competenceXPTotal = RdDItemCompetence.computeTotalXP(formData.competences);
|
||||||
formData.calc.fatigue= RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max);
|
formData.calc.fatigue = RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max);
|
||||||
|
|
||||||
formData.competences.forEach(item => {
|
formData.competences.forEach(item => {
|
||||||
item.system.isVisible = this.options.recherche
|
item.system.isVisible = this.options.recherche
|
||||||
? RdDItemCompetence.nomContientTexte(item, this.options.recherche.text)
|
? RdDItemCompetence.nomContientTexte(item, this.options.recherche.text)
|
||||||
: (!this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item));
|
: (!this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item));
|
||||||
RdDItemCompetence.levelUp(item, formData.system.compteurs.experience.value);
|
RdDItemCompetence.levelUp(item, formData.system.compteurs.experience.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -121,22 +110,14 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
/* -------------------------------------------- */ /** @override */
|
/* -------------------------------------------- */ /** @override */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
this.html = html;
|
|
||||||
|
|
||||||
HtmlUtility._showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
// Everything below here is only needed if the sheet is editable
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
this.html.find('.item-split').click(async event => {
|
|
||||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
|
||||||
RdDSheetUtility.splitItem(item, this.actor);
|
|
||||||
});
|
|
||||||
this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true))
|
|
||||||
this.html.find('.item-delete').click(async event => RdDUtility.confirmerSuppressionItem(this, RdDSheetUtility.getItem(event, this.actor)));
|
|
||||||
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
|
|
||||||
this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItem());
|
|
||||||
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor));
|
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor));
|
||||||
|
|
||||||
this.html.find('.subacteur-delete').click(async event => {
|
this.html.find('.subacteur-delete').click(async event => {
|
||||||
const li = RdDSheetUtility.getEventElement(event);
|
const li = RdDSheetUtility.getEventElement(event);
|
||||||
const actorId = li.data("actor-id");
|
const actorId = li.data("actor-id");
|
||||||
@@ -170,14 +151,17 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
this.html.find('.creer-tache').click(async event => {
|
this.html.find('.creer-tache').click(async event => {
|
||||||
this.createEmptyTache();
|
this.createEmptyTache();
|
||||||
});
|
});
|
||||||
this.html.find('.creer-un-objet').click(async event => {
|
this.html.find('.creer-tache-blessure-legere').click(async event => {
|
||||||
RdDUtility.selectObjetType(this);
|
this.actor.createTacheBlessure('legere');
|
||||||
|
});
|
||||||
|
this.html.find('.creer-tache-blessure-grave').click(async event => {
|
||||||
|
this.actor.createTacheBlessure('grave');
|
||||||
|
});
|
||||||
|
this.html.find('.creer-tache-blessure-critique').click(async event => {
|
||||||
|
this.actor.createTacheBlessure('critique');
|
||||||
});
|
});
|
||||||
this.html.find('.creer-une-oeuvre').click(async event => {
|
this.html.find('.creer-une-oeuvre').click(async event => {
|
||||||
RdDUtility.selectTypeOeuvre(this);
|
this.selectTypeOeuvreToCreate();
|
||||||
});
|
|
||||||
this.html.find('.nettoyer-conteneurs').click(async event => {
|
|
||||||
this.actor.nettoyerConteneurs();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Blessure control
|
// Blessure control
|
||||||
@@ -274,7 +258,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
|
|
||||||
// Points de reve actuel
|
// Points de reve actuel
|
||||||
this.html.find('.ptreve-actuel a').click(async event => {
|
this.html.find('.ptreve-actuel a').click(async event => {
|
||||||
this.actor.rollCarac('reve-actuel');
|
this.actor.rollCarac('reve-actuel', true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Roll Weapon1
|
// Roll Weapon1
|
||||||
@@ -308,7 +292,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.repos').click(async event => {
|
this.html.find('.repos').click(async event => {
|
||||||
await DialogRepos.create(this.actor);
|
await this.actor.repos();
|
||||||
});
|
});
|
||||||
this.html.find('.delete-active-effect').click(async event => {
|
this.html.find('.delete-active-effect').click(async event => {
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
@@ -321,10 +305,6 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
await this.actor.removeEffects();
|
await this.actor.removeEffects();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.html.find('.conteneur-name a').click(async event => {
|
|
||||||
RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event));
|
|
||||||
this.render(true);
|
|
||||||
});
|
|
||||||
this.html.find('.carac-xp-augmenter').click(async event => {
|
this.html.find('.carac-xp-augmenter').click(async event => {
|
||||||
let caracName = event.currentTarget.name.replace("augmenter.", "");
|
let caracName = event.currentTarget.name.replace("augmenter.", "");
|
||||||
this.actor.updateCaracXPAuto(caracName);
|
this.actor.updateCaracXPAuto(caracName);
|
||||||
@@ -383,7 +363,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
})
|
})
|
||||||
.keyup(async event => {
|
.keyup(async event => {
|
||||||
const nouvelleRecherche = this._optionRecherche(event.currentTarget);
|
const nouvelleRecherche = this._optionRecherche(event.currentTarget);
|
||||||
if (this.options.recherche?.text != nouvelleRecherche?.text){
|
if (this.options.recherche?.text != nouvelleRecherche?.text) {
|
||||||
this.options.recherche = nouvelleRecherche;
|
this.options.recherche = nouvelleRecherche;
|
||||||
if (this.timerRecherche) {
|
if (this.timerRecherche) {
|
||||||
clearTimeout(this.timerRecherche);
|
clearTimeout(this.timerRecherche);
|
||||||
@@ -414,19 +394,12 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
this.actor.setPointsDeSeuil(event.currentTarget.value);
|
this.actor.setPointsDeSeuil(event.currentTarget.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('#attribut-protection-edit').change(async event => {
|
|
||||||
this.actor.updateAttributeValue(event.currentTarget.attributes.name.value, parseInt(event.target.value));
|
|
||||||
});
|
|
||||||
|
|
||||||
// On stress change
|
// On stress change
|
||||||
this.html.find('.compteur-edit').change(async event => {
|
this.html.find('.compteur-edit').change(async event => {
|
||||||
let fieldName = event.currentTarget.attributes.name.value;
|
let fieldName = event.currentTarget.attributes.name.value;
|
||||||
this.actor.updateCompteurValue(fieldName, parseInt(event.target.value));
|
this.actor.updateCompteurValue(fieldName, parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('#ethylisme').change(async event => {
|
|
||||||
this.actor.setEthylisme(parseInt(event.target.value));
|
|
||||||
});
|
|
||||||
this.html.find('.stress-test').click(async event => {
|
this.html.find('.stress-test').click(async event => {
|
||||||
this.actor.transformerStress();
|
this.actor.transformerStress();
|
||||||
});
|
});
|
||||||
@@ -450,13 +423,6 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
this.actor.jetEndurance();
|
this.actor.jetEndurance();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.monnaie-plus').click(async event => {
|
|
||||||
this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), 1);
|
|
||||||
});
|
|
||||||
this.html.find('.monnaie-moins').click(async event => {
|
|
||||||
this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), -1);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.html.find('.vie-plus').click(async event => {
|
this.html.find('.vie-plus').click(async event => {
|
||||||
this.actor.santeIncDec("vie", 1);
|
this.actor.santeIncDec("vie", 1);
|
||||||
});
|
});
|
||||||
@@ -495,29 +461,33 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _onDropItem(event, dragData) {
|
async selectTypeOeuvreToCreate() {
|
||||||
const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id')
|
let typeObjets = RdDItem.getTypesOeuvres();
|
||||||
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, dragData, this.objetVersConteneur)
|
let content = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
|
||||||
if (dropParams) {
|
for (let typeName of typeObjets) {
|
||||||
const callSuper = await this.actor.processDropItem(dropParams)
|
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
||||||
if (callSuper) {
|
|
||||||
await super._onDropItem(event, dragData)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
content += '</select>';
|
||||||
|
let dialog = new Dialog({
|
||||||
/* -------------------------------------------- */
|
title: "Créer une oeuvre",
|
||||||
async createItem(name, type) {
|
content: content,
|
||||||
await this.actor.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
|
buttons: {
|
||||||
|
create: {
|
||||||
|
icon: '<i class="fas fa-check"></i>',
|
||||||
|
label: "Créer l'oeuvre",
|
||||||
|
callback: () => this.actor.createItem($(".item-type").val())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async createEmptyTache() {
|
async createEmptyTache() {
|
||||||
await this.createItem('Nouvelle tache', 'tache');
|
await this.actor.createItem('tache', 'Nouvelle tache');
|
||||||
}
|
}
|
||||||
|
|
||||||
_optionRecherche(target) {
|
_optionRecherche(target) {
|
||||||
if (!target.value?.length){
|
if (!target.value?.length) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -546,8 +516,8 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
const sheetTabs = this.element.find(".sheet-tabs");
|
const sheetTabs = this.element.find(".sheet-tabs");
|
||||||
const sheetBody = this.element.find(".sheet-body");
|
const sheetBody = this.element.find(".sheet-body");
|
||||||
let bodyHeight = position.height - sheetHeader[0].clientHeight;
|
let bodyHeight = position.height - sheetHeader[0].clientHeight;
|
||||||
if (sheetTabs.length>0) {
|
if (sheetTabs.length > 0) {
|
||||||
bodyHeight -= sheetTabs[0].clientHeight;
|
bodyHeight -= sheetTabs[0].clientHeight;
|
||||||
}
|
}
|
||||||
sheetBody.css("height", bodyHeight);
|
sheetBody.css("height", bodyHeight);
|
||||||
return position;
|
return position;
|
||||||
|
|||||||
838
module/actor.js
242
module/actor/base-actor-sheet.js
Normal file
@@ -0,0 +1,242 @@
|
|||||||
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { DialogSplitItem } from "../dialog-split-item.js";
|
||||||
|
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
||||||
|
import { Monnaie } from "../item-monnaie.js";
|
||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
|
* @extends {ActorSheet}
|
||||||
|
*/
|
||||||
|
export class RdDBaseActorSheet extends ActorSheet {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static get defaultOptions() {
|
||||||
|
RdDUtility.initAfficheContenu();
|
||||||
|
return mergeObject(super.defaultOptions, {
|
||||||
|
classes: ["rdd", "sheet", "actor"],
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html",
|
||||||
|
width: 550,
|
||||||
|
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
||||||
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
|
||||||
|
showCompNiveauBase: false,
|
||||||
|
vueDetaillee: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async getData() {
|
||||||
|
Monnaie.validerMonnaies(this.actor.itemTypes['monnaie']);
|
||||||
|
|
||||||
|
this.actor.recompute();
|
||||||
|
let formData = {
|
||||||
|
title: this.title,
|
||||||
|
id: this.actor.id,
|
||||||
|
type: this.actor.type,
|
||||||
|
img: this.actor.img,
|
||||||
|
name: this.actor.name,
|
||||||
|
system: this.actor.system,
|
||||||
|
description: await TextEditor.enrichHTML(this.actor.system.description, { async: true }),
|
||||||
|
notesmj: await TextEditor.enrichHTML(this.actor.system.notesmj, { async: true }),
|
||||||
|
options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable)
|
||||||
|
}
|
||||||
|
|
||||||
|
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
||||||
|
formData.calc = {
|
||||||
|
fortune: Monnaie.toSolsDeniers(this.actor.getFortune()),
|
||||||
|
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
||||||
|
encTotal: await this.actor.computeEncTotal(),
|
||||||
|
}
|
||||||
|
|
||||||
|
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||||
|
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||||
|
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static filterItemsPerTypeForSheet(formData, itemTypes) {
|
||||||
|
formData.recettescuisine = Misc.arrayOrEmpty(itemTypes['recettecuisine']);
|
||||||
|
formData.recettesAlchimiques = Misc.arrayOrEmpty(itemTypes['recettealchimique']);
|
||||||
|
formData.maladies = Misc.arrayOrEmpty(itemTypes['maladie']);
|
||||||
|
formData.poisons = Misc.arrayOrEmpty(itemTypes['poison']);
|
||||||
|
formData.possessions = Misc.arrayOrEmpty(itemTypes['possession']);
|
||||||
|
formData.maladiesPoisons = formData.maladies.concat(formData.poisons);
|
||||||
|
formData.competences = (itemTypes['competence'] ?? []).concat(itemTypes['competencecreature'] ?? []);
|
||||||
|
formData.sortsReserve = Misc.arrayOrEmpty(itemTypes['sortreserve']);
|
||||||
|
|
||||||
|
formData.sorts = Misc.arrayOrEmpty(itemTypes['sort']);
|
||||||
|
formData.rencontres = Misc.arrayOrEmpty(itemTypes['rencontre']);
|
||||||
|
formData.casestmr = Misc.arrayOrEmpty(itemTypes['casetmr']);
|
||||||
|
formData.signesdraconiques = Misc.arrayOrEmpty(itemTypes['signedraconique']);
|
||||||
|
formData.queues = Misc.arrayOrEmpty(itemTypes['queue']);
|
||||||
|
formData.souffles = Misc.arrayOrEmpty(itemTypes['souffle']);
|
||||||
|
formData.ombres = Misc.arrayOrEmpty(itemTypes['ombre']);
|
||||||
|
formData.tetes = Misc.arrayOrEmpty(itemTypes['tete']);
|
||||||
|
formData.taches = Misc.arrayOrEmpty(itemTypes['tache']);
|
||||||
|
formData.meditations = Misc.arrayOrEmpty(itemTypes['meditation']);
|
||||||
|
formData.chants = Misc.arrayOrEmpty(itemTypes['chant']);
|
||||||
|
formData.danses = Misc.arrayOrEmpty(itemTypes['danse']);
|
||||||
|
formData.musiques = Misc.arrayOrEmpty(itemTypes['musique']);
|
||||||
|
formData.oeuvres = Misc.arrayOrEmpty(itemTypes['oeuvre']);
|
||||||
|
formData.jeux = Misc.arrayOrEmpty(itemTypes['jeu']);
|
||||||
|
|
||||||
|
formData.services = Misc.arrayOrEmpty(itemTypes['service']);
|
||||||
|
formData.conteneurs = Misc.arrayOrEmpty(itemTypes['conteneur']);
|
||||||
|
formData.materiel = Misc.arrayOrEmpty(itemTypes['objet']);
|
||||||
|
formData.armes = Misc.arrayOrEmpty(itemTypes['arme']);
|
||||||
|
formData.armures = Misc.arrayOrEmpty(itemTypes['armure']);
|
||||||
|
formData.munitions = Misc.arrayOrEmpty(itemTypes['munition']);
|
||||||
|
formData.livres = Misc.arrayOrEmpty(itemTypes['livre']);
|
||||||
|
formData.potions = Misc.arrayOrEmpty(itemTypes['potion']);
|
||||||
|
formData.plantes = Misc.arrayOrEmpty(itemTypes['plante']);
|
||||||
|
formData.ingredients = Misc.arrayOrEmpty(itemTypes['ingredient']);
|
||||||
|
formData.faunes = Misc.arrayOrEmpty(itemTypes['faune']);
|
||||||
|
formData.herbes = Misc.arrayOrEmpty(itemTypes['herbe']);
|
||||||
|
formData.nourritureboissons = Misc.arrayOrEmpty(itemTypes['nourritureboisson']);
|
||||||
|
formData.gemmes = Misc.arrayOrEmpty(itemTypes['gemme']);
|
||||||
|
formData.monnaie = Misc.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere());
|
||||||
|
|
||||||
|
formData.objets = RdDItem.getItemTypesInventaire('all')
|
||||||
|
.map(t => Misc.arrayOrEmpty(itemTypes[t]))
|
||||||
|
.reduce((a, b) => a.concat(b), [])
|
||||||
|
.sort(Misc.ascending(it => it.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */ /** @override */
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html = html;
|
||||||
|
|
||||||
|
this.html.find('.conteneur-name a').click(async event => {
|
||||||
|
RdDUtility.toggleAfficheContenu(this.getItemId(event));
|
||||||
|
this.render(true);
|
||||||
|
});
|
||||||
|
this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true))
|
||||||
|
this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat());
|
||||||
|
this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat());
|
||||||
|
|
||||||
|
// Everything below here is only needed if the sheet is editable
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
this.html.find('.item-split').click(async event => {
|
||||||
|
const item = this.getItem(event);
|
||||||
|
RdDSheetUtility.splitItem(item, this.actor);
|
||||||
|
});
|
||||||
|
this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, this.getItem(event)));
|
||||||
|
this.html.find('.item-vendre').click(async event => this.vendre(this.getItem(event)));
|
||||||
|
|
||||||
|
this.html.find('.creer-un-objet').click(async event => {
|
||||||
|
this.selectObjetTypeToCreate();
|
||||||
|
});
|
||||||
|
this.html.find('.nettoyer-conteneurs').click(async event => {
|
||||||
|
this.actor.nettoyerConteneurs();
|
||||||
|
});
|
||||||
|
this.html.find('.monnaie-plus').click(async event => {
|
||||||
|
this.actor.monnaieIncDec(this.getItemId(event), 1);
|
||||||
|
});
|
||||||
|
this.html.find('.monnaie-moins').click(async event => {
|
||||||
|
this.actor.monnaieIncDec(this.getItemId(event), -1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getItemId(event) {
|
||||||
|
return RdDSheetUtility.getItemId(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
getItem(event) {
|
||||||
|
return RdDSheetUtility.getItem(event, this.actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
_getHeaderButtons() {
|
||||||
|
let buttons = super._getHeaderButtons();
|
||||||
|
buttons.unshift({
|
||||||
|
class: "montrer",
|
||||||
|
icon: "fas fa-comment",
|
||||||
|
onclick: ev => this.actor.postActorToChat()
|
||||||
|
});
|
||||||
|
return buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async _onDropItem(event, dragData) {
|
||||||
|
const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id')
|
||||||
|
const dropParams = await RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, dragData, this.objetVersConteneur)
|
||||||
|
if (dropParams) {
|
||||||
|
const callSuper = await this.actor.processDropItem(dropParams)
|
||||||
|
if (callSuper) {
|
||||||
|
await super._onDropItem(event, dragData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async selectObjetTypeToCreate() {
|
||||||
|
let typeObjets = this.getTypesInventaire().sort(Misc.ascending(type => Misc.typeName('Item', type)));
|
||||||
|
let content = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
|
||||||
|
for (let typeName of typeObjets) {
|
||||||
|
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
||||||
|
}
|
||||||
|
content += '</select>';
|
||||||
|
let d = new Dialog({
|
||||||
|
title: "Créer un équipement",
|
||||||
|
content: content,
|
||||||
|
buttons: {
|
||||||
|
create: {
|
||||||
|
icon: '<i class="fas fa-check"></i>',
|
||||||
|
label: "Créer l'objet",
|
||||||
|
callback: () => this.actor.createItem($(".item-type").val())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
d.render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTypesInventaire() {
|
||||||
|
return RdDItem.getItemTypesInventaire();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
setPosition(options = {}) {
|
||||||
|
const position = super.setPosition(options);
|
||||||
|
const sheetHeader = this.element.find(".sheet-header");
|
||||||
|
const sheetTabs = this.element.find(".sheet-tabs");
|
||||||
|
const sheetBody = this.element.find(".sheet-body");
|
||||||
|
let bodyHeight = position.height - sheetHeader[0].clientHeight;
|
||||||
|
if (sheetTabs.length > 0) {
|
||||||
|
bodyHeight -= sheetTabs[0].clientHeight;
|
||||||
|
}
|
||||||
|
sheetBody.css("height", bodyHeight);
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** @override */
|
||||||
|
_updateObject(event, formData) {
|
||||||
|
// Update the Actor
|
||||||
|
return this.actor.update(formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
async splitItem(item) {
|
||||||
|
const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split));
|
||||||
|
dialog.render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onSplitItem(item, split) {
|
||||||
|
if (split >= 1 && split < item.system.quantite) {
|
||||||
|
await item.diminuerQuantite(split);
|
||||||
|
const splitItem = duplicate(item);
|
||||||
|
splitItem.system.quantite = split;
|
||||||
|
await this.actor.createEmbeddedDocuments('Item', [splitItem])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vendre(item) {
|
||||||
|
item?.proposerVente(this.actor.getQuantiteDisponible(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
627
module/actor/base-actor.js
Normal file
@@ -0,0 +1,627 @@
|
|||||||
|
import { ChatUtility } from "../chat-utility.js";
|
||||||
|
import { SYSTEM_SOCKET_ID } from "../constants.js";
|
||||||
|
import { Monnaie } from "../item-monnaie.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDAudio } from "../rdd-audio.js";
|
||||||
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
|
import { SystemCompendiums } from "../settings/system-compendiums.js";
|
||||||
|
|
||||||
|
export class RdDBaseActor extends Actor {
|
||||||
|
|
||||||
|
static getDefaultImg(itemType) {
|
||||||
|
return game.system.rdd.actorClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static init() {
|
||||||
|
Hooks.on("preUpdateItem", (item, change, options, id) => RdDBaseActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id));
|
||||||
|
Hooks.on("createItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onCreateItem(item, options, id));
|
||||||
|
Hooks.on("deleteItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onDeleteItem(item, options, id));
|
||||||
|
Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static onSocketMessage(sockmsg) {
|
||||||
|
switch (sockmsg.msg) {
|
||||||
|
case "msg_remote_actor_call":
|
||||||
|
return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId);
|
||||||
|
case "msg_reset_nombre_astral":
|
||||||
|
console.log("RESET ASTRAL", game.user.character);
|
||||||
|
game.user.character.resetNombreAstral();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static remoteActorCall(callData, userId = undefined) {
|
||||||
|
userId = userId ?? Misc.firstConnectedGMId();
|
||||||
|
if (userId == game.user.id) {
|
||||||
|
RdDBaseActor.onRemoteActorCall(callData, userId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_remote_actor_call", data: callData, userId: userId });
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static onRemoteActorCall(callData, userId) {
|
||||||
|
if (userId == game.user.id) {
|
||||||
|
const actor = game.actors.get(callData?.actorId);
|
||||||
|
if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
|
||||||
|
const args = callData.args;
|
||||||
|
console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')');
|
||||||
|
actor[callData.method](...args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getParentActor(document) {
|
||||||
|
return document?.parent instanceof Actor ? document.parent : undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cet methode surcharge Actor.create() pour ajouter si besoin des Items par défaut:
|
||||||
|
* compétences et monnaies.
|
||||||
|
*
|
||||||
|
* @param {Object} actorData template d'acteur auquel ajouter des informations.
|
||||||
|
* @param {Object} options optionspour customiser la création
|
||||||
|
*/
|
||||||
|
static async create(actorData, options) {
|
||||||
|
// import depuis un compendium
|
||||||
|
if (actorData instanceof Array) {
|
||||||
|
return super.create(actorData, options);
|
||||||
|
}
|
||||||
|
// Création d'un acteur avec des items (uniquement en cas de duplication): pas besoin d'ajouter d'items
|
||||||
|
if (actorData.items) {
|
||||||
|
return await super.create(actorData, options);
|
||||||
|
}
|
||||||
|
actorData.items = [];
|
||||||
|
if (actorData.type == "personnage") {
|
||||||
|
const competences = await SystemCompendiums.getCompetences(actorData.type);
|
||||||
|
actorData.items = actorData.items.concat(competences.map(i => i.toObject()))
|
||||||
|
.concat(Monnaie.monnaiesStandard());
|
||||||
|
}
|
||||||
|
else if (actorData.type == "commerce") {
|
||||||
|
actorData.items = actorData.items.concat(Monnaie.monnaiesStandard());
|
||||||
|
}
|
||||||
|
return super.create(actorData, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(docData, context = {}) {
|
||||||
|
if (!context.rdd?.ready) {
|
||||||
|
mergeObject(context, { rdd: { ready: true } });
|
||||||
|
const ActorConstructor = game.system.rdd.actorClasses[docData.type];
|
||||||
|
if (ActorConstructor) {
|
||||||
|
if (!docData.img) {
|
||||||
|
docData.img = ActorConstructor.defaultIcon;
|
||||||
|
}
|
||||||
|
return new ActorConstructor(docData, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super(docData, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
isCreatureEntite() { return this.type == 'creature' || this.type == 'entite'; }
|
||||||
|
isCreature() { return this.type == 'creature'; }
|
||||||
|
isEntite() { return this.type == 'entite'; }
|
||||||
|
isPersonnage() { return this.type == 'personnage'; }
|
||||||
|
isVehicule() { return this.type == 'vehicule'; }
|
||||||
|
|
||||||
|
getItem(id, type = undefined) {
|
||||||
|
const item = this.items.get(id);
|
||||||
|
if (type == undefined || (item?.type == type)) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); }
|
||||||
|
filterItems(filter, type = undefined) { return this.listItems(type)?.filter(filter) ?? []; }
|
||||||
|
findItemLike(idOrName, type) {
|
||||||
|
return this.getItem(idOrName, type)
|
||||||
|
?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) });
|
||||||
|
}
|
||||||
|
|
||||||
|
getMonnaie(id) { return this.findItemLike(id, 'monnaie'); }
|
||||||
|
|
||||||
|
recompute() { }
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async onPreUpdateItem(item, change, options, id) { }
|
||||||
|
|
||||||
|
async onCreateItem(item, options, id) { }
|
||||||
|
|
||||||
|
async onDeleteItem(item, options, id) { }
|
||||||
|
|
||||||
|
async onUpdateActor(update, options, actorId) { }
|
||||||
|
|
||||||
|
async onTimeChanging(oldTimestamp, newTimestamp) {
|
||||||
|
this.items.filter(it => it.isFinPeriode(oldTimestamp, newTimestamp))
|
||||||
|
.forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp))
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getFortune() {
|
||||||
|
return Monnaie.getFortune(this.itemTypes['monnaie']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async monnaieIncDec(id, value) {
|
||||||
|
let monnaie = this.getMonnaie(id);
|
||||||
|
if (monnaie) {
|
||||||
|
const quantite = Math.max(0, monnaie.system.quantite + value);
|
||||||
|
await this.updateEmbeddedDocuments('Item', [{ _id: monnaie.id, 'system.quantite': quantite }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
computePrixTotalEquipement() {
|
||||||
|
return this.items.filter(it => it.isInventaire())
|
||||||
|
.filter(it => !it.isMonnaie())
|
||||||
|
.map(it => it.valeurTotale())
|
||||||
|
.reduce(Misc.sum(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async payerSols(depense) {
|
||||||
|
depense = Number(depense);
|
||||||
|
if (depense == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let fortune = this.getFortune();
|
||||||
|
console.log("payer", game.user.character, depense, fortune);
|
||||||
|
let msg = "";
|
||||||
|
if (fortune >= depense) {
|
||||||
|
await Monnaie.optimiserFortune(this, fortune - depense);
|
||||||
|
msg = `Vous avez payé <strong>${depense} Sols</strong>, qui ont été soustraits de votre argent.`;
|
||||||
|
RdDAudio.PlayContextAudio("argent"); // Petit son
|
||||||
|
} else {
|
||||||
|
msg = "Vous n'avez pas assez d'argent pour payer cette somme !";
|
||||||
|
}
|
||||||
|
|
||||||
|
let message = {
|
||||||
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
||||||
|
content: msg
|
||||||
|
};
|
||||||
|
ChatMessage.create(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
async depenserSols(sols) {
|
||||||
|
let reste = this.getFortune() - Number(sols);
|
||||||
|
if (reste >= 0) {
|
||||||
|
await Monnaie.optimiserFortune(this, reste);
|
||||||
|
}
|
||||||
|
return reste;
|
||||||
|
}
|
||||||
|
|
||||||
|
async ajouterSols(sols, fromActorId = undefined) {
|
||||||
|
sols = Number(sols);
|
||||||
|
if (sols == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sols < 0) {
|
||||||
|
ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fromActorId && !game.user.isGM) {
|
||||||
|
RdDBaseActor.remoteActorCall({
|
||||||
|
userId: Misc.connectedGMOrUser(),
|
||||||
|
actorId: this.id,
|
||||||
|
method: 'ajouterSols', args: [sols, fromActorId]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const fromActor = game.actors.get(fromActorId)
|
||||||
|
await Monnaie.optimiserFortune(this, sols + this.getFortune());
|
||||||
|
|
||||||
|
RdDAudio.PlayContextAudio("argent"); // Petit son
|
||||||
|
ChatMessage.create({
|
||||||
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
||||||
|
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
getQuantiteDisponible(item) {
|
||||||
|
return item?.isService() ? undefined : item?.getQuantite();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async achatVente(achat) {
|
||||||
|
if (achat.vendeurId == achat.acheteurId) {
|
||||||
|
ui.notifications.info("Inutile de se vendre à soi-même");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!Misc.isUniqueConnectedGM()) {
|
||||||
|
RdDBaseActor.remoteActorCall({
|
||||||
|
actorId: achat.vendeurId ?? achat.acheteurId,
|
||||||
|
method: 'achatVente',
|
||||||
|
args: [achat]
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const cout = Number(achat.prixTotal ?? 0);
|
||||||
|
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
|
||||||
|
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined;
|
||||||
|
const vente = achat.vente;
|
||||||
|
const quantite = (achat.choix.nombreLots ?? 1) * (vente.tailleLot);
|
||||||
|
const itemVendu = vendeur?.getItem(vente.item._id);
|
||||||
|
if (!this.verifierQuantite(vendeur, itemVendu, quantite)) {
|
||||||
|
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (acheteur && !acheteur.verifierFortune(cout)) {
|
||||||
|
ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.decrementerVente(vendeur, itemVendu, quantite, cout);
|
||||||
|
if (acheteur) {
|
||||||
|
await acheteur.depenserSols(cout);
|
||||||
|
const createdItemId = await acheteur.creerQuantiteItem(vente.item, quantite);
|
||||||
|
await acheteur.consommerNourritureAchetee(achat, vente, createdItemId);
|
||||||
|
}
|
||||||
|
if (cout > 0) {
|
||||||
|
RdDAudio.PlayContextAudio("argent");
|
||||||
|
}
|
||||||
|
const chatAchatItem = duplicate(vente);
|
||||||
|
chatAchatItem.quantiteTotal = quantite;
|
||||||
|
ChatMessage.create({
|
||||||
|
user: achat.userId,
|
||||||
|
speaker: { alias: (acheteur ?? vendeur).name },
|
||||||
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
||||||
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html', chatAchatItem)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!vente.quantiteIllimite) {
|
||||||
|
if (vente.quantiteNbLots <= achat.choix.nombreLots) {
|
||||||
|
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
|
||||||
|
}
|
||||||
|
else if (achat.chatMessageIdVente) {
|
||||||
|
vente["properties"] = itemVendu.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async decrementerVente(vendeur, itemVendu, quantite, cout) {
|
||||||
|
if (vendeur) {
|
||||||
|
await vendeur.ajouterSols(cout);
|
||||||
|
await vendeur.decrementerQuantiteItem(itemVendu, quantite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verifierFortune(cout) {
|
||||||
|
return this.getFortune() >= cout;
|
||||||
|
}
|
||||||
|
|
||||||
|
verifierQuantite(vendeur, item, quantiteTotal) {
|
||||||
|
const disponible = vendeur?.getQuantiteDisponible(item);
|
||||||
|
return disponible == undefined || disponible >= quantiteTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
async consommerNourritureAchetee(achat, vente, createdItemId) {
|
||||||
|
if (achat.choix.consommer && vente.item.type == 'nourritureboisson' && createdItemId != undefined) {
|
||||||
|
achat.choix.doses = achat.choix.nombreLots;
|
||||||
|
await this.consommerNourritureboisson(createdItemId, achat.choix, vente.actingUserId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async decrementerQuantiteItem(item, quantite, options = { supprimerSiZero: true }) {
|
||||||
|
if (item.isService()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let resteQuantite = (item.system.quantite ?? 1) - quantite;
|
||||||
|
if (resteQuantite <= 0) {
|
||||||
|
if (options.supprimerSiZero) {
|
||||||
|
await this.deleteEmbeddedDocuments("Item", [item.id]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': 0 }]);
|
||||||
|
}
|
||||||
|
if (resteQuantite < 0) {
|
||||||
|
ui.notifications.warn(`La quantité de ${item.name} était insuffisante, l'objet a donc été supprimé`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (resteQuantite > 0) {
|
||||||
|
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': resteQuantite }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async creerQuantiteItem(item, quantite) {
|
||||||
|
if (this.canReceive(item)) {
|
||||||
|
const isItemEmpilable = "quantite" in item.system;
|
||||||
|
const baseItem = {
|
||||||
|
type: item.type,
|
||||||
|
img: item.img,
|
||||||
|
name: item.name,
|
||||||
|
system: mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined })
|
||||||
|
};
|
||||||
|
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
|
||||||
|
const items = await this.createEmbeddedDocuments("Item", newItems);
|
||||||
|
return items.length > 0 ? items[0].id : undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
computeMalusSurEncombrement() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEncombrementMax() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async computeEncTotal() {
|
||||||
|
if (!this.pack) {
|
||||||
|
this.encTotal = this.items.map(it => it.getEncTotal()).reduce(Misc.sum(), 0);
|
||||||
|
return this.encTotal;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
async createItem(type, name = undefined) {
|
||||||
|
if (!name) {
|
||||||
|
name = 'Nouveau ' + Misc.typeName('Item', type);
|
||||||
|
}
|
||||||
|
await this.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
canReceive(item) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async processDropItem(params) {
|
||||||
|
const targetActorId = this.id;
|
||||||
|
const sourceActorId = params.sourceActorId;
|
||||||
|
const itemId = params.itemId;
|
||||||
|
const destId = params.destId;
|
||||||
|
const srcId = params.srcId;
|
||||||
|
if (sourceActorId && sourceActorId != targetActorId) {
|
||||||
|
console.log("Moving objects", sourceActorId, targetActorId, itemId);
|
||||||
|
this.moveItemsBetweenActors(itemId, sourceActorId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let result = true;
|
||||||
|
const item = this.getItem(itemId);
|
||||||
|
if (item?.isInventaire('all') && sourceActorId == targetActorId) {
|
||||||
|
// rangement
|
||||||
|
if (srcId != destId && itemId != destId) { // déplacement de l'objet
|
||||||
|
const src = this.getItem(srcId);
|
||||||
|
const dest = this.getItem(destId);
|
||||||
|
const cible = this.getContenantOrParent(dest);
|
||||||
|
const [empilable, message] = item.isInventaireEmpilable(dest);
|
||||||
|
if (empilable) {
|
||||||
|
await dest.empiler(item)
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
// changer de conteneur
|
||||||
|
else if (!cible || this.conteneurPeutContenir(cible, item)) {
|
||||||
|
await this.enleverDeConteneur(item, src, params.onEnleverConteneur);
|
||||||
|
await this.ajouterDansConteneur(item, cible, params.onAjouterDansConteneur);
|
||||||
|
if (message && !dest.isConteneur()) {
|
||||||
|
ui.notifications.info(cible
|
||||||
|
? `${message}<br>${item.name} a été déplacé dans: ${cible.name}`
|
||||||
|
: `${message}<br>${item.name} a été sorti du conteneur`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.computeEncTotal();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getContenantOrParent(dest) {
|
||||||
|
if (!dest || dest.isConteneur()) {
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
return this.getContenant(dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
getContenant(item) {
|
||||||
|
return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
conteneurPeutContenir(dest, item) {
|
||||||
|
if (!dest) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!dest.isConteneur()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const destData = dest
|
||||||
|
if (this._isConteneurContenu(item, dest)) {
|
||||||
|
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${destData.name} !`);
|
||||||
|
return false; // Loop detected !
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculer le total actuel des contenus
|
||||||
|
let encContenu = this.getRecursiveEnc(dest) - Number(destData.system.encombrement);
|
||||||
|
let newEnc = this.getRecursiveEnc(item); // Calculer le total actuel du nouvel objet
|
||||||
|
|
||||||
|
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
|
||||||
|
if (Number(destData.system.capacite) < encContenu + newEnc) {
|
||||||
|
ui.notifications.warn(
|
||||||
|
`Le conteneur ${dest.name} a une capacité de ${destData.system.capacite}, et contient déjà ${encContenu}.
|
||||||
|
Impossible d'y ranger: ${item.name} d'encombrement ${newEnc}!`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
_isConteneurContenu(item, conteneur) {
|
||||||
|
if (item?.isConteneur()) { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant
|
||||||
|
for (let id of item.system.contenu) {
|
||||||
|
let subObjet = this.getItem(id);
|
||||||
|
if (subObjet?.id == conteneur.id) {
|
||||||
|
return true; // Loop detected !
|
||||||
|
}
|
||||||
|
if (subObjet?.isConteneur()) {
|
||||||
|
return this._isConteneurContenu(subObjet, conteneur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getRecursiveEnc(objet) {
|
||||||
|
if (!objet) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const tplData = objet.system;
|
||||||
|
if (objet.type != 'conteneur') {
|
||||||
|
return Number(tplData.encombrement) * Number(tplData.quantite);
|
||||||
|
}
|
||||||
|
const encContenus = tplData.contenu.map(idContenu => this.getRecursiveEnc(this.getItem(idContenu)));
|
||||||
|
return encContenus.reduce(Misc.sum(), 0)
|
||||||
|
+ Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** Ajoute un item dans un conteneur, sur la base
|
||||||
|
* de leurs ID */
|
||||||
|
async ajouterDansConteneur(item, conteneur, onAjouterDansConteneur) {
|
||||||
|
if (!conteneur) {
|
||||||
|
// TODO: afficher
|
||||||
|
item.estContenu = false;
|
||||||
|
}
|
||||||
|
else if (conteneur.isConteneur()) {
|
||||||
|
item.estContenu = true;
|
||||||
|
await this.updateEmbeddedDocuments('Item', [{
|
||||||
|
_id: conteneur.id,
|
||||||
|
'system.contenu': [...conteneur.system.contenu, item.id]
|
||||||
|
}]);
|
||||||
|
onAjouterDansConteneur(item.id, conteneur.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */
|
||||||
|
async nettoyerConteneurs() {
|
||||||
|
RdDConfirm.confirmer({
|
||||||
|
settingConfirmer: "confirmation-vider",
|
||||||
|
content: `<p>Etes vous certain de vouloir vider tous les conteneurs ?</p>`,
|
||||||
|
title: 'Vider les conteneurs',
|
||||||
|
buttonLabel: 'Vider',
|
||||||
|
onAction: async () => {
|
||||||
|
const corrections = [];
|
||||||
|
for (let item of this.items) {
|
||||||
|
if (item.estContenu) {
|
||||||
|
item.estContenu = undefined;
|
||||||
|
}
|
||||||
|
if (item.type == 'conteneur' && item.system.contenu.length > 0) {
|
||||||
|
corrections.push({ _id: item.id, 'system.contenu': [] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (corrections.length > 0) {
|
||||||
|
await this.updateEmbeddedDocuments('Item', corrections);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
buildSubConteneurObjetList(conteneurId, deleteList) {
|
||||||
|
let conteneur = this.getItem(conteneurId);
|
||||||
|
if (conteneur?.type == 'conteneur') { // Si c'est un conteneur
|
||||||
|
for (let subId of conteneur.system.contenu) {
|
||||||
|
let subObj = this.getItem(subId);
|
||||||
|
if (subObj) {
|
||||||
|
if (subObj.type == 'conteneur') {
|
||||||
|
this.buildSubConteneurObjetList(subId, deleteList);
|
||||||
|
}
|
||||||
|
deleteList.push({ id: subId, conteneurId: conteneurId });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async deleteAllConteneur(itemId, options) {
|
||||||
|
let list = [];
|
||||||
|
list.push({ id: itemId, conteneurId: undefined }); // Init list
|
||||||
|
this.buildSubConteneurObjetList(itemId, list);
|
||||||
|
await this.deleteEmbeddedDocuments('Item', list.map(it => it.id), options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** Supprime un item d'un conteneur, sur la base
|
||||||
|
* de leurs ID */
|
||||||
|
async enleverDeConteneur(item, conteneur, onEnleverDeConteneur) {
|
||||||
|
if (conteneur?.isConteneur()) {
|
||||||
|
item.estContenu = false;
|
||||||
|
await this.updateEmbeddedDocuments('Item', [{
|
||||||
|
_id: conteneur.id,
|
||||||
|
'system.contenu': conteneur.system.contenu.filter(id => id != item.id)
|
||||||
|
}]);
|
||||||
|
onEnleverDeConteneur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async moveItemsBetweenActors(itemId, sourceActorId) {
|
||||||
|
let itemsList = []
|
||||||
|
let sourceActor = game.actors.get(sourceActorId);
|
||||||
|
itemsList.push({ id: itemId, conteneurId: undefined }); // Init list
|
||||||
|
sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list
|
||||||
|
|
||||||
|
const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id))
|
||||||
|
.map(it => duplicate(it))
|
||||||
|
.map(it => { it.system.contenu = []; return it; });
|
||||||
|
let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate);
|
||||||
|
|
||||||
|
let itemMap = this._buildMapOldNewId(itemsList, newItems);
|
||||||
|
|
||||||
|
for (let item of itemsList) { // Second boucle pour traiter la remise en conteneurs
|
||||||
|
// gestion conteneur/contenu
|
||||||
|
if (item.conteneurId) { // l'Objet était dans un conteneur
|
||||||
|
let newConteneurId = itemMap[item.conteneurId]; // Get conteneur
|
||||||
|
let newConteneur = this.getItem(newConteneurId);
|
||||||
|
|
||||||
|
let newItemId = itemMap[item.id]; // Get newItem
|
||||||
|
|
||||||
|
console.log('New conteneur filling!', newConteneur, newItemId, item);
|
||||||
|
let contenu = duplicate(newConteneur.system.contenu);
|
||||||
|
contenu.push(newItemId);
|
||||||
|
await this.updateEmbeddedDocuments('Item', [{ _id: newConteneurId, 'system.contenu': contenu }]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let item of itemsList) {
|
||||||
|
await sourceActor.deleteEmbeddedDocuments('Item', [item.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_buildMapOldNewId(itemsList, newItems) {
|
||||||
|
let itemMap = {};
|
||||||
|
for (let i = 0; i < itemsList.length; i++) {
|
||||||
|
itemMap[itemsList[i].id] = newItems[i].id; // Pour garder le lien ancien / nouveau
|
||||||
|
}
|
||||||
|
return itemMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async postActorToChat(modeOverride) {
|
||||||
|
let chatData = {
|
||||||
|
doctype: 'Actor',
|
||||||
|
id: this.id,
|
||||||
|
type: this.type,
|
||||||
|
img: this.img,
|
||||||
|
pack: this.pack,
|
||||||
|
name: this.name,
|
||||||
|
system: { description: this.system.description }
|
||||||
|
}
|
||||||
|
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.html', chatData)
|
||||||
|
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
95
module/actor/commerce-sheet.js
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
import { DialogItemAchat } from "../dialog-item-achat.js";
|
||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
||||||
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
|
import { RdDBaseActorSheet } from "./base-actor-sheet.js";
|
||||||
|
import { RdDCommerce } from "./commerce.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
|
* @extends {ActorSheet}
|
||||||
|
*/
|
||||||
|
export class RdDCommerceSheet extends RdDBaseActorSheet {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static get defaultOptions() {
|
||||||
|
return mergeObject(super.defaultOptions, {
|
||||||
|
classes: ["rdd", "sheet", "actor"],
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html",
|
||||||
|
width: 600,
|
||||||
|
height: 720,
|
||||||
|
tabs: [],
|
||||||
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
get title() {
|
||||||
|
if (this.actor.token && this.actor.token != this.actor.prototypeToken) {
|
||||||
|
return this.actor.token.name;
|
||||||
|
}
|
||||||
|
return super.title
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData() {
|
||||||
|
const formData = await super.getData();
|
||||||
|
if (this.actor.token && this.actor.token != this.actor.prototypeToken) {
|
||||||
|
mergeObject(formData,
|
||||||
|
{
|
||||||
|
title: this.actor.token.name,
|
||||||
|
token: {
|
||||||
|
img: this.actor.token.texture.src
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ overwrite: true });
|
||||||
|
|
||||||
|
}
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** @override */
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
this.html.find('a.item-acheter').click(async event => await this.vente(this.getItem(event)));
|
||||||
|
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
this.html.find('a.item-quantite-moins').click(async event => await this.getItem(event)?.quantiteIncDec(-1, { supprimerSiZero: false }));
|
||||||
|
this.html.find('a.item-quantite-plus').click(async event => await this.getItem(event)?.quantiteIncDec(1));
|
||||||
|
this.html.find('input.item-quantite').change(async event => {
|
||||||
|
const newQuantite = Math.max(0, Number.parseInt(this.html.find(event.currentTarget).val()));
|
||||||
|
await this.getItem(event)?.update({ "system.quantite": newQuantite });
|
||||||
|
})
|
||||||
|
this.html.find('input.item-cout').change(async event => {
|
||||||
|
const newCout = Math.max(0, Number(this.html.find(event.currentTarget).val()));
|
||||||
|
await this.getItem(event)?.update({ "system.cout": newCout });
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getTypesInventaire() {
|
||||||
|
return RdDItem.getItemTypesInventaire('all');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async vente(item) {
|
||||||
|
const acheteur = RdDUtility.getSelectedActor();
|
||||||
|
if (!acheteur) {
|
||||||
|
ui.notifications.warn(`Pas d'acheteur sélectionné`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const disponible = this.actor.getQuantiteDisponible(item)
|
||||||
|
if (disponible == 0) {
|
||||||
|
ui.notifications.warn(`${this.name} n'a plus de ${item.name} en vente`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await DialogItemAchat.onAcheter({
|
||||||
|
item,
|
||||||
|
vendeur: this.actor,
|
||||||
|
acheteur,
|
||||||
|
quantiteIllimite: disponible == undefined,
|
||||||
|
nbLots: disponible ?? 1,
|
||||||
|
tailleLot: 1,
|
||||||
|
prixLot: item.calculerPrixCommercant()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
53
module/actor/commerce.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDBaseActor } from "./base-actor.js";
|
||||||
|
|
||||||
|
export class RdDCommerce extends RdDBaseActor {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/services/commerce.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareData() {
|
||||||
|
super.prepareData();
|
||||||
|
}
|
||||||
|
prepareDerivedData() {
|
||||||
|
super.prepareDerivedData();
|
||||||
|
}
|
||||||
|
|
||||||
|
canReceive(item) {
|
||||||
|
if (item.isInventaire('all')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.canReceive(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
getQuantiteDisponible(item) {
|
||||||
|
return this.system.illimite || item.isService() ? undefined : item.getQuantite();
|
||||||
|
}
|
||||||
|
|
||||||
|
verifierFortune(cout) {
|
||||||
|
return this.system.illimite || super.verifierFortune(cout);
|
||||||
|
}
|
||||||
|
async depenserSols(cout) {
|
||||||
|
if (this.system.illimite) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await super.depenserSols(cout)
|
||||||
|
}
|
||||||
|
|
||||||
|
async consommerNourritureAchetee(achat, vente, createdItemId) {
|
||||||
|
// ne pas consommer pour un commerce
|
||||||
|
}
|
||||||
|
|
||||||
|
async decrementerQuantiteItem(item, quantite) {
|
||||||
|
if (this.system.illimite) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await super.decrementerQuantiteItem(item, quantite, { supprimerSiZero: false });
|
||||||
|
}
|
||||||
|
|
||||||
|
calculerPrix(item) {
|
||||||
|
const pourcentage = this.system.pourcentage ?? 100;
|
||||||
|
return Misc.keepDecimals(Math.ceil(item.system.cout * pourcentage) / 100, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
import { SYSTEM_RDD } from "./constants.js";
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
|
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||||
|
|
||||||
|
|
||||||
const LATEST_USED_JOURNAL_ID = "chronologie-dernier-journal";
|
const LATEST_USED_JOURNAL_ID = "chronologie-dernier-journal";
|
||||||
@@ -16,40 +18,20 @@ export class DialogChronologie extends Dialog {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
static async create() {
|
static async create() {
|
||||||
const dateRdD = game.system.rdd.calendrier.getCalendrier();
|
|
||||||
const dialogData = {
|
const dialogData = {
|
||||||
auteur: game.user.name,
|
auteur: game.user.name,
|
||||||
isGM: game.user.isGM,
|
isGM: game.user.isGM,
|
||||||
information: "",
|
information: "",
|
||||||
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
|
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
|
||||||
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
|
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
|
||||||
dateRdD: dateRdD,
|
timestamp: game.system.rdd.calendrier.timestamp,
|
||||||
jourRdD: dateRdD.jour +1,
|
|
||||||
heureRdD: game.system.rdd.calendrier.getCurrentHeure(),
|
|
||||||
dateReel: DialogChronologie.getCurrentDateTime()
|
dateReel: DialogChronologie.getCurrentDateTime()
|
||||||
};
|
};
|
||||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.html", dialogData);
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.html", dialogData);
|
||||||
const dialog = new DialogChronologie(html);
|
const dialog = new DialogChronologie(html, dialogData);
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(html) {
|
|
||||||
const options = {
|
|
||||||
classes: ["DialogChronologie"],
|
|
||||||
width: 500,
|
|
||||||
height: 'fit-content',
|
|
||||||
'z-index': 99999
|
|
||||||
};
|
|
||||||
const conf = {
|
|
||||||
title: "Chronologie",
|
|
||||||
content: html,
|
|
||||||
buttons: {
|
|
||||||
ajout: { label: "Ajouter", callback: it => this.ajouter() },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
super(conf, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getCurrentDateTime() {
|
static getCurrentDateTime() {
|
||||||
return new Date().toLocaleString("sv-SE", {
|
return new Date().toLocaleString("sv-SE", {
|
||||||
year: "numeric",
|
year: "numeric",
|
||||||
@@ -60,18 +42,61 @@ export class DialogChronologie extends Dialog {
|
|||||||
}).replace(" ", "T");
|
}).replace(" ", "T");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constructor(html, dialogData) {
|
||||||
|
const options = {
|
||||||
|
classes: ["DialogChronologie"],
|
||||||
|
width: 500,
|
||||||
|
height: 'fit-content',
|
||||||
|
'z-index': 99999
|
||||||
|
};
|
||||||
|
const timeData = dialogData.timestamp.toCalendrier()
|
||||||
|
const conf = {
|
||||||
|
title: `Chronologie - ${timeData.jourDuMois} ${timeData.mois.label} - Heure ${timeData.heure.label}`,
|
||||||
|
content: html,
|
||||||
|
buttons: {
|
||||||
|
}
|
||||||
|
};
|
||||||
|
super(conf, options);
|
||||||
|
this.dialogData = dialogData;
|
||||||
|
}
|
||||||
|
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
|
||||||
this.html = html;
|
this.html = html;
|
||||||
|
super.activateListeners(html);
|
||||||
|
const journalPrecedent = game.journal.get(this.dialogData.journalId);
|
||||||
|
this.showChronologiePreset(!(journalPrecedent?.canUserModify(game.user)))
|
||||||
|
|
||||||
|
this.html.find("a.chronologie-preset-show").click(event => this.showChronologiePreset(true));
|
||||||
|
this.html.find("a.chronologie-preset-hide").click(event => this.showChronologiePreset(false));
|
||||||
|
this.html.find("button.chronologie-ajouter").click(event => this.ajouter());
|
||||||
|
}
|
||||||
|
|
||||||
|
showChronologiePreset(showPreset) {
|
||||||
|
HtmlUtility.showControlWhen(this.html.find(".chronologie-preset-show"), !showPreset);
|
||||||
|
HtmlUtility.showControlWhen(this.html.find(".chronologie-preset-hide"), showPreset);
|
||||||
|
HtmlUtility.showControlWhen(this.html.find(".chronologie-preset"), showPreset);
|
||||||
}
|
}
|
||||||
|
|
||||||
async ajouter() {
|
async ajouter() {
|
||||||
await this.forceValidation();
|
await this.forceValidation();
|
||||||
const { journalId, journalEntry } = this.findJournal();
|
const { journalId, journalEntry } = this.findJournal();
|
||||||
// ajouter à la page ou créer une page
|
if (journalEntry?.canUserModify(game.user)) {
|
||||||
this.addContentToJournal(journalEntry, await this.prepareChronologieEntry());
|
const journalParameters = this.extractJournalParameters();
|
||||||
|
|
||||||
this.storeLatestUsedJournalEntry(journalId);
|
const jour = journalParameters.dateRdD.jour;
|
||||||
|
const mois = journalParameters.dateRdD.mois.label;
|
||||||
|
const annee = journalParameters.dateRdD.annee;
|
||||||
|
const section = `${jour} ${mois} ${annee}`
|
||||||
|
const content = await this.prepareChronologieEntry(journalParameters);
|
||||||
|
// ajouter à la page ou créer une page
|
||||||
|
this.addContentToJournal(journalEntry, section, content);
|
||||||
|
this.storeLatestUsedJournalEntry(journalId);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const journal = this.html.find("form.rdddialogchrono select[name='journalId']").val();
|
||||||
|
ui.notifications.warn(`Le journal ${journal} n'est pas accessible`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async forceValidation() {
|
async forceValidation() {
|
||||||
@@ -84,8 +109,8 @@ export class DialogChronologie extends Dialog {
|
|||||||
return { journalId, journalEntry };
|
return { journalId, journalEntry };
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepareChronologieEntry() {
|
async prepareChronologieEntry(journalParameters) {
|
||||||
return await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chronologie-entry.html", this.extractJournalParameters());
|
return await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chronologie-entry.html", journalParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
extractJournalParameters() {
|
extractJournalParameters() {
|
||||||
@@ -93,28 +118,29 @@ export class DialogChronologie extends Dialog {
|
|||||||
auteur: this.html.find("form.rdddialogchrono :input[name='auteur']").val(),
|
auteur: this.html.find("form.rdddialogchrono :input[name='auteur']").val(),
|
||||||
information: this.html.find("form.rdddialogchrono :input[name='information']").val(),
|
information: this.html.find("form.rdddialogchrono :input[name='information']").val(),
|
||||||
dateRdD: {
|
dateRdD: {
|
||||||
jour: this.html.find("form.rdddialogchrono :input[name='jourRdD']").val(),
|
jour: this.html.find("form.rdddialogchrono :input[name='chronologie.jourDuMois']").val(),
|
||||||
moisRdD: this.html.find("form.rdddialogchrono :input[name='dateRdD.moisRdD.key']").val(),
|
mois: RdDTimestamp.definition(this.html.find("form.rdddialogchrono :input[name='chronologie.mois']").val()),
|
||||||
annee: this.html.find("form.rdddialogchrono :input[name='dateRdD.annee']").val()
|
annee: this.html.find("form.rdddialogchrono :input[name='chronologie.annee']").val(),
|
||||||
|
heure: RdDTimestamp.definition(this.html.find("form.rdddialogchrono :input[name='chronologie.heure']").val()),
|
||||||
|
minute: this.html.find("form.rdddialogchrono :input[name='chronologie.minute']").val(),
|
||||||
},
|
},
|
||||||
heureRdD: this.html.find("form.rdddialogchrono :input[name='heureRdD']").val(),
|
|
||||||
dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val().replace('T', ' ')
|
dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val().replace('T', ' ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addContentToJournal(journalEntry, content) {
|
addContentToJournal(journalEntry, section, content) {
|
||||||
let page = journalEntry.pages.find(p => p.type == 'text' && Grammar.equalsInsensitive(p.name, 'Chronologie'));
|
let page = journalEntry.pages.find(p => p.type == 'text' && Grammar.equalsInsensitive(p.name, section));
|
||||||
if (page) {
|
if (page) {
|
||||||
page.update({ 'text.content': content + '\n' + page.text.content });
|
page.update({ 'text.content': page.text.content + '\n' + content });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
journalEntry.createEmbeddedDocuments('JournalEntryPage', [this.newPageChronologie(content)]);
|
journalEntry.createEmbeddedDocuments('JournalEntryPage', [this.newPageChronologie(section, content)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newPageChronologie(content) {
|
newPageChronologie(section, content) {
|
||||||
return new JournalEntryPage({
|
return new JournalEntryPage({
|
||||||
name: 'Chronologie',
|
name: section,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
title: { show: true, level: 1 },
|
title: { show: true, level: 1 },
|
||||||
text: { content: content, format: 1 }
|
text: { content: content, format: 1 }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
|
import { RdDItemSigneDraconique } from "./item/signedraconique.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
export class DialogCreateSigneDraconique extends Dialog {
|
export class DialogCreateSigneDraconique extends Dialog {
|
||||||
@@ -98,7 +98,7 @@ export class DialogCreateSigneDraconique extends Dialog {
|
|||||||
|
|
||||||
async setEphemere(ephemere) {
|
async setEphemere(ephemere) {
|
||||||
this.dialogData.signe.system.ephemere = ephemere;
|
this.dialogData.signe.system.ephemere = ephemere;
|
||||||
HtmlUtility._showControlWhen(this.html.find(".signe-system-duree"), ephemere);
|
HtmlUtility.showControlWhen(this.html.find(".signe-system-duree"), ephemere);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSelectActor(event) {
|
async onSelectActor(event) {
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
|
import { Misc } from "./misc.js";
|
||||||
import { Monnaie } from "./item-monnaie.js";
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
|
||||||
export class DialogItemAchat extends Dialog {
|
export class DialogItemAchat extends Dialog {
|
||||||
|
|
||||||
static venteData(button) {
|
static preparerAchat(chatButton) {
|
||||||
const vendeurId = button.attributes['data-vendeurId']?.value;
|
const vendeurId = chatButton.attributes['data-vendeurId']?.value;
|
||||||
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
|
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
|
||||||
const acheteur = RdDUtility.getSelectedActor();
|
const acheteur = RdDUtility.getSelectedActor();
|
||||||
const json = button.attributes['data-jsondata']?.value;
|
const json = chatButton.attributes['data-jsondata']?.value;
|
||||||
if (!acheteur && !vendeur) {
|
if (!acheteur && !vendeur) {
|
||||||
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
|
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -18,46 +17,67 @@ export class DialogItemAchat extends Dialog {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const prixLot = Number(button.attributes['data-prixLot']?.value ?? 0);
|
|
||||||
return {
|
return {
|
||||||
item: json ? JSON.parse(json) : undefined,
|
item: (json ? JSON.parse(json) : undefined),
|
||||||
actingUserId: game.user.id,
|
vendeur,
|
||||||
vendeurId: vendeurId,
|
acheteur,
|
||||||
vendeur: vendeur,
|
nbLots: parseInt(chatButton.attributes['data-quantiteNbLots']?.value),
|
||||||
acheteur: acheteur,
|
tailleLot: parseInt(chatButton.attributes['data-tailleLot']?.value ?? 1),
|
||||||
tailleLot: parseInt(button.attributes['data-tailleLot']?.value ?? 1),
|
prixLot: Number(chatButton.attributes['data-prixLot']?.value ?? 0),
|
||||||
quantiteIllimite: button.attributes['data-quantiteIllimite']?.value == 'true',
|
quantiteIllimite: chatButton.attributes['data-quantiteIllimite']?.value == 'true',
|
||||||
quantiteNbLots: parseInt(button.attributes['data-quantiteNbLots']?.value),
|
chatMessageIdVente: RdDUtility.findChatMessageId(chatButton),
|
||||||
choix: {
|
|
||||||
nombreLots: 1,
|
|
||||||
seForcer: false,
|
|
||||||
supprimerSiZero: true
|
|
||||||
},
|
|
||||||
prixLot: prixLot,
|
|
||||||
prixTotal: prixLot,
|
|
||||||
isVente: prixLot > 0,
|
|
||||||
chatMessageIdVente: RdDUtility.findChatMessageId(button)
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static async onAcheter(venteData) {
|
|
||||||
|
static async onAcheter({ item, vendeur, acheteur, tailleLot, prixLot, nbLots, quantiteIllimite, chatMessageIdVente }) {
|
||||||
|
const venteData = {
|
||||||
|
item,
|
||||||
|
actingUserId: game.user.id,
|
||||||
|
vendeurId: vendeur?.id,
|
||||||
|
vendeur,
|
||||||
|
acheteur,
|
||||||
|
tailleLot,
|
||||||
|
quantiteIllimite,
|
||||||
|
quantiteNbLots: nbLots,
|
||||||
|
choix: { seForcer: false, supprimerSiZero: true },
|
||||||
|
prixLot,
|
||||||
|
isVente: prixLot > 0,
|
||||||
|
isConsommable: item.type == 'nourritureboisson' && acheteur?.isPersonnage(),
|
||||||
|
chatMessageIdVente
|
||||||
|
};
|
||||||
|
|
||||||
|
DialogItemAchat.changeNombreLots(venteData, 1);
|
||||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
|
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
|
||||||
new DialogItemAchat(html, venteData).render(true);
|
new DialogItemAchat(html, venteData).render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static changeNombreLots(venteData, nombreLots) {
|
||||||
|
venteData.choix.nombreLots = nombreLots;
|
||||||
|
venteData.prixTotal = (nombreLots * venteData.prixLot).toFixed(2);
|
||||||
|
if (venteData.isConsommable) {
|
||||||
|
const doses = nombreLots * venteData.tailleLot;
|
||||||
|
venteData.totalSust = Misc.keepDecimals(doses * (venteData.item.system.sust ?? 0), 2);
|
||||||
|
venteData.totalDesaltere = venteData.item.system.boisson
|
||||||
|
? Misc.keepDecimals(doses * (venteData.item.system.desaltere ?? 0), 2)
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constructor(html, venteData) {
|
constructor(html, venteData) {
|
||||||
const isConsommable = venteData.item.type == 'nourritureboisson' && venteData.acheteur?.isPersonnage();
|
|
||||||
let options = { classes: ["dialogachat"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
let options = { classes: ["dialogachat"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
||||||
|
|
||||||
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
|
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
|
||||||
const buttons = {};
|
const buttons = {};
|
||||||
if (isConsommable) {
|
if (venteData.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[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
|
||||||
buttons["decliner"] = { label: "Décliner", callback: it => { } };
|
buttons["decliner"] = { label: "Décliner", callback: it => { } };
|
||||||
|
const acheteur = venteData.acheteur?.name ?? 'Un acheteur';
|
||||||
|
const vendeur = venteData.vendeur?.name ?? 'Un vendeur';
|
||||||
let conf = {
|
let conf = {
|
||||||
title: venteData.acheteur ? venteData.acheteur.name + " - " + actionAchat : actionAchat,
|
title: `${acheteur} - ${actionAchat} à ${vendeur}`,
|
||||||
content: html,
|
content: html,
|
||||||
default: actionAchat,
|
default: actionAchat,
|
||||||
buttons: buttons
|
buttons: buttons
|
||||||
@@ -98,13 +118,21 @@ export class DialogItemAchat extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setNombreLots(nombreLots) {
|
setNombreLots(nombreLots) {
|
||||||
if (nombreLots > this.venteData.quantiteNbLots) {
|
|
||||||
ui.notifications.warn(`Seulement ${this.venteData.quantiteNbLots} lots disponibles, vous ne pouvez pas en prendre ${nombreLots}`)
|
if (!this.venteData.quantiteIllimite) {
|
||||||
|
if (!this.venteData.quantiteIllimite && nombreLots > this.venteData.quantiteNbLots) {
|
||||||
|
ui.notifications.warn(`Seulement ${this.venteData.quantiteNbLots} lots disponibles, vous ne pouvez pas en prendre ${nombreLots}`)
|
||||||
|
}
|
||||||
|
nombreLots = Math.min(nombreLots, this.venteData.quantiteNbLots);
|
||||||
}
|
}
|
||||||
this.venteData.choix.nombreLots = Math.min(nombreLots, this.venteData.quantiteNbLots);
|
|
||||||
this.venteData.prixTotal = (nombreLots * this.venteData.prixLot).toFixed(2);
|
DialogItemAchat.changeNombreLots(this.venteData, nombreLots);
|
||||||
this.html.find(".nombreLots").val(this.venteData.choix.nombreLots);
|
|
||||||
|
this.html.find(".nombreLots").val(nombreLots);
|
||||||
this.html.find(".prixTotal").text(this.venteData.prixTotal);
|
this.html.find(".prixTotal").text(this.venteData.prixTotal);
|
||||||
|
this.html.find("span.total-sust").text(this.venteData.totalSust);
|
||||||
|
this.html.find("span.total-desaltere").text(this.venteData.totalDesaltere);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,21 +2,22 @@ import { HtmlUtility } from "./html-utility.js";
|
|||||||
|
|
||||||
export class DialogItemVente extends Dialog {
|
export class DialogItemVente extends Dialog {
|
||||||
|
|
||||||
static async display(item, callback) {
|
static async display({ item, callback, quantiteMax = undefined }) {
|
||||||
const quantite = item.isConteneur() ? 1 : item.system.quantite;
|
const quantite = quantiteMax ?? item.getQuantite() ?? 1;
|
||||||
|
const isOwned = item.parent;
|
||||||
const venteData = {
|
const venteData = {
|
||||||
item: item,
|
item: item,
|
||||||
alias: item.actor?.name ?? game.user.name,
|
alias: item.actor?.name ?? game.user.name,
|
||||||
vendeurId: item.actor?.id,
|
vendeurId: item.actor?.id,
|
||||||
prixOrigine: item.system.cout,
|
prixOrigine: item.calculerPrixCommercant(),
|
||||||
prixUnitaire: item.system.cout,
|
prixUnitaire: item.calculerPrixCommercant(),
|
||||||
prixLot: item.system.cout,
|
prixLot: item.calculerPrixCommercant(),
|
||||||
tailleLot: 1,
|
tailleLot: 1,
|
||||||
quantiteNbLots: quantite,
|
quantiteNbLots: quantite,
|
||||||
quantiteMaxLots: quantite,
|
quantiteMaxLots: quantite,
|
||||||
quantiteMax: quantite ,
|
quantiteMax: quantite,
|
||||||
quantiteIllimite: !item.isOwned,
|
quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !isOwned,
|
||||||
isOwned: item.isOwned,
|
isOwned: isOwned,
|
||||||
};
|
};
|
||||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
|
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
|
||||||
return new DialogItemVente(venteData, html, callback).render(true);
|
return new DialogItemVente(venteData, html, callback).render(true);
|
||||||
@@ -39,22 +40,33 @@ export class DialogItemVente extends Dialog {
|
|||||||
|
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
this.html = html;
|
|
||||||
HtmlUtility._showControlWhen(this.html.find(".quantiteNbLots"), !this.venteData.quantiteIllimite)
|
|
||||||
|
|
||||||
|
this.html = html;
|
||||||
this.html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
|
this.html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
|
||||||
this.html.find(".quantiteNbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
|
this.html.find(".quantiteNbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
|
||||||
this.html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked));
|
this.html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked));
|
||||||
this.html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value)));
|
this.html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value)));
|
||||||
|
|
||||||
|
this.setQuantiteIllimite(this.venteData.quantiteIllimite);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onProposer(it) {
|
async onProposer(it) {
|
||||||
await this.html.find(".tailleLot").change();
|
this.updateVente(this.getChoixVente());
|
||||||
await this.html.find(".quantiteNbLots").change();
|
|
||||||
await this.html.find(".quantiteIllimite").change();
|
|
||||||
await this.html.find(".prixLot").change();
|
|
||||||
this.callback(this.venteData);
|
this.callback(this.venteData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateVente(update) {
|
||||||
|
mergeObject(this.venteData, update);
|
||||||
|
}
|
||||||
|
|
||||||
|
getChoixVente() {
|
||||||
|
return {
|
||||||
|
quantiteNbLots: Number(this.html.find(".quantiteNbLots").val()),
|
||||||
|
tailleLot: Number(this.html.find(".tailleLot").val()),
|
||||||
|
quantiteIllimite: this.html.find(".quantiteIllimite").is(':checked'),
|
||||||
|
prixLot: Number(this.html.find(".prixLot").val())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
setPrixLot(prixLot) {
|
setPrixLot(prixLot) {
|
||||||
@@ -62,32 +74,29 @@ export class DialogItemVente extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setTailleLot(tailleLot) {
|
setTailleLot(tailleLot) {
|
||||||
// recalculer le prix du lot
|
const maxLots = Math.floor(this.venteData.quantiteMax / tailleLot);
|
||||||
if (tailleLot != this.venteData.tailleLot) {
|
this.updateVente({
|
||||||
this.venteData.prixLot = (tailleLot * this.venteData.prixOrigine).toFixed(2);
|
tailleLot,
|
||||||
this.html.find(".prixLot").val(this.venteData.prixLot);
|
quantiteNbLots: Math.min(maxLots, this.venteData.quantiteNbLots),
|
||||||
}
|
quantiteMaxLots: maxLots,
|
||||||
this.venteData.tailleLot = tailleLot;
|
prixLot: (tailleLot * this.venteData.prixOrigine).toFixed(2)
|
||||||
if (this.venteData.isOwned) {
|
});
|
||||||
// recalculer le nombre de lots max
|
|
||||||
this.venteData.quantiteMaxLots = Math.floor(this.venteData.quantiteMax / tailleLot);
|
this.html.find(".prixLot").val(this.venteData.prixLot);
|
||||||
this.venteData.quantiteNbLots = Math.min(this.venteData.quantiteMaxLots, this.venteData.quantiteNbLots);
|
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
|
||||||
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
|
this.html.find(".quantiteNbLots").attr("max", this.venteData.quantiteMaxLots)
|
||||||
this.html.find(".quantiteNbLots").attr("max", this.venteData.quantiteMaxLots)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setNbLots(nbLots) {
|
setNbLots(nbLots) {
|
||||||
if (this.venteData.isOwned) {
|
this.updateVente({
|
||||||
nbLots = Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots));
|
quantiteNbLots: this.venteData.isOwned ? Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots)) : nbLots
|
||||||
}
|
})
|
||||||
this.venteData.quantiteNbLots = nbLots;
|
|
||||||
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
|
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
|
||||||
}
|
}
|
||||||
|
|
||||||
setQuantiteIllimite(checked) {
|
setQuantiteIllimite(checked) {
|
||||||
this.venteData.quantiteIllimite = checked;
|
this.updateVente({ quantiteIllimite: checked })
|
||||||
this.html.find(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles");
|
this.html.find(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles");
|
||||||
HtmlUtility._showControlWhen(this.html.find(".quantiteNbLots"), !this.venteData.quantiteIllimite)
|
HtmlUtility.showControlWhen(this.html.find(".quantiteNbLots"), !this.venteData.quantiteIllimite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Misc } from "./misc.js";
|
|
||||||
|
|
||||||
export class DialogRepos extends Dialog {
|
export class DialogRepos extends Dialog {
|
||||||
|
|
||||||
@@ -9,7 +8,7 @@ export class DialogRepos extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(html, actor) {
|
constructor(html, actor) {
|
||||||
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 500, height: 400, 'z-index': 99999 };
|
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
||||||
let conf = {
|
let conf = {
|
||||||
title: "Se reposer",
|
title: "Se reposer",
|
||||||
content: html,
|
content: html,
|
||||||
@@ -33,6 +32,7 @@ export class DialogRepos extends Dialog {
|
|||||||
const selection = await this.html.find("[name='repos']:checked").val();
|
const selection = await this.html.find("[name='repos']:checked").val();
|
||||||
const nbHeures = Number.parseInt(await this.html.find("[name='nb-heures']").val());
|
const nbHeures = Number.parseInt(await this.html.find("[name='nb-heures']").val());
|
||||||
const nbJours = Number.parseInt(await this.html.find("[name='nb-jours']").val());
|
const nbJours = Number.parseInt(await this.html.find("[name='nb-jours']").val());
|
||||||
|
console.log("ACTOR", this.actor)
|
||||||
switch (selection) {
|
switch (selection) {
|
||||||
case "sieste": {
|
case "sieste": {
|
||||||
await this.actor.dormir(nbHeures);
|
await this.actor.dormir(nbHeures);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export class DialogSplitItem extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(item, splitData, html, callback) {
|
constructor(item, splitData, html, callback) {
|
||||||
let options = { classes: ["dialogsplit"], width: 300, height: 160, 'z-index': 99999 };
|
let options = { classes: ["dialogsplit"], width: 300, height: 'fit-content', 'z-index': 99999 };
|
||||||
let conf = {
|
let conf = {
|
||||||
title: "Séparer en deux",
|
title: "Séparer en deux",
|
||||||
content: html,
|
content: html,
|
||||||
|
|||||||
@@ -1,223 +1,78 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
import { SYSTEM_RDD } from "./constants.js";
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { CompendiumTableHelpers, CompendiumTable } from "./settings/system-compendiums.js";
|
import { CompendiumTableHelpers, CompendiumTable, SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
|
|
||||||
const RARETES = [
|
|
||||||
{ name: 'Commune', frequence: 54, min: 27, max: 108 },
|
|
||||||
{ name: 'Frequente', frequence: 18, min: 9, max: 36 },
|
|
||||||
{ name: 'Rare', frequence: 6, min: 3, max: 12 },
|
|
||||||
{ name: 'Rarissime', frequence: 2, min: 1, max: 4 }]
|
|
||||||
const DEFAULT_RARETE = 1;
|
|
||||||
|
|
||||||
const SETTINGS_LISTE_MILIEUX = "liste-milieux";
|
const COMPENDIUMS_RECHERCHE = 'compendiums-recherche';
|
||||||
const MILIEUX = [
|
|
||||||
"Collines",
|
|
||||||
"Cours d'eau",
|
|
||||||
"Déserts",
|
|
||||||
"Forêts",
|
|
||||||
"Marais",
|
|
||||||
"Maritimes",
|
|
||||||
"Montagnes",
|
|
||||||
"Plaines",
|
|
||||||
"Sous-sols"
|
|
||||||
]
|
|
||||||
const ITEM_ENVIRONNEMENT_TYPES = [
|
|
||||||
'herbe', 'ingredient', 'faune'
|
|
||||||
]
|
|
||||||
|
|
||||||
export class Environnement {
|
export class Environnement {
|
||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
game.settings.register(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX, {
|
game.settings.register(SYSTEM_RDD, COMPENDIUMS_RECHERCHE, {
|
||||||
name: "Liste des milieux proposés",
|
name: COMPENDIUMS_RECHERCHE,
|
||||||
hint: "Liste des milieux proposés pour la faune&flore, séparés par des virgules",
|
default: [
|
||||||
|
SystemCompendiums.getCompendium('faune-flore-mineraux'),
|
||||||
|
SystemCompendiums.getCompendium('meditations-et-ecrits'),
|
||||||
|
SystemCompendiums.getCompendium('equipement')
|
||||||
|
],
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: true,
|
config: false,
|
||||||
default: MILIEUX.reduce(Misc.joining(',')),
|
type: Object
|
||||||
type: String
|
|
||||||
});
|
});
|
||||||
|
|
||||||
game.system.rdd.environnement = new Environnement();
|
game.system.rdd.environnement = new Environnement();
|
||||||
|
Hooks.once('ready', () => game.system.rdd.environnement.onReady());
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.table = new CompendiumTable('faune-flore-mineraux', 'Item', ITEM_ENVIRONNEMENT_TYPES)
|
this.compendiums = [];
|
||||||
|
this.compendiumTables = [];
|
||||||
|
this.mapMilieux = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
static getRarete(name = undefined) {
|
async onReady() {
|
||||||
return RARETES.find(it => it.name == name) ?? RARETES[DEFAULT_RARETE];
|
await this.$prepareCompendiums()
|
||||||
}
|
|
||||||
|
|
||||||
static getFrequenceRarete(rarete, field = undefined) {
|
|
||||||
const selected = this.getRarete(rarete);
|
|
||||||
return selected[field];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async milieux() {
|
async milieux() {
|
||||||
return Object.values(await this.mapMilieux());
|
return Object.values(this.mapMilieux);
|
||||||
}
|
}
|
||||||
|
|
||||||
async mapMilieux() {
|
async saveCompendiums(compendiumIds) {
|
||||||
const compendiumItems = await this.getElements(it => 1, it => ITEM_ENVIRONNEMENT_TYPES.includes(it.type));
|
game.settings.set(SYSTEM_RDD, COMPENDIUMS_RECHERCHE, compendiumIds);
|
||||||
return Misc.indexLowercase(this.getMilieuxSettings().concat(Environnement.listMilieux(compendiumItems)));
|
await this.$prepareCompendiums();
|
||||||
}
|
}
|
||||||
|
|
||||||
static listMilieux(items) {
|
async $prepareCompendiums() {
|
||||||
return Misc.concat(items.map(it => Environnement.$itemToMilieux(it).filter(m => m)));
|
this.compendiums = game.settings.get(SYSTEM_RDD, COMPENDIUMS_RECHERCHE).filter(c => SystemCompendiums.getPack(c));
|
||||||
|
|
||||||
|
this.compendiumTables = this.compendiums.map(it => new CompendiumTable(it, 'Item'));
|
||||||
|
const compendiumItems = await this.getElements(it => 1, it => it.isInventaire());
|
||||||
|
const fromCompendiums = Misc.concat(compendiumItems.map(it => it.getMilieux().filter(m => m)));
|
||||||
|
this.mapMilieux = Misc.indexLowercase(fromCompendiums);
|
||||||
}
|
}
|
||||||
|
|
||||||
async autresMilieux(item) {
|
async autresMilieux(item) {
|
||||||
const mapMilieux = await this.mapMilieux();
|
const milieuxExistants = item.getMilieux().map(it => Grammar.toLowerCaseNoAccent(it));
|
||||||
const milieuxExistants = Environnement.$itemToMilieux(item).map(it => Grammar.toLowerCaseNoAccent(it));
|
return Object.keys(this.mapMilieux)
|
||||||
return Object.keys(mapMilieux)
|
|
||||||
.filter(it => !milieuxExistants.includes(it))
|
.filter(it => !milieuxExistants.includes(it))
|
||||||
.map(it => mapMilieux[it]);
|
.map(it => this.mapMilieux[it]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static $itemToMilieux(item) {
|
|
||||||
return item.system.environnement.map(env => env.milieu);
|
|
||||||
}
|
|
||||||
|
|
||||||
getMilieuxSettings() {
|
|
||||||
return game.settings.get(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX).split(',').map(it => it.trim()).filter(it => it != '');
|
|
||||||
}
|
|
||||||
|
|
||||||
async findEnvironnementsLike(search) {
|
|
||||||
const milieux = await this.mapMilieux();
|
|
||||||
const searchLower = Grammar.toLowerCaseNoAccent(search);
|
|
||||||
const keys = Object.keys(milieux).filter(it => it.includes(searchLower));
|
|
||||||
if (keys.length > 1) {
|
|
||||||
const milieuExact = milieux[searchLower];
|
|
||||||
if (milieuExact) {
|
|
||||||
return [milieuExact];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys.map(k => milieux[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async searchToChatMessage(milieux, typeName) {
|
|
||||||
const table = await this.buildEnvironnementTable(milieux);
|
|
||||||
await CompendiumTableHelpers.tableToChatMessage(table, 'Item', ITEM_ENVIRONNEMENT_TYPES, typeName);
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRandom(milieux, typeName) {
|
|
||||||
const table = await this.buildEnvironnementTable(milieux);
|
|
||||||
return await CompendiumTableHelpers.getRandom(table, 'Item', ITEM_ENVIRONNEMENT_TYPES, undefined, typeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
async buildEnvironnementTable(milieux) {
|
|
||||||
const filterMilieux = item => item.system?.environnement.filter(env => milieux.includes(env.milieu));
|
|
||||||
const itemRareteEnMilieu = item => {
|
|
||||||
const raretes = filterMilieux(item);
|
|
||||||
const frequenceMax = Math.max(raretes.map(env => env.frequence));
|
|
||||||
return raretes.find(env => env.frequence == frequenceMax);
|
|
||||||
}
|
|
||||||
const itemFrequenceEnMilieu = item => itemRareteEnMilieu(item)?.frequence ?? 0;
|
|
||||||
const isPresentEnMilieu = item => itemFrequenceEnMilieu(item) > 0;
|
|
||||||
return await this.table.buildTable(itemFrequenceEnMilieu, isPresentEnMilieu);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async getElements(itemFrequence, filter) {
|
async getElements(itemFrequence, filter) {
|
||||||
return await this.table.getContent(itemFrequence, filter);
|
const compendiumsElement = await Promise.all(
|
||||||
|
this.compendiumTables.map(async compTable => await compTable.getContent(itemFrequence, filter))
|
||||||
|
);
|
||||||
|
const elements = compendiumsElement.reduce((a, b) => a.concat(b));
|
||||||
|
elements.sort(Misc.ascending(it => it.name))
|
||||||
|
return elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildTable(itemFrequence, filter = it => true) {
|
||||||
|
if (!itemFrequence) {
|
||||||
|
itemFrequence = it => it.getFrequence()
|
||||||
|
}
|
||||||
|
const elements = await this.getElements(itemFrequence, filter);;
|
||||||
|
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EnvironmentSheetHelper {
|
|
||||||
|
|
||||||
static defaultOptions(defaultOptions) {
|
|
||||||
return mergeObject(defaultOptions, {
|
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static setPosition(sheet, superPosition) {
|
|
||||||
const position = superPosition;
|
|
||||||
const sheetHeader = sheet.element.find(".sheet-header");
|
|
||||||
const sheetBody = sheet.element.find(".sheet-body");
|
|
||||||
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async getData(sheet, formData) {
|
|
||||||
return mergeObject(formData, {
|
|
||||||
milieux: await game.system.rdd.environnement.autresMilieux(sheet.item)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static activateListeners(sheet) {
|
|
||||||
if (!sheet.options.editable) return;
|
|
||||||
|
|
||||||
sheet.html.find("input.input-selection-milieu").keypress(event => {
|
|
||||||
if (event.keyCode == '13') {
|
|
||||||
EnvironmentSheetHelper.onAddMilieu(sheet, event);
|
|
||||||
}
|
|
||||||
event.stopPropagation();
|
|
||||||
})
|
|
||||||
sheet.html.find("a.milieu-add").click(event => EnvironmentSheetHelper.onAddMilieu(sheet, event));
|
|
||||||
sheet.html.find("div.environnement-milieu a.milieu-delete").click(event => EnvironmentSheetHelper.onDeleteMilieu(sheet, event));
|
|
||||||
sheet.html.find("div.environnement-milieu select.environnement-rarete").change(event => EnvironmentSheetHelper.onChange(sheet, event,
|
|
||||||
updated => EnvironmentSheetHelper.$changeRarete(sheet, event, updated)));
|
|
||||||
sheet.html.find("div.environnement-milieu input[name='environnement-frequence']").change(event => EnvironmentSheetHelper.onChange(sheet, event,
|
|
||||||
updated => EnvironmentSheetHelper.$changeFrequence(sheet, event, updated)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static $changeFrequence(sheet, event, updated) {
|
|
||||||
updated.frequence = Number(sheet.html.find(event.currentTarget).val());
|
|
||||||
}
|
|
||||||
|
|
||||||
static $changeRarete(sheet, event, updated) {
|
|
||||||
const name = sheet.html.find(event.currentTarget).val();
|
|
||||||
const rarete = Environnement.getRarete(name);
|
|
||||||
updated.rarete = rarete.name;
|
|
||||||
updated.frequence = rarete.frequence;
|
|
||||||
// updated.frequence = Math.min(
|
|
||||||
// Math.max(rarete.min, updated.frequence ?? rarete.frequence),
|
|
||||||
// rarete.max);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async onAddMilieu(sheet, event) {
|
|
||||||
const milieu = sheet.html.find('input.input-selection-milieu').val();
|
|
||||||
if (!milieu) {
|
|
||||||
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${sheet.item.name}`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const list = sheet.item.system.environnement;
|
|
||||||
const exists = list.find(it => it.milieu == milieu);
|
|
||||||
if (exists) {
|
|
||||||
ui.notifications.warn(`${sheet.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const rarete = Environnement.getRarete();
|
|
||||||
const newList = [...list, { milieu, rarete: rarete.name, frequence: rarete.frequence }].sort(Misc.ascending(it => it.milieu))
|
|
||||||
await sheet.item.update({ 'system.environnement': newList })
|
|
||||||
}
|
|
||||||
|
|
||||||
static async onDeleteMilieu(sheet, event) {
|
|
||||||
const milieu = EnvironmentSheetHelper.$getEventMilieu(sheet, event);
|
|
||||||
if (milieu != undefined) {
|
|
||||||
const newList = sheet.item.system.environnement.filter(it => it.milieu != milieu)
|
|
||||||
.sort(Misc.ascending(it => it.milieu));
|
|
||||||
await sheet.item.update({ 'system.environnement': newList });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async onChange(sheet, event, doMutation) {
|
|
||||||
const list = sheet.item.system.environnement;
|
|
||||||
const milieu = EnvironmentSheetHelper.$getEventMilieu(sheet, event);
|
|
||||||
const updated = list.find(it => it.milieu == milieu);
|
|
||||||
if (updated) {
|
|
||||||
doMutation(updated);
|
|
||||||
const newList = [...list.filter(it => it.milieu != milieu), updated]
|
|
||||||
.sort(Misc.ascending(it => it.milieu));
|
|
||||||
await sheet.item.update({ 'system.environnement': newList });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static $getEventMilieu(sheet, event) {
|
|
||||||
return sheet.html.find(event.currentTarget)?.parents("div.environnement-milieu").data("milieu");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
export class HtmlUtility{
|
export class HtmlUtility{
|
||||||
static _showControlWhen(jQuerySelector, condition) {
|
static showControlWhen(jQuerySelector, condition) {
|
||||||
if (condition) {
|
if (condition) {
|
||||||
jQuerySelector.show();
|
jQuerySelector.show();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
|
||||||
import { Misc } from "./misc.js";
|
|
||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
import { RdDCombatManager } from "./rdd-combat.js";
|
||||||
|
|
||||||
const nomCategorieParade = {
|
const nomCategorieParade = {
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ const xp_par_niveau = [5, 5, 5, 10, 10, 10, 10, 15, 15, 15, 15, 20, 20, 20, 20,
|
|||||||
const niveau_max = xp_par_niveau.length - 10;
|
const niveau_max = xp_par_niveau.length - 10;
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const limitesArchetypes = [
|
const limitesArchetypes = [
|
||||||
{ "niveau": 0, "nombreMax": 100, "nombre": 0 },
|
{ "niveau": 0, "nombreMax": 100, "reste": 100 },
|
||||||
{ "niveau": 1, "nombreMax": 10, "nombre": 0 },
|
{ "niveau": 1, "nombreMax": 10, "reste": 10 },
|
||||||
{ "niveau": 2, "nombreMax": 9, "nombre": 0 },
|
{ "niveau": 2, "nombreMax": 9, "reste": 9 },
|
||||||
{ "niveau": 3, "nombreMax": 8, "nombre": 0 },
|
{ "niveau": 3, "nombreMax": 8, "reste": 8 },
|
||||||
{ "niveau": 4, "nombreMax": 7, "nombre": 0 },
|
{ "niveau": 4, "nombreMax": 7, "reste": 7 },
|
||||||
{ "niveau": 5, "nombreMax": 6, "nombre": 0 },
|
{ "niveau": 5, "nombreMax": 6, "reste": 6 },
|
||||||
{ "niveau": 6, "nombreMax": 5, "nombre": 0 },
|
{ "niveau": 6, "nombreMax": 5, "reste": 5 },
|
||||||
{ "niveau": 7, "nombreMax": 4, "nombre": 0 },
|
{ "niveau": 7, "nombreMax": 4, "reste": 4 },
|
||||||
{ "niveau": 8, "nombreMax": 3, "nombre": 0 },
|
{ "niveau": 8, "nombreMax": 3, "reste": 3 },
|
||||||
{ "niveau": 9, "nombreMax": 2, "nombre": 0 },
|
{ "niveau": 9, "nombreMax": 2, "reste": 2 },
|
||||||
{ "niveau": 10, "nombreMax": 1, "nombre": 0 },
|
{ "niveau": 10, "nombreMax": 1, "reste": 1 },
|
||||||
{ "niveau": 11, "nombreMax": 1, "nombre": 0 }
|
{ "niveau": 11, "nombreMax": 1, "reste": 1 }
|
||||||
];
|
];
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -267,23 +267,20 @@ export class RdDItemCompetence extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static computeResumeArchetype(competences) {
|
static computeResumeArchetype(competences) {
|
||||||
const archetype = RdDItemCompetence.getLimitesArchetypes();
|
const computed = duplicate(limitesArchetypes);
|
||||||
competences.map(it => Math.max(0, it.system.niveau_archetype))
|
competences.map(it => Math.max(0, it.system.niveau_archetype))
|
||||||
.forEach(niveau => {
|
.filter(n => n > 0)
|
||||||
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
|
.forEach(n => {
|
||||||
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;
|
computed[n] = computed[n] ?? { niveau: n, nombreMax: 0, reste: 0 };
|
||||||
|
computed[n].reste = computed[n].reste - 1;
|
||||||
});
|
});
|
||||||
return archetype;
|
return computed.filter(it => it.reste > 0 && it.niveau > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getLimitesArchetypes() {
|
|
||||||
return duplicate(limitesArchetypes);
|
|
||||||
}
|
|
||||||
|
|
||||||
static triVisible(competences) {
|
static triVisible(competences) {
|
||||||
return competences.filter(it => it.system.isVisible)
|
return competences.filter(it => it.system.isVisible)
|
||||||
.sort((a, b) => RdDItemCompetence.compare(a,b))
|
.sort((a, b) => RdDItemCompetence.compare(a, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
static $positionTri(comp) {
|
static $positionTri(comp) {
|
||||||
@@ -308,7 +305,7 @@ export class RdDItemCompetence extends Item {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static compare(a,b) {
|
static compare(a, b) {
|
||||||
const diff = RdDItemCompetence.$positionTri(a) - RdDItemCompetence.$positionTri(b);
|
const diff = RdDItemCompetence.$positionTri(a) - RdDItemCompetence.$positionTri(b);
|
||||||
return diff ? diff : a.name.localeCompare(b.name);
|
return diff ? diff : a.name.localeCompare(b.name);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +0,0 @@
|
|||||||
import { EnvironmentSheetHelper } from "./environnement.js";
|
|
||||||
import { RdDItemSheet } from "./item-sheet.js";
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
|
||||||
|
|
||||||
export class RdDFauneItemSheet extends RdDItemSheet {
|
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "faune" };
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPosition(options = {}) {
|
|
||||||
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
async getData() {
|
|
||||||
const formData = await super.getData();
|
|
||||||
return await EnvironmentSheetHelper.getData(this, formData);
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
if (!this.options.editable) return;
|
|
||||||
|
|
||||||
EnvironmentSheetHelper.activateListeners(this);
|
|
||||||
|
|
||||||
html.find("a.linked-actor-delete").click(event => this.onDeleteLinkedActor());
|
|
||||||
html.find("a.preparer-nourriture").click(event => this.preparerNourriture(event));
|
|
||||||
html.find("a.manger-nourriture").click(event => this.mangerNourriture(event));
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onDropActor(event, dragData) {
|
|
||||||
console.log('faune:dropActor', event, dragData)
|
|
||||||
const linkedActor = fromUuidSync(dragData.uuid);
|
|
||||||
if (linkedActor?.pack) {
|
|
||||||
this.item.update({
|
|
||||||
'system.actor.pack': linkedActor.pack,
|
|
||||||
'system.actor.id': linkedActor._id,
|
|
||||||
'system.actor.name': linkedActor.name
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui.notifications.warn(`${linkedActor.name} ne provient pas d'un compendium.
|
|
||||||
<br>Choisissez une créature du compendium pour représenter un élément de faune générique`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async onDeleteLinkedActor() {
|
|
||||||
this.item.update({
|
|
||||||
'system.actor.pack': '',
|
|
||||||
'system.actor.id': '',
|
|
||||||
'system.actor.name': ''
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async preparerNourriture(event) {
|
|
||||||
if (this.actor) {
|
|
||||||
await this.actor.preparerNourriture(this.item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async mangerNourriture(event) {
|
|
||||||
if (this.actor) {
|
|
||||||
await this.actor.mangerNourriture(this.item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import { EnvironmentSheetHelper } from "./environnement.js";
|
|
||||||
import { RdDItemSheet } from "./item-sheet.js";
|
|
||||||
|
|
||||||
export class RdDHerbeItemSheet extends RdDItemSheet {
|
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "herbe" };
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPosition(options = {}) {
|
|
||||||
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
async getData() {
|
|
||||||
const formData = await super.getData();
|
|
||||||
return await EnvironmentSheetHelper.getData(this, formData);
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
EnvironmentSheetHelper.activateListeners(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import { EnvironmentSheetHelper } from "./environnement.js";
|
|
||||||
import { RdDItemSheet } from "./item-sheet.js";
|
|
||||||
|
|
||||||
export class RdDIngredientItemSheet extends RdDItemSheet {
|
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "ingredient" };
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPosition(options = {}) {
|
|
||||||
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
async getData() {
|
|
||||||
const formData = await super.getData();
|
|
||||||
return await EnvironmentSheetHelper.getData(this, formData);
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
EnvironmentSheetHelper.activateListeners(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,27 +2,28 @@ import { Misc } from "./misc.js";
|
|||||||
import { LOG_HEAD } from "./constants.js";
|
import { LOG_HEAD } from "./constants.js";
|
||||||
|
|
||||||
const MONNAIE_ETAIN = {
|
const MONNAIE_ETAIN = {
|
||||||
name: "Etain (1 denier)", type: 'monnaie',
|
name: "Denier (étain)", type: 'monnaie',
|
||||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
|
||||||
system: { quantite: 0, cout: 0.01, encombrement: 0.001, description: "" }
|
system: { quantite: 0, cout: 0.01, encombrement: 0.001, description: "" }
|
||||||
};
|
};
|
||||||
const MONNAIE_BRONZE = {
|
const MONNAIE_BRONZE = {
|
||||||
name: "Bronze (10 deniers)", type: 'monnaie',
|
name: "Sou (bronze)", type: 'monnaie',
|
||||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp",
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp",
|
||||||
system: { quantite: 0, cout: 0.10, encombrement: 0.002, description: "" }
|
system: { quantite: 0, cout: 0.10, encombrement: 0.002, description: "" }
|
||||||
};
|
};
|
||||||
const MONNAIE_ARGENT = {
|
const MONNAIE_ARGENT = {
|
||||||
name: "Argent (1 sol)", type: 'monnaie',
|
name: "Sol (argent)", type: 'monnaie',
|
||||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp",
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp",
|
||||||
system: { quantite: 0, cout: 1, encombrement: 0.003, description: "" }
|
system: { quantite: 0, cout: 1, encombrement: 0.003, description: "" }
|
||||||
};
|
};
|
||||||
const MONNAIE_OR = {
|
const MONNAIE_OR = {
|
||||||
name: "Or (10 sols)", type: 'monnaie',
|
name: "Dragon (or)", type: 'monnaie',
|
||||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
|
||||||
system: { quantite: 0, cout: 10, encombrement: 0.004, description: "" }
|
system: { quantite: 0, cout: 10, encombrement: 0.004, description: "" }
|
||||||
};
|
};
|
||||||
|
|
||||||
const MONNAIES_STANDARD = [MONNAIE_ETAIN, MONNAIE_BRONZE, MONNAIE_ARGENT, MONNAIE_OR];
|
const MONNAIES_STANDARD = [MONNAIE_ETAIN, MONNAIE_BRONZE, MONNAIE_ARGENT, MONNAIE_OR];
|
||||||
|
const VALEUR_DENIERS = sols => Math.max(Math.floor((sols ?? 0) * 100), 0);
|
||||||
|
|
||||||
export class Monnaie {
|
export class Monnaie {
|
||||||
|
|
||||||
@@ -40,15 +41,11 @@ export class Monnaie {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static deValeur(monnaie, valeur) {
|
static deValeur(monnaie, valeur) {
|
||||||
return Monnaie.valEntiere(valeur) == Monnaie.valEntiere(monnaie.system.cout)
|
return VALEUR_DENIERS(valeur) == VALEUR_DENIERS(monnaie.system.cout)
|
||||||
}
|
|
||||||
|
|
||||||
static valEntiere(sols) {
|
|
||||||
return Math.max(Math.floor((sols??0)*100), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static triValeurEntiere() {
|
static triValeurEntiere() {
|
||||||
return Misc.ascending(item => Monnaie.valEntiere(item.system.cout))
|
return Misc.ascending(item => VALEUR_DENIERS(item.system.cout))
|
||||||
}
|
}
|
||||||
|
|
||||||
static async creerMonnaiesStandard(actor) {
|
static async creerMonnaiesStandard(actor) {
|
||||||
@@ -65,29 +62,52 @@ export class Monnaie {
|
|||||||
return deniers;
|
return deniers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static toSolsDeniers(fortune) {
|
||||||
|
return {
|
||||||
|
sols: Math.floor(fortune),
|
||||||
|
deniers: Math.round(100 * (fortune - Math.floor(fortune)))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
static getFortune(monnaies) {
|
||||||
|
return (monnaies??[])
|
||||||
|
.map(m => Number(m.system.cout) * Number(m.system.quantite))
|
||||||
|
.reduce(Misc.sum(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
static async optimiserFortune(actor, fortune) {
|
static async optimiserFortune(actor, fortune) {
|
||||||
let resteEnDeniers = Math.round(fortune*100);
|
let resteEnDeniers = Math.round(fortune * 100);
|
||||||
let monnaies = actor.itemTypes['monnaie'];
|
let monnaies = actor.itemTypes['monnaie'];
|
||||||
let updates = [];
|
let updates = [];
|
||||||
let parValeur = Misc.classifyFirst(monnaies, it => Monnaie.valEntiere(it.system.cout));
|
Monnaie.validerMonnaies(monnaies, actor);
|
||||||
for (let valeurDeniers of [1000, 100, 10, 1]) {
|
|
||||||
|
let parValeur = Misc.classifyFirst(monnaies, it => VALEUR_DENIERS(it.system.cout));
|
||||||
|
for (let valeurDeniers of [1000, 100, 10, 1]) {
|
||||||
const itemPiece = parValeur[valeurDeniers];
|
const itemPiece = parValeur[valeurDeniers];
|
||||||
if (itemPiece) {
|
if (itemPiece) {
|
||||||
const quantite = Math.floor(resteEnDeniers / valeurDeniers);
|
const quantite = Math.floor(resteEnDeniers / valeurDeniers);
|
||||||
if (quantite != itemPiece.system.quantite) {
|
if (quantite != itemPiece.system.quantite) {
|
||||||
updates.push({ _id: parValeur[valeurDeniers].id, 'system.quantite': quantite });
|
updates.push({ _id: parValeur[valeurDeniers].id, 'system.quantite': quantite });
|
||||||
}
|
}
|
||||||
resteEnDeniers -= quantite*valeurDeniers;
|
resteEnDeniers -= quantite * valeurDeniers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log('Monnaie.optimiserFortune', actor.name, 'total', fortune, 'parValeur', parValeur, 'updates', updates, 'reste', resteEnDeniers);
|
console.log('Monnaie.optimiserFortune', actor.name, 'total', fortune, 'parValeur', parValeur, 'updates', updates, 'reste', resteEnDeniers);
|
||||||
if (updates.length > 0) {
|
if (updates.length > 0) {
|
||||||
await actor.updateEmbeddedDocuments('Item', updates);
|
await actor.updateEmbeddedDocuments('Item', updates);
|
||||||
}
|
}
|
||||||
if (resteEnDeniers > 0){
|
if (resteEnDeniers > 0) {
|
||||||
// créer le reste en deniers fortune en deniers
|
// créer le reste en deniers fortune en deniers
|
||||||
await Monnaie.creerMonnaiesDeniers(actor, resteEnDeniers);
|
await Monnaie.creerMonnaiesDeniers(actor, resteEnDeniers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static validerMonnaies(monnaies, actor = undefined) {
|
||||||
|
monnaies.filter(it => VALEUR_DENIERS(it.system.cout) == 0)
|
||||||
|
.map(it => `La monnaie ${it.name} de l'acteur ${actor?.name ?? 'sélectionné'} a une valeur de 0!`)
|
||||||
|
.forEach(message => {
|
||||||
|
ui.notifications.warn(message);
|
||||||
|
console.warn(message);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { SYSTEM_RDD } from "./constants.js";
|
|||||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
|
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the basic ItemSheet for RdD specific items
|
* Extend the basic ItemSheet for RdD specific items
|
||||||
@@ -60,13 +61,13 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
buttons.unshift({
|
buttons.unshift({
|
||||||
class: "vendre",
|
class: "vendre",
|
||||||
icon: "fas fa-comments-dollar",
|
icon: "fas fa-comments-dollar",
|
||||||
onclick: ev => this.item.proposerVente()
|
onclick: ev => this.item.proposerVente(1)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
buttons.unshift({
|
buttons.unshift({
|
||||||
class: "montrer",
|
class: "montrer",
|
||||||
icon: "fas fa-comment",
|
icon: "fas fa-comment",
|
||||||
onclick: ev => this.item.postItem()
|
onclick: ev => this.item.postItemToChat()
|
||||||
});
|
});
|
||||||
return buttons
|
return buttons
|
||||||
}
|
}
|
||||||
@@ -85,22 +86,17 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getData() {
|
async getData() {
|
||||||
let formData = {
|
let formData = {
|
||||||
id: this.item.id,
|
|
||||||
title: this.item.name,
|
title: this.item.name,
|
||||||
|
id: this.item.id,
|
||||||
type: this.item.type,
|
type: this.item.type,
|
||||||
img: this.item.img,
|
img: this.item.img,
|
||||||
name: this.item.name,
|
name: this.item.name,
|
||||||
system: this.item.system,
|
system: this.item.system,
|
||||||
isGM: game.user.isGM,
|
|
||||||
actorId: this.actor?.id,
|
actorId: this.actor?.id,
|
||||||
isOwned: this.actor ? true : false,
|
|
||||||
owner: this.item.isOwner,
|
|
||||||
editable: this.isEditable,
|
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
|
||||||
isSoins: false,
|
|
||||||
description: await TextEditor.enrichHTML(this.item.system.description, { async: true }),
|
description: await TextEditor.enrichHTML(this.item.system.description, { async: true }),
|
||||||
descriptionmj: await TextEditor.enrichHTML(this.item.system.descriptionmj, { async: true }),
|
descriptionmj: await TextEditor.enrichHTML(this.item.system.descriptionmj, { async: true }),
|
||||||
isComestible: this.item.isComestible()
|
isComestible: this.item.getUtilisationCuisine(),
|
||||||
|
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable)
|
||||||
}
|
}
|
||||||
|
|
||||||
const competences = await SystemCompendiums.getCompetences(this.actor?.type);
|
const competences = await SystemCompendiums.getCompetences(this.actor?.type);
|
||||||
@@ -135,18 +131,14 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
RdDGemme.calculDataDerivees(this.item);
|
RdDGemme.calculDataDerivees(this.item);
|
||||||
}
|
}
|
||||||
if (this.item.type == 'potion') {
|
if (this.item.type == 'potion') {
|
||||||
if (this.dateUpdated) {
|
await RdDHerbes.addPotionFormData(formData);
|
||||||
formData.system.prdate = this.dateUpdated;
|
|
||||||
this.dateUpdated = undefined;
|
|
||||||
}
|
|
||||||
await RdDHerbes.updatePotionData(formData);
|
|
||||||
}
|
}
|
||||||
if (formData.isOwned && this.item.type == 'herbe' && (formData.system.categorie == 'Soin' || formData.system.categorie == 'Repos')) {
|
if (formData.options.isOwned && this.item.type == 'herbe' && (formData.system.categorie == 'Soin' || formData.system.categorie == 'Repos')) {
|
||||||
formData.isIngredientPotionBase = true;
|
formData.isIngredientPotionBase = true;
|
||||||
}
|
}
|
||||||
if (this.item.type == 'sortreserve') {
|
if (this.item.type == 'sortreserve') {
|
||||||
const sortId = this.item.system.sortid;
|
const sortId = this.item.system.sortid;
|
||||||
formData.sort = formData.isOwned ? this.item.actor.items.get(sortId) : game.items.get(sortId);
|
formData.sort = formData.options.isOwned ? this.item.actor.items.get(sortId) : game.items.get(sortId);
|
||||||
}
|
}
|
||||||
formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
|
formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
|
||||||
|
|
||||||
@@ -159,10 +151,10 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
this.html = html;
|
this.html = html;
|
||||||
|
|
||||||
let itemSheetDialog = this;
|
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs')
|
||||||
|
|| game.user.isGM
|
||||||
HtmlUtility._showControlWhen(this.html.find(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.item.isOwned);
|
|| !this.item.isOwned);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
|
HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
// Everything below here is only needed if the sheet is editable
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
@@ -178,11 +170,21 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
RdDUtility.checkThanatosXP(this.item.name);
|
RdDUtility.checkThanatosXP(this.item.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.html.find(".item-cout input[name='system.cout']").change(event => {
|
||||||
|
if (this.item.isMonnaie()) {
|
||||||
|
const value = event.currentTarget.value;
|
||||||
|
if (Number(value) == 0) {
|
||||||
|
ui.notifications.error(`${this.actor?.name ?? 'Monnaie'}: La monnaie ${this.item.name} a maintenant une valeur de 0, et ne peut plus être utilisée pour payer!`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
this.html.find('.enchanteDate').change((event) => {
|
this.html.find('.date-enchantement').change((event) => {
|
||||||
let jour = Number(this.html.find('[name="splitDate.day"]').val());
|
const jour = Number(this.html.find('input.date-enchantement[name="enchantement.jour"]').val());
|
||||||
let mois = this.html.find('[name="splitDate.month"]').val();
|
const mois = RdDTimestamp.definition(this.html.find('select.date-enchantement[name="enchantement.mois"]').val());
|
||||||
this.dateUpdated = game.system.rdd.calendrier.getIndexFromDate(jour, mois);
|
const indexDate = game.system.rdd.calendrier.getIndexFromDate(jour, mois.heure);
|
||||||
|
this.item.update({ 'system.prdate': indexDate });
|
||||||
|
console.warn(`Date d'enchantement modifiée ${jour}/${mois.heure}: ${indexDate}`)
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item));
|
this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item));
|
||||||
@@ -201,12 +203,17 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, async () => itemSheetDialog.render(true)));
|
this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, async () => this.render(true)));
|
||||||
this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true));
|
this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true));
|
||||||
this.html.find('.item-delete').click(async event => RdDUtility.confirmerSuppressionItem(this, RdDSheetUtility.getItem(event, this.actor)));
|
this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, RdDSheetUtility.getItem(event, this.actor)));
|
||||||
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
|
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
|
||||||
this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItem());
|
this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItemToChat());
|
||||||
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, async () => itemSheetDialog.render(true)));
|
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, async () => this.render(true)));
|
||||||
|
|
||||||
|
const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: duplicate(timestamp) })
|
||||||
|
|
||||||
|
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', updateItemTimestamp);
|
||||||
|
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getEventActor(event) {
|
_getEventActor(event) {
|
||||||
@@ -215,6 +222,7 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
return actor;
|
return actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _onSelectCategorie(event) {
|
async _onSelectCategorie(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|||||||
@@ -1,4 +1,18 @@
|
|||||||
export class RdDItemTache extends Item {
|
const BASE_TACHE_SOIN_BLESSURE = { type: "tache", img: 'systems/foundryvtt-reve-de-dragon/icons/competence_chirurgie.webp', system: { carac: "dexterite", competence: "Chirurgie", periodicite: "1 round", fatigue: 0, } }
|
||||||
|
const TACHES_SOIN_BLESSURE = {
|
||||||
|
'critique': { name: 'Blessure critique', system: { difficulte: -6, points_de_tache: 6 } },
|
||||||
|
'grave': { name: 'Blessure grave', system: { difficulte: -4, points_de_tache: 4 } },
|
||||||
|
'legere': { name: 'Blessure légère', system: { difficulte: -2, points_de_tache: 2 } },
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RdDItemTache extends Item {
|
||||||
|
|
||||||
|
static prepareTacheSoin(gravite) {
|
||||||
|
const blessure = TACHES_SOIN_BLESSURE[gravite]
|
||||||
|
if (blessure) {
|
||||||
|
return mergeObject(duplicate(BASE_TACHE_SOIN_BLESSURE), blessure)
|
||||||
|
}
|
||||||
|
ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`)
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
317
module/item.js
@@ -2,16 +2,20 @@ import { DialogItemVente } from "./dialog-item-vente.js";
|
|||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDHerbes } from "./rdd-herbes.js";
|
import { RdDHerbes } from "./rdd-herbes.js";
|
||||||
|
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
|
import { RdDRaretes } from "./item/raretes.js";
|
||||||
|
|
||||||
const typesObjetsInventaire = [
|
const typesInventaireMateriel = [
|
||||||
"arme",
|
"arme",
|
||||||
"armure",
|
"armure",
|
||||||
"conteneur",
|
"conteneur",
|
||||||
|
"faune",
|
||||||
"gemme",
|
"gemme",
|
||||||
"herbe",
|
"herbe",
|
||||||
|
"plante",
|
||||||
"ingredient",
|
"ingredient",
|
||||||
"faune",
|
|
||||||
"livre",
|
"livre",
|
||||||
"monnaie",
|
"monnaie",
|
||||||
"munition",
|
"munition",
|
||||||
@@ -19,11 +23,18 @@ const typesObjetsInventaire = [
|
|||||||
"objet",
|
"objet",
|
||||||
"potion",
|
"potion",
|
||||||
]
|
]
|
||||||
|
const typesInventaire = {
|
||||||
|
materiel: typesInventaireMateriel,
|
||||||
|
all: ['service'].concat(typesInventaireMateriel),
|
||||||
|
}
|
||||||
|
|
||||||
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
|
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
|
||||||
const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"]
|
const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"]
|
||||||
const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"]
|
const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"]
|
||||||
const typesObjetsEffet = ["possession", "poison", "maladie"]
|
const typesObjetsEffet = ["possession", "poison", "maladie"]
|
||||||
const typesObjetsCompetence = ["competence", "competencecreature"]
|
const typesObjetsCompetence = ["competence", "competencecreature"]
|
||||||
|
const typesObjetsTemporels = ["poison", "maladie", "queue", "ombre", "souffle", "signedraconique", "rencontre"]
|
||||||
|
const typesEnvironnement = typesInventaireMateriel;
|
||||||
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
|
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
|
||||||
const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc
|
const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc
|
||||||
densité 3.5 (~2.3 à 4, parfois plus) -- https://www.juwelo.fr/guide-des-pierres/faits-et-chiffres/
|
densité 3.5 (~2.3 à 4, parfois plus) -- https://www.juwelo.fr/guide-des-pierres/faits-et-chiffres/
|
||||||
@@ -57,6 +68,7 @@ export const defaultItemImg = {
|
|||||||
poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp",
|
poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp",
|
||||||
oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp",
|
oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp",
|
||||||
nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
|
nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
|
||||||
|
service: "systems/foundryvtt-reve-de-dragon/icons/services/lit.webp",
|
||||||
signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
|
signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
|
||||||
gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp",
|
gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp",
|
||||||
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
||||||
@@ -69,11 +81,7 @@ export const defaultItemImg = {
|
|||||||
export class RdDItem extends Item {
|
export class RdDItem extends Item {
|
||||||
|
|
||||||
static getDefaultImg(itemType) {
|
static getDefaultImg(itemType) {
|
||||||
return defaultItemImg[itemType];
|
return game.system.rdd.itemClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
||||||
}
|
|
||||||
|
|
||||||
static isItemInventaire(newLocal) {
|
|
||||||
return typesObjetsInventaire.includes(newLocal.type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static isFieldInventaireModifiable(type, field) {
|
static isFieldInventaireModifiable(type, field) {
|
||||||
@@ -92,6 +100,48 @@ export class RdDItem extends Item {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async getCorrespondingItem(itemRef) {
|
||||||
|
if (itemRef.pack) {
|
||||||
|
return await SystemCompendiums.loadDocument(itemRef)
|
||||||
|
}
|
||||||
|
return game.items.get(itemRef.id ?? itemRef._id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getItemTypesInventaire(mode = 'materiel') {
|
||||||
|
return typesInventaire[mode ?? 'materiel']
|
||||||
|
}
|
||||||
|
static getItemTypesDraconiques() {
|
||||||
|
return typesObjetsDraconiques;
|
||||||
|
}
|
||||||
|
static getItemTypesEnvironnement() {
|
||||||
|
return typesEnvironnement;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getTypesOeuvres() {
|
||||||
|
return typesObjetsOeuvres
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(docData, context = {}) {
|
||||||
|
if (!context.rdd?.ready) {
|
||||||
|
mergeObject(context, { rdd: { ready: true } });
|
||||||
|
const ItemConstructor = game.system.rdd.itemClasses[docData.type];
|
||||||
|
if (ItemConstructor) {
|
||||||
|
if (!docData.img) {
|
||||||
|
docData.img = ItemConstructor.defaultIcon;
|
||||||
|
}
|
||||||
|
return new ItemConstructor(docData, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!docData.img) {
|
||||||
|
docData.img = RdDItem.getDefaultImg(docData.type);
|
||||||
|
}
|
||||||
|
super(docData, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
getUniteQuantite() {
|
getUniteQuantite() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case "monnaie": return "(Pièces)"
|
case "monnaie": return "(Pièces)"
|
||||||
@@ -107,47 +157,56 @@ export class RdDItem extends Item {
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(itemData, context) {
|
isCompetencePersonnage() { return this.type == 'competence' }
|
||||||
if (!itemData.img) {
|
isCompetenceCreature() { return this.type == 'competencecreature' }
|
||||||
itemData.img = RdDItem.getDefaultImg(itemData.type);
|
isConteneur() { return this.type == 'conteneur'; }
|
||||||
|
isMonnaie() { return this.type == 'monnaie'; }
|
||||||
|
isPotion() { return this.type == 'potion'; }
|
||||||
|
isNourritureBoisson() { return this.type == 'nourritureboisson'; }
|
||||||
|
isService() { return this.type == 'service'; }
|
||||||
|
|
||||||
|
isCompetence() { return typesObjetsCompetence.includes(this.type) }
|
||||||
|
isTemporel() { return typesObjetsTemporels.includes(this.type) }
|
||||||
|
isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
|
||||||
|
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
|
||||||
|
isEffet() { return typesObjetsEffet.includes(this.type) }
|
||||||
|
isConnaissance() { return typesObjetsConnaissance.includes(this.type) }
|
||||||
|
|
||||||
|
isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); }
|
||||||
|
isBoisson() { return this.isNourritureBoisson() && this.system.boisson; }
|
||||||
|
isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
|
||||||
|
isHerbeAPotion() { return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
|
||||||
|
|
||||||
|
isPresentDansMilieux(milieux) {
|
||||||
|
return this.getEnvironnements(milieux).length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
getEnvironnements(milieux = undefined) {
|
||||||
|
const environnements = this.isInventaire() ? this.system.environnement : undefined;
|
||||||
|
if (milieux == undefined || !environnements) {
|
||||||
|
return environnements ?? [];
|
||||||
}
|
}
|
||||||
super(itemData, context);
|
return environnements.filter(env => milieux.includes(env.milieu))
|
||||||
}
|
}
|
||||||
|
|
||||||
static getItemTypesInventaire() {
|
getMilieux() {
|
||||||
return typesObjetsInventaire
|
return this.getEnvironnements().map(env => env.milieu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getTypesOeuvres() {
|
getRaretes(milieux = undefined) {
|
||||||
return typesObjetsOeuvres
|
if (this.isInventaire()) {
|
||||||
|
const raretes = this.getEnvironnements(milieux).map(env => RdDRaretes.byCode(env.rarete));
|
||||||
|
if (milieux == undefined && raretes.length == 0) {
|
||||||
|
return [RdDRaretes.rareteFrequente()];
|
||||||
|
}
|
||||||
|
return raretes;
|
||||||
|
}
|
||||||
|
return [RdDRaretes.rareteEgale()];
|
||||||
}
|
}
|
||||||
|
|
||||||
isCompetencePersonnage() {
|
getFrequence(milieux = undefined) {
|
||||||
return this.type == 'competence'
|
const frequences = this.getEnvironnements(milieux).map(it => it.frequence);
|
||||||
}
|
return frequences.length == 0 ? 0 : Math.max(...frequences);
|
||||||
isCompetenceCreature() {
|
|
||||||
return this.type == 'competencecreature'
|
|
||||||
}
|
|
||||||
isCompetence() {
|
|
||||||
return typesObjetsCompetence.includes(this.type)
|
|
||||||
}
|
|
||||||
isInventaire() {
|
|
||||||
return RdDItem.isItemInventaire(this)
|
|
||||||
}
|
|
||||||
isOeuvre() {
|
|
||||||
return typesObjetsOeuvres.includes(this.type)
|
|
||||||
}
|
|
||||||
isDraconique() {
|
|
||||||
return typesObjetsDraconiques.includes(this.type)
|
|
||||||
}
|
|
||||||
isEffet() {
|
|
||||||
return typesObjetsEffet.includes(this.type)
|
|
||||||
}
|
|
||||||
isConnaissance() {
|
|
||||||
return typesObjetsConnaissance.includes(this.type)
|
|
||||||
}
|
|
||||||
isConteneur() {
|
|
||||||
return this.type == 'conteneur';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getItemGroup() {
|
getItemGroup() {
|
||||||
@@ -160,43 +219,79 @@ export class RdDItem extends Item {
|
|||||||
return "autres";
|
return "autres";
|
||||||
}
|
}
|
||||||
|
|
||||||
isConteneurNonVide() {
|
isConteneurNonVide() { return this.isConteneur() && (this.system.contenu?.length ?? 0) > 0; }
|
||||||
return this.isConteneur() && (this.system.contenu?.length ?? 0) > 0;
|
isConteneurVide() { return this.isConteneur() && (this.system.contenu?.length ?? 0) == 0; }
|
||||||
|
isVideOuNonConteneur() { return !this.isConteneur() || (this.system.contenu?.length ?? 0) == 0; }
|
||||||
|
|
||||||
|
isFinPeriode(oldTimestamp, newTimestamp) {
|
||||||
|
if (!this.isTemporel()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const finPeriode = new RdDTimestamp(this.system.temporel.fin);
|
||||||
|
return oldTimestamp.compare(finPeriode) < 0 && finPeriode.compare(newTimestamp) <= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
isConteneurVide() {
|
async onCreateItemTemporel(actor) {
|
||||||
return this.isConteneur() && (this.system.contenu?.length ?? 0) == 0;
|
if (this.isTemporel()) {
|
||||||
|
const timestampDebut = game.system.rdd.calendrier.timestamp;
|
||||||
|
const timestampFin = await this.calculerFinPeriodeTemporel(timestampDebut);
|
||||||
|
await actor.updateEmbeddedDocuments('Item', [{
|
||||||
|
_id: this.id,
|
||||||
|
'system.temporel.debut': duplicate(timestampDebut),
|
||||||
|
'system.temporel.fin': duplicate(timestampFin),
|
||||||
|
}])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isVideOuNonConteneur() {
|
async calculerFinPeriodeTemporel(timestampDebut) {
|
||||||
return !this.isConteneur() || (this.system.contenu?.length ?? 0) == 0;
|
return timestampDebut;
|
||||||
}
|
}
|
||||||
|
|
||||||
isNourritureBoisson() {
|
async onFinPeriodeTemporel(oldTimestamp, newTimestamp) {
|
||||||
return this.type == 'nourritureboisson';
|
if (this.isTemporel() && this.actor) {
|
||||||
|
await this.onFinPeriode(oldTimestamp, newTimestamp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isComestible() {
|
async onFinPeriode(oldTimestamp, newTimestamp) {
|
||||||
|
console.log(`${this.actor.name}: l'objet ${this.name} a expiré et été supprimé`);
|
||||||
|
await this.actor?.deleteEmbeddedDocuments('Item', [this.id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
getUtilisation() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'nourritureboisson': return 'pret';
|
case 'potion':
|
||||||
case 'herbe':
|
switch (this.system.categorie) {
|
||||||
return this.system.categorie == 'Cuisine' && this.system.sust > 0 ? 'brut' : '';
|
case 'Alchimie': case 'AlchimieEnchante': case 'AlchimieAutre': return 'alchimie'
|
||||||
case 'faune':
|
case 'Cuisine': return 'cuisine'
|
||||||
return this.system.sust > 0 ? 'brut' : '';
|
case 'Remede': case 'Repos': case 'ReposEnchante': case 'Soin': case 'SoinEnchante': return 'soins'
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
case 'nourritureboisson': return 'cuisine';
|
||||||
|
case 'herbe': case 'faune': case 'ingredient': case 'plante':
|
||||||
|
switch (this.system.categorie) {
|
||||||
|
case 'Cuisine': return 'cuisine';
|
||||||
|
case 'Toxique': case 'Poison': return 'poison';
|
||||||
|
case 'Alchimie': return 'alchimie'
|
||||||
|
case 'Soin': case 'Repos': return 'soins'
|
||||||
|
}
|
||||||
|
return this.system.sust > 0 ? 'cuisine' : '';
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
isAlcool() {
|
getUtilisationCuisine() {
|
||||||
return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise;
|
if (this.getUtilisation() == 'cuisine') {
|
||||||
|
switch (this.type) {
|
||||||
|
case 'nourritureboisson':
|
||||||
|
return 'pret';
|
||||||
|
case 'herbe': case 'faune': case 'ingredient': case 'plante':
|
||||||
|
return 'brut';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
isHerbeAPotion() {
|
|
||||||
return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos');
|
|
||||||
}
|
|
||||||
isPotion() {
|
|
||||||
return this.type == 'potion';
|
|
||||||
}
|
|
||||||
isCristalAlchimique() {
|
isCristalAlchimique() {
|
||||||
return this.type == 'objet' && Grammar.toLowerCaseNoAccent(this.name) == 'cristal alchimique' && this.system.quantite > 0;
|
return this.type == 'objet' && Grammar.toLowerCaseNoAccent(this.name) == 'cristal alchimique' && this.system.quantite > 0;
|
||||||
}
|
}
|
||||||
@@ -205,16 +300,22 @@ export class RdDItem extends Item {
|
|||||||
return this.system.magique
|
return this.system.magique
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isItemCommerce() {
|
||||||
|
return this.parent?.type == 'commerce';
|
||||||
|
}
|
||||||
|
|
||||||
getQuantite() {
|
getQuantite() {
|
||||||
return Math.round(this.isConteneur() ? 1 : (this.system.quantite ?? 0))
|
return this.isService() ? undefined : Math.round(this.system.quantite ?? 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
getEncTotal() {
|
getEncTotal() {
|
||||||
return this.getEnc() * this.getQuantite();
|
return (this.isService() ? 0 : this.getQuantite()) * this.getEnc();
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnc() {
|
getEnc() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
|
case 'service':
|
||||||
|
return 0;
|
||||||
case 'herbe':
|
case 'herbe':
|
||||||
return this.getEncHerbe();
|
return this.getEncHerbe();
|
||||||
case 'gemme':
|
case 'gemme':
|
||||||
@@ -233,13 +334,21 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
valeurTotale() {
|
valeurTotale() {
|
||||||
return this.getQuantite() * this.valeur()
|
return (this.isService() ? 1 : this.getQuantite()) * this.valeur()
|
||||||
}
|
}
|
||||||
|
|
||||||
valeur() {
|
valeur() {
|
||||||
return this.system.cout ?? 0
|
return this.system.cout ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calculerPrixCommercant() {
|
||||||
|
if (this.isItemCommerce()) {
|
||||||
|
// appliquer le pourcentage
|
||||||
|
return this.parent.calculerPrix(this);
|
||||||
|
}
|
||||||
|
return this.system.cout;
|
||||||
|
}
|
||||||
|
|
||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
super.prepareDerivedData();
|
super.prepareDerivedData();
|
||||||
if (this.isInventaire()) {
|
if (this.isInventaire()) {
|
||||||
@@ -268,7 +377,7 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
if (this.actor?.isPersonnage()) {
|
if (this.actor?.isPersonnage()) {
|
||||||
const warn = options.warnIfNot;
|
const warn = options.warnIfNot;
|
||||||
if (this.isComestible() == 'brut') {
|
if (this.getUtilisationCuisine() == 'brut') {
|
||||||
return 'Utiliser';
|
return 'Utiliser';
|
||||||
}
|
}
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
@@ -281,7 +390,7 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async actionPrincipale(actor, onActionItem = async () => { }) {
|
async actionPrincipale(actor, onActionItem = async () => { }) {
|
||||||
if (!this.getActionPrincipale()) {
|
if (!this.getActionPrincipale()) {
|
||||||
@@ -317,7 +426,7 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onCreateDecoupeComestible(actor) {
|
async onCreateDecoupeComestible(actor) {
|
||||||
if (actor && this.isComestible() == 'brut' && this.system.sust != 1) {
|
if (actor && this.getUtilisationCuisine() == 'brut' && this.system.sust != 1) {
|
||||||
if (this.system.sust < 1) {
|
if (this.system.sust < 1) {
|
||||||
await actor.updateEmbeddedDocuments('Item', [{
|
await actor.updateEmbeddedDocuments('Item', [{
|
||||||
_id: this.id,
|
_id: this.id,
|
||||||
@@ -338,7 +447,7 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async empiler(item) {
|
async empiler(item) {
|
||||||
if (this.isComestible() == 'brut') {
|
if (this.getUtilisationCuisine() == 'brut') {
|
||||||
const sust = this.system.sust + item.system.sust;
|
const sust = this.system.sust + item.system.sust;
|
||||||
const encombrement = this.system.encombrement + item.system.encombrement;
|
const encombrement = this.system.encombrement + item.system.encombrement;
|
||||||
await this.update({
|
await this.update({
|
||||||
@@ -352,7 +461,7 @@ export class RdDItem extends Item {
|
|||||||
await item.delete();
|
await item.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
|
async quantiteIncDec(nombre, options = { supprimerSiZero: false }) {
|
||||||
const quantite = Number(this.system.quantite ?? -1);
|
const quantite = Number(this.system.quantite ?? -1);
|
||||||
if (quantite >= 0) {
|
if (quantite >= 0) {
|
||||||
const reste = Math.max(quantite + Number(nombre), 0);
|
const reste = Math.max(quantite + Number(nombre), 0);
|
||||||
@@ -389,8 +498,8 @@ export class RdDItem extends Item {
|
|||||||
return [false, `Impossible de regrouper ${this.name} avec ${other.name}`];
|
return [false, `Impossible de regrouper ${this.name} avec ${other.name}`];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const excludedProperties = ['quantite', 'cout', 'encTotal'];
|
const excludedProperties = ['quantite', 'cout', 'encTotal', 'environnement', 'contenu'];
|
||||||
if (this.isComestible()) {
|
if (this.getUtilisationCuisine()) {
|
||||||
excludedProperties.push('sust', 'encombrement');
|
excludedProperties.push('sust', 'encombrement');
|
||||||
}
|
}
|
||||||
let differences = Object.entries(this.system)
|
let differences = Object.entries(this.system)
|
||||||
@@ -407,54 +516,63 @@ export class RdDItem extends Item {
|
|||||||
return [true, undefined];
|
return [true, undefined];
|
||||||
}
|
}
|
||||||
|
|
||||||
async proposerVente() {
|
async proposerVente(quantiteMax = undefined) {
|
||||||
console.log(this);
|
console.log(this);
|
||||||
if (this.isConteneurNonVide()) {
|
if (this.isConteneurNonVide()) {
|
||||||
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`);
|
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await DialogItemVente.display(this, async (vente) => {
|
await DialogItemVente.display({
|
||||||
vente["properties"] = this.getProprietes();
|
item: this,
|
||||||
if (vente.isOwned) {
|
quantiteMax,
|
||||||
if (vente.quantiteNbLots * vente.tailleLot > vente.quantiteMax) {
|
callback: async (vente) => {
|
||||||
ui.notifications.warn(`Vous avez ${vente.quantiteMax} ${vente.item.name}, ce n'est pas suffisant pour vendre ${vente.quantiteNbLots} de ${vente.tailleLot}`)
|
vente["properties"] = this.getProprietes();
|
||||||
return;
|
if (vente.isOwned) {
|
||||||
|
if (vente.quantiteNbLots * vente.tailleLot > vente.quantiteMax) {
|
||||||
|
ui.notifications.warn(`Vous avez ${vente.quantiteMax} ${vente.item.name}, ce n'est pas suffisant pour vendre ${vente.quantiteNbLots} de ${vente.tailleLot}`)
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
vente.jsondata = JSON.stringify(vente.item);
|
||||||
vente.jsondata = JSON.stringify(vente.item);
|
|
||||||
|
|
||||||
console.log(vente);
|
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
|
||||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
|
ChatMessage.create(RdDUtility.chatDataSetup(html));
|
||||||
ChatMessage.create(RdDUtility.chatDataSetup(html));
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getProprietes() {
|
getProprietes() {
|
||||||
return this[`_${this.type}ChatData`]().filter(it => it != undefined);
|
if (this[`_${this.type}ChatData`]) {
|
||||||
|
return this[`_${this.type}ChatData`]().filter(it => it != undefined);
|
||||||
|
}
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async postItem(modeOverride) {
|
async postItemToChat(modeOverride) {
|
||||||
console.log(this);
|
console.log(this);
|
||||||
let chatData = duplicate(this);
|
let chatData = {
|
||||||
chatData["properties"] = this.getProprietes();
|
doctype: 'Item',
|
||||||
if (this.actor) {
|
id: this.id,
|
||||||
chatData.actor = { id: this.actor.id };
|
type: this.type,
|
||||||
|
img: this.img,
|
||||||
|
pack: this.pack,
|
||||||
|
name: this.name,
|
||||||
|
actor: this.actor ? { id: this.actor.id } : undefined,
|
||||||
|
system: { description: this.system.description },
|
||||||
|
properties: this.getProprietes(),
|
||||||
}
|
}
|
||||||
// JSON object for easy creation
|
renderTemplate(this.getChatItemTemplate(), chatData).then(html => {
|
||||||
chatData.jsondata = JSON.stringify(
|
|
||||||
{
|
|
||||||
compendium: "postedItem",
|
|
||||||
payload: chatData,
|
|
||||||
});
|
|
||||||
|
|
||||||
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-item.html', chatData).then(html => {
|
|
||||||
let chatOptions = RdDUtility.chatDataSetup(html, modeOverride);
|
let chatOptions = RdDUtility.chatDataSetup(html, modeOverride);
|
||||||
ChatMessage.create(chatOptions)
|
ChatMessage.create(chatOptions)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getChatItemTemplate() {
|
||||||
|
return 'systems/foundryvtt-reve-de-dragon/templates/post-item.html';
|
||||||
|
}
|
||||||
|
|
||||||
static propertyIfDefined(name, val, condition = true) {
|
static propertyIfDefined(name, val, condition = true) {
|
||||||
return condition ? `<b>${name}</b>: ${val}` : undefined;
|
return condition ? `<b>${name}</b>: ${val}` : undefined;
|
||||||
}
|
}
|
||||||
@@ -703,5 +821,4 @@ export class RdDItem extends Item {
|
|||||||
...this._inventaireTemplateChatData()
|
...this._inventaireTemplateChatData()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
47
module/item/maladie.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDTimestamp } from "../rdd-timestamp.js";
|
||||||
|
|
||||||
|
export class RdDItemMaladie extends RdDItem {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/maladie.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
async calculerFinPeriodeTemporel(debut) {
|
||||||
|
return await debut.addPeriode(this.system.periode.nombre, this.system.periode.unite);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onFinPeriode(oldTimestamp, newTimestamp) {
|
||||||
|
await RdDItemMaladie.notifierMaladiePoison(this, oldTimestamp, newTimestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
static async notifierMaladiePoison(mal, oldTimestamp, newTimestamp) {
|
||||||
|
if (mal.actor) {
|
||||||
|
const souffrance = mal.system.identifie
|
||||||
|
? `de ${mal.name}`
|
||||||
|
: `d'un mal inconnu`
|
||||||
|
ChatMessage.create({ content: `${mal.actor.name} souffre ${souffrance} (${Misc.typeName('Item', mal.type)}): vérifiez que les effets ne se sont pas aggravés !` });
|
||||||
|
mal.postItemToChat('gmroll');
|
||||||
|
await RdDItemMaladie.prolongerPeriode(mal,oldTimestamp, newTimestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async prolongerPeriode(mal, oldTimestamp, newTimestamp) {
|
||||||
|
if (mal.actor) {
|
||||||
|
// TODO: déterminer le nombre de périodes écoulées
|
||||||
|
console.log(`${mal.actor.name}: le mal ${mal.name} a atteint la fin de sa période et été prolongé`);
|
||||||
|
const current = newTimestamp;
|
||||||
|
const finPeriode = new RdDTimestamp(mal.system.temporel.fin)
|
||||||
|
const periodeSuivante = (finPeriode.compare(current) > 0 ? finPeriode : current);
|
||||||
|
const timestampFin = await mal.calculerFinPeriodeTemporel(periodeSuivante);
|
||||||
|
|
||||||
|
await mal.actor.updateEmbeddedDocuments('Item', [{
|
||||||
|
_id: mal.id,
|
||||||
|
'system.temporel.fin': duplicate(timestampFin),
|
||||||
|
}])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
11
module/item/ombre.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
|
||||||
|
export class RdDItemOmbre extends RdDItem {
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
async calculerFinPeriodeTemporel(debut) {
|
||||||
|
return await debut.appliquerDuree(this.system.duree, this.parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
17
module/item/poison.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
import { RdDItemMaladie } from "./maladie.js";
|
||||||
|
|
||||||
|
export class RdDItemPoison extends RdDItem {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
async calculerFinPeriodeTemporel(debut) {
|
||||||
|
return await debut.addPeriode(this.system.periode.nombre, this.system.periode.unite) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onFinPeriode(oldTimestamp, newTimestamp) {
|
||||||
|
RdDItemMaladie.notifierMaladiePoison(this, oldTimestamp, newTimestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
13
module/item/queue.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
|
||||||
|
export class RdDItemQueue extends RdDItem {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
async calculerFinPeriodeTemporel(debut) {
|
||||||
|
return await debut.appliquerDuree(this.system.duree, this.parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
31
module/item/raretes.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
const RARETE_COMMUNE = { code: 'Commune', label: 'Commune', frequence: 54, min: 27, max: 108 };
|
||||||
|
const RARETE_FREQUENTE = { code: 'Frequente', label: 'Fréquente', frequence: 18, min: 9, max: 36 };
|
||||||
|
const RARETE_RARE = { code: 'Rare', label: 'Rare', frequence: 6, min: 3, max: 12 };
|
||||||
|
const RARETE_RARISSIME = { code: 'Rarissime', label: 'Rarissime', frequence: 2, min: 1, max: 4 };
|
||||||
|
const RARETE_INEXISTANT = { code: 'Inexistant', label: 'Inexistant', frequence: 0, min: 0, max: 0 };
|
||||||
|
const RARETE_EGALE = { code: 'eqal', label: 'Egal', frequence: 1, min: 1, max: 1 };
|
||||||
|
|
||||||
|
const RARETES = [
|
||||||
|
RARETE_COMMUNE,
|
||||||
|
RARETE_FREQUENTE,
|
||||||
|
RARETE_RARE,
|
||||||
|
RARETE_RARISSIME,
|
||||||
|
RARETE_INEXISTANT,
|
||||||
|
]
|
||||||
|
|
||||||
|
export class RdDRaretes {
|
||||||
|
|
||||||
|
static rareteFrequente() { return RARETE_FREQUENTE; }
|
||||||
|
static rareteEgale() { return RARETE_EGALE; }
|
||||||
|
static raretes() { return RARETES; }
|
||||||
|
|
||||||
|
static byCode(code = undefined) {
|
||||||
|
return RARETES.find(it => it.code == code) ?? RARETE_FREQUENTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getChamp(rarete, field = undefined) {
|
||||||
|
return RdDRaretes.byCode(rarete)[field ?? 'frequence'];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { EffetsRencontre } from "./effets-rencontres.js";
|
import { EffetsRencontre } from "../effets-rencontres.js";
|
||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
|
||||||
const tableEffets = [
|
const tableEffets = [
|
||||||
{ code: "messager", resultat: "succes", description: "Envoie un message à (force) cases", method: EffetsRencontre.messager },
|
{ code: "messager", resultat: "succes", description: "Envoie un message à (force) cases", method: EffetsRencontre.messager },
|
||||||
@@ -36,7 +37,11 @@ const tableEffets = [
|
|||||||
// { code: "epart-souffle", resultat: "echec", description: "Souffle de dragon sur échec particulier" },
|
// { code: "epart-souffle", resultat: "echec", description: "Souffle de dragon sur échec particulier" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export class RdDRencontre {
|
export class RdDRencontre extends RdDItem {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp";
|
||||||
|
}
|
||||||
|
|
||||||
static getEffetsSucces() { return RdDRencontre.getEffets("succes"); }
|
static getEffetsSucces() { return RdDRencontre.getEffets("succes"); }
|
||||||
static getEffetsEchec() { return RdDRencontre.getEffets("echec"); }
|
static getEffetsEchec() { return RdDRencontre.getEffets("echec"); }
|
||||||
@@ -68,4 +73,8 @@ export class RdDRencontre {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async calculerFinPeriodeTemporel(debut) {
|
||||||
|
return await debut.nouvelleHeure().addHeures(12);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
17
module/item/service.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
|
||||||
|
export class RdDItemService extends RdDItem {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/services/lit.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
isService() { return true; }
|
||||||
|
getProprietes() {
|
||||||
|
return [
|
||||||
|
RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite != 0),
|
||||||
|
RdDItem.propertyIfDefined('Moral', 'Situation heureuse', this.system.moral),
|
||||||
|
RdDItem.propertyIfDefined('Coût', `${this.calculerPrixCommercant()} sols`),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
120
module/item/sheet-base-inventaire.js
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
import { HtmlUtility } from "../html-utility.js";
|
||||||
|
import { RdDItemSheet } from "../item-sheet.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDRaretes } from "./raretes.js";
|
||||||
|
|
||||||
|
const TYPE_ITEMS_NATURELS = ["faune", "herbe", "plante", "ingredient"];
|
||||||
|
|
||||||
|
export class RdDItemInventaireSheet extends RdDItemSheet {
|
||||||
|
|
||||||
|
static get defaultOptions() {
|
||||||
|
return mergeObject(RdDItemSheet.defaultOptions, {
|
||||||
|
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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 = await super.getData();
|
||||||
|
return mergeObject(formData, {
|
||||||
|
milieux: await game.system.rdd.environnement.autresMilieux(this.item)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
HtmlUtility.showControlWhen(this.html.find("div.description-milieu"), TYPE_ITEMS_NATURELS.includes(this.item.type));
|
||||||
|
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
this.html.find("a.preparer-nourriture").click(event => this.preparerNourriture(event));
|
||||||
|
this.html.find("a.manger-nourriture").click(event => this.mangerNourriture(event));
|
||||||
|
|
||||||
|
this.html.find("input.input-selection-milieu").keypress(event => {
|
||||||
|
if (event.keyCode == '13') {
|
||||||
|
this.onAddMilieu(event);
|
||||||
|
}
|
||||||
|
event.stopPropagation();
|
||||||
|
})
|
||||||
|
this.html.find("a.milieu-add").click(event => this.onAddMilieu(event));
|
||||||
|
this.html.find("div.environnement-milieu a.milieu-delete").click(event => this.onDeleteMilieu(event));
|
||||||
|
this.html.find("div.environnement-milieu select.environnement-rarete").change(event => this.onChange(event,
|
||||||
|
updated => this.$changeRarete(event, updated)));
|
||||||
|
this.html.find("div.environnement-milieu input[name='environnement-frequence']").change(event => this.onChange(event,
|
||||||
|
updated => this.$changeFrequence(event, updated)));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async preparerNourriture(event) {
|
||||||
|
if (this.actor && this.item.getUtilisationCuisine() == 'brut') {
|
||||||
|
await this.actor.preparerNourriture(this.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async mangerNourriture(event) {
|
||||||
|
if (this.actor && this.item.getUtilisation() == 'cuisine') {
|
||||||
|
await this.actor.mangerNourriture(this.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$changeFrequence(event, updated) {
|
||||||
|
updated.frequence = Number(this.html.find(event.currentTarget).val());
|
||||||
|
}
|
||||||
|
|
||||||
|
$changeRarete(event, updated) {
|
||||||
|
const code = this.html.find(event.currentTarget).val();
|
||||||
|
const rarete = RdDRaretes.byCode(code);
|
||||||
|
updated.rarete = rarete.code;
|
||||||
|
updated.frequence = rarete.frequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onAddMilieu(event) {
|
||||||
|
const milieu = this.html.find('input.input-selection-milieu').val();
|
||||||
|
if (!milieu) {
|
||||||
|
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${this.item.name}`);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const list = this.item.getEnvironnements();
|
||||||
|
const exists = list.find(it => it.milieu == milieu);
|
||||||
|
if (exists) {
|
||||||
|
ui.notifications.warn(`${this.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const rarete = RdDRaretes.rareteFrequente();
|
||||||
|
const added = { milieu, rarete: rarete.code, frequence: rarete.frequence };
|
||||||
|
const newList = [added, ...list].sort(Misc.ascending(it => it.milieu))
|
||||||
|
await this.item.update({ 'system.environnement': newList })
|
||||||
|
}
|
||||||
|
|
||||||
|
async onDeleteMilieu(event) {
|
||||||
|
const milieu = this.$getEventMilieu(event);
|
||||||
|
if (milieu != undefined) {
|
||||||
|
const newList = this.item.getEnvironnements().filter(it => it.milieu != milieu)
|
||||||
|
.sort(Misc.ascending(it => it.milieu));
|
||||||
|
await this.item.update({ 'system.environnement': newList });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async onChange(event, doMutation) {
|
||||||
|
const list = this.item.system.environnement;
|
||||||
|
const milieu = this.$getEventMilieu(event);
|
||||||
|
const updated = list.find(it => it.milieu == milieu);
|
||||||
|
if (updated) {
|
||||||
|
doMutation(updated);
|
||||||
|
const newList = [...list.filter(it => it.milieu != milieu), updated]
|
||||||
|
.sort(Misc.ascending(it => it.milieu));
|
||||||
|
await this.item.update({ 'system.environnement': newList });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$getEventMilieu(event) {
|
||||||
|
return this.html.find(event.currentTarget)?.parents("div.environnement-milieu").data("milieu");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { RdDItemSheet } from "./item-sheet.js";
|
import { RdDBaseActorSheet } from "../actor/base-actor-sheet.js";
|
||||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
|
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
||||||
|
|
||||||
export class RdDConteneurItemSheet extends RdDItemSheet {
|
export class RdDConteneurItemSheet extends RdDItemInventaireSheet {
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "conteneur" };
|
static get ITEM_TYPE() { return "conteneur" };
|
||||||
|
|
||||||
@@ -27,8 +28,7 @@ export class RdDConteneurItemSheet extends RdDItemSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
prepareConteneurData(formData) {
|
prepareConteneurData(formData) {
|
||||||
RdDUtility.filterEquipementParType(formData, this.actor.itemTypes);
|
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
||||||
|
|
||||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||||
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
|
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,8 @@ export class RdDConteneurItemSheet extends RdDItemSheet {
|
|||||||
const dragData = {
|
const dragData = {
|
||||||
actorId: this.actor.id,
|
actorId: this.actor.id,
|
||||||
type: "Item",
|
type: "Item",
|
||||||
data: item.system
|
data: item.system,
|
||||||
|
uuid: item.uuid
|
||||||
};
|
};
|
||||||
|
|
||||||
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
|
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
|
||||||
@@ -51,7 +52,8 @@ export class RdDConteneurItemSheet extends RdDItemSheet {
|
|||||||
|
|
||||||
async _onDropItem(event, dragData) {
|
async _onDropItem(event, dragData) {
|
||||||
if (this.actor) {
|
if (this.actor) {
|
||||||
const dropParams = RdDSheetUtility.prepareItemDropParameters(this.item.id, this.actor, dragData, this.objetVersConteneur);
|
const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id') ?? this.item.id
|
||||||
|
const dropParams = await RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, dragData, this.objetVersConteneur);
|
||||||
await this.actor.processDropItem(dropParams);
|
await this.actor.processDropItem(dropParams);
|
||||||
await this.render(true);
|
await this.render(true);
|
||||||
}
|
}
|
||||||
38
module/item/sheet-faune.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
||||||
|
|
||||||
|
export class RdDFauneItemSheet extends RdDItemInventaireSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "faune" };
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
html.find("a.linked-actor-delete").click(event => this.onDeleteLinkedActor());
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onDropActor(event, dragData) {
|
||||||
|
console.log('faune:dropActor', event, dragData)
|
||||||
|
const linkedActor = fromUuidSync(dragData.uuid);
|
||||||
|
if (linkedActor?.pack) {
|
||||||
|
this.item.update({
|
||||||
|
'system.actor.pack': linkedActor.pack,
|
||||||
|
'system.actor.id': linkedActor._id,
|
||||||
|
'system.actor.name': linkedActor.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.warn(`${linkedActor.name} ne provient pas d'un compendium.
|
||||||
|
<br>Choisissez une créature du compendium pour représenter un élément de faune générique`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async onDeleteLinkedActor() {
|
||||||
|
this.item.update({
|
||||||
|
'system.actor.pack': '',
|
||||||
|
'system.actor.id': '',
|
||||||
|
'system.actor.name': ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
6
module/item/sheet-herbe.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
||||||
|
|
||||||
|
export class RdDHerbeItemSheet extends RdDItemInventaireSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "herbe" };
|
||||||
|
}
|
||||||
5
module/item/sheet-ingredient.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
||||||
|
|
||||||
|
export class RdDIngredientItemSheet extends RdDItemInventaireSheet {
|
||||||
|
static get ITEM_TYPE() { return "ingredient" };
|
||||||
|
}
|
||||||
7
module/item/sheet-plante.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
||||||
|
|
||||||
|
export class RdDPlanteItemSheet extends RdDItemInventaireSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "plante" };
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
import { RdDRencontre } from "./item-rencontre.js";
|
import { RdDRencontre } from "./rencontre.js";
|
||||||
import { RdDItemSheet } from "./item-sheet.js";
|
import { RdDItemSheet } from "../item-sheet.js";
|
||||||
|
|
||||||
export class RdDRencontreItemSheet extends RdDItemSheet {
|
export class RdDRencontreItemSheet extends RdDItemSheet {
|
||||||
|
|
||||||
@@ -23,15 +23,8 @@ export class RdDRencontreItemSheet extends RdDItemSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getData() {
|
async getData() {
|
||||||
const formData = duplicate(this.item);
|
const formData = await super.getData();
|
||||||
mergeObject(formData, {
|
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: {
|
effets: {
|
||||||
succes: {
|
succes: {
|
||||||
liste: RdDRencontre.getEffetsSucces(),
|
liste: RdDRencontre.getEffetsSucces(),
|
||||||
16
module/item/sheet-service.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { RdDItemSheet } from "../item-sheet.js";
|
||||||
|
|
||||||
|
export class RdDServiceItemSheet extends RdDItemSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "service" };
|
||||||
|
|
||||||
|
async getData() {
|
||||||
|
const formData = await super.getData();
|
||||||
|
formData.disabled = formData.options.isGM || formData.options.isOwned ? '' : 'disabled';
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { RdDItemSheet } from "./item-sheet.js";
|
import { RdDItemSheet } from "../item-sheet.js";
|
||||||
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
|
import { RdDItemSigneDraconique } from "./signedraconique.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "../tmr-utility.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item sheet pour signes draconiques
|
* Item sheet pour signes draconiques
|
||||||
@@ -23,18 +23,9 @@ export class RdDSigneDraconiqueItemSheet extends RdDItemSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getData() {
|
async getData() {
|
||||||
const formData = duplicate(this.item);
|
const formData = await super.getData();
|
||||||
this.tmrs = TMRUtility.buildSelectionTypesTMR(this.item.system.typesTMR);
|
this.tmrs = TMRUtility.buildSelectionTypesTMR(this.item.system.typesTMR);
|
||||||
mergeObject(formData, {
|
formData.tmrs = this.tmrs;
|
||||||
tmrs: this.tmrs,
|
|
||||||
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",
|
|
||||||
});
|
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
import { defaultItemImg } from "./item.js";
|
import { RdDItem, defaultItemImg } from "../item.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "../misc.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "../rdd-dice.js";
|
||||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
import { RdDRollTables } from "../rdd-rolltables.js";
|
||||||
import { TMRType, TMRUtility } from "./tmr-utility.js";
|
import { RdDTimestamp } from "../rdd-timestamp.js";
|
||||||
|
import { TMRType, TMRUtility } from "../tmr-utility.js";
|
||||||
|
|
||||||
const tableSignesIndicatifs = [
|
const tableSignesIndicatifs = [
|
||||||
{ rarete: "Très facile", difficulte: 0, xp: 6, nbCases: 14 },
|
{ rarete: "Très facile", difficulte: 0, xp: 6, nbCases: 14 },
|
||||||
@@ -15,7 +16,17 @@ const tableSignesIndicatifs = [
|
|||||||
|
|
||||||
const DIFFICULTE_LECTURE_SIGNE_MANQUE = +11;
|
const DIFFICULTE_LECTURE_SIGNE_MANQUE = +11;
|
||||||
|
|
||||||
export class RdDItemSigneDraconique {
|
export class RdDItemSigneDraconique extends RdDItem {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async calculerFinPeriodeTemporel(debut) {
|
||||||
|
// TODO
|
||||||
|
return RdDTimestamp.formulesDuree().find(it => it.code == "").calcul(debut, this.actor);
|
||||||
|
}
|
||||||
|
|
||||||
static prepareSigneDraconiqueMeditation(meditation, rolled) {
|
static prepareSigneDraconiqueMeditation(meditation, rolled) {
|
||||||
return {
|
return {
|
||||||
@@ -96,6 +107,6 @@ export class RdDItemSigneDraconique {
|
|||||||
|
|
||||||
static async randomSigneDescription() {
|
static async randomSigneDescription() {
|
||||||
return await RdDRollTables.drawTextFromRollTable("Signes draconiques", false);
|
return await RdDRollTables.drawTextFromRollTable("Signes draconiques", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
13
module/item/souffle.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
|
||||||
|
export class RdDItemSouffle extends RdDItem {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
async calculerFinPeriodeTemporel(debut) {
|
||||||
|
return await debut.appliquerDuree(this.system.duree, this.parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,10 @@
|
|||||||
|
import { RdDBaseActor } from "./actor/base-actor.js";
|
||||||
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
||||||
import { Environnement } from "./environnement.js";
|
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
|
import { Monnaie } from "./item-monnaie.js";
|
||||||
|
import { RdDItem } from "./item.js";
|
||||||
|
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||||
|
import { RdDRaretes } from "./item/raretes.js";
|
||||||
|
|
||||||
class Migration {
|
class Migration {
|
||||||
get code() { return "sample"; }
|
get code() { return "sample"; }
|
||||||
@@ -29,6 +33,39 @@ class Migration {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _1_5_34_migrationPngWebp {
|
||||||
|
get code() { return "migrationPngWebp"; }
|
||||||
|
get version() { return "1.5.34"; }
|
||||||
|
async migrate() {
|
||||||
|
|
||||||
|
const regexOldPngJpg = /(systems\/foundryvtt-reve-de-dragon\/icons\/.*)\.(png|jpg)/;
|
||||||
|
const replaceWithWebp = '$1.webp';
|
||||||
|
function convertImgToWebp(img) {
|
||||||
|
return img.replace(regexOldPngJpg, replaceWithWebp);
|
||||||
|
}
|
||||||
|
function prepareDocumentsImgUpdate(documents) {
|
||||||
|
return documents.filter(it => it.img && it.img.match(regexOldPngJpg))
|
||||||
|
.map(it => {
|
||||||
|
return { _id: it.id, img: convertImgToWebp(it.img) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const itemsUpdates = prepareDocumentsImgUpdate(game.items);
|
||||||
|
const actorsUpdates = prepareDocumentsImgUpdate(game.actors);
|
||||||
|
//Migrate system png to webp
|
||||||
|
await Item.updateDocuments(itemsUpdates);
|
||||||
|
await Actor.updateDocuments(actorsUpdates);
|
||||||
|
game.actors.forEach(actor => {
|
||||||
|
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
|
||||||
|
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
|
||||||
|
}
|
||||||
|
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
|
||||||
|
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class _10_0_16_MigrationSortsReserve extends Migration {
|
class _10_0_16_MigrationSortsReserve extends Migration {
|
||||||
get code() { return "creation-item-sort-reserve"; }
|
get code() { return "creation-item-sort-reserve"; }
|
||||||
get version() { return "10.0.16"; }
|
get version() { return "10.0.16"; }
|
||||||
@@ -236,7 +273,7 @@ class _10_3_0_Inventaire extends Migration {
|
|||||||
}
|
}
|
||||||
_updatesMonnaies(items) {
|
_updatesMonnaies(items) {
|
||||||
return items
|
return items
|
||||||
.filter(it => ['monnaie'].includes(it.type) && it.system.cout == undefined)
|
.filter(it => ['monnaie'].includes(it.type) && it.system.valeur_deniers != undefined)
|
||||||
.map(it => { return { _id: it.id, 'system.cout': it.system.valeur_deniers / 100, 'system.valeur_deniers': undefined } });
|
.map(it => { return { _id: it.id, 'system.cout': it.system.valeur_deniers / 100, 'system.valeur_deniers': undefined } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -251,10 +288,130 @@ class _10_3_0_FrequenceEnvironnement extends Migration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_updatesFrequences(it) {
|
_updatesFrequences(it) {
|
||||||
|
const rarete = RdDRaretes.byCode(it.system.rarete);
|
||||||
return {
|
return {
|
||||||
_id: it.id,
|
_id: it.id,
|
||||||
'system.rarete': undefined,
|
'system.rarete': undefined,
|
||||||
'system.environnement': [{ milieu: it.system.milieu, rarete: it.system.rarete, frequence: Environnement.getFrequenceRarete(it.system.rarete, 'frequence') }]
|
'system.environnement': [{ milieu: it.system.milieu, rarete: rarete.code, frequence: rarete.frequence }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _10_3_17_Monnaies extends Migration {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.mapValeur = {
|
||||||
|
"Etain (1 denier)": { name: 'Denier (étain)', system: { cout: 0.01 } },
|
||||||
|
"Bronze (10 deniers)": { name: "Sou (bronze)", system: { cout: 0.1 } },
|
||||||
|
"Argent (1 sol)": { name: "Sol (argent)", system: { cout: 1 } },
|
||||||
|
"Or (10 sols)": { name: "Dragon (or)", system: { cout: 10 } }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
get code() { return "migration-monnaies"; }
|
||||||
|
get version() { return "10.3.17"; }
|
||||||
|
|
||||||
|
async migrate() {
|
||||||
|
await this.applyItemsUpdates(items => this._updatesMonnaies(items));
|
||||||
|
}
|
||||||
|
|
||||||
|
_updatesMonnaies(items) {
|
||||||
|
return items
|
||||||
|
.filter(it => 'monnaie' == it.type)
|
||||||
|
.filter(it => this.mapValeur[it.name] != undefined)
|
||||||
|
.map(it => {
|
||||||
|
const correction = this.mapValeur[it.name];
|
||||||
|
return {
|
||||||
|
_id: it.id,
|
||||||
|
'name': correction.name,
|
||||||
|
'system.cout': correction.system.cout,
|
||||||
|
'system.valeur_deniers': undefined
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _10_4_6_ServicesEnCommerces extends Migration {
|
||||||
|
|
||||||
|
get code() { return "migration-service-acteurs"; }
|
||||||
|
get version() { return "10.4.6"; }
|
||||||
|
|
||||||
|
async migrate() {
|
||||||
|
const servicesToMigrate = game.items.filter(it => it.type == 'service');
|
||||||
|
servicesToMigrate.forEach(async service => {
|
||||||
|
const commerce = await this.convertServiceToCommerce(service);
|
||||||
|
await RdDBaseActor.create(commerce, { renderSheet: false });
|
||||||
|
await service.delete();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async convertServiceToCommerce(service) {
|
||||||
|
return {
|
||||||
|
name: service.name, img: service.img, type: 'commerce',
|
||||||
|
system: {
|
||||||
|
description: service.system.description,
|
||||||
|
notesmj: service.system.descriptionmj,
|
||||||
|
illimite: service.system.illimite
|
||||||
|
},
|
||||||
|
items: await this.transformInventaireCommerce(service)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async transformInventaireCommerce(service) {
|
||||||
|
const serviceItems = (service.system.items ?? []);
|
||||||
|
const commerceItems = await Promise.all(serviceItems.map(async (it) => { return await this.transformToItemBoutique(it); }));
|
||||||
|
return commerceItems.concat(Monnaie.monnaiesStandard());
|
||||||
|
}
|
||||||
|
|
||||||
|
async transformToItemBoutique(serviceRefItem) {
|
||||||
|
const item = await RdDItem.getCorrespondingItem(serviceRefItem);
|
||||||
|
const itemToCreate = {
|
||||||
|
name: item.name, img: item.img, type: item.type,
|
||||||
|
system: mergeObject({ cout: serviceRefItem.system.cout, quantite: serviceRefItem.system.quantite }, item.system, { overwrite: false })
|
||||||
|
};
|
||||||
|
return itemToCreate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class _10_5_0_UpdatePeriodicite extends Migration {
|
||||||
|
get code() { return "migration-periodicite-poisons-maladies"; }
|
||||||
|
get version() { return "10.5.0"; }
|
||||||
|
|
||||||
|
async migrate() {
|
||||||
|
await this.applyItemsUpdates(items => this._updatePeriodicite(items));
|
||||||
|
}
|
||||||
|
|
||||||
|
_updatePeriodicite(items) {
|
||||||
|
return items.filter(it => ['poison', 'maladie'].includes(it.type))
|
||||||
|
.filter(it => it.system.periodicite != "")
|
||||||
|
.map(it => {
|
||||||
|
let [incubation, periodicite] = this.getPeriodicite(it);
|
||||||
|
const periode = periodicite.split(' ');
|
||||||
|
let unite = periode.length == 2
|
||||||
|
? RdDTimestamp.formulesPeriode().find(it => Grammar.includesLowerCaseNoAccent(periode[1], it.code))?.code
|
||||||
|
: undefined
|
||||||
|
if (unite && Number(periode[0])) {
|
||||||
|
return {
|
||||||
|
_id: it.id,
|
||||||
|
'system.periodicite': undefined,
|
||||||
|
'system.incubation': incubation,
|
||||||
|
'system.periode.nombre': Number.parseInt(periode[0]),
|
||||||
|
'system.periode.unite': unite
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return {
|
||||||
|
_id: it.id,
|
||||||
|
'system.periodicite': undefined,
|
||||||
|
'system.incubation': it.system.periodicite
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}).filter(it => it != undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
getPeriodicite(it) {
|
||||||
|
let p = it.system.periodicite.split(/[\/\\]/);
|
||||||
|
switch (p.length) {
|
||||||
|
case 2: return [p[0].trim(), p[1].trim()];
|
||||||
|
case 1: return ["", it.system.periodicite.trim()];
|
||||||
|
default: return [it.system.periodicite.trim(), ""];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -262,6 +419,7 @@ class _10_3_0_FrequenceEnvironnement extends Migration {
|
|||||||
export class Migrations {
|
export class Migrations {
|
||||||
static getMigrations() {
|
static getMigrations() {
|
||||||
return [
|
return [
|
||||||
|
new _1_5_34_migrationPngWebp(),
|
||||||
new _10_0_16_MigrationSortsReserve(),
|
new _10_0_16_MigrationSortsReserve(),
|
||||||
new _10_0_17_MigrationCompetenceCreature(),
|
new _10_0_17_MigrationCompetenceCreature(),
|
||||||
new _10_0_21_VehiculeStructureResistanceMax(),
|
new _10_0_21_VehiculeStructureResistanceMax(),
|
||||||
@@ -269,7 +427,10 @@ export class Migrations {
|
|||||||
new _10_2_5_ArmesTirLancer(),
|
new _10_2_5_ArmesTirLancer(),
|
||||||
new _10_2_10_DesirLancinant_IdeeFixe(),
|
new _10_2_10_DesirLancinant_IdeeFixe(),
|
||||||
new _10_3_0_Inventaire(),
|
new _10_3_0_Inventaire(),
|
||||||
new _10_3_0_FrequenceEnvironnement()
|
new _10_3_0_FrequenceEnvironnement(),
|
||||||
|
new _10_3_17_Monnaies(),
|
||||||
|
new _10_4_6_ServicesEnCommerces(),
|
||||||
|
new _10_5_0_UpdatePeriodicite(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,18 +445,12 @@ export class Migrations {
|
|||||||
}
|
}
|
||||||
|
|
||||||
migrate() {
|
migrate() {
|
||||||
const currentVersion = game.settings.get(SYSTEM_RDD,"systemMigrationVersion");
|
const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion");
|
||||||
//if (isNewerVersion(game.system.version, currentVersion)) {
|
if (isNewerVersion(game.system.version, currentVersion)) {
|
||||||
if (true) { /* comment previous and uncomment here to test before upgrade */
|
//if (true) { /* comment previous and uncomment here to test before upgrade */
|
||||||
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
|
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
|
||||||
if (migrations.length > 0) {
|
if (migrations.length > 0) {
|
||||||
migrations.sort((a, b) =>
|
migrations.sort((a, b) => this.compareVersions(a, b));
|
||||||
isNewerVersion(a.version, b.version)
|
|
||||||
? 1
|
|
||||||
: isNewerVersion(b.version, a.version)
|
|
||||||
? -1
|
|
||||||
: 0
|
|
||||||
);
|
|
||||||
migrations.forEach(async (m) => {
|
migrations.forEach(async (m) => {
|
||||||
ui.notifications.info(
|
ui.notifications.info(
|
||||||
`Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}`
|
`Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}`
|
||||||
@@ -321,4 +476,8 @@ export class Migrations {
|
|||||||
console.log(LOG_HEAD + `No system version changed`);
|
console.log(LOG_HEAD + `No system version changed`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
compareVersions(a, b) {
|
||||||
|
return isNewerVersion(a.version, b.version) ? 1 : isNewerVersion(b.version, a.version) ? -1 : 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ export class Misc {
|
|||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static arrayOrEmpty(items) {
|
||||||
|
return items?.length ? items : [];
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Converts the value to an integer, or to 0 if undefined/null/not representing integer
|
* Converts the value to an integer, or to 0 if undefined/null/not representing integer
|
||||||
* @param {*} value value to convert to an integer using parseInt
|
* @param {*} value value to convert to an integer using parseInt
|
||||||
@@ -82,6 +85,7 @@ export class Misc {
|
|||||||
list.forEach(it => addToObj(obj, it))
|
list.forEach(it => addToObj(obj, it))
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static concat(lists) {
|
static concat(lists) {
|
||||||
return lists.reduce((a, b) => a.concat(b), []);
|
return lists.reduce((a, b) => a.concat(b), []);
|
||||||
}
|
}
|
||||||
@@ -135,11 +139,11 @@ export class Misc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isRollModeHiddenToPlayer() {
|
static isRollModeHiddenToPlayer() {
|
||||||
switch (game.settings.get("core", "rollMode")) {
|
switch (game.settings.get("core", "rollMode")) {
|
||||||
case CONST.DICE_ROLL_MODES.BLIND:
|
case CONST.DICE_ROLL_MODES.BLIND:
|
||||||
case CONST.DICE_ROLL_MODES.SELF: return true;
|
case CONST.DICE_ROLL_MODES.SELF: return true;
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
static getActiveUser(id) {
|
static getActiveUser(id) {
|
||||||
@@ -150,11 +154,11 @@ export class Misc {
|
|||||||
return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
|
return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isOwnerPlayer(actor, user=undefined) {
|
static isOwnerPlayer(actor, user = undefined) {
|
||||||
return actor.testUserPermission(user ?? game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER)
|
return actor.testUserPermission(user ?? game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER)
|
||||||
}
|
}
|
||||||
|
|
||||||
static isOwnerPlayerOrUniqueConnectedGM(actor, user =undefined){
|
static isOwnerPlayerOrUniqueConnectedGM(actor, user = undefined) {
|
||||||
return Misc.isOwnerPlayer(actor, user) ?? Misc.isUniqueConnectedGM();
|
return Misc.isOwnerPlayer(actor, user) ?? Misc.isUniqueConnectedGM();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,11 @@ export class RdDAlchimie {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static processManipulation(recette, actorId = undefined) {
|
static processManipulation(recette, actorId = undefined) {
|
||||||
//console.log("CALLED", recette, recette.isOwned, actorId );
|
|
||||||
let manip = recette.system.manipulation;
|
let manip = recette.system.manipulation;
|
||||||
let matchArray = manip.match(matchOperations);
|
let matchArray = manip.match(matchOperations);
|
||||||
if (matchArray) {
|
if (matchArray) {
|
||||||
for (let matchStr of matchArray) {
|
for (let matchStr of matchArray) {
|
||||||
let result = matchStr.match(matchOperationTerms);
|
let result = matchStr.match(matchOperationTerms);
|
||||||
//console.log("RESULT ", result);
|
|
||||||
if (result[1] && result[2]) {
|
if (result[1] && result[2]) {
|
||||||
let commande = Misc.upperFirst(result[1]);
|
let commande = Misc.upperFirst(result[1]);
|
||||||
let replacement = this[`_alchimie${commande}`](recette, result[2], actorId);
|
let replacement = this[`_alchimie${commande}`](recette, result[2], actorId);
|
||||||
@@ -27,20 +25,19 @@ export class RdDAlchimie {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _alchimieCouleur(recette, couleurs, actorId) {
|
static _alchimieCouleur(recette, couleurs, actorId) {
|
||||||
if (actorId) {
|
return RdDAlchimie._alchimieLink(recette, couleurs, actorId, 'couleur', 'Température');
|
||||||
return `<span class="alchimie-tache"><a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="couleur" data-alchimie-data="${couleurs}">couleur ${couleurs}</a></span>`;
|
|
||||||
} else {
|
|
||||||
return `<span class="alchimie-tache">couleur ${couleurs} </span>`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _alchimieConsistance(recette, consistances, actorId) {
|
static _alchimieConsistance(recette, consistances, actorId) {
|
||||||
if (actorId) {
|
return RdDAlchimie._alchimieLink(recette, consistances, actorId, 'consistance', 'Consistance');
|
||||||
return `<span class="alchimie-tache"><a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="consistance" data-alchimie-data="${consistances}">consistance ${consistances}</a></span>`;
|
}
|
||||||
} else {
|
|
||||||
return `<span class="alchimie-tache">consistance ${consistances} </span>`;
|
static _alchimieLink(recette, termes, actorId, tacheAlchimie, labelTache) {
|
||||||
}
|
const difficulte = RdDAlchimie.getDifficulte(termes);
|
||||||
|
const link = actorId ? ` <a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="${tacheAlchimie}" data-alchimie-data="${termes}">` : '';
|
||||||
|
const endLink = actorId ? '</a>' : '';
|
||||||
|
return `<span class="alchimie-tache">${link}${labelTache} ${termes} (${difficulte})${endLink}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|||||||
@@ -3,23 +3,28 @@
|
|||||||
* Extend the base Dialog entity by defining a custom window to perform roll.
|
* Extend the base Dialog entity by defining a custom window to perform roll.
|
||||||
* @extends {Dialog}
|
* @extends {Dialog}
|
||||||
*/
|
*/
|
||||||
export class RdDAstrologieEditeur extends Dialog {
|
export class RdDAstrologieEditeur extends Dialog {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(html, calendrier, calendrierData) {
|
constructor(html, calendrier, calendrierData) {
|
||||||
|
|
||||||
let myButtons = {
|
let myButtons = {
|
||||||
resetButton: { label: "Re-tirer les nombres astraux", callback: html => this.resetNombreAstraux() },
|
resetButton: { label: "Re-tirer les nombres astraux", callback: html => this.resetNombreAstraux() },
|
||||||
saveButton: { label: "Fermer", callback: html => this.fillData() }
|
saveButton: { label: "Fermer", callback: html => {} }
|
||||||
};
|
};
|
||||||
|
|
||||||
// Common conf
|
// Common conf
|
||||||
let dialogConf = { content: html, title: "Editeur d'Astrologie", buttons: myButtons, default: "saveButton" };
|
let dialogConf = { content: html, title: "Editeur d'Astrologie", buttons: myButtons, default: "saveButton" };
|
||||||
let dialogOptions = { classes: ["rdd-roll-dialog"], width: 600, height: 300, 'z-index': 99999 }
|
let dialogOptions = {
|
||||||
|
classes: ["rdd-roll-dialog"], width: 600,
|
||||||
|
height: 'fit-content',
|
||||||
|
'max-height': 800,
|
||||||
|
'z-index': 99999
|
||||||
|
}
|
||||||
super(dialogConf, dialogOptions)
|
super(dialogConf, dialogOptions)
|
||||||
|
|
||||||
this.calendrier = calendrier;
|
this.calendrier = calendrier;
|
||||||
this.updateData( calendrierData );
|
this.updateData(calendrierData);
|
||||||
}
|
}
|
||||||
|
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
@@ -28,7 +33,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async resetNombreAstraux() {
|
async resetNombreAstraux() {
|
||||||
game.system.rdd.calendrier.resetNombreAstral();
|
game.system.rdd.calendrier.resetNombreAstral();
|
||||||
await game.system.rdd.calendrier.rebuildListeNombreAstral();
|
await game.system.rdd.calendrier.rebuildListeNombreAstral();
|
||||||
@@ -36,12 +41,8 @@
|
|||||||
game.system.rdd.calendrier.showAstrologieEditor();
|
game.system.rdd.calendrier.showAstrologieEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
fillData( ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
updateData( calendrierData ) {
|
updateData(calendrierData) {
|
||||||
this.calendrierData = duplicate(calendrierData);
|
this.calendrierData = duplicate(calendrierData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import { SYSTEM_SOCKET_ID } from "./constants.js";
|
|||||||
export class RdDAstrologieJoueur extends Dialog {
|
export class RdDAstrologieJoueur extends Dialog {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async create(actor, dialogConfig) {
|
static async create(actor) {
|
||||||
|
|
||||||
let dialogData = {
|
let dialogData = {
|
||||||
nombres: this.organizeNombres(actor),
|
nombres: this.organizeNombres(actor),
|
||||||
@@ -20,24 +20,22 @@ export class RdDAstrologieJoueur extends Dialog {
|
|||||||
astrologie: RdDItemCompetence.findCompetence(actor.items, 'Astrologie')
|
astrologie: RdDItemCompetence.findCompetence(actor.items, 'Astrologie')
|
||||||
}
|
}
|
||||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', dialogData);
|
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', dialogData);
|
||||||
let options = { classes: ["rdd-roll-dialog"], width: 600, height: 500, 'z-index': 99999 };
|
|
||||||
if (dialogConfig.options) {
|
const options = { classes: ["rdd-roll-dialog"], width: 600, height: 'fit-content', 'z-index': 99999 };
|
||||||
mergeObject(options, dialogConfig.options, { overwrite: true });
|
const dialog = new RdDAstrologieJoueur(html, actor, dialogData, options);
|
||||||
}
|
dialog.render(true);
|
||||||
return new RdDAstrologieJoueur(html, actor, dialogData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(html, actor, dialogData) {
|
constructor(html, actor, dialogData, dialogOptions) {
|
||||||
const dialogConf = {
|
const dialogConf = {
|
||||||
title: "Nombres Astraux",
|
title: "Nombres Astraux",
|
||||||
content: html,
|
content: html,
|
||||||
default: "saveButton",
|
default: "saveButton",
|
||||||
buttons: {
|
buttons: {
|
||||||
saveButton: { label: "Fermer", callback: html => this.quitDialog() }
|
saveButton: { label: "Fermer", callback: html => {} }
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const dialogOptions = { classes: ["rdd-roll-dialog"], width: 600, height: 300, 'z-index': 99999 };
|
|
||||||
super(dialogConf, dialogOptions);
|
super(dialogConf, dialogOptions);
|
||||||
|
|
||||||
this.actor = actor;
|
this.actor = actor;
|
||||||
@@ -49,9 +47,7 @@ export class RdDAstrologieJoueur extends Dialog {
|
|||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
this.html = html;
|
this.html = html;
|
||||||
|
|
||||||
this.html.find(function () {
|
this.html.find("[name='diffConditions']").val(0);
|
||||||
this.html.find("[name='diffConditions']").val(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
this.html.find('[name="jet-astrologie"]').click((event) => {
|
this.html.find('[name="jet-astrologie"]').click((event) => {
|
||||||
this.requestJetAstrologie();
|
this.requestJetAstrologie();
|
||||||
@@ -60,7 +56,7 @@ export class RdDAstrologieJoueur extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static organizeNombres(actor) {
|
static organizeNombres(actor) {
|
||||||
let itemNombres = actor.listItemsData('nombreastral');
|
let itemNombres = actor.listItems('nombreastral');
|
||||||
let itemFiltered = {};
|
let itemFiltered = {};
|
||||||
for (let item of itemNombres) {
|
for (let item of itemNombres) {
|
||||||
if (itemFiltered[item.system.jourindex]) {
|
if (itemFiltered[item.system.jourindex]) {
|
||||||
@@ -97,8 +93,4 @@ export class RdDAstrologieJoueur extends Dialog {
|
|||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
quitDialog() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Misc } from "./misc.js";
|
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the base Dialog entity by defining a custom window to perform roll.
|
* Extend the base Dialog entity by defining a custom window to perform roll.
|
||||||
@@ -12,7 +12,7 @@ export class RdDCalendrierEditeur extends Dialog {
|
|||||||
content: html,
|
content: html,
|
||||||
title: "Editeur de date/heure",
|
title: "Editeur de date/heure",
|
||||||
buttons: {
|
buttons: {
|
||||||
save: { label: "Enregistrer", callback: html => this.fillData() }
|
save: { label: "Enregistrer", callback: html => this.saveCalendrier() }
|
||||||
},
|
},
|
||||||
default: "save"
|
default: "save"
|
||||||
};
|
};
|
||||||
@@ -26,22 +26,37 @@ export class RdDCalendrierEditeur extends Dialog {
|
|||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
this.html = html;
|
this.html = html;
|
||||||
this.html.find("input[name='nomMois']").val(this.calendrierData.moisKey);
|
|
||||||
this.html.find("select[name='nomHeure']").val(this.calendrierData.heureKey);
|
this.html.find("input[name='calendar.annee']").val(this.calendrierData.annee);
|
||||||
this.html.find("select[name='jourMois']").val(this.calendrierData.jourMois);
|
this.html.find("select[name='calendar.mois']").val(this.calendrierData.mois.key);
|
||||||
this.html.find("select[name='minutesRelative']").val(calendrierData.minutesRelative);
|
this.html.find("select[name='calendar.heure']").val(this.calendrierData.heure.key);
|
||||||
this.html.find("select[name='annee']").val(this.calendrierData.annee);
|
RdDCalendrierEditeur.setLimited(this.html.find("input[name='calendar.jourDuMois']"), this.calendrierData.jourDuMois, 1, 28);
|
||||||
|
RdDCalendrierEditeur.setLimited(this.html.find("input[name='calendar.minute']"), this.calendrierData.minute, 0, 119);
|
||||||
|
}
|
||||||
|
|
||||||
|
static setLimited(input, init, min, max) {
|
||||||
|
input.val(init);
|
||||||
|
input.change(event => {
|
||||||
|
const val = Number.parseInt(input.val());
|
||||||
|
if (val < min) {
|
||||||
|
input.val(min);
|
||||||
|
}
|
||||||
|
if (val > max) {
|
||||||
|
input.val(max);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
fillData() {
|
saveCalendrier() {
|
||||||
this.calendrierData.annee = this.html.find("input[name='annee']").val();
|
const annee = Number.parseInt(this.html.find("input[name='calendar.annee']").val());
|
||||||
this.calendrierData.moisKey = this.html.find("select[name='nomMois']").val();
|
const mois = this.html.find("select[name='calendar.mois']").val();
|
||||||
this.calendrierData.heureKey = this.html.find("select[name='nomHeure']").val();
|
const jour = Number.parseInt(this.html.find("input[name='calendar.jourDuMois']").val());
|
||||||
this.calendrierData.jourMois = this.html.find("select[name='jourMois']").val();
|
const heure = this.html.find("select[name='calendar.heure']").val();
|
||||||
this.calendrierData.minutesRelative = this.html.find("select[name='minutesRelative']").val();
|
const minute = Number.parseInt(this.html.find("input[name='calendar.minute']").val());
|
||||||
|
|
||||||
this.calendrier.saveEditeur(this.calendrierData)
|
this.calendrier.setNewTimestamp(RdDTimestamp.timestamp(annee, mois, jour, heure, minute))
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|||||||
@@ -1,44 +1,17 @@
|
|||||||
/* -------------------------------------------- */
|
|
||||||
import { RdDCalendrierEditeur } from "./rdd-calendrier-editeur.js";
|
import { RdDCalendrierEditeur } from "./rdd-calendrier-editeur.js";
|
||||||
import { RdDAstrologieEditeur } from "./rdd-astrologie-editeur.js";
|
import { RdDAstrologieEditeur } from "./rdd-astrologie-editeur.js";
|
||||||
import { HtmlUtility } from "./html-utility.js";
|
|
||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { Grammar } from "./grammar.js";
|
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
import { DialogChronologie } from "./dialog-chronologie.js";
|
import { DialogChronologie } from "./dialog-chronologie.js";
|
||||||
|
import { RdDTimestamp, WORLD_TIMESTAMP_SETTING } from "./rdd-timestamp.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
const RDD_JOUR_PAR_MOIS = 28;
|
||||||
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' },
|
|
||||||
"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' },
|
|
||||||
"dragon": { key: "dragon", label: "Dragon", lettreFont: 'd', saison: "ete", heure: 4, icon: 'hd05.svg' },
|
|
||||||
"epees": { key: "epees", label: "Epées", lettreFont: 'e', saison: "ete", heure: 5, icon: 'hd06.svg' },
|
|
||||||
"lyre": { key: "lyre", label: "Lyre", lettreFont: 'l', saison: "automne", heure: 6, icon: 'hd07.svg' },
|
|
||||||
"serpent": { key: "serpent", label: "Serpent", lettreFont: 's', saison: "automne", heure: 7, icon: 'hd08.svg' },
|
|
||||||
"poissonacrobate": { key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "automne", heure: 8, icon: 'hd09.svg' },
|
|
||||||
"araignee": { key: "araignee", label: "Araignée", lettreFont: 'a', saison: "hiver", heure: 9, icon: 'hd10.svg' },
|
|
||||||
"roseau": { key: "roseau", label: "Roseau", lettreFont: 'r', saison: "hiver", heure: 10, icon: 'hd11.svg' },
|
|
||||||
"chateaudormant": { key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "hiver", heure: 11, icon: 'hd12.svg' }
|
|
||||||
};
|
|
||||||
const saisonsDef = {
|
|
||||||
"printemps": { label: "Printemps" },
|
|
||||||
"ete": { label: "Eté" },
|
|
||||||
"automne": { label: "Automne" },
|
|
||||||
"hiver": { label: "Hiver" }
|
|
||||||
};
|
|
||||||
|
|
||||||
const RDD_MOIS_PAR_AN = 12;
|
|
||||||
export const RDD_JOUR_PAR_MOIS = 28;
|
|
||||||
const RDD_HEURES_PAR_JOUR = 12;
|
const RDD_HEURES_PAR_JOUR = 12;
|
||||||
const RDD_MINUTES_PAR_HEURES = 120;
|
|
||||||
const MAX_NOMBRE_ASTRAL = 12;
|
const MAX_NOMBRE_ASTRAL = 12;
|
||||||
|
const JOURS_DU_MOIS = Array(RDD_JOUR_PAR_MOIS).fill().map((item, index) => 1 + index);
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDCalendrier extends Application {
|
export class RdDCalendrier extends Application {
|
||||||
@@ -55,57 +28,6 @@ export class RdDCalendrier extends Application {
|
|||||||
return { top: 200, left: 200 };
|
return { top: 200, left: 200 };
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDefSigne(chiffre) {
|
|
||||||
chiffre = chiffre % RDD_MOIS_PAR_AN;
|
|
||||||
return Object.values(heuresDef).find(h => h.heure == chiffre);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getSigneAs(key, value) {
|
|
||||||
const heure = (typeof value == 'string' || typeof value == 'number') && Number.isInteger(Number(value))
|
|
||||||
? Number(value)
|
|
||||||
: (typeof value == 'string') ? RdDCalendrier.getChiffreFromSigne(value)
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
if (heure != undefined && ['key', 'label', 'lettreFont', 'saison', 'heure', 'icon'].includes(key)) {
|
|
||||||
return RdDCalendrier.getDefSigne(heure)[key]
|
|
||||||
}
|
|
||||||
if (heure != undefined && ['webp'].includes(key)) {
|
|
||||||
return RdDCalendrier.getDefSigne(heure)['icon'].replace('svg', 'webp');
|
|
||||||
}
|
|
||||||
console.error(`Appel à getSigneAs('${key}', ${value}) avec une clé/heure incorrects`);
|
|
||||||
return value;
|
|
||||||
|
|
||||||
}
|
|
||||||
static getChiffreFromSigne(signe) {
|
|
||||||
return heuresList.indexOf(signe);
|
|
||||||
}
|
|
||||||
|
|
||||||
static createCalendrierInitial() {
|
|
||||||
return {
|
|
||||||
heureRdD: 0,
|
|
||||||
minutesRelative: 0,
|
|
||||||
indexJour: 0,
|
|
||||||
annee: 0,
|
|
||||||
moisRdD: 0,
|
|
||||||
moisLabel: heuresDef["vaisseau"].label,
|
|
||||||
jour: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCalendrier(index) {
|
|
||||||
index = index ?? this.getCurrentDayIndex();
|
|
||||||
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(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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
// position
|
// position
|
||||||
@@ -114,19 +36,23 @@ export class RdDCalendrier extends Application {
|
|||||||
this.calendrierPos = RdDCalendrier.createCalendrierPos();
|
this.calendrierPos = RdDCalendrier.createCalendrierPos();
|
||||||
game.settings.set(SYSTEM_RDD, "calendrier-pos", this.calendrierPos);
|
game.settings.set(SYSTEM_RDD, "calendrier-pos", this.calendrierPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calendrier
|
// Calendrier
|
||||||
this.calendrier = duplicate(game.settings.get(SYSTEM_RDD, "calendrier") ?? RdDCalendrier.createCalendrierInitial());
|
this.timestamp = RdDTimestamp.getWorldTime();
|
||||||
this.calendrier.annee = this.calendrier.annee ?? Math.floor((this.calendrier.moisRdD ?? 0) / RDD_MOIS_PAR_AN);
|
|
||||||
this.calendrier.moisRdD = (this.calendrier.moisRdD ?? 0) % RDD_MOIS_PAR_AN;
|
|
||||||
|
|
||||||
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
|
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
|
||||||
game.settings.set(SYSTEM_RDD, "calendrier", this.calendrier);
|
RdDTimestamp.setWorldTime(this.timestamp);
|
||||||
|
|
||||||
this.listeNombreAstral = this.getListeNombreAstral();
|
this.listeNombreAstral = this.getListeNombreAstral();
|
||||||
this.rebuildListeNombreAstral(HIDE_DICE); // Ensure always up-to-date
|
this.rebuildListeNombreAstral(HIDE_DICE); // Ensure always up-to-date
|
||||||
}
|
}
|
||||||
console.log('RdDCalendrier.constructor()', this.calendrier, this.calendrierPos, this.listeNombreAstral);
|
console.log('RdDCalendrier.constructor()', this.timestamp, this.timestamp.toCalendrier(), this.calendrierPos, this.listeNombreAstral);
|
||||||
|
Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
async onUpdateSetting(setting, update, options, id) {
|
||||||
|
if (setting.key == SYSTEM_RDD + '.' + WORLD_TIMESTAMP_SETTING) {
|
||||||
|
this.timestamp = RdDTimestamp.getWorldTime();
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -227,48 +153,50 @@ export class RdDCalendrier extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getDateFromIndex(index) {
|
dateCourante() {
|
||||||
const dateRdD = this.getCalendrier(index);
|
return this.timestamp.formatDate();
|
||||||
return (dateRdD.jour + 1) + ' ' + dateRdD.moisLabel;
|
}
|
||||||
|
|
||||||
|
isAfterIndexDate(indexDate) {
|
||||||
|
// TODO: standardize
|
||||||
|
return indexDate < this.timestamp.indexDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getDayMonthFromIndex(index = undefined) {
|
heureCourante() { return RdDTimestamp.definition(this.timestamp.heure); }
|
||||||
const dateRdD = this.getCalendrier(index);
|
|
||||||
return {
|
|
||||||
day: dateRdD.jour + 1,
|
|
||||||
month: heuresList[dateRdD.moisRdD]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getCurrentHeure() {
|
getCurrentMinute() { return this.timestamp.indexMinute; }
|
||||||
return heuresList[this.calendrier.heureRdD];
|
|
||||||
|
getTimestampFinChateauDormant(nbJours = 0) {
|
||||||
|
return this.timestamp.nouveauJour().addJour(nbJours);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
getTimestampFinHeure(nbHeures = 0) {
|
||||||
getCurrentDayIndex() {
|
return this.timestamp.nouvelleHeure().addHeures(nbHeures);
|
||||||
return (((this.calendrier.annee ?? 0) * RDD_MOIS_PAR_AN + (this.calendrier.moisRdD ?? 0)) * RDD_JOUR_PAR_MOIS) + (this.calendrier.jour ?? 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getIndexFromDate(jour, mois) {
|
getIndexFromDate(jour, mois) {
|
||||||
return (heuresDef[mois].heure * RDD_JOUR_PAR_MOIS) + jour - 1;
|
const addYear = mois < this.timestamp.mois || (mois == this.timestamp.mois && jour < this.timestamp.jour)
|
||||||
|
const time = RdDTimestamp.timestamp(this.timestamp.annee + (addYear ? 1 : 0), mois, jour);
|
||||||
|
return time.indexDate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getJoursSuivants(num) {
|
getJoursSuivants(count) {
|
||||||
let jours = [];
|
let jours = [];
|
||||||
let index = this.getCurrentDayIndex();
|
let indexDate = this.timestamp.indexDate;
|
||||||
for (let i = 0; i < num; i++) {
|
for (let i = 0; i < count; i++, indexDate++) {
|
||||||
jours[i] = { label: this.getDateFromIndex(index + i), index: index + i };
|
jours[i] = { label: RdDTimestamp.formatIndexDate(indexDate), index: indexDate };
|
||||||
}
|
}
|
||||||
return jours;
|
return jours;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async ajouterNombreAstral(index, showDice = SHOW_DICE) {
|
async ajouterNombreAstral(indexDate, showDice = SHOW_DICE) {
|
||||||
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: showDice, rollMode: "selfroll" });
|
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: showDice, rollMode: "selfroll" });
|
||||||
const dateFuture = this.getDateFromIndex(index);
|
const dateFuture = RdDTimestamp.formatIndexDate(indexDate);
|
||||||
if (showDice != HIDE_DICE) {
|
if (showDice != HIDE_DICE) {
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
whisper: ChatMessage.getWhisperRecipients("GM"),
|
whisper: ChatMessage.getWhisperRecipients("GM"),
|
||||||
@@ -278,20 +206,14 @@ export class RdDCalendrier extends Application {
|
|||||||
return {
|
return {
|
||||||
nombreAstral: nombreAstral,
|
nombreAstral: nombreAstral,
|
||||||
valeursFausses: [],
|
valeursFausses: [],
|
||||||
index: index
|
index: indexDate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getCurrentNombreAstral() {
|
|
||||||
let indexDate = this.getCurrentDayIndex();
|
|
||||||
return this.getNombreAstral(indexDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
resetNombreAstral() {
|
resetNombreAstral() {
|
||||||
this.listeNombreAstral = [];
|
this.listeNombreAstral = [];
|
||||||
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral);
|
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", []);
|
||||||
|
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
msg: "msg_reset_nombre_astral",
|
msg: "msg_reset_nombre_astral",
|
||||||
@@ -300,19 +222,27 @@ export class RdDCalendrier extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getNombreAstral(indexDate) {
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} indexDate la date pour laquelle obtenir le nombre astral. Si undefined, on prend la date du jour
|
||||||
|
* @returns le nombre astral pour la date, ou pour la date du jour si la date n'est pas fournie.
|
||||||
|
* Si aucun nombre astral n'est trouvé, retourne 0 (cas où l'on demanderait un nombre astral en dehors des 12 jours courant et à venir)
|
||||||
|
*/
|
||||||
|
getNombreAstral(indexDate = undefined) {
|
||||||
|
if (indexDate == undefined) {
|
||||||
|
indexDate = this.timestamp.indexDate;
|
||||||
|
}
|
||||||
const listNombreAstral = this.getListeNombreAstral();
|
const listNombreAstral = this.getListeNombreAstral();
|
||||||
let astralData = listNombreAstral.find((nombreAstral, i) => nombreAstral.index == indexDate);
|
let astralData = listNombreAstral.find((nombreAstral, i) => nombreAstral.index == indexDate);
|
||||||
return astralData?.nombreAstral;
|
return astralData?.nombreAstral ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async rebuildListeNombreAstral(showDice = HIDE_DICE) {
|
async rebuildListeNombreAstral(showDice = HIDE_DICE) {
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
let jourCourant = this.getCurrentDayIndex();
|
|
||||||
let newList = [];
|
let newList = [];
|
||||||
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
||||||
let dayIndex = jourCourant + i;
|
let dayIndex = this.timestamp.indexDate + i;
|
||||||
let na = this.listeNombreAstral.find(n => n.index == dayIndex);
|
let na = this.listeNombreAstral.find(n => n.index == dayIndex);
|
||||||
if (na) {
|
if (na) {
|
||||||
newList[i] = na;
|
newList[i] = na;
|
||||||
@@ -320,11 +250,20 @@ export class RdDCalendrier extends Application {
|
|||||||
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice);
|
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", newList);
|
|
||||||
this.listeNombreAstral = newList;
|
this.listeNombreAstral = newList;
|
||||||
|
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", newList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async setNewTimestamp(newTimestamp) {
|
||||||
|
game.actors.forEach(actor => actor.onTimeChanging(this.timestamp, newTimestamp));
|
||||||
|
RdDTimestamp.setWorldTime(newTimestamp);
|
||||||
|
this.timestamp = newTimestamp;
|
||||||
|
await this.rebuildListeNombreAstral();
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onCalendarButton(ev) {
|
async onCalendarButton(ev) {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
@@ -339,101 +278,43 @@ export class RdDCalendrier extends Application {
|
|||||||
this.updateDisplay();
|
this.updateDisplay();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
checkMaladie( periode) {
|
|
||||||
for (let actor of game.actors) {
|
|
||||||
if (actor.type == 'personnage') {
|
|
||||||
let maladies = actor.items.filter( item => (item.type == 'maladie' || (item.type == 'poison' && item.system.active) ) && item.system.periodicite.toLowerCase().includes(periode) );
|
|
||||||
for (let maladie of maladies) {
|
|
||||||
if ( maladie.system.identifie) {
|
|
||||||
ChatMessage.create({ content: `${actor.name} souffre de ${maladie.name} (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
|
|
||||||
} else {
|
|
||||||
ChatMessage.create({ content: `${actor.name} souffre d'un mal inconnu (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
|
|
||||||
}
|
|
||||||
let itemMaladie = actor.getObjet(maladie.id)
|
|
||||||
itemMaladie.postItem( 'gmroll');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async incrementTime(minutes = 0) {
|
async incrementTime(minutes = 0) {
|
||||||
this.calendrier.minutesRelative += minutes;
|
await this.setNewTimestamp(this.timestamp.addMinutes(minutes));
|
||||||
this.checkMaladie("round");
|
|
||||||
this.checkMaladie("minute");
|
|
||||||
if (this.calendrier.minutesRelative >= RDD_MINUTES_PAR_HEURES) {
|
|
||||||
this.calendrier.minutesRelative -= RDD_MINUTES_PAR_HEURES;
|
|
||||||
this.calendrier.heureRdD += 1;
|
|
||||||
this.checkMaladie("heure");
|
|
||||||
}
|
|
||||||
if (this.calendrier.heureRdD >= RDD_HEURES_PAR_JOUR) {
|
|
||||||
this.calendrier.heureRdD -= RDD_HEURES_PAR_JOUR;
|
|
||||||
await this.incrementerJour();
|
|
||||||
this.checkMaladie("heure");
|
|
||||||
this.checkMaladie("jour");
|
|
||||||
}
|
|
||||||
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier));
|
|
||||||
// Notification aux joueurs // TODO: replace with Hook on game settings update
|
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
|
||||||
msg: "msg_sync_time",
|
|
||||||
data: duplicate(this.calendrier)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async incrementerJour() {
|
async incrementerJour() {
|
||||||
const index = this.getCurrentDayIndex() + 1;
|
await this.setNewTimestamp(this.timestamp.nouveauJour());
|
||||||
this.calendrier = this.getCalendrier(index);
|
|
||||||
await this.rebuildListeNombreAstral();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
syncPlayerTime(calendrier) {
|
async positionnerHeure(heure) {
|
||||||
this.calendrier = duplicate(calendrier); // Local copy update
|
const indexDate = this.timestamp.indexDate;
|
||||||
this.updateDisplay();
|
const addDay = this.timestamp.heure < heure ? 0 : 1;
|
||||||
}
|
await this.setNewTimestamp(new RdDTimestamp({
|
||||||
|
indexDate: indexDate + addDay, indexHeure: 0
|
||||||
/* -------------------------------------------- */
|
})
|
||||||
async positionnerHeure(indexHeure) {
|
.addHeures(heure))
|
||||||
if (indexHeure <= this.calendrier.heureRdD) {
|
|
||||||
await this.incrementerJour();
|
|
||||||
}
|
|
||||||
this.calendrier.heureRdD = indexHeure;
|
|
||||||
this.calendrier.minutesRelative = 0;
|
|
||||||
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
fillCalendrierData(formData = {}) {
|
fillCalendrierData(formData = {}) {
|
||||||
const mois = RdDCalendrier.getDefSigne(this.calendrier.moisRdD);
|
mergeObject(formData, this.timestamp.toCalendrier());
|
||||||
const heure = RdDCalendrier.getDefSigne(this.calendrier.heureRdD);
|
|
||||||
console.log('fillCalendrierData', this.calendrier, mois, heure);
|
|
||||||
|
|
||||||
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.annee = this.calendrier.annee;
|
|
||||||
formData.iconMois = dossierIconesHeures + mois.icon;
|
|
||||||
formData.nomHeure = heure.label;
|
|
||||||
formData.iconHeure = dossierIconesHeures + heure.icon;
|
|
||||||
formData.nomSaison = saisonsDef[mois.saison].label;
|
|
||||||
formData.heureRdD = this.calendrier.heureRdD;
|
|
||||||
formData.minutesRelative = this.calendrier.minutesRelative;
|
|
||||||
formData.isGM = game.user.isGM;
|
formData.isGM = game.user.isGM;
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getLectureAstrologieDifficulte(dateIndex) {
|
getLectureAstrologieDifficulte(dateIndex) {
|
||||||
let indexNow = this.getCurrentDayIndex();
|
let indexNow = this.timestamp.indexDate;
|
||||||
let diffDay = dateIndex - indexNow;
|
let diffDay = dateIndex - indexNow;
|
||||||
return - Math.floor(diffDay / 2);
|
return - Math.floor(diffDay / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async requestNombreAstral(request) {
|
async requestNombreAstral(request) {
|
||||||
|
const actor = game.actors.get(request.id);
|
||||||
if (Misc.isUniqueConnectedGM()) { // Only once
|
if (Misc.isUniqueConnectedGM()) { // Only once
|
||||||
console.log(request);
|
console.log(request);
|
||||||
let jourDiff = this.getLectureAstrologieDifficulte(request.date);
|
let jourDiff = this.getLectureAstrologieDifficulte(request.date);
|
||||||
@@ -445,18 +326,26 @@ export class RdDCalendrier extends Application {
|
|||||||
rollMode: "blindroll"
|
rollMode: "blindroll"
|
||||||
};
|
};
|
||||||
await RdDResolutionTable.rollData(rollData);
|
await RdDResolutionTable.rollData(rollData);
|
||||||
let nbAstral = this.getNombreAstral(request.date);
|
|
||||||
request.rolled = rollData.rolled;
|
request.rolled = rollData.rolled;
|
||||||
request.isValid = true;
|
request.isValid = request.rolled.isSuccess;
|
||||||
if (!request.rolled.isSuccess) {
|
request.nbAstral = this.getNombreAstral(request.date);
|
||||||
request.isValid = false;
|
|
||||||
nbAstral = await RdDDice.rollTotal("1dhr" + nbAstral, { rollMode: "selfroll" });
|
if (request.rolled.isSuccess) {
|
||||||
// Mise à jour des nombres astraux du joueur
|
if (request.rolled.isPart) {
|
||||||
let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == request.date);
|
// Gestion expérience (si existante)
|
||||||
astralData.valeursFausses.push({ actorId: request.id, nombreAstral: nbAstral });
|
request.competence = actor.getCompetence("astrologie")
|
||||||
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral);
|
request.selectedCarac = actor.system.carac["vue"];
|
||||||
|
actor.appliquerAjoutExperience(request, 'hide');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
request.nbAstral = nbAstral;
|
else {
|
||||||
|
request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, {
|
||||||
|
rollMode: "selfroll", showDice: HIDE_DICE
|
||||||
|
});
|
||||||
|
// Mise à jour des nombres astraux du joueur
|
||||||
|
this.addNbAstralIncorect(request.id, request.date, request.nbAstral);
|
||||||
|
}
|
||||||
|
|
||||||
if (Misc.getActiveUser(request.userId)?.isGM) {
|
if (Misc.getActiveUser(request.userId)?.isGM) {
|
||||||
RdDUtility.responseNombreAstral(request);
|
RdDUtility.responseNombreAstral(request);
|
||||||
} else {
|
} else {
|
||||||
@@ -468,57 +357,21 @@ export class RdDCalendrier extends Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
addNbAstralIncorect(actorId, date, nbAstral) {
|
||||||
findHeure(heure) {
|
let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == date);
|
||||||
heure = Grammar.toLowerCaseNoAccentNoSpace(heure);
|
astralData.valeursFausses.push({ actorId: actorId, nombreAstral: nbAstral });
|
||||||
let parHeureOuLabel = Object.values(heuresDef).filter(it => (it.heure + 1) == parseInt(heure) || Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure);
|
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral);
|
||||||
if (parHeureOuLabel.length == 1) {
|
|
||||||
return parHeureOuLabel[0];
|
|
||||||
}
|
|
||||||
let parLabelPartiel = Object.values(heuresDef).filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label).includes(heure));
|
|
||||||
if (parLabelPartiel.length > 0) {
|
|
||||||
parLabelPartiel.sort(Misc.ascending(h => h.label.length));
|
|
||||||
return parLabelPartiel[0];
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getHeureNumber( hNum) {
|
|
||||||
let heure = Object.values(heuresDef).find(it => (it.heure) == hNum);
|
|
||||||
return heure
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
static ecartHeureChance(heureNaissance, nombreAstral, heure) {
|
||||||
getHeuresChanceMalchance(heureNaissance) {
|
return (heureNaissance + nombreAstral - heure) % RDD_HEURES_PAR_JOUR;
|
||||||
let heuresChancesMalchances = [];
|
|
||||||
let defHeure = this.findHeure(heureNaissance);
|
|
||||||
if (defHeure) {
|
|
||||||
let hn = defHeure.heure;
|
|
||||||
let chiffreAstral = this.getCurrentNombreAstral() ?? 0;
|
|
||||||
heuresChancesMalchances[0] = { value : "+4", heures: [this.getHeureNumber((hn + chiffreAstral) % RDD_HEURES_PAR_JOUR).label]};
|
|
||||||
heuresChancesMalchances[1] = { value : "+2", heures: [this.getHeureNumber((hn + chiffreAstral+4) % RDD_HEURES_PAR_JOUR).label,
|
|
||||||
this.getHeureNumber((hn + chiffreAstral + 8) % RDD_HEURES_PAR_JOUR).label ] };
|
|
||||||
heuresChancesMalchances[2] = { value : "-4", heures: [this.getHeureNumber((hn + chiffreAstral+6) % RDD_HEURES_PAR_JOUR).label]};
|
|
||||||
heuresChancesMalchances[3] = { value : "-2", heures: [this.getHeureNumber((hn + chiffreAstral+3) % RDD_HEURES_PAR_JOUR).label,
|
|
||||||
this.getHeureNumber((hn + chiffreAstral + 9) % RDD_HEURES_PAR_JOUR).label ]};
|
|
||||||
}
|
|
||||||
return heuresChancesMalchances;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getAjustementAstrologique(heureNaissance, name = undefined) {
|
getAjustementAstrologique(heureNaissance, name = undefined) {
|
||||||
let defHeure = this.findHeure(heureNaissance);
|
let defHeure = RdDTimestamp.findHeure(heureNaissance);
|
||||||
if (defHeure) {
|
if (defHeure) {
|
||||||
let hn = defHeure.heure;
|
return RdDCalendrier.ajustementAstrologiqueHeure(defHeure.heure, this.getNombreAstral(), this.timestamp.heure);
|
||||||
let chiffreAstral = this.getCurrentNombreAstral() ?? 0;
|
|
||||||
let heureCourante = this.calendrier.heureRdD;
|
|
||||||
let ecartChance = (hn + chiffreAstral - heureCourante) % RDD_HEURES_PAR_JOUR;
|
|
||||||
switch (ecartChance) {
|
|
||||||
case 0: return 4;
|
|
||||||
case 4: case 8: return 2;
|
|
||||||
case 6: return -4;
|
|
||||||
case 3: case 9: return -2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (name) {
|
else if (name) {
|
||||||
ui.notifications.warn(name + " n'a pas d'heure de naissance, ou elle est incorrecte : " + heureNaissance);
|
ui.notifications.warn(name + " n'a pas d'heure de naissance, ou elle est incorrecte : " + heureNaissance);
|
||||||
@@ -529,12 +382,20 @@ export class RdDCalendrier extends Application {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ajustementAstrologiqueHeure(hn, nbAstral, heure) {
|
||||||
|
switch (RdDCalendrier.ecartHeureChance(hn, nbAstral, heure)) {
|
||||||
|
case 0: return 4;
|
||||||
|
case 4: case 8: return 2;
|
||||||
|
case 6: return -4;
|
||||||
|
case 3: case 9: return -2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getData() {
|
getData() {
|
||||||
let formData = super.getData();
|
let formData = super.getData();
|
||||||
|
|
||||||
this.fillCalendrierData(formData);
|
this.fillCalendrierData(formData);
|
||||||
|
|
||||||
this.setPos(this.calendrierPos);
|
this.setPos(this.calendrierPos);
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
@@ -563,50 +424,40 @@ export class RdDCalendrier extends Application {
|
|||||||
updateDisplay() {
|
updateDisplay() {
|
||||||
let calendrier = this.fillCalendrierData();
|
let calendrier = this.fillCalendrierData();
|
||||||
// Rebuild text du calendrier
|
// Rebuild text du calendrier
|
||||||
let dateHTML = `${calendrier.jourMois} ${calendrier.nomMois} ${calendrier.annee} (${calendrier.nomSaison})`
|
let dateHTML = `${calendrier.jourDuMois} ${calendrier.mois.label} (${calendrier.mois.saison}) de l'année ${calendrier.annee}`
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
dateHTML = dateHTML + " - NA: " + (this.getCurrentNombreAstral() ?? "indéterminé");
|
dateHTML = dateHTML + "<br>Nombre Astral: " + (this.getNombreAstral() ?? "?");
|
||||||
}
|
}
|
||||||
for (let handle of document.getElementsByClassName("calendar-date-rdd")) {
|
for (let handle of document.getElementsByClassName("calendar-date-rdd")) {
|
||||||
handle.innerHTML = dateHTML;
|
handle.innerHTML = dateHTML;
|
||||||
}
|
}
|
||||||
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
|
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
|
||||||
heure.innerHTML = calendrier.nomHeure;
|
heure.innerHTML = calendrier.heure.label;
|
||||||
}
|
}
|
||||||
for (const minute of document.getElementsByClassName("calendar-time-disp")) {
|
for (const minute of document.getElementsByClassName("calendar-time-disp")) {
|
||||||
minute.innerHTML = `${calendrier.minutesRelative} minutes`;
|
minute.innerHTML = `${calendrier.minute} minutes`;
|
||||||
}
|
}
|
||||||
for (const heureImg of document.getElementsByClassName("calendar-heure-img")) {
|
for (const heureImg of document.getElementsByClassName("calendar-heure-img")) {
|
||||||
heureImg.src = calendrier.iconHeure;
|
heureImg.src = calendrier.heure.icon;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async saveEditeur(calendrierData) {
|
async saveEditeur(calendrierData) {
|
||||||
this.calendrier.minutesRelative = Number(calendrierData.minutesRelative);
|
const newTimestamp = RdDTimestamp.timestamp(
|
||||||
this.calendrier.jour = Number(calendrierData.jourMois) - 1;
|
Number.parseInt(calendrierData.annee),
|
||||||
this.calendrier.moisRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.moisKey);
|
calendrierData.mois.heure,
|
||||||
this.calendrier.annee = Number(calendrierData.annee);
|
Number.parseInt(calendrierData.jourMois),
|
||||||
this.calendrier.heureRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.heureKey);
|
calendrierData.heure.heure,
|
||||||
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier));
|
Number.parseInt(calendrierData.minutes)
|
||||||
|
);
|
||||||
await this.rebuildListeNombreAstral();
|
await this.setNewTimestamp(newTimestamp);
|
||||||
|
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
|
||||||
msg: "msg_sync_time",
|
|
||||||
data: duplicate(this.calendrier)
|
|
||||||
});
|
|
||||||
|
|
||||||
this.updateDisplay();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async showCalendarEditor() {
|
async showCalendarEditor() {
|
||||||
let calendrierData = duplicate(this.fillCalendrierData());
|
let calendrierData = this.fillCalendrierData();
|
||||||
if (this.editeur == undefined) {
|
if (this.editeur == undefined) {
|
||||||
calendrierData.jourMoisOptions = RdDCalendrier.buildJoursMois();
|
|
||||||
calendrierData.heuresOptions = [0, 1];
|
|
||||||
calendrierData.minutesOptions = Array(RDD_MINUTES_PAR_HEURES).fill().map((item, index) => 0 + index);
|
|
||||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', calendrierData);
|
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', calendrierData);
|
||||||
this.editeur = new RdDCalendrierEditeur(html, this, calendrierData)
|
this.editeur = new RdDCalendrierEditeur(html, this, calendrierData)
|
||||||
}
|
}
|
||||||
@@ -614,33 +465,38 @@ export class RdDCalendrier extends Application {
|
|||||||
this.editeur.render(true);
|
this.editeur.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static buildJoursMois() {
|
static buildJoursMois() { return JOURS_DU_MOIS; }
|
||||||
return Array(RDD_JOUR_PAR_MOIS).fill().map((item, index) => 1 + index);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async showAstrologieEditor() {
|
async showAstrologieEditor() {
|
||||||
let calendrierData = duplicate(this.fillCalendrierData());
|
const calendrierData = duplicate(this.fillCalendrierData());
|
||||||
let astrologieArray = [];
|
|
||||||
this.listeNombreAstral = this.listeNombreAstral || [];
|
this.listeNombreAstral = this.listeNombreAstral || [];
|
||||||
for (let astralData of this.listeNombreAstral) {
|
|
||||||
astralData.humanDate = this.getDateFromIndex(astralData.index);
|
calendrierData.astrologieData = this.listeNombreAstral.map(astro => {
|
||||||
for (let vf of astralData.valeursFausses) {
|
const timestamp = new RdDTimestamp({ indexDate: astro.index });
|
||||||
|
astro.date = { mois: timestamp.mois, jour: timestamp.jour + 1 }
|
||||||
|
for (let vf of astro.valeursFausses) {
|
||||||
let actor = game.actors.get(vf.actorId);
|
let actor = game.actors.get(vf.actorId);
|
||||||
vf.actorName = (actor) ? actor.name : "Inconnu";
|
vf.actorName = (actor) ? actor.name : "Inconnu";
|
||||||
}
|
}
|
||||||
astrologieArray.push(duplicate(astralData));
|
return astro;
|
||||||
}
|
});
|
||||||
let heuresParActeur = {};
|
|
||||||
for (let actor of game.actors) {
|
const nbAstral = this.getNombreAstral()
|
||||||
let heureNaissance = actor.getHeureNaissance();
|
calendrierData.heures = Array.from(Array(RDD_HEURES_PAR_JOUR).keys());
|
||||||
if ( heureNaissance) {
|
calendrierData.ajustementsActeur = game.actors.filter(it => it.isPersonnage() && it.hasPlayerOwner).map(actor => {
|
||||||
heuresParActeur[actor.name] = this.getHeuresChanceMalchance(heureNaissance);
|
return {
|
||||||
}
|
actor,
|
||||||
}
|
ajustements: calendrierData.heures.map(heure => {
|
||||||
//console.log("ASTRO", astrologieArray);
|
const hn = RdDTimestamp.findHeure(actor.getHeureNaissance())?.heure;
|
||||||
calendrierData.astrologieData = astrologieArray;
|
return {
|
||||||
calendrierData.heuresParActeur = heuresParActeur;
|
heure,
|
||||||
|
ajustement: RdDCalendrier.ajustementAstrologiqueHeure(hn, nbAstral, heure)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-astrologie-template.html', calendrierData);
|
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-astrologie-template.html', calendrierData);
|
||||||
let astrologieEditeur = new RdDAstrologieEditeur(html, this, calendrierData)
|
let astrologieEditeur = new RdDAstrologieEditeur(html, this, calendrierData)
|
||||||
astrologieEditeur.updateData(calendrierData);
|
astrologieEditeur.updateData(calendrierData);
|
||||||
|
|||||||
@@ -39,9 +39,10 @@ const tableCaracDerivee = {
|
|||||||
|
|
||||||
export class RdDCarac {
|
export class RdDCarac {
|
||||||
|
|
||||||
static isAgiliteOuDerivee(selectedCarac) {
|
static isAgiliteOuDerobee(selectedCarac) {
|
||||||
return selectedCarac?.label.match(/(Agilité|Dérobée)/);
|
return selectedCarac?.label.match(/(Agilité|Dérobée)/);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isVolonte(selectedCarac) {
|
static isVolonte(selectedCarac) {
|
||||||
return selectedCarac?.label == 'Volonté';
|
return selectedCarac?.label == 'Volonté';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
import { ENTITE_BLURETTE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
import { DialogSelectTarget } from "./dialog-select-target.js";
|
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { RdDItemArme } from "./item-arme.js";
|
import { RdDItemArme } from "./item-arme.js";
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
@@ -111,10 +110,10 @@ export class RdDCombatManager extends Combat {
|
|||||||
if (!roll.total) {
|
if (!roll.total) {
|
||||||
roll.evaluate({ async: false });
|
roll.evaluate({ async: false });
|
||||||
}
|
}
|
||||||
if (roll.total <= 0) roll.total = 0.00;
|
const total = Math.max(roll.total, 0.00);
|
||||||
console.log("Compute init for", rollFormula, roll.total, combatant);
|
console.log("Compute init for", rollFormula, roll, total, combatant);
|
||||||
let id = combatant._id || combatant.id;
|
let id = combatant._id || combatant.id;
|
||||||
await this.updateEmbeddedDocuments("Combatant", [{ _id: id, initiative: roll.total }]);
|
await this.updateEmbeddedDocuments("Combatant", [{ _id: id, initiative: total }]);
|
||||||
|
|
||||||
// Send a chat message
|
// Send a chat message
|
||||||
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
|
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
|
||||||
@@ -162,7 +161,6 @@ export class RdDCombatManager extends Combat {
|
|||||||
if (arme.system.unemain && arme.system.deuxmains && !dommages.includes("/")) {
|
if (arme.system.unemain && arme.system.deuxmains && !dommages.includes("/")) {
|
||||||
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
|
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
|
||||||
}
|
}
|
||||||
console.log(">>>>", arme)
|
|
||||||
if ((arme.system.unemain && arme.system.competence) ||
|
if ((arme.system.unemain && arme.system.competence) ||
|
||||||
(arme.system.competence.toLowerCase().includes("corps à corps"))) {
|
(arme.system.competence.toLowerCase().includes("corps à corps"))) {
|
||||||
actions.push(RdDCombatManager.$prepareAttaqueArme({
|
actions.push(RdDCombatManager.$prepareAttaqueArme({
|
||||||
@@ -248,7 +246,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
}
|
}
|
||||||
if (actor.isCreatureEntite()) {
|
if (actor.isCreatureEntite()) {
|
||||||
actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']));
|
actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']));
|
||||||
} else {
|
} else if (actor.isPersonnage()) {
|
||||||
// Recupération des items 'arme'
|
// Recupération des items 'arme'
|
||||||
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
|
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
|
||||||
//.concat(RdDItemArme.empoignade())
|
//.concat(RdDItemArme.empoignade())
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
|||||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { CompendiumTableHelpers } from "./settings/system-compendiums.js";
|
import { CompendiumTableHelpers } from "./settings/system-compendiums.js";
|
||||||
|
import { FenetreRechercheTirage } from "./tirage/fenetre-recherche-tirage.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
|
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
|
||||||
@@ -23,6 +24,7 @@ export class RdDCommands {
|
|||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
const rddCommands = new RdDCommands();
|
const rddCommands = new RdDCommands();
|
||||||
|
game.system.rdd.commands = rddCommands;
|
||||||
|
|
||||||
Hooks.on("chatMessage", (html, content, msg) => {
|
Hooks.on("chatMessage", (html, content, msg) => {
|
||||||
if (content[0] == '/') {
|
if (content[0] == '/') {
|
||||||
@@ -35,7 +37,6 @@ export class RdDCommands {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
game.system.rdd.commands = rddCommands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -63,7 +64,6 @@ export class RdDCommands {
|
|||||||
<br><strong>/table rencontre deso</strong> affiche la table des rencontres en Désolation
|
<br><strong>/table rencontre deso</strong> affiche la table des rencontres en Désolation
|
||||||
<br><strong>/table rencontre mauvaise</strong> affiche la table des mauvaises rencontres`
|
<br><strong>/table rencontre mauvaise</strong> affiche la table des mauvaises rencontres`
|
||||||
});
|
});
|
||||||
this.registerCommand({ path: ["/table", "milieu"], func: (content, msg, params) => this.tableMilieu(msg, params, 'liste'), descr: "Affiche la table des ressource naturelles pour un milieu donné" });
|
|
||||||
|
|
||||||
this.registerCommand({ path: ["/tirer", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('chat'), descr: "Tire une compétence au hasard" });
|
this.registerCommand({ path: ["/tirer", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('chat'), descr: "Tire une compétence au hasard" });
|
||||||
this.registerCommand({ path: ["/tirer", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('chat'), descr: "Tire une Queue de Dragon" });
|
this.registerCommand({ path: ["/tirer", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('chat'), descr: "Tire une Queue de Dragon" });
|
||||||
@@ -75,7 +75,7 @@ export class RdDCommands {
|
|||||||
this.registerCommand({ path: ["/tirer", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe('chat'), descr: "Tire une Idée fixe" });
|
this.registerCommand({ path: ["/tirer", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe('chat'), descr: "Tire une Idée fixe" });
|
||||||
this.registerCommand({ path: ["/tirer", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('chat'), descr: "Tire un Désir Lancinant" });
|
this.registerCommand({ path: ["/tirer", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('chat'), descr: "Tire un Désir Lancinant" });
|
||||||
this.registerCommand({ path: ["/tirer", "rencontre"], func: (content, msg, params) => this.getRencontreTMR(params), descr: `Détermine une rencontre dans les TMR (synonyme de "/tmrr")` });
|
this.registerCommand({ path: ["/tirer", "rencontre"], func: (content, msg, params) => this.getRencontreTMR(params), descr: `Détermine une rencontre dans les TMR (synonyme de "/tmrr")` });
|
||||||
this.registerCommand({ path: ["/tirer", "milieu"], func: (content, msg, params) => this.tableMilieu(msg, params, 'chat'), descr: "Effectue un tirage dans la table desressource naturelles pour un milieu donné" });
|
this.registerCommand({ path: ["/tirage"], func: (content, msg, params) => this.tirage(), descr: "Ouvre la fenêtre de recherche et tirage" });
|
||||||
|
|
||||||
this.registerCommand({ path: ["/meteo"], func: (content, msg, params) => this.getMeteo(msg, params), descr: "Propose une météo marine" });
|
this.registerCommand({ path: ["/meteo"], func: (content, msg, params) => this.getMeteo(msg, params), descr: "Propose une météo marine" });
|
||||||
this.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
|
this.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
|
||||||
@@ -206,16 +206,16 @@ export class RdDCommands {
|
|||||||
let rollMode = game.settings.get("core", "rollMode");
|
let rollMode = game.settings.get("core", "rollMode");
|
||||||
if (["gmroll", "blindroll"].includes(rollMode)) {
|
if (["gmroll", "blindroll"].includes(rollMode)) {
|
||||||
msg["whisper"] = ChatMessage.getWhisperRecipients("GM");
|
msg["whisper"] = ChatMessage.getWhisperRecipients("GM");
|
||||||
}
|
}
|
||||||
if (rollMode === "blindroll"){
|
if (rollMode === "blindroll") {
|
||||||
msg["blind"] = true;
|
msg["blind"] = true;
|
||||||
}
|
}
|
||||||
msg["type"] = 0;
|
msg["type"] = 0;
|
||||||
|
|
||||||
if (!this.commandsTable) {
|
if (!this.commandsTable) {
|
||||||
this._registerCommands();
|
this._registerCommands();
|
||||||
}
|
}
|
||||||
|
|
||||||
let command = commandLine[0].toLowerCase();
|
let command = commandLine[0].toLowerCase();
|
||||||
if (this._isCommandHandled(command)) {
|
if (this._isCommandHandled(command)) {
|
||||||
let params = commandLine.slice(1);
|
let params = commandLine.slice(1);
|
||||||
@@ -225,7 +225,7 @@ export class RdDCommands {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isCommandHandled(command){
|
_isCommandHandled(command) {
|
||||||
return this.commandsTable[command] != undefined;
|
return this.commandsTable[command] != undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -254,10 +254,7 @@ export class RdDCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async help(msg) {
|
async help(msg, table = undefined) {
|
||||||
this.help(msg, undefined);
|
|
||||||
}
|
|
||||||
async help(msg, table) {
|
|
||||||
let commands = []
|
let commands = []
|
||||||
this._buildSubTableHelp(commands, table ?? this.commandsTable);
|
this._buildSubTableHelp(commands, table ?? this.commandsTable);
|
||||||
|
|
||||||
@@ -331,7 +328,7 @@ export class RdDCommands {
|
|||||||
diff = 0;
|
diff = 0;
|
||||||
}
|
}
|
||||||
const caracName = params[0];
|
const caracName = params[0];
|
||||||
let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : undefined;
|
let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : { name: undefined };
|
||||||
if (competence) {
|
if (competence) {
|
||||||
for (let actor of actors) {
|
for (let actor of actors) {
|
||||||
await actor.rollCaracCompetence(caracName, competence.name, diff);
|
await actor.rollCaracCompetence(caracName, competence.name, diff);
|
||||||
@@ -398,32 +395,6 @@ export class RdDCommands {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async tableMilieu(msg, params, toChat) {
|
|
||||||
if (params && params.length > 0) {
|
|
||||||
const search = Misc.join(params, ' ');
|
|
||||||
const milieux = await game.system.rdd.environnement.findEnvironnementsLike(search);
|
|
||||||
if (milieux.length == 0) {
|
|
||||||
const tous = Object.values(await game.system.rdd.environnement.milieux());
|
|
||||||
return RdDCommands._chatAnswer(msg, `<strong>Aucun milieu correspondant à '${search}'.</strong>
|
|
||||||
<br>Milieux disponibles:
|
|
||||||
<br><ul class="chat-list"><li>${tous.reduce(Misc.joining('</li><li>'))}</li></ul>`);
|
|
||||||
}
|
|
||||||
if (milieux.length > 1) {
|
|
||||||
ui.notifications.warn(`<strong>Plusieurs milieux correspondent à '${search}'</strong>:
|
|
||||||
<br><ul class="chat-list"><li>${milieux.reduce(Misc.joining('</li><li>'))}</li></ul>`);
|
|
||||||
}
|
|
||||||
const tableName = `ressources en ${milieux.reduce(Misc.joining(', '))}`;
|
|
||||||
if (toChat == 'liste') {
|
|
||||||
return await game.system.rdd.environnement.searchToChatMessage(milieux, tableName);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const row = await game.system.rdd.environnement.getRandom(milieux, tableName);
|
|
||||||
await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getCoutXpComp(msg, params) {
|
getCoutXpComp(msg, params) {
|
||||||
if (params && (params.length == 1 || params.length == 2)) {
|
if (params && (params.length == 1 || params.length == 2)) {
|
||||||
@@ -448,17 +419,27 @@ export class RdDCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async creerSignesDraconiques() {
|
async creerSignesDraconiques() {
|
||||||
DialogCreateSigneDraconique.createSigneForActors();
|
if (game.user.isGM) {
|
||||||
|
DialogCreateSigneDraconique.createSigneForActors();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.warn("Seul le MJ est autorisé à utiliser la commande /signe");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async supprimerSignesDraconiquesEphemeres() {
|
async supprimerSignesDraconiquesEphemeres() {
|
||||||
game.actors.forEach(actor => {
|
if (game.user.isGM) {
|
||||||
const ephemeres = actor.items.filter(item => item.type = 'signedraconique' && item.system.ephemere);
|
game.actors.forEach(actor => {
|
||||||
if (ephemeres.length > 0) {
|
const ephemeres = actor.items.filter(item => item.type = 'signedraconique' && item.system.ephemere);
|
||||||
actor.deleteEmbeddedDocuments("Item", ephemeres.map(item => item.id));
|
if (ephemeres.length > 0) {
|
||||||
}
|
actor.deleteEmbeddedDocuments("Item", ephemeres.map(item => item.id));
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.warn("Seul le MJ est autorisé à utiliser la commande /signe");
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,5 +482,8 @@ export class RdDCommands {
|
|||||||
return await RdDMeteo.getMeteo();
|
return await RdDMeteo.getMeteo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async tirage() {
|
||||||
|
FenetreRechercheTirage.create();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
import { SYSTEM_RDD } from "./constants.js";
|
||||||
|
|
||||||
export class RddCompendiumOrganiser {
|
export class RdDCompendiumOrganiser {
|
||||||
static init() {
|
static init() {
|
||||||
Hooks.on('renderCompendium', async (pack, html, compendiumData) => RddCompendiumOrganiser.onRenderCompendium(pack, html, compendiumData))
|
Hooks.on('renderCompendium', async (pack, html, compendiumData) => RdDCompendiumOrganiser.onRenderCompendium(pack, html, compendiumData))
|
||||||
}
|
}
|
||||||
|
|
||||||
static async onRenderCompendium(compendium, html, compendiumData) {
|
static async onRenderCompendium(compendium, html, compendiumData) {
|
||||||
@@ -10,14 +10,14 @@ export class RddCompendiumOrganiser {
|
|||||||
const pack = compendium.collection
|
const pack = compendium.collection
|
||||||
if (pack.metadata.system === SYSTEM_RDD) {
|
if (pack.metadata.system === SYSTEM_RDD) {
|
||||||
html.find('.directory-item').each((i, element) => {
|
html.find('.directory-item').each((i, element) => {
|
||||||
RddCompendiumOrganiser.setEntityTypeName(pack, element);
|
RdDCompendiumOrganiser.setEntityTypeName(pack, element);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async setEntityTypeName(pack, element) {
|
static async setEntityTypeName(pack, element) {
|
||||||
const label = RddCompendiumOrganiser.getEntityTypeLabel(await pack.getDocument(element.dataset.documentId));
|
const label = RdDCompendiumOrganiser.getEntityTypeLabel(await pack.getDocument(element.dataset.documentId));
|
||||||
RddCompendiumOrganiser.insertEntityType(element, label);
|
RdDCompendiumOrganiser.insertEntityType(element, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
static insertEntityType(element, label) {
|
static insertEntityType(element, label) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { RdDUtility } from "./rdd-utility.js";
|
|
||||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
|
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDHerbes extends Item {
|
export class RdDHerbes extends Item {
|
||||||
@@ -29,7 +28,7 @@ export class RdDHerbes extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async updatePotionData(formData) {
|
static async addPotionFormData(formData) {
|
||||||
formData.isSoins = formData.system.categorie.includes('Soin');
|
formData.isSoins = formData.system.categorie.includes('Soin');
|
||||||
formData.isRepos = formData.system.categorie.includes('Repos');
|
formData.isRepos = formData.system.categorie.includes('Repos');
|
||||||
if (formData.isSoins) {
|
if (formData.isSoins) {
|
||||||
@@ -40,9 +39,8 @@ export class RdDHerbes extends Item {
|
|||||||
}
|
}
|
||||||
formData.herbesSoins = RdDHerbes.buildHerbesList(this.herbesSoins, 12);
|
formData.herbesSoins = RdDHerbes.buildHerbesList(this.herbesSoins, 12);
|
||||||
formData.herbesRepos = RdDHerbes.buildHerbesList(this.herbesRepos, 7);
|
formData.herbesRepos = RdDHerbes.buildHerbesList(this.herbesRepos, 7);
|
||||||
formData.jourMoisOptions = RdDCalendrier.buildJoursMois();
|
formData.dateActuelle = game.system.rdd.calendrier.dateCourante();
|
||||||
formData.dateActuelle = game.system.rdd.calendrier.getDateFromIndex();
|
formData.enchantement = RdDTimestamp.splitIndexDate(formData.system.prdate);
|
||||||
formData.splitDate = game.system.rdd.calendrier.getDayMonthFromIndex(formData.system.prdate);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { Misc } from "./misc.js";
|
|
||||||
|
|
||||||
export class RdDHotbar {
|
export class RdDHotbar {
|
||||||
|
|
||||||
|
|||||||
@@ -1,345 +1,348 @@
|
|||||||
/**
|
|
||||||
* RdD system
|
|
||||||
* Author: LeRatierBretonnien
|
|
||||||
* Software License: GNU GPLv3
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
// Import Modules
|
|
||||||
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
import { RdDActor } from "./actor.js";
|
import { Migrations } from './migrations.js';
|
||||||
import { RdDItemSheet } from "./item-sheet.js";
|
|
||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
|
||||||
import { RdDActorCreatureSheet } from "./actor-creature-sheet.js";
|
|
||||||
import { RdDActorVehiculeSheet } from "./actor-vehicule-sheet.js";
|
|
||||||
import { RdDActorEntiteSheet } from "./actor-entite-sheet.js";
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
import { RdDCalendrier } from "./rdd-calendrier.js";
|
||||||
|
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||||
|
import { DialogChronologie } from "./dialog-chronologie.js";
|
||||||
|
|
||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
import { RdDTokenHud } from "./rdd-token-hud.js";
|
import { RdDTokenHud } from "./rdd-token-hud.js";
|
||||||
import { RdDCommands } from "./rdd-commands.js";
|
import { RdDCommands } from "./rdd-commands.js";
|
||||||
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
|
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
|
||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { StatusEffects } from "./settings/status-effects.js";
|
import { StatusEffects } from "./settings/status-effects.js";
|
||||||
import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js";
|
import { RdDCompendiumOrganiser } from "./rdd-compendium-organiser.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||||
import { RdDHotbar } from "./rdd-hotbar-drop.js"
|
import { RdDHotbar } from "./rdd-hotbar-drop.js"
|
||||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||||
import { RdDHerbes } from "./rdd-herbes.js";
|
import { RdDHerbes } from "./rdd-herbes.js";
|
||||||
import { RdDItem } from "./item.js";
|
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { RdDPossession } from "./rdd-possession.js";
|
import { RdDPossession } from "./rdd-possession.js";
|
||||||
import { RdDSigneDraconiqueItemSheet } from "./item-signedraconique-sheet.js";
|
|
||||||
import { Misc } from "./misc.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 { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
import { RdDRencontreItemSheet } from "./item-rencontre-sheet.js";
|
|
||||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
|
||||||
import { RdDHerbeItemSheet } from "./item-herbe-sheet.js";
|
|
||||||
import { Environnement } from "./environnement.js";
|
import { Environnement } from "./environnement.js";
|
||||||
import { RdDIngredientItemSheet } from "./item-ingredient-sheet.js";
|
|
||||||
import { RdDFauneItemSheet } from "./item-faune-sheet.js";
|
|
||||||
import { RdDConteneurItemSheet } from "./item-conteneur-sheet.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
import { RdDActor } from "./actor.js";
|
||||||
/* Foundry VTT Initialization */
|
import { RdDBaseActor } from "./actor/base-actor.js";
|
||||||
/* -------------------------------------------- */
|
import { RdDCommerce } from "./actor/commerce.js";
|
||||||
|
import { RdDActorSheet } from "./actor-sheet.js";
|
||||||
|
import { RdDCommerceSheet } from "./actor/commerce-sheet.js";
|
||||||
|
import { RdDActorCreatureSheet } from "./actor-creature-sheet.js";
|
||||||
|
import { RdDActorVehiculeSheet } from "./actor-vehicule-sheet.js";
|
||||||
|
import { RdDActorEntiteSheet } from "./actor-entite-sheet.js";
|
||||||
|
|
||||||
|
import { RdDItem } from "./item.js";
|
||||||
|
import { RdDItemService } from "./item/service.js";
|
||||||
|
import { RdDItemMaladie } from "./item/maladie.js";
|
||||||
|
import { RdDItemPoison } from "./item/poison.js";
|
||||||
|
import { RdDItemSigneDraconique } from "./item/signedraconique.js";
|
||||||
|
import { RdDItemQueue } from "./item/queue.js";
|
||||||
|
import { RdDItemOmbre } from "./item/ombre.js";
|
||||||
|
import { RdDItemSouffle } from "./item/souffle.js";
|
||||||
|
import { RdDRencontre } from "./item/rencontre.js";
|
||||||
|
|
||||||
|
import { RdDItemSheet } from "./item-sheet.js";
|
||||||
|
import { RdDServiceItemSheet } from "./item/sheet-service.js";
|
||||||
|
import { RdDRencontreItemSheet } from "./item/sheet-rencontre.js";
|
||||||
|
import { RdDHerbeItemSheet } from "./item/sheet-herbe.js";
|
||||||
|
import { RdDPlanteItemSheet } from "./item/sheet-plante.js";
|
||||||
|
import { RdDIngredientItemSheet } from "./item/sheet-ingredient.js";
|
||||||
|
import { RdDFauneItemSheet } from "./item/sheet-faune.js";
|
||||||
|
import { RdDConteneurItemSheet } from "./item/sheet-conteneur.js";
|
||||||
|
import { RdDSigneDraconiqueItemSheet } from "./item/sheet-signedraconique.js";
|
||||||
|
import { RdDItemInventaireSheet } from "./item/sheet-base-inventaire.js";
|
||||||
|
|
||||||
/************************************************************************************/
|
/**
|
||||||
Hooks.once("init", async function () {
|
* RdD system
|
||||||
console.log(`Initializing Reve de Dragon System`);
|
* Author: LeRatierBretonnien
|
||||||
|
* Software License: GNU GPLv3
|
||||||
|
*/
|
||||||
|
export class SystemReveDeDragon {
|
||||||
|
|
||||||
// preload handlebars templates
|
static start() {
|
||||||
RdDUtility.preloadHandlebarsTemplates();
|
const system = new SystemReveDeDragon();
|
||||||
// Create useful storage space
|
Hooks.once('init', async () => await system.onInit());
|
||||||
game.system.rdd = {
|
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d));
|
||||||
TMRUtility,
|
|
||||||
RdDUtility,
|
|
||||||
RdDHotbar,
|
|
||||||
RdDPossession,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
constructor() {
|
||||||
game.settings.register(SYSTEM_RDD, "accorder-entite-cauchemar", {
|
this.RdDUtility = RdDUtility;
|
||||||
name: "Accorder le rêve aux entités",
|
this.RdDHotbar = RdDHotbar;
|
||||||
hint: "A quel moment les personnages doivent accorder leur rêve aux entités de cauchemar",
|
this.itemClasses = {
|
||||||
scope: "world",
|
service: RdDItemService,
|
||||||
config: true,
|
maladie: RdDItemMaladie,
|
||||||
type: String,
|
poison: RdDItemPoison,
|
||||||
choices: { // If choices are defined, the resulting setting will be a select menu
|
queue: RdDItemQueue,
|
||||||
"avant-attaque": "Avant l'attaque",
|
ombre: RdDItemOmbre,
|
||||||
"avant-defense": "Avant la défense",
|
souffle: RdDItemSouffle,
|
||||||
"avant-encaissement": "Avant l'encaissement",
|
signedraconique: RdDItemSigneDraconique,
|
||||||
},
|
rencontre: RdDRencontre
|
||||||
default: "avant-encaissement"
|
}
|
||||||
});
|
this.actorClasses = {
|
||||||
|
creature: RdDActor,
|
||||||
/* -------------------------------------------- */
|
entite: RdDActor,
|
||||||
game.settings.register(SYSTEM_RDD, "calendrier", {
|
personnage: RdDActor,
|
||||||
name: "calendrier",
|
vehicule: RdDActor,
|
||||||
scope: "world",
|
commerce: RdDCommerce,
|
||||||
config: false,
|
|
||||||
default: RdDCalendrier.createCalendrierInitial(),
|
|
||||||
type: Object
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
game.settings.register(SYSTEM_RDD, "migration-png-webp-1.5.34", {
|
|
||||||
name: "calendrier",
|
|
||||||
scope: "world",
|
|
||||||
config: false,
|
|
||||||
default: false,
|
|
||||||
type: Boolean
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
game.settings.register(SYSTEM_RDD, "liste-nombre-astral", {
|
|
||||||
name: "liste-nombre-astral",
|
|
||||||
scope: "world",
|
|
||||||
config: false,
|
|
||||||
default: [],
|
|
||||||
type: Object
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
game.settings.register(SYSTEM_RDD, "calendrier-pos", {
|
|
||||||
name: "calendrierPos",
|
|
||||||
scope: "client",
|
|
||||||
config: false,
|
|
||||||
default: RdDCalendrier.createCalendrierPos(),
|
|
||||||
type: Object
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", {
|
|
||||||
name: "Supprimer les dialogues de combat",
|
|
||||||
hint: "Si désactivée, tous les dialogues de combat sont conservés dans la conversation",
|
|
||||||
scope: "world",
|
|
||||||
config: true,
|
|
||||||
default: true,
|
|
||||||
type: Boolean
|
|
||||||
});
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
game.settings.register(SYSTEM_RDD, "activer-sons-audio", {
|
|
||||||
name: "Activer les bruitages intégrés",
|
|
||||||
hint: "Si activé, certaines actions en jeu déclenchent un son d'ambiance",
|
|
||||||
scope: "world",
|
|
||||||
config: true,
|
|
||||||
default: true,
|
|
||||||
type: Boolean
|
|
||||||
});
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
game.settings.register(SYSTEM_RDD, "appliquer-famine-soif", {
|
|
||||||
name: "Notifier de la famine et la soif pour",
|
|
||||||
hint: "Indique si les cas de famine et de soif seront indiqués durant Château Dormant",
|
|
||||||
scope: "world",
|
|
||||||
config: true,
|
|
||||||
type: String,
|
|
||||||
choices: {
|
|
||||||
"aucun": "ni la famine, ni la soif",
|
|
||||||
"famine": "seulement la famine",
|
|
||||||
"famine-soif": "la famine et la soif",
|
|
||||||
},
|
|
||||||
default: "aucun"
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
// Set an initiative formula for the system
|
|
||||||
CONFIG.Combat.initiative = {
|
|
||||||
formula: "1+(1d6/10)",
|
|
||||||
decimals: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => {
|
|
||||||
console.log(">>>>> MSG RECV", sockmsg);
|
|
||||||
try {
|
|
||||||
RdDUtility.onSocketMessage(sockmsg);
|
|
||||||
RdDCombat.onSocketMessage(sockmsg);
|
|
||||||
ChatUtility.onSocketMessage(sockmsg);
|
|
||||||
RdDActor.onSocketMessage(sockmsg);
|
|
||||||
} catch (e) {
|
|
||||||
console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg, ' => ', e)
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
// Define custom Entity classes
|
|
||||||
CONFIG.Actor.documentClass = RdDActor;
|
|
||||||
CONFIG.Item.documentClass = RdDItem;
|
|
||||||
CONFIG.RDD = {
|
|
||||||
resolutionTable: RdDResolutionTable.resolutionTable,
|
|
||||||
carac_array: RdDUtility.getCaracArray(),
|
|
||||||
ajustementsConditions: RdDUtility.getAjustementsConditions(),
|
|
||||||
difficultesLibres: RdDUtility.getDifficultesLibres()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// Register sheet application classes
|
/* Foundry VTT Initialization */
|
||||||
Actors.unregisterSheet("core", ActorSheet);
|
/* -------------------------------------------- */
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true });
|
async onInit() {
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDActorCreatureSheet, { types: ["creature"], makeDefault: true });
|
game.system.rdd = this;
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true });
|
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true });
|
|
||||||
Items.unregisterSheet("core", ItemSheet);
|
|
||||||
|
|
||||||
RdDItemSheet.register(RdDSigneDraconiqueItemSheet);
|
console.log(`Initializing Reve de Dragon System`);
|
||||||
RdDItemSheet.register(RdDRencontreItemSheet);
|
|
||||||
RdDItemSheet.register(RdDConteneurItemSheet);
|
|
||||||
RdDItemSheet.register(RdDHerbeItemSheet);
|
|
||||||
RdDItemSheet.register(RdDFauneItemSheet);
|
|
||||||
RdDItemSheet.register(RdDIngredientItemSheet);
|
|
||||||
|
|
||||||
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
|
// preload handlebars templates
|
||||||
types: [
|
RdDUtility.preloadHandlebarsTemplates();
|
||||||
"competence", "competencecreature",
|
|
||||||
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
|
|
||||||
"objet", "arme", "armure", "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();
|
this.initSystemSettings();
|
||||||
DialogChronologie.init();
|
|
||||||
ReglesOptionelles.init();
|
|
||||||
RdDUtility.init();
|
|
||||||
RdDDice.init();
|
|
||||||
RdDCommands.init();
|
|
||||||
RdDCombat.init();
|
|
||||||
RdDCombatManager.init();
|
|
||||||
RdDTokenHud.init();
|
|
||||||
RdDActor.init();
|
|
||||||
RddCompendiumOrganiser.init();
|
|
||||||
EffetsDraconiques.init()
|
|
||||||
TMRUtility.init();
|
|
||||||
RdDHotbar.initDropbar();
|
|
||||||
RdDPossession.init();
|
|
||||||
TMRRencontres.init();
|
|
||||||
Environnement.init();
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
function messageDeBienvenue() {
|
// Set an initiative formula for the system
|
||||||
if (game.user.isGM) {
|
CONFIG.Combat.initiative = {
|
||||||
ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">');
|
formula: "1+(1d6/10)",
|
||||||
ChatMessage.create({
|
decimals: 2
|
||||||
user: game.user.id,
|
};
|
||||||
content: `<div id="message-bienvenue-rdd"><span class="rdd-roll-part">Bienvenue dans le Rêve des Dragons !</span>
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => {
|
||||||
|
console.log(">>>>> MSG RECV", sockmsg);
|
||||||
|
try {
|
||||||
|
RdDUtility.onSocketMessage(sockmsg);
|
||||||
|
RdDCombat.onSocketMessage(sockmsg);
|
||||||
|
ChatUtility.onSocketMessage(sockmsg);
|
||||||
|
RdDBaseActor.onSocketMessage(sockmsg);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg, ' => ', e)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
// Define custom Entity classes
|
||||||
|
CONFIG.Actor.documentClass = RdDBaseActor;
|
||||||
|
CONFIG.Item.documentClass = RdDItem;
|
||||||
|
CONFIG.RDD = {
|
||||||
|
resolutionTable: RdDResolutionTable.resolutionTable,
|
||||||
|
carac_array: RdDUtility.getCaracArray(),
|
||||||
|
ajustementsConditions: RdDUtility.getAjustementsConditions(),
|
||||||
|
difficultesLibres: RdDUtility.getDifficultesLibres()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
// Register sheet application classes
|
||||||
|
Actors.unregisterSheet("core", ActorSheet);
|
||||||
|
Actors.registerSheet(SYSTEM_RDD, RdDCommerceSheet, { types: ["commerce"], makeDefault: true });
|
||||||
|
Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true });
|
||||||
|
Actors.registerSheet(SYSTEM_RDD, RdDActorCreatureSheet, { types: ["creature"], makeDefault: true });
|
||||||
|
Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true });
|
||||||
|
Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true });
|
||||||
|
Items.unregisterSheet("core", ItemSheet);
|
||||||
|
|
||||||
|
RdDItemSheet.register(RdDSigneDraconiqueItemSheet);
|
||||||
|
RdDItemSheet.register(RdDRencontreItemSheet);
|
||||||
|
RdDItemSheet.register(RdDConteneurItemSheet);
|
||||||
|
RdDItemSheet.register(RdDHerbeItemSheet);
|
||||||
|
RdDItemSheet.register(RdDFauneItemSheet);
|
||||||
|
RdDItemSheet.register(RdDPlanteItemSheet);
|
||||||
|
RdDItemSheet.register(RdDIngredientItemSheet);
|
||||||
|
RdDItemSheet.register(RdDServiceItemSheet);
|
||||||
|
|
||||||
|
Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, {
|
||||||
|
types: [
|
||||||
|
"objet", "arme", "armure", "livre", "potion", "munition",
|
||||||
|
"monnaie", "nourritureboisson", "gemme",
|
||||||
|
], makeDefault: true
|
||||||
|
});
|
||||||
|
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
|
||||||
|
types: [
|
||||||
|
"competence", "competencecreature",
|
||||||
|
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
|
||||||
|
"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
|
||||||
|
RdDTimestamp.init();
|
||||||
|
SystemCompendiums.init();
|
||||||
|
DialogChronologie.init();
|
||||||
|
ReglesOptionelles.init();
|
||||||
|
RdDUtility.init();
|
||||||
|
RdDDice.init();
|
||||||
|
RdDCommands.init();
|
||||||
|
RdDCombat.init();
|
||||||
|
RdDCombatManager.init();
|
||||||
|
RdDTokenHud.init();
|
||||||
|
RdDBaseActor.init();
|
||||||
|
RdDCompendiumOrganiser.init();
|
||||||
|
EffetsDraconiques.init()
|
||||||
|
TMRUtility.init();
|
||||||
|
RdDHotbar.initDropbar();
|
||||||
|
RdDPossession.init();
|
||||||
|
TMRRencontres.init();
|
||||||
|
Environnement.init();
|
||||||
|
|
||||||
|
Hooks.once('ready', () => this.onReady());
|
||||||
|
}
|
||||||
|
|
||||||
|
initSystemSettings() {
|
||||||
|
game.settings.register(SYSTEM_RDD, "accorder-entite-cauchemar", {
|
||||||
|
name: "Accorder le rêve aux entités",
|
||||||
|
hint: "A quel moment les personnages doivent accorder leur rêve aux entités de cauchemar",
|
||||||
|
scope: "world",
|
||||||
|
config: true,
|
||||||
|
type: String,
|
||||||
|
choices: {
|
||||||
|
"avant-attaque": "Avant l'attaque",
|
||||||
|
"avant-defense": "Avant la défense",
|
||||||
|
"avant-encaissement": "Avant l'encaissement",
|
||||||
|
},
|
||||||
|
default: "avant-encaissement"
|
||||||
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
game.settings.register(SYSTEM_RDD, "liste-nombre-astral", {
|
||||||
|
name: "liste-nombre-astral",
|
||||||
|
scope: "world",
|
||||||
|
config: false,
|
||||||
|
default: [],
|
||||||
|
type: Object
|
||||||
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
game.settings.register(SYSTEM_RDD, "calendrier-pos", {
|
||||||
|
name: "calendrierPos",
|
||||||
|
scope: "client",
|
||||||
|
config: false,
|
||||||
|
default: RdDCalendrier.createCalendrierPos(),
|
||||||
|
type: Object
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", {
|
||||||
|
name: "Supprimer les dialogues de combat",
|
||||||
|
hint: "Si désactivée, tous les dialogues de combat sont conservés dans la conversation",
|
||||||
|
scope: "world",
|
||||||
|
config: true,
|
||||||
|
default: true,
|
||||||
|
type: Boolean
|
||||||
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
game.settings.register(SYSTEM_RDD, "activer-sons-audio", {
|
||||||
|
name: "Activer les bruitages intégrés",
|
||||||
|
hint: "Si activé, certaines actions en jeu déclenchent un son d'ambiance",
|
||||||
|
scope: "world",
|
||||||
|
config: true,
|
||||||
|
default: true,
|
||||||
|
type: Boolean
|
||||||
|
});
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
game.settings.register(SYSTEM_RDD, "appliquer-famine-soif", {
|
||||||
|
name: "Notifier de la famine et la soif pour",
|
||||||
|
hint: "Indique si les cas de famine et de soif seront indiqués durant Château Dormant",
|
||||||
|
scope: "world",
|
||||||
|
config: true,
|
||||||
|
type: String,
|
||||||
|
choices: {
|
||||||
|
"aucun": "ni la famine, ni la soif",
|
||||||
|
"famine": "seulement la famine",
|
||||||
|
"famine-soif": "la famine et la soif",
|
||||||
|
},
|
||||||
|
default: "aucun"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async onReady() {
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Foundry VTT Initialization */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
// CSS patch for v9
|
||||||
|
if (game.version) {
|
||||||
|
let sidebar = document.getElementById("sidebar");
|
||||||
|
sidebar.style.width = "min-content";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
|
new Migrations().migrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusEffects.onReady();
|
||||||
|
RdDHerbes.initializeHerbes();
|
||||||
|
RdDDice.onReady();
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Affiche/Init le calendrier */
|
||||||
|
let calendrier = new RdDCalendrier();
|
||||||
|
let templatePath = "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html";
|
||||||
|
let templateData = {};
|
||||||
|
renderTemplate(templatePath, templateData).then(html => {
|
||||||
|
calendrier.render(true);
|
||||||
|
});
|
||||||
|
game.system.rdd.calendrier = calendrier; // Reference;
|
||||||
|
|
||||||
|
// Avertissement si joueur sans personnage
|
||||||
|
if (!game.user.isGM && game.user.character == undefined) {
|
||||||
|
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !");
|
||||||
|
ChatMessage.create({
|
||||||
|
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !",
|
||||||
|
user: game.user.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
|
this.messageDeBienvenue();
|
||||||
|
this.registerUsageCount(SYSTEM_RDD);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
messageDeBienvenue() {
|
||||||
|
if (game.user.isGM) {
|
||||||
|
ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">');
|
||||||
|
ChatMessage.create({
|
||||||
|
user: game.user.id,
|
||||||
|
content: `<div id="message-bienvenue-rdd"><span class="rdd-roll-part">Bienvenue dans le Rêve des Dragons !</span>
|
||||||
<br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs}
|
<br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs}
|
||||||
<br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
|
<br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
|
||||||
` });
|
` });
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
// Register world usage statistics
|
|
||||||
function registerUsageCount(registerKey) {
|
|
||||||
if (game.user.isGM) {
|
|
||||||
game.settings.register("world", "world-key", {
|
|
||||||
name: "Unique world key",
|
|
||||||
scope: "world",
|
|
||||||
config: false,
|
|
||||||
default: "NONE",
|
|
||||||
type: String
|
|
||||||
});
|
|
||||||
|
|
||||||
let worldKey = game.settings.get("world", "world-key")
|
|
||||||
if (worldKey == undefined || worldKey == "") {
|
|
||||||
worldKey = randomID(32)
|
|
||||||
game.settings.set("world", "world-key", worldKey)
|
|
||||||
}
|
}
|
||||||
let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.version}"`
|
|
||||||
$.ajax(regURL)
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/* Foundry VTT Initialization */
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
Hooks.once("ready", async function () {
|
|
||||||
await migrationPngWebp_1_5_34()
|
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
|
||||||
new Migrations().migrate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusEffects.onReady();
|
|
||||||
RdDHerbes.initializeHerbes();
|
|
||||||
RdDDice.onReady();
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Affiche/Init le calendrier */
|
// Register world usage statistics
|
||||||
let calendrier = new RdDCalendrier();
|
async registerUsageCount(registerKey) {
|
||||||
let templatePath = "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html";
|
if (game.user.isGM) {
|
||||||
let templateData = {};
|
game.settings.register("world", "world-key", {
|
||||||
renderTemplate(templatePath, templateData).then(html => {
|
name: "Unique world key",
|
||||||
calendrier.render(true);
|
scope: "world",
|
||||||
});
|
config: false,
|
||||||
game.system.rdd.calendrier = calendrier; // Reference;
|
default: "NONE",
|
||||||
|
type: String
|
||||||
|
});
|
||||||
|
|
||||||
// Avertissement si joueur sans personnage
|
let worldKey = game.settings.get("world", "world-key")
|
||||||
if (!game.user.isGM && game.user.character == undefined) {
|
if (worldKey == undefined || worldKey == "") {
|
||||||
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !");
|
worldKey = randomID(32)
|
||||||
ChatMessage.create({
|
game.settings.set("world", "world-key", worldKey)
|
||||||
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !",
|
|
||||||
user: game.user.id
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
|
||||||
messageDeBienvenue();
|
|
||||||
registerUsageCount(SYSTEM_RDD);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
async function migrationPngWebp_1_5_34() {
|
|
||||||
if (!game.settings.get(SYSTEM_RDD, "migration-png-webp-1.5.34")) {
|
|
||||||
const regexOldPngJpg = /(systems\/foundryvtt-reve-de-dragon\/icons\/.*)\.(png|jpg)/;
|
|
||||||
const replaceWithWebp = '$1.webp';
|
|
||||||
function convertImgToWebp(img) {
|
|
||||||
return img.replace(regexOldPngJpg, replaceWithWebp);
|
|
||||||
}
|
|
||||||
function prepareDocumentsImgUpdate(documents) {
|
|
||||||
return documents.filter(it => it.img && it.img.match(regexOldPngJpg))
|
|
||||||
.map(it => {
|
|
||||||
return { _id: it.id, img: convertImgToWebp(it.img) }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
const itemsUpdates = prepareDocumentsImgUpdate(game.items);
|
|
||||||
const actorsUpdates = prepareDocumentsImgUpdate(game.actors);
|
|
||||||
//Migrate system png to webp
|
|
||||||
await Item.updateDocuments(itemsUpdates);
|
|
||||||
await Actor.updateDocuments(actorsUpdates);
|
|
||||||
game.actors.forEach(actor => {
|
|
||||||
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
|
|
||||||
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
|
|
||||||
}
|
}
|
||||||
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
|
let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.version}"`
|
||||||
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
|
$.ajax(regURL)
|
||||||
});
|
/* -------------------------------------------- */
|
||||||
game.settings.set(SYSTEM_RDD, "migration-png-webp-1.5.34", true)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// CSS patch for v9
|
|
||||||
if (game.version) {
|
|
||||||
let sidebar = document.getElementById("sidebar");
|
|
||||||
sidebar.style.width = "min-content";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
SystemReveDeDragon.start();
|
||||||
/* Dice-so-nice ready */
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d));
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { RdDActor } from "./actor.js";
|
import { RdDBaseActor } from "./actor/base-actor.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ export class RdDNameGen {
|
|||||||
|
|
||||||
static async onCreerActeur(event) {
|
static async onCreerActeur(event) {
|
||||||
const button = event.currentTarget;
|
const button = event.currentTarget;
|
||||||
await RdDActor.create({
|
await RdDBaseActor.create({
|
||||||
name: button.attributes['data-nom'].value,
|
name: button.attributes['data-nom'].value,
|
||||||
type: button.attributes['data-type'].value
|
type: button.attributes['data-type'].value
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -115,17 +115,16 @@ export class RdDRollResolutionTable extends Dialog {
|
|||||||
rollData.finalLevel = this._computeFinalLevel(rollData);
|
rollData.finalLevel = this._computeFinalLevel(rollData);
|
||||||
|
|
||||||
const htmlTable = await RdDResolutionTable.buildHTMLTable({
|
const htmlTable = await RdDResolutionTable.buildHTMLTable({
|
||||||
carac:rollData.caracValue,
|
carac: rollData.caracValue,
|
||||||
level: rollData.finalLevel
|
level: rollData.finalLevel,
|
||||||
|
maxCarac: 20,
|
||||||
|
maxLevel: 10
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mise à jour valeurs
|
// Mise à jour valeurs
|
||||||
this.html.find("[name='carac']").val(rollData.caracValue);
|
this.html.find("[name='carac']").val(rollData.caracValue);
|
||||||
this.html.find(".roll-param-resolution").text(rollData.selectedCarac.value + " / " + Misc.toSignedString(rollData.finalLevel));
|
this.html.find(".roll-param-resolution").text(rollData.selectedCarac.value + " / " + Misc.toSignedString(rollData.finalLevel));
|
||||||
this.html.find(".table-resolution").remove();
|
this.html.find("div.placeholder-resolution").empty().append(htmlTable)
|
||||||
this.html.find(".table-proba-reussite").remove();
|
|
||||||
|
|
||||||
this.html.find("div.placeholder-resolution").append(htmlTable)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -276,11 +276,11 @@ export class RdDRoll extends Dialog {
|
|||||||
const diffVariable = RdDItemSort.isDifficulteVariable(sort);
|
const diffVariable = RdDItemSort.isDifficulteVariable(sort);
|
||||||
const coutVariable = RdDItemSort.isCoutVariable(sort);
|
const coutVariable = RdDItemSort.isCoutVariable(sort);
|
||||||
|
|
||||||
HtmlUtility._showControlWhen(this.html.find(".div-sort-non-rituel"), !sort.system.isrituel);
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-non-rituel"), !sort.system.isrituel);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".div-sort-difficulte-var"), diffVariable);
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-difficulte-var"), diffVariable);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".div-sort-difficulte-fixe"), !diffVariable);
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-difficulte-fixe"), !diffVariable);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".div-sort-ptreve-var"), coutVariable);
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-ptreve-var"), coutVariable);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".div-sort-ptreve-fixe"), !coutVariable);
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-ptreve-fixe"), !coutVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
async setSelectedSigneDraconique(signe) {
|
async setSelectedSigneDraconique(signe) {
|
||||||
@@ -311,11 +311,11 @@ export class RdDRoll extends Dialog {
|
|||||||
const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel))
|
const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel))
|
||||||
const adjustements = await this.buildAjustements(rollData);
|
const adjustements = await this.buildAjustements(rollData);
|
||||||
|
|
||||||
HtmlUtility._showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac));
|
HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac));
|
||||||
HtmlUtility._showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
|
HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
|
||||||
HtmlUtility._showControlWhen(this.html.find(".utilisation-moral"), rollData.use.appelAuMoral);
|
HtmlUtility.showControlWhen(this.html.find(".utilisation-moral"), rollData.use.appelAuMoral);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".diffMoral"), rollData.ajustements.moralTotal.used);
|
HtmlUtility.showControlWhen(this.html.find(".diffMoral"), rollData.ajustements.moralTotal.used);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
HtmlUtility.showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
||||||
|
|
||||||
// Mise à jour valeurs
|
// Mise à jour valeurs
|
||||||
this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
|
this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
|
||||||
|
|||||||
@@ -95,8 +95,9 @@ export class RdDRollTables {
|
|||||||
const row = await table.getRandom(itemFrequence, filter);
|
const row = await table.getRandom(itemFrequence, filter);
|
||||||
if (row) {
|
if (row) {
|
||||||
await CompendiumTableHelpers.tableRowToChatMessage(row, type);
|
await CompendiumTableHelpers.tableRowToChatMessage(row, type);
|
||||||
|
return row.document;
|
||||||
}
|
}
|
||||||
return row;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|||||||
@@ -1,7 +1,24 @@
|
|||||||
import { DialogSplitItem } from "./dialog-split-item.js";
|
import { DialogSplitItem } from "./dialog-split-item.js";
|
||||||
|
import { RdDItem } from "./item.js";
|
||||||
|
|
||||||
export class RdDSheetUtility {
|
export class RdDSheetUtility {
|
||||||
|
|
||||||
|
static mergeDocumentRights(options, document, editable) {
|
||||||
|
const userRightLevel = game.user.isGM
|
||||||
|
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
|
||||||
|
: document.getUserLevel(game.user);
|
||||||
|
mergeObject(options, {
|
||||||
|
isGM: game.user.isGM,
|
||||||
|
isOwned: document.parent,
|
||||||
|
editable: editable,
|
||||||
|
cssClass: editable ? "editable" : "locked",
|
||||||
|
isLimited: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED,
|
||||||
|
isObserver: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER,
|
||||||
|
isOwner: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
|
||||||
|
});
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
static getItem(event, actor) {
|
static getItem(event, actor) {
|
||||||
return actor.items.get(RdDSheetUtility.getItemId(event))
|
return actor.items.get(RdDSheetUtility.getItemId(event))
|
||||||
}
|
}
|
||||||
@@ -19,8 +36,11 @@ export class RdDSheetUtility {
|
|||||||
return $(event.currentTarget)?.parents(".item");
|
return $(event.currentTarget)?.parents(".item");
|
||||||
}
|
}
|
||||||
|
|
||||||
static prepareItemDropParameters(destItemId, actor, dragData, objetVersConteneur) {
|
static async prepareItemDropParameters(destItemId, actor, dragData, objetVersConteneur) {
|
||||||
const item = fromUuidSync(dragData.uuid)
|
let item = fromUuidSync(dragData.uuid);
|
||||||
|
if (item.pack && !item.system) {
|
||||||
|
item = await RdDItem.getCorrespondingItem(item);
|
||||||
|
}
|
||||||
if (actor.canReceive(item)) {
|
if (actor.canReceive(item)) {
|
||||||
return {
|
return {
|
||||||
destId: destItemId,
|
destId: destItemId,
|
||||||
|
|||||||
309
module/rdd-timestamp.js
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
import { SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
|
import { Grammar } from "./grammar.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
|
|
||||||
|
export const WORLD_TIMESTAMP_SETTING = "calendrier";
|
||||||
|
|
||||||
|
const RDD_MOIS_PAR_AN = 12;
|
||||||
|
const RDD_JOURS_PAR_MOIS = 28;
|
||||||
|
const RDD_JOURS_PAR_AN = 336; //RDD_JOURS_PAR_MOIS * RDD_MOIS_PAR_AN;
|
||||||
|
const RDD_HEURES_PAR_JOUR = 12;
|
||||||
|
const RDD_MINUTES_PAR_HEURES = 120;
|
||||||
|
const RDD_MINUTES_PAR_JOUR = 1440; //RDD_HEURES_PAR_JOUR * RDD_MINUTES_PAR_HEURES;
|
||||||
|
const ROUNDS_PAR_MINUTE = 10;
|
||||||
|
|
||||||
|
const DEFINITION_HEURES = [
|
||||||
|
{ key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "Printemps" },
|
||||||
|
{ key: "sirene", label: "Sirène", lettreFont: 'i', saison: "Printemps" },
|
||||||
|
{ key: "faucon", label: "Faucon", lettreFont: 'f', saison: "Printemps" },
|
||||||
|
{ key: "couronne", label: "Couronne", lettreFont: '', saison: "Eté" },
|
||||||
|
{ key: "dragon", label: "Dragon", lettreFont: 'd', saison: "Eté" },
|
||||||
|
{ key: "epees", label: "Epées", lettreFont: 'e', saison: "Eté" },
|
||||||
|
{ key: "lyre", label: "Lyre", lettreFont: 'l', saison: "Automne" },
|
||||||
|
{ key: "serpent", label: "Serpent", lettreFont: 's', saison: "Automne" },
|
||||||
|
{ key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne" },
|
||||||
|
{ key: "araignee", label: "Araignée", lettreFont: 'a', saison: "Hiver" },
|
||||||
|
{ key: "roseau", label: "Roseau", lettreFont: 'r', saison: "Hiver" },
|
||||||
|
{ key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "Hiver" },
|
||||||
|
]
|
||||||
|
|
||||||
|
const FORMULES_DUREE = [
|
||||||
|
{ code: "", label: "", calcul: async (t, actor) => t.addJours(100 * RDD_JOURS_PAR_AN) },
|
||||||
|
{ code: "jour", label: "1 jour", calcul: async (t, actor) => t.nouveauJour().addJours(1) },
|
||||||
|
{ code: "1d7jours", label: "1d7 jour", calcul: async (t, actor) => t.nouveauJour().addJours(await RdDDice.rollTotal('1d7', { showDice: SHOW_DICE })) },
|
||||||
|
{ code: "1ddr", label: "Un dé draconique jours", calcul: async (t, actor) => t.nouveauJour().addJours(await RdDDice.rollTotal('1dr+7', { showDice: SHOW_DICE })) },
|
||||||
|
{ code: "hn", label: "Fin de l'Heure de Naissance", calcul: async (t, actor) => t.finHeure(actor.getHeureNaissance()) },
|
||||||
|
// { code: "1h", label: "Une heure", calcul: async (t, actor) => t.nouvelleHeure().addHeures(1) },
|
||||||
|
// { code: "12h", label: "12 heures", calcul: async (t, actor) => t.nouvelleHeure().addHeures(12) },
|
||||||
|
// { code: "chateaudormant", label: "Fin Chateau dormant", calcul: async (t, actor) => t.nouveauJour() },
|
||||||
|
// { code: "special", label: "Spéciale", calcul: async (t, actor) => t.addJours(100 * RDD_JOURS_PAR_AN) },
|
||||||
|
]
|
||||||
|
const FORMULES_PERIODE = [
|
||||||
|
{ code: 'round', label: "Rounds", calcul: async (t, nombre) => t.addMinutes(nombre / 10) },
|
||||||
|
{ code: 'minute', label: "Minutes", calcul: async (t, nombre) => t.addMinutes(nombre) },
|
||||||
|
{ code: 'heure', label: "Heures", calcul: async (t, nombre) => t.addHeures(nombre) },
|
||||||
|
{ code: 'jour', label: "Jours", calcul: async (t, nombre) => t.addJours(nombre) },
|
||||||
|
]
|
||||||
|
|
||||||
|
export class RdDTimestamp {
|
||||||
|
|
||||||
|
static iconeHeure(heure) {
|
||||||
|
return `systems/foundryvtt-reve-de-dragon/icons/heures/hd${heure < 9 ? '0' : ''}${heure + 1}.svg`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static init() {
|
||||||
|
game.settings.register(SYSTEM_RDD, WORLD_TIMESTAMP_SETTING, {
|
||||||
|
name: WORLD_TIMESTAMP_SETTING,
|
||||||
|
scope: "world",
|
||||||
|
config: false,
|
||||||
|
default: { indexDate: 0, indexMinute: 0 },
|
||||||
|
type: Object
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let i = 0; i < DEFINITION_HEURES.length; i++) {
|
||||||
|
DEFINITION_HEURES[i].heure = i;
|
||||||
|
DEFINITION_HEURES[i].icon = RdDTimestamp.iconeHeure(i);
|
||||||
|
DEFINITION_HEURES[i].webp = DEFINITION_HEURES[i].icon.replace(".svg", ".webp");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param signe
|
||||||
|
* @returns L'entrée de DEFINITION_HEURES correspondant au signe
|
||||||
|
*/
|
||||||
|
static definition(signe) {
|
||||||
|
if (signe == undefined) {
|
||||||
|
signe = 0;
|
||||||
|
}
|
||||||
|
if (Number.isInteger(signe)) {
|
||||||
|
return DEFINITION_HEURES[signe % RDD_HEURES_PAR_JOUR];
|
||||||
|
}
|
||||||
|
let definition = DEFINITION_HEURES.find(it => it.key == signe);
|
||||||
|
if (!definition) {
|
||||||
|
definition = Misc.findFirstLike(signe, DEFINITION_HEURES, { mapper: it => it.label, description: 'signe' });
|
||||||
|
}
|
||||||
|
return definition
|
||||||
|
}
|
||||||
|
|
||||||
|
static formulesDuree() {
|
||||||
|
return FORMULES_DUREE
|
||||||
|
}
|
||||||
|
|
||||||
|
static formulesPeriode() {
|
||||||
|
return FORMULES_PERIODE
|
||||||
|
}
|
||||||
|
|
||||||
|
static imgSigneHeure(heure) {
|
||||||
|
return RdDTimestamp.imgSigne(RdDTimestamp.definition(heure));
|
||||||
|
}
|
||||||
|
|
||||||
|
static imgSigne(signe) {
|
||||||
|
return signe == undefined ? '' : `<img class="img-signe-heure" src="${signe.webp}" alt="${signe.label}"/>`
|
||||||
|
}
|
||||||
|
|
||||||
|
static handleTimestampEditor(html, path, consumeTimestamp = async (path, timestamp) => { }) {
|
||||||
|
const fields = {
|
||||||
|
annee: html.find(`input[name="${path}.annee"]`),
|
||||||
|
mois: html.find(`select[name="${path}.mois"]`),
|
||||||
|
jourDuMois: html.find(`input[name="${path}.jourDuMois"]`),
|
||||||
|
heure: html.find(`select[name="${path}.heure"]`),
|
||||||
|
minute: html.find(`input[name="${path}.minute"]`)
|
||||||
|
};
|
||||||
|
|
||||||
|
async function onChangeTimestamp(fields, path) {
|
||||||
|
const annee = Number(fields.annee.val());
|
||||||
|
const mois = fields.mois.val();
|
||||||
|
const jour = Number(fields.jourDuMois.val());
|
||||||
|
const heure = fields.heure.val();
|
||||||
|
const minute = Number(fields.minute.val());
|
||||||
|
await consumeTimestamp(path, RdDTimestamp.timestamp(annee, mois, jour, heure, minute));
|
||||||
|
}
|
||||||
|
|
||||||
|
fields.annee.change(async (event) => await onChangeTimestamp(fields, path));
|
||||||
|
fields.mois.change(async (event) => await onChangeTimestamp(fields, path));
|
||||||
|
fields.jourDuMois.change(async (event) => await onChangeTimestamp(fields, path));
|
||||||
|
fields.heure.change(async (event) => await onChangeTimestamp(fields, path));
|
||||||
|
fields.minute.change(async (event) => await onChangeTimestamp(fields, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static findHeure(heure) {
|
||||||
|
heure = Grammar.toLowerCaseNoAccentNoSpace(heure);
|
||||||
|
let parHeureOuLabel = DEFINITION_HEURES.filter(it => (it.heure) == parseInt(heure) % RDD_HEURES_PAR_JOUR || Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure);
|
||||||
|
if (parHeureOuLabel.length == 1) {
|
||||||
|
return parHeureOuLabel[0];
|
||||||
|
}
|
||||||
|
let parLabelPartiel = DEFINITION_HEURES.filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label).includes(heure));
|
||||||
|
if (parLabelPartiel.length > 0) {
|
||||||
|
parLabelPartiel.sort(Misc.ascending(h => h.label.length));
|
||||||
|
return parLabelPartiel[0];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param indexDate: la date (depuis le jour 0)
|
||||||
|
* @return la version formattée de la date
|
||||||
|
*/
|
||||||
|
static formatIndexDate(indexDate) {
|
||||||
|
return new RdDTimestamp({ indexDate }).formatDate()
|
||||||
|
}
|
||||||
|
|
||||||
|
static splitIndexDate(indexDate) {
|
||||||
|
const timestamp = new RdDTimestamp({ indexDate });
|
||||||
|
return {
|
||||||
|
jour: timestamp.jour + 1,
|
||||||
|
mois: RdDTimestamp.definition(timestamp.mois).key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getWorldTime() {
|
||||||
|
let worldTime = game.settings.get(SYSTEM_RDD, WORLD_TIMESTAMP_SETTING);
|
||||||
|
if (worldTime.indexJour != undefined && worldTime.heureRdD != undefined) {
|
||||||
|
// Migration
|
||||||
|
worldTime = {
|
||||||
|
indexDate: worldTime.indexJour,
|
||||||
|
indexMinute: worldTime.heureRdD * 120 + worldTime.minutesRelative
|
||||||
|
};
|
||||||
|
RdDTimestamp.setWorldTime(new RdDTimestamp(worldTime))
|
||||||
|
}
|
||||||
|
return new RdDTimestamp(worldTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
static setWorldTime(timestamp) {
|
||||||
|
game.settings.set(SYSTEM_RDD, WORLD_TIMESTAMP_SETTING, duplicate(timestamp));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** construit un RdDTimestamp à partir de l'année/mois/jour/heure?/minute? */
|
||||||
|
static timestamp(annee, mois, jour, heure = 0, minute = 0) {
|
||||||
|
mois = this.definition(mois)?.heure
|
||||||
|
heure = this.definition(heure)?.heure
|
||||||
|
return new RdDTimestamp({
|
||||||
|
indexDate: (jour - 1) + (mois + annee * RDD_MOIS_PAR_AN) * RDD_JOURS_PAR_MOIS,
|
||||||
|
indexMinute: heure * RDD_MINUTES_PAR_HEURES + minute
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructeur d'un timestamp.
|
||||||
|
* Selon les paramètres, l'objet construit se base su:
|
||||||
|
* - le timestamp
|
||||||
|
* - la date numérique + minute (dans la journée)
|
||||||
|
* @param indexDate: la date à utiliser pour ce timestamp
|
||||||
|
* @param indexMinute: la minute de la journée à utiliser pour ce timestamp
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
constructor({ indexDate, indexMinute = undefined }) {
|
||||||
|
this.indexDate = indexDate
|
||||||
|
this.indexMinute = indexMinute ?? 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convertit le timestamp en une structure avec les informations utiles
|
||||||
|
* pour afficher la date et l'heure
|
||||||
|
*/
|
||||||
|
toCalendrier() {
|
||||||
|
return {
|
||||||
|
timestamp: this,
|
||||||
|
annee: this.annee,
|
||||||
|
mois: RdDTimestamp.definition(this.mois),
|
||||||
|
jour: this.jour,
|
||||||
|
jourDuMois: this.jour + 1,
|
||||||
|
heure: RdDTimestamp.definition(this.heure),
|
||||||
|
minute: this.minute
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
get annee() { return Math.floor(this.indexDate / RDD_JOURS_PAR_AN) }
|
||||||
|
get mois() { return Math.floor((this.indexDate % RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
|
||||||
|
get jour() { return (this.indexDate % RDD_JOURS_PAR_AN) % RDD_JOURS_PAR_MOIS }
|
||||||
|
get heure() { return Math.floor(this.indexMinute / RDD_MINUTES_PAR_HEURES) }
|
||||||
|
get minute() { return this.indexMinute % RDD_MINUTES_PAR_HEURES }
|
||||||
|
get round() { return ROUNDS_PAR_MINUTE * (this.indexMinute - Math.floor(this.indexMinute)) }
|
||||||
|
|
||||||
|
formatDate() {
|
||||||
|
const jour = this.jour + 1;
|
||||||
|
const mois = RdDTimestamp.definition(this.mois).label;
|
||||||
|
const annee = this.annee ?? '';
|
||||||
|
return `${jour} ${mois}` + (annee ? ' ' + annee : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
nouveauJour() { return new RdDTimestamp({ indexDate: this.indexDate + 1, indexMinute: 0 }) }
|
||||||
|
|
||||||
|
nouvelleHeure() {
|
||||||
|
return this.heure >= RDD_HEURES_PAR_JOUR ? this.nouveauJour() : new RdDTimestamp({
|
||||||
|
indexDate: this.indexDate,
|
||||||
|
indexMinute: (this.heure + 1) * RDD_MINUTES_PAR_HEURES
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
addJours(jours) {
|
||||||
|
return jours == 0 ? this : new RdDTimestamp({
|
||||||
|
indexDate: this.indexDate + jours,
|
||||||
|
indexMinute: this.indexMinute
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
addHeures(heures) {
|
||||||
|
if (heures == 0) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
const heure = this.heure + heures;
|
||||||
|
return new RdDTimestamp({
|
||||||
|
indexDate: this.indexDate + Math.floor(heure / RDD_HEURES_PAR_JOUR),
|
||||||
|
indexMinute: this.indexMinute + (heure % RDD_HEURES_PAR_JOUR) * RDD_MINUTES_PAR_HEURES
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
addMinutes(minutes) {
|
||||||
|
if (minutes == 0) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
const indexMinute = this.indexMinute + minutes;
|
||||||
|
const jours = Math.floor(indexMinute / RDD_MINUTES_PAR_JOUR)
|
||||||
|
return new RdDTimestamp({
|
||||||
|
indexDate: this.indexDate + jours,
|
||||||
|
indexMinute: indexMinute - (jours * RDD_MINUTES_PAR_JOUR)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
addPeriode(nombre, unite) {
|
||||||
|
const formule = FORMULES_PERIODE.find(it => it.code == unite);
|
||||||
|
if (formule) {
|
||||||
|
return formule.calcul(this, nombre);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.info(`Pas de période pour ${unite ?? 'Aucune uinité définie'}`)
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
finHeure(heure) {
|
||||||
|
return this.nouvelleHeure().addHeures((12 + heure - this.heure) % 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
async appliquerDuree(duree, actor) {
|
||||||
|
const formule = FORMULES_DUREE.find(it => it.code == duree) ?? FORMULES_DUREE.find(it => it.code == "");
|
||||||
|
return await formule.calcul(this, actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
compare(timestamp) {
|
||||||
|
let diff = this.indexDate - timestamp.indexDate
|
||||||
|
if (diff == 0) {
|
||||||
|
diff = this.indexMinute - timestamp.indexMinute
|
||||||
|
}
|
||||||
|
return diff < 0 ? -1 : diff > 0 ? 1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
difference(timestamp) {
|
||||||
|
const jours = this.indexDate - timestamp.indexDate;
|
||||||
|
const minutes = this.indexMinute - timestamp.indexMinute;
|
||||||
|
return {
|
||||||
|
jours: jours,
|
||||||
|
heures: Math.floor(minutes / RDD_MINUTES_PAR_HEURES),
|
||||||
|
minutes: minutes % RDD_MINUTES_PAR_HEURES
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,8 +15,9 @@ import { HtmlUtility } from "./html-utility.js";
|
|||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
import { STATUSES } from "./settings/status-effects.js";
|
||||||
import { RdDRencontre } from "./item-rencontre.js";
|
import { RdDRencontre } from "./item/rencontre.js";
|
||||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
import { RdDCalendrier } from "./rdd-calendrier.js";
|
||||||
|
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
@@ -207,8 +208,8 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HtmlUtility._showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
||||||
HtmlUtility._showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord()));
|
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord()));
|
||||||
|
|
||||||
// Roll Sort
|
// Roll Sort
|
||||||
this.html.find('.lancer-sort').click((event) => {
|
this.html.find('.lancer-sort').click((event) => {
|
||||||
@@ -245,7 +246,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
const coord = this._getActorCoord();
|
const coord = this._getActorCoord();
|
||||||
|
|
||||||
HtmlUtility._showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
|
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
|
||||||
|
|
||||||
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
||||||
ptsreve.innerHTML = this.actor.system.reve.reve.value;
|
ptsreve.innerHTML = this.actor.system.reve.reve.value;
|
||||||
@@ -284,7 +285,12 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onActionRencontre(action, tmr) {
|
async onActionRencontre(action, tmr, rencontre) {
|
||||||
|
if (!this.currentRencontre){
|
||||||
|
ui.notifications.warn("#612 Rencontre perdue, récupération en cours. Vous pouvez contacter l'équipe avec les logs pour aider à résoudre ce problème")
|
||||||
|
console.error("#612 Rencontre perdue", action, tmr, rencontre, this);
|
||||||
|
this.currentRencontre = rencontre;
|
||||||
|
}
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'derober':
|
case 'derober':
|
||||||
await this.derober();
|
await this.derober();
|
||||||
@@ -405,6 +411,8 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _tentativeMaitrise(rencData) {
|
async _tentativeMaitrise(rencData) {
|
||||||
|
this.rencontreState = 'normal';
|
||||||
|
|
||||||
rencData.reve = this.actor.getReveActuel();
|
rencData.reve = this.actor.getReveActuel();
|
||||||
rencData.etat = this.actor.getEtatGeneral();
|
rencData.etat = this.actor.getEtatGeneral();
|
||||||
|
|
||||||
@@ -450,7 +458,6 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
this._tentativeMaitrise(rencData);
|
this._tentativeMaitrise(rencData);
|
||||||
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
|
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
|
||||||
}, 2000);
|
}, 2000);
|
||||||
this.rencontreState == 'normal';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
formatMessageRencontre(rencData, template) {
|
formatMessageRencontre(rencData, template) {
|
||||||
@@ -460,14 +467,14 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
messageDuree = ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
|
messageDuree = ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
messageDuree = ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
|
messageDuree = ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const compiled = Handlebars.compile(template);
|
const compiled = Handlebars.compile(template);
|
||||||
return compiled(rencData) + messageDuree ;
|
return compiled(rencData) + messageDuree;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return template + messageDuree ;
|
return template + messageDuree;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -520,7 +527,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
this.currentRencontre = await this._jetDeRencontre(tmr);
|
this.currentRencontre = await this._jetDeRencontre(tmr);
|
||||||
if (this.currentRencontre) {
|
if (this.currentRencontre) {
|
||||||
if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)){
|
if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)) {
|
||||||
// rencontre en attente suite à dérobade
|
// rencontre en attente suite à dérobade
|
||||||
await this.maitriserRencontre();
|
await this.maitriserRencontre();
|
||||||
}
|
}
|
||||||
@@ -550,7 +557,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
this.currentRencontre = present.clone({
|
this.currentRencontre = present.clone({
|
||||||
'system.force': await RdDDice.rollTotal(present.system.formule),
|
'system.force': await RdDDice.rollTotal(present.system.formule),
|
||||||
'system.coord': tmr.coord
|
'system.coord': tmr.coord
|
||||||
}, {save: false});
|
}, { save: false });
|
||||||
|
|
||||||
await EffetsDraconiques.presentCites.ouvrirLePresent(this.actor, presentCite);
|
await EffetsDraconiques.presentCites.ouvrirLePresent(this.actor, presentCite);
|
||||||
this.removeToken(tmr, presentCite);
|
this.removeToken(tmr, presentCite);
|
||||||
@@ -587,6 +594,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
|
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
|
||||||
} else {
|
} else {
|
||||||
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
|
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -839,7 +847,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
async processSortReserve(sortReserve) {
|
async processSortReserve(sortReserve) {
|
||||||
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
|
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
|
||||||
console.log("declencheSortEnReserve", sortReserve);
|
console.log("declencheSortEnReserve", sortReserve);
|
||||||
const heureCible = RdDCalendrier.getSigneAs('label', sortReserve.system.heurecible);
|
const heureCible = RdDTimestamp.definition(sortReserve.system.heurecible).label;
|
||||||
this._tellToUserAndGM(`Vous avez déclenché
|
this._tellToUserAndGM(`Vous avez déclenché
|
||||||
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"}
|
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"}
|
||||||
en réserve <strong>${sortReserve.name}</strong>
|
en réserve <strong>${sortReserve.name}</strong>
|
||||||
|
|||||||
@@ -29,12 +29,13 @@ export class RdDTMRRencontreDialog extends Dialog {
|
|||||||
this.toClose = false;
|
this.toClose = false;
|
||||||
this.tmr = tmr;
|
this.tmr = tmr;
|
||||||
this.tmrApp = tmrApp;
|
this.tmrApp = tmrApp;
|
||||||
|
this.rencontre = rencontre;
|
||||||
this.tmrApp.minimize();
|
this.tmrApp.minimize();
|
||||||
}
|
}
|
||||||
|
|
||||||
async onButtonAction(action) {
|
async onButtonAction(action) {
|
||||||
this.toClose = true;
|
this.toClose = true;
|
||||||
this.tmrApp.onActionRencontre(action, this.tmr)
|
this.tmrApp.onActionRencontre(action, this.tmr, this.rencontre)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|||||||
@@ -111,6 +111,6 @@ export class RdDTokenHud {
|
|||||||
|
|
||||||
static _toggleHudListActive(hud, list) {
|
static _toggleHudListActive(hud, list) {
|
||||||
hud.toggleClass('active');
|
hud.toggleClass('active');
|
||||||
HtmlUtility._showControlWhen(list, hud.hasClass('active'));
|
HtmlUtility.showControlWhen(list, hud.hasClass('active'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,14 +8,13 @@ import { DialogItemAchat } from "./dialog-item-achat.js";
|
|||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
import { Monnaie } from "./item-monnaie.js";
|
|
||||||
import { RdDPossession } from "./rdd-possession.js";
|
import { RdDPossession } from "./rdd-possession.js";
|
||||||
import { RdDNameGen } from "./rdd-namegen.js";
|
import { RdDNameGen } from "./rdd-namegen.js";
|
||||||
import { RdDConfirm } from "./rdd-confirm.js";
|
import { RdDConfirm } from "./rdd-confirm.js";
|
||||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
|
||||||
import { Environnement } from "./environnement.js";
|
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
|
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||||
|
import { RdDRaretes } from "./item/raretes.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// This table starts at 0 -> niveau -10
|
// This table starts at 0 -> niveau -10
|
||||||
@@ -126,6 +125,7 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/actor/header-hautreve.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html',
|
||||||
@@ -149,6 +149,7 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html',
|
||||||
@@ -169,39 +170,18 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-animaux.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-animaux.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html',
|
||||||
//Items
|
//Items
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/boutons-comestible.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item/boutons-comestible.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item/temporel.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-arme-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-armure-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-objet-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-conteneur-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-sort-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-herbe-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-ingredient-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-faune-sheet.html',
|
|
||||||
'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-rencontre-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-queue-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/header-item.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-tarot-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-tete-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-ombre-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-monnaie-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-meditation-sheet.html',
|
|
||||||
'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
|
// partial enums
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
|
||||||
@@ -212,7 +192,6 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-herbesoin-ingredient.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html',
|
||||||
@@ -220,8 +199,13 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/enum-periode.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html',
|
||||||
// Partials
|
// Partials
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html',
|
||||||
@@ -294,13 +278,21 @@ export class RdDUtility {
|
|||||||
Handlebars.registerHelper('apostrophe', (article, str) => Grammar.apostrophe(article, str));
|
Handlebars.registerHelper('apostrophe', (article, str) => Grammar.apostrophe(article, str));
|
||||||
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str));
|
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str));
|
||||||
Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args));
|
Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args));
|
||||||
Handlebars.registerHelper('buildConteneur', (objet) => { return new Handlebars.SafeString(RdDUtility.buildConteneur(objet)); });
|
Handlebars.registerHelper('buildLigneInventaire', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildLigneInventaire(item, options)); });
|
||||||
Handlebars.registerHelper('buildContenu', (objet) => { return new Handlebars.SafeString(RdDUtility.buildContenu(objet, 1, true)); });
|
Handlebars.registerHelper('buildInventaireConteneur', (actorId, itemId, options) => { return new Handlebars.SafeString(RdDUtility.buildInventaireConteneur(actorId, itemId, options)); });
|
||||||
|
Handlebars.registerHelper('buildContenuConteneur', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildContenuConteneur(item, options)); });
|
||||||
|
Handlebars.registerHelper('calculerPrixCommercant', item => item.calculerPrixCommercant());
|
||||||
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
|
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
|
||||||
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
|
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
|
||||||
Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type));
|
Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type));
|
||||||
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
|
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
|
||||||
Handlebars.registerHelper('signeHeure', (key, heure) => RdDCalendrier.getSigneAs(key, heure));
|
|
||||||
|
Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) });
|
||||||
|
Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) });
|
||||||
|
Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier());
|
||||||
|
Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree());
|
||||||
|
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
|
||||||
|
|
||||||
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
|
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
|
||||||
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
|
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
|
||||||
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
|
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
|
||||||
@@ -308,68 +300,18 @@ export class RdDUtility {
|
|||||||
Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
|
Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
|
||||||
Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite());
|
Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite());
|
||||||
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
|
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
|
||||||
Handlebars.registerHelper('getFrequenceRarete', (rarete, field) => Environnement.getFrequenceRarete(rarete, field));
|
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
|
||||||
return loadTemplates(templatePaths);
|
return loadTemplates(templatePaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getItem(itemId, actorId = undefined) {
|
static getItem(itemId, actorId = undefined) {
|
||||||
return actorId ? game.actors.get(actorId)?.getObjet(itemId) : game.items.get(itemId);
|
return actorId ? game.actors.get(actorId)?.getItem(itemId) : game.items.get(itemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
static linkCompendium(pack, id, name) {
|
static linkCompendium(pack, id, name) {
|
||||||
return `@Compendium[${pack}.${id}]{${name}}`;
|
return `@Compendium[${pack}.${id}]{${name}}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async creerObjet(actorSheet) {
|
|
||||||
let itemType = $(".item-type").val();
|
|
||||||
await actorSheet.createItem('Nouveau ' + itemType, itemType);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async selectObjetType(actorSheet) {
|
|
||||||
let typeObjets = RdDItem.getItemTypesInventaire();
|
|
||||||
let options = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
|
|
||||||
for (let typeName of typeObjets) {
|
|
||||||
options += `<option value="${typeName}">${typeName}</option>`
|
|
||||||
}
|
|
||||||
options += '</select>';
|
|
||||||
let d = new Dialog({
|
|
||||||
title: "Créer un équipement",
|
|
||||||
content: options,
|
|
||||||
buttons: {
|
|
||||||
one: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: "Créer l'objet",
|
|
||||||
callback: () => this.creerObjet(actorSheet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
d.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async selectTypeOeuvre(actorSheet) {
|
|
||||||
let typeObjets = RdDItem.getTypesOeuvres();
|
|
||||||
let options = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
|
|
||||||
for (let typeName of typeObjets) {
|
|
||||||
options += `<option value="${typeName}">${typeName}</option>`
|
|
||||||
}
|
|
||||||
options += '</select>';
|
|
||||||
let d = new Dialog({
|
|
||||||
title: "Créer un équipement",
|
|
||||||
content: options,
|
|
||||||
buttons: {
|
|
||||||
one: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: "Créer l'objet",
|
|
||||||
callback: () => this.creerObjet(actorSheet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
d.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static buildListOptions(min, max) {
|
static buildListOptions(min, max) {
|
||||||
let options = ""
|
let options = ""
|
||||||
@@ -409,68 +351,6 @@ export class RdDUtility {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static filterItemsPerTypeForSheet(formData, itemTypes) {
|
|
||||||
|
|
||||||
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']);
|
|
||||||
formData.souffles = this.arrayOrEmpty(itemTypes['souffle']);
|
|
||||||
formData.ombres = this.arrayOrEmpty(itemTypes['ombre']);
|
|
||||||
formData.tetes = this.arrayOrEmpty(itemTypes['tete']);
|
|
||||||
formData.taches = this.arrayOrEmpty(itemTypes['tache']);
|
|
||||||
formData.meditations = this.arrayOrEmpty(itemTypes['meditation']);
|
|
||||||
formData.chants = this.arrayOrEmpty(itemTypes['chant']);
|
|
||||||
formData.danses = this.arrayOrEmpty(itemTypes['danse']);
|
|
||||||
formData.musiques = this.arrayOrEmpty(itemTypes['musique']);
|
|
||||||
formData.oeuvres = this.arrayOrEmpty(itemTypes['oeuvre']);
|
|
||||||
formData.jeux = this.arrayOrEmpty(itemTypes['jeu']);
|
|
||||||
|
|
||||||
formData.recettescuisine = this.arrayOrEmpty(itemTypes['recettecuisine']);
|
|
||||||
formData.recettesAlchimiques = this.arrayOrEmpty(itemTypes['recettealchimique']);
|
|
||||||
formData.maladies = this.arrayOrEmpty(itemTypes['maladie']);
|
|
||||||
formData.poisons = this.arrayOrEmpty(itemTypes['poison']);
|
|
||||||
formData.possessions = this.arrayOrEmpty(itemTypes['possession']);
|
|
||||||
formData.maladiesPoisons = formData.maladies.concat(formData.poisons);
|
|
||||||
formData.competences = (itemTypes['competence'] ?? []).concat(itemTypes['competencecreature'] ?? []);
|
|
||||||
formData.sortsReserve = this.arrayOrEmpty(itemTypes['sortreserve']);
|
|
||||||
}
|
|
||||||
|
|
||||||
static filterEquipementParType(formData, itemTypes) {
|
|
||||||
formData.conteneurs = this.arrayOrEmpty(itemTypes['conteneur']);
|
|
||||||
|
|
||||||
formData.materiel = this.arrayOrEmpty(itemTypes['objet']);
|
|
||||||
formData.armes = this.arrayOrEmpty(itemTypes['arme']);
|
|
||||||
formData.armures = this.arrayOrEmpty(itemTypes['armure']);
|
|
||||||
formData.munitions = this.arrayOrEmpty(itemTypes['munition']);
|
|
||||||
formData.livres = this.arrayOrEmpty(itemTypes['livre']);
|
|
||||||
formData.potions = this.arrayOrEmpty(itemTypes['potion']);
|
|
||||||
formData.ingredients = this.arrayOrEmpty(itemTypes['ingredient']);
|
|
||||||
formData.faunes = this.arrayOrEmpty(itemTypes['faune']);
|
|
||||||
formData.herbes = this.arrayOrEmpty(itemTypes['herbe']);
|
|
||||||
formData.monnaie = this.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere());
|
|
||||||
formData.nourritureboissons = this.arrayOrEmpty(itemTypes['nourritureboisson']);
|
|
||||||
formData.gemmes = this.arrayOrEmpty(itemTypes['gemme']);
|
|
||||||
|
|
||||||
formData.objets = formData.conteneurs
|
|
||||||
.concat(formData.materiel)
|
|
||||||
.concat(formData.armes)
|
|
||||||
.concat(formData.armures)
|
|
||||||
.concat(formData.munitions)
|
|
||||||
.concat(formData.livres)
|
|
||||||
.concat(formData.potions)
|
|
||||||
.concat(formData.ingredients)
|
|
||||||
.concat(formData.herbes)
|
|
||||||
.concat(formData.faunes)
|
|
||||||
.concat(formData.monnaie)
|
|
||||||
.concat(formData.nourritureboissons)
|
|
||||||
.concat(formData.gemmes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static buildArbreDeConteneurs(conteneurs, objets) {
|
static buildArbreDeConteneurs(conteneurs, objets) {
|
||||||
let objetVersConteneur = {};
|
let objetVersConteneur = {};
|
||||||
@@ -515,33 +395,58 @@ export class RdDUtility {
|
|||||||
return conteneurs.filter((conteneur, index, arr) => !conteneur.estContenu);
|
return conteneurs.filter((conteneur, index, arr) => !conteneur.estContenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
static prepareOptionsArbreInventaire(item, optionsArbre) {
|
||||||
/** Construit la structure récursive des conteneurs, avec imbrication potentielle
|
if (!optionsArbre.profondeur) {
|
||||||
*
|
optionsArbre.profondeur = 1
|
||||||
*/
|
};
|
||||||
static buildConteneur(objet, profondeur) {
|
if (!optionsArbre.templateItem) {
|
||||||
if (!profondeur) profondeur = 1;
|
optionsArbre.templateItem = item.parent?.type == 'commerce'
|
||||||
objet.niveau = profondeur;
|
? "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html"
|
||||||
const isConteneur = objet.type == 'conteneur';
|
: "systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html";
|
||||||
const isOuvert = isConteneur && this.getAfficheContenu(objet._id);
|
}
|
||||||
const isVide = isConteneur && objet.system.contenu.length == 0;
|
item.niveau = optionsArbre.profondeur;
|
||||||
const conteneur = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html']({
|
|
||||||
item: objet,
|
|
||||||
vide: isVide,
|
|
||||||
ouvert: isOuvert
|
|
||||||
});
|
|
||||||
const contenu = isConteneur ? RdDUtility.buildContenu(objet, profondeur, isOuvert) : '';
|
|
||||||
return conteneur + contenu;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static buildContenu(objet, profondeur, afficherContenu) {
|
|
||||||
if (!profondeur) profondeur = 1;
|
/**
|
||||||
objet.niveau = profondeur;
|
* Construit la structure récursive des conteneurs, avec imbrication potentielle
|
||||||
const display = afficherContenu ? 'item-display-show' : 'item-display-hide';
|
*/
|
||||||
let strContenu = `<ul class='item-list alterne-list ${display} list-item-margin${Math.min(profondeur,6)}'>`;
|
static buildLigneInventaire(item, options = {}, optionsArbre = { ouvert: false, profondeur: 1 }) {
|
||||||
for (let subItem of objet.subItems) {
|
RdDUtility.prepareOptionsArbreInventaire(item, optionsArbre);
|
||||||
strContenu += this.buildConteneur(subItem, profondeur + 1);
|
|
||||||
|
const isConteneur = item.type == 'conteneur';
|
||||||
|
const inventaire = {
|
||||||
|
item: item,
|
||||||
|
vide: isConteneur && item.system.contenu.length == 0,
|
||||||
|
ouvert: isConteneur && RdDUtility.getAfficheContenu(item._id),
|
||||||
|
options: options
|
||||||
|
};
|
||||||
|
optionsArbre.ouvert = inventaire.ouvert
|
||||||
|
const ligneObjet = Handlebars.partials[optionsArbre.templateItem](inventaire);
|
||||||
|
if (isConteneur) {
|
||||||
|
return ligneObjet + RdDUtility.buildContenuConteneur(item, options, optionsArbre);
|
||||||
|
}
|
||||||
|
return ligneObjet;
|
||||||
|
}
|
||||||
|
|
||||||
|
static buildInventaireConteneur(actorId, itemId, options) {
|
||||||
|
const actor = game.actors.get(actorId)
|
||||||
|
const item = actor?.items.get(itemId)
|
||||||
|
if (item) {
|
||||||
|
return RdDUtility.buildContenuConteneur(item, options, { ouvert: true, profondeur: 1 });
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static buildContenuConteneur(conteneur, options = {}, optionsArbre = {}) {
|
||||||
|
RdDUtility.prepareOptionsArbreInventaire(conteneur, optionsArbre);
|
||||||
|
const display = optionsArbre.ouvert ? 'item-display-show' : 'item-display-hide';
|
||||||
|
let strContenu = `<ul class='item-list alterne-list ${display} list-item-margin${Math.min(optionsArbre.profondeur, 6)}'>`;
|
||||||
|
optionsArbre.profondeur++;
|
||||||
|
for (let contenu of conteneur.subItems) {
|
||||||
|
strContenu += this.buildLigneInventaire(contenu, options, optionsArbre);
|
||||||
}
|
}
|
||||||
return strContenu + "</ul>";
|
return strContenu + "</ul>";
|
||||||
}
|
}
|
||||||
@@ -693,7 +598,7 @@ export class RdDUtility {
|
|||||||
|
|
||||||
return await RdDUtility.prepareEncaissement(rollData, roll, armure);
|
return await RdDUtility.prepareEncaissement(rollData, roll, armure);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async prepareEncaissement(rollData, roll, armure) {
|
static async prepareEncaissement(rollData, roll, armure) {
|
||||||
const jetTotal = roll.total + rollData.dmg.total - armure;
|
const jetTotal = roll.total + rollData.dmg.total - armure;
|
||||||
@@ -709,11 +614,11 @@ export class RdDUtility {
|
|||||||
encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20);
|
encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20);
|
||||||
encaissement.penetration = rollData.arme?.system.penetration ?? 0;
|
encaissement.penetration = rollData.arme?.system.penetration ?? 0;
|
||||||
encaissement.blessures = (
|
encaissement.blessures = (
|
||||||
encaissement.critiques> 0 ? "Critique":
|
encaissement.critiques > 0 ? "Critique" :
|
||||||
encaissement.graves> 0 ? "Grave":
|
encaissement.graves > 0 ? "Grave" :
|
||||||
encaissement.legeres> 0 ? "Légère":
|
encaissement.legeres > 0 ? "Légère" :
|
||||||
encaissement.eraflures>0 ? "Contusions/Eraflures":
|
encaissement.eraflures > 0 ? "Contusions/Eraflures" :
|
||||||
'Aucune'
|
'Aucune'
|
||||||
);
|
);
|
||||||
return encaissement;
|
return encaissement;
|
||||||
}
|
}
|
||||||
@@ -767,8 +672,6 @@ export class RdDUtility {
|
|||||||
switch (sockmsg.msg) {
|
switch (sockmsg.msg) {
|
||||||
case "msg_gm_chat_message":
|
case "msg_gm_chat_message":
|
||||||
return ChatUtility.handleGMChatMessage(sockmsg.data);
|
return ChatUtility.handleGMChatMessage(sockmsg.data);
|
||||||
case "msg_sync_time":
|
|
||||||
return game.system.rdd.calendrier.syncPlayerTime(sockmsg.data);
|
|
||||||
case "msg_request_nombre_astral":
|
case "msg_request_nombre_astral":
|
||||||
return game.system.rdd.calendrier.requestNombreAstral(sockmsg.data);
|
return game.system.rdd.calendrier.requestNombreAstral(sockmsg.data);
|
||||||
case "msg_response_nombre_astral":
|
case "msg_response_nombre_astral":
|
||||||
@@ -813,7 +716,7 @@ export class RdDUtility {
|
|||||||
|
|
||||||
// gestion bouton tchat Acheter
|
// gestion bouton tchat Acheter
|
||||||
html.on("click", '.button-acheter', event => {
|
html.on("click", '.button-acheter', event => {
|
||||||
const venteData = DialogItemAchat.venteData(event.currentTarget);
|
const venteData = DialogItemAchat.preparerAchat(event.currentTarget);
|
||||||
if (venteData) {
|
if (venteData) {
|
||||||
DialogItemAchat.onAcheter(venteData);
|
DialogItemAchat.onAcheter(venteData);
|
||||||
}
|
}
|
||||||
@@ -829,6 +732,18 @@ export class RdDUtility {
|
|||||||
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget));
|
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
html.on("click", '.rdd-world-content-link', async event => {
|
||||||
|
const htmlElement = html.find(event.currentTarget);
|
||||||
|
const id = htmlElement?.data("id");
|
||||||
|
const doctype = htmlElement?.data("doctype");
|
||||||
|
switch (doctype ?? 'Item') {
|
||||||
|
case 'Actor':
|
||||||
|
return game.actors.get(id)?.sheet.render(true);
|
||||||
|
case 'Item':
|
||||||
|
default:
|
||||||
|
return game.items.get(id)?.sheet.render(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static findChatMessageId(current) {
|
static findChatMessageId(current) {
|
||||||
@@ -904,7 +819,7 @@ export class RdDUtility {
|
|||||||
if (p2[2] == 'd') deniers += Number(p2[1]);
|
if (p2[2] == 'd') deniers += Number(p2[1]);
|
||||||
if (p2[2] == 's') sols += Number(p2[1]);
|
if (p2[2] == 's') sols += Number(p2[1]);
|
||||||
|
|
||||||
let sommeAPayer = sols + deniers/100;
|
let sommeAPayer = sols + deniers / 100;
|
||||||
let msgPayer = `La somme de ${sols} Sols et ${deniers} Deniers est à payer<br>
|
let msgPayer = `La somme de ${sols} Sols et ${deniers} Deniers est à payer<br>
|
||||||
<a class='payer-button chat-card-button' data-somme-a-payer='${sommeAPayer}'>Payer</a>`
|
<a class='payer-button chat-card-button' data-somme-a-payer='${sommeAPayer}'>Payer</a>`
|
||||||
ChatMessage.create({ content: msgPayer });
|
ChatMessage.create({ content: msgPayer });
|
||||||
@@ -946,7 +861,7 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async confirmerSuppressionItem(sheet, item, htmlToDelete) {
|
static async confirmActorItemDelete(sheet, item, htmlToDelete) {
|
||||||
const itemId = item.id;
|
const itemId = item.id;
|
||||||
const confirmationSuppression = {
|
const confirmationSuppression = {
|
||||||
settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(),
|
settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(),
|
||||||
@@ -987,10 +902,10 @@ export class RdDUtility {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static afficherHeuresChanceMalchance(heureNaissance) {
|
static afficherHeuresChanceMalchance(heureNaissance) {
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
let heure = game.system.rdd.calendrier.findHeure(heureNaissance);
|
const heure = RdDTimestamp.findHeure(heureNaissance - 1);
|
||||||
if (heureNaissance && heure) {
|
if (heureNaissance && heure) {
|
||||||
let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance);
|
let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance);
|
||||||
const current = game.system.rdd.calendrier.findHeure(game.system.rdd.calendrier.getCurrentHeure());
|
const current = game.system.rdd.calendrier.heureCourante();
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
content: `A l'heure de <strong>${current.label}</strong>, le modificateur de Chance/Malchance est de <strong>${Misc.toSignedString(ajustement)}</strong> pour l'heure de naissance <strong>${heure.label}</strong>.`,
|
content: `A l'heure de <strong>${current.label}</strong>, le modificateur de Chance/Malchance est de <strong>${Misc.toSignedString(ajustement)}</strong> pour l'heure de naissance <strong>${heure.label}</strong>.`,
|
||||||
whisper: ChatMessage.getWhisperRecipients("GM")
|
whisper: ChatMessage.getWhisperRecipients("GM")
|
||||||
|
|||||||
@@ -56,14 +56,14 @@ export const referenceAjustements = {
|
|||||||
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined })
|
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined })
|
||||||
},
|
},
|
||||||
malusArmure: {
|
malusArmure: {
|
||||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac),
|
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac),
|
||||||
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac),
|
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac),
|
||||||
getLabel: (rollData, actor) => 'Malus armure',
|
getLabel: (rollData, actor) => 'Malus armure',
|
||||||
getValue: (rollData, actor) => actor.getMalusArmure()
|
getValue: (rollData, actor) => actor.getMalusArmure()
|
||||||
},
|
},
|
||||||
encTotal: {
|
encTotal: {
|
||||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
||||||
isUsed: (rollData, actor) => !rollData.oeuvre && RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) && rollData.use.encTotal,
|
isUsed: (rollData, actor) => !rollData.oeuvre && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) && rollData.use.encTotal,
|
||||||
getLabel: (rollData, actor) => 'Encombrement total',
|
getLabel: (rollData, actor) => 'Encombrement total',
|
||||||
getValue: (rollData, actor) => -actor.getEncTotal()
|
getValue: (rollData, actor) => -actor.getEncTotal()
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -52,12 +52,16 @@ export class SystemCompendiums extends FormApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static getPack(compendium) {
|
static getPack(compendium) {
|
||||||
|
const pack = game.packs.get(compendium);
|
||||||
|
if (pack) {
|
||||||
|
return pack;
|
||||||
|
}
|
||||||
return game.packs.get(SystemCompendiums.getCompendium(compendium)) ?? game.packs.get(SystemCompendiums._getDefaultCompendium(compendium));
|
return game.packs.get(SystemCompendiums.getCompendium(compendium)) ?? game.packs.get(SystemCompendiums._getDefaultCompendium(compendium));
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getPackContent(compendium, docType) {
|
static async getPackContent(compendium, docType) {
|
||||||
const pack = SystemCompendiums.getPack(compendium);
|
const pack = SystemCompendiums.getPack(compendium);
|
||||||
if (pack.metadata.type == docType) {
|
if (pack?.metadata.type == docType) {
|
||||||
return await pack.getDocuments();
|
return await pack.getDocuments();
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
@@ -87,6 +91,11 @@ export class SystemCompendiums extends FormApplication {
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async loadDocument(document) {
|
||||||
|
const pack = game.packs.get(document.pack);
|
||||||
|
return await pack.getDocument(document.id ?? document._id);
|
||||||
|
}
|
||||||
|
|
||||||
static async getItems(compendium, itemType = undefined) {
|
static async getItems(compendium, itemType = undefined) {
|
||||||
const items = await SystemCompendiums.getPackContent(compendium, 'Item');
|
const items = await SystemCompendiums.getPackContent(compendium, 'Item');
|
||||||
return (itemType ? items.filter(it => it.type == itemType) : items);
|
return (itemType ? items.filter(it => it.type == itemType) : items);
|
||||||
@@ -172,7 +181,7 @@ export class SystemCompendiums extends FormApplication {
|
|||||||
*/
|
*/
|
||||||
export class CompendiumTable {
|
export class CompendiumTable {
|
||||||
|
|
||||||
constructor(compendium, type, subTypes, sorting = undefined) {
|
constructor(compendium, type, subTypes = undefined, sorting = undefined) {
|
||||||
this.compendium = compendium;
|
this.compendium = compendium;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.subTypes = subTypes;
|
this.subTypes = subTypes;
|
||||||
@@ -182,13 +191,13 @@ export class CompendiumTable {
|
|||||||
async getContent(itemFrequence = it => it.system.frequence, filter = it => true) {
|
async getContent(itemFrequence = it => it.system.frequence, filter = it => true) {
|
||||||
return await SystemCompendiums.getContent(this.compendium,
|
return await SystemCompendiums.getContent(this.compendium,
|
||||||
this.type,
|
this.type,
|
||||||
it => this.subTypes.includes(it.type) && filter(it),
|
it => (!this.subTypes || this.subTypes.includes(it.type)) && itemFrequence(it) > 0 && filter(it),
|
||||||
itemFrequence,
|
itemFrequence,
|
||||||
this.sorting);
|
this.sorting);
|
||||||
}
|
}
|
||||||
|
|
||||||
async buildTable(itemFrequence = it => it.system.frequence, filter = it => true) {
|
async buildTable(itemFrequence = it => it.system.frequence, filter = it => true) {
|
||||||
const elements = await this.getContent(filter, itemFrequence);
|
const elements = await this.getContent(itemFrequence, filter);
|
||||||
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -220,9 +229,23 @@ export class CompendiumTableHelpers {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getRandom(table, type, subTypes, forcedRoll = undefined, localisation = undefined) {
|
static concatTables(...tables) {
|
||||||
|
const rows = tables.reduce((a, b) => a.concat(b));
|
||||||
|
let max = 0;
|
||||||
|
const total = rows.map(it => it.frequence).reduce(Misc.sum(), 0);
|
||||||
|
return rows.map(row => {
|
||||||
|
const frequence = row.frequence;
|
||||||
|
row.min = max + 1;
|
||||||
|
row.max = max + frequence;
|
||||||
|
row.total = total
|
||||||
|
max += frequence;
|
||||||
|
return row;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
static async getRandom(table, type, subTypes = ['objet'], forcedRoll = undefined, localisation = undefined) {
|
||||||
if (table.length == 0) {
|
if (table.length == 0) {
|
||||||
ui.notifications.warn(`Aucun ${Misc.typeName(type, subTypes[0])} trouvé dans ${localisation ?? ' les compendiums'}`);
|
const typeName = Misc.typeName(type, subTypes[0]);
|
||||||
|
ui.notifications.warn(`Aucun ${typeName} trouvé dans ${localisation ?? ' les compendiums'}`);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return await CompendiumTableHelpers.selectRow(table, forcedRoll);
|
return await CompendiumTableHelpers.selectRow(table, forcedRoll);
|
||||||
@@ -255,7 +278,7 @@ export class CompendiumTableHelpers {
|
|||||||
roll: row.roll,
|
roll: row.roll,
|
||||||
document: row.document,
|
document: row.document,
|
||||||
percentages,
|
percentages,
|
||||||
typeName: Misc.typeName(type, row.document.type),
|
typeName: Misc.typeName(type, row.document?.type ?? 'objet'),
|
||||||
isGM: game.user.isGM,
|
isGM: game.user.isGM,
|
||||||
});
|
});
|
||||||
const messageData = {
|
const messageData = {
|
||||||
|
|||||||
359
module/tirage/fenetre-recherche-tirage.js
Normal file
@@ -0,0 +1,359 @@
|
|||||||
|
import { RdDItem } from '../item.js';
|
||||||
|
import { HtmlUtility } from '../html-utility.js';
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { CompendiumTableHelpers } from '../settings/system-compendiums.js';
|
||||||
|
import { RdDRaretes } from '../item/raretes.js';
|
||||||
|
import { Grammar } from '../grammar.js';
|
||||||
|
|
||||||
|
const FILTER_GROUPS = [
|
||||||
|
{ group: 'type', label: "Type d'objet" },
|
||||||
|
{ group: 'comestible', label: 'Alimentaire' },
|
||||||
|
{ group: 'utilisation', label: 'Utilisation' },
|
||||||
|
{ group: 'rarete', label: 'Rarete' },
|
||||||
|
{ group: 'qualite', label: 'Qualité' },
|
||||||
|
{ group: 'enc', label: 'Encombrement' },
|
||||||
|
{ group: 'prix', label: 'Prix' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const FILTERS = [
|
||||||
|
{ group: 'comestible', code: 'comestible', label: 'Comestible', check: (item, milieux) => item.getUtilisation() == 'cuisine' },
|
||||||
|
{ group: 'comestible', code: 'pret', label: 'Préparé', check: (item, milieux) => item.getUtilisationCuisine() == 'pret' },
|
||||||
|
{ group: 'comestible', code: 'brut', label: 'A préparer', check: (item, milieux) => item.getUtilisationCuisine() == 'brut' },
|
||||||
|
{ group: 'comestible', code: 'boisson', label: 'Boisson', check: (item, milieux) => item.isBoisson() },
|
||||||
|
{ group: 'comestible', code: 'alcool', label: 'Alcool', check: (item, milieux) => item.isAlcool() },
|
||||||
|
{ group: 'comestible', code: 'immangeable', label: 'Immangeable', check: (item, milieux) => item.isInventaire() && item.getUtilisation() != 'cuisine' },
|
||||||
|
|
||||||
|
{ group: 'utilisation', code: 'alchimie', label: 'Alchimique', check: (item, milieux) => item.isInventaire() && item.getUtilisation() == 'alchimie' },
|
||||||
|
{ group: 'utilisation', code: 'soins', label: 'Médical', check: (item, milieux) => item.isInventaire() && item.getUtilisation() == 'soins' },
|
||||||
|
{ group: 'utilisation', code: 'poison', label: 'Toxique', check: (item, milieux) => item.isInventaire() && item.getUtilisation() == 'poison' },
|
||||||
|
{ group: 'utilisation', code: 'cuisine', label: 'Cuisine', check: (item, milieux) => item.isInventaire() && item.getUtilisation() == 'cuisine' },
|
||||||
|
{ group: 'utilisation', code: 'autres', label: 'Autres/inconnu', check: (item, milieux) => !item.isInventaire() || item.getUtilisation() == '' },
|
||||||
|
|
||||||
|
{ group: "qualite", code: "mauvaise", label: "Mauvaise (négative)", check: (item, milieux) => item.isInventaire() && item.system.qualite < 0 },
|
||||||
|
{ group: "qualite", code: "quelconque", label: "Quelconque (0)", check: (item, milieux) => item.isInventaire() && item.system.qualite == 0 },
|
||||||
|
{ group: "qualite", code: "correcte", label: "Correcte (1-3)", check: (item, milieux) => item.isInventaire() && 1 <= item.system.qualite && item.system.qualite <= 3 },
|
||||||
|
{ group: "qualite", code: "bonne", label: "Bonne (4-6)", check: (item, milieux) => item.isInventaire() && 4 <= item.system.qualite && item.system.qualite <= 6 },
|
||||||
|
{ group: "qualite", code: "excellente", label: "Excellente (7-9)", check: (item, milieux) => item.isInventaire() && 7 <= item.system.qualite && item.system.qualite <= 9 },
|
||||||
|
{ group: "qualite", code: "mythique", label: "Mythique (10+)", check: (item, milieux) => item.isInventaire() && 10 <= item.system.qualite },
|
||||||
|
|
||||||
|
{ group: "enc", code: "negligeable", label: "Négligeable (jusqu'à 0.1)", check: (item, milieux) => item.isInventaire() && item.system.encombrement <= 0.1 },
|
||||||
|
{ group: "enc", code: "leger", label: "Léger (0.1 à 0.5)", check: (item, milieux) => item.isInventaire() && 0.1 < item.system.encombrement && item.system.encombrement <= 0.5 },
|
||||||
|
{ group: "enc", code: "moyen", label: "Moyen (0.5 à 1.5)", check: (item, milieux) => item.isInventaire() && 0.5 < item.system.encombrement && item.system.encombrement <= 1.5 },
|
||||||
|
{ group: "enc", code: "lourd", label: "Lourd (1.5 à 3)", check: (item, milieux) => item.isInventaire() && 1.5 < item.system.encombrement && item.system.encombrement <= 3 },
|
||||||
|
{ group: "enc", code: "massif", label: "Massif (3 à 10)", check: (item, milieux) => item.isInventaire() && 3 < item.system.encombrement && item.system.encombrement <= 10 },
|
||||||
|
{ group: "enc", code: "anemort", label: "Un âne mort (plus de 10)", check: (item, milieux) => item.isInventaire() && 10 < item.system.encombrement },
|
||||||
|
|
||||||
|
{ group: "prix", code: "gratuit", label: "Gratuit", check: (item, milieux) => item.isInventaire() && item.system.cout == 0 },
|
||||||
|
{ group: "prix", code: "deniers", label: "Deniers (étain)", check: (item, milieux) => item.isInventaire() && 0 < item.system.cout && item.system.cout < 0.1 },
|
||||||
|
{ group: "prix", code: "bronze", label: "Sous (bronze)", check: (item, milieux) => item.isInventaire() && 0.1 <= item.system.cout && item.system.cout < 1 },
|
||||||
|
{ group: "prix", code: "sols", label: "Sols (argent)", check: (item, milieux) => item.isInventaire() && 1 <= item.system.cout && item.system.cout < 10 },
|
||||||
|
{ group: "prix", code: "dragons", label: "Dragons (or)", check: (item, milieux) => item.isInventaire() && 10 <= item.system.cout },
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
function $filterMilieux(milieux) {
|
||||||
|
return milieux.map(m => {
|
||||||
|
return {
|
||||||
|
code: m,
|
||||||
|
label: m,
|
||||||
|
check: (item, milieux) => item.isPresentDansMilieux(m)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function $filterRarete() {
|
||||||
|
return RdDRaretes.raretes()
|
||||||
|
.filter(it => it.frequence > 0)
|
||||||
|
.map(r => {
|
||||||
|
return {
|
||||||
|
group: 'rarete',
|
||||||
|
code: r.code,
|
||||||
|
label: r.label,
|
||||||
|
check: (item, milieux) => item.getRaretes(milieux).map(it => it.code).includes(r.code)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function $filterTypes() {
|
||||||
|
return RdDItem.getItemTypesInventaire().map(type => {
|
||||||
|
return {
|
||||||
|
group: 'type',
|
||||||
|
code: type,
|
||||||
|
label: Misc.typeName('Item', type),
|
||||||
|
check: (item, milieux) => item.type == type
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function $getAllFilters() {
|
||||||
|
return FILTERS
|
||||||
|
.concat($filterTypes())
|
||||||
|
.concat($filterRarete());
|
||||||
|
}
|
||||||
|
|
||||||
|
function $addFilterToGroup(groups, filter) {
|
||||||
|
if (filter.group && filter.code && filter.label) {
|
||||||
|
let fg = groups.find(g => g.group == filter.group);
|
||||||
|
if (fg == undefined) {
|
||||||
|
groups.push({ group: filter.group, label: filter.group, filters: [filter] })
|
||||||
|
}
|
||||||
|
else if (fg.filters == undefined) {
|
||||||
|
fg.filters = [filter];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fg.filters.push(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.warn("Filtre incorrect, pas de groupe/code/label", filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function $loadFilters(parameters) {
|
||||||
|
$getAllFilters(parameters.milieux).forEach(f => $addFilterToGroup(parameters.filterGroups, f));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export class FenetreRechercheTirage extends Application {
|
||||||
|
static get defaultOptions() {
|
||||||
|
return mergeObject(super.defaultOptions, {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/tirage/fenetre-recherche-tirage.hbs",
|
||||||
|
title: `Recherches et tirages`,
|
||||||
|
width: 600,
|
||||||
|
height: 600,
|
||||||
|
popOut: true,
|
||||||
|
dragDrop: [{ dragSelector: "a.content-link" }],
|
||||||
|
resizable: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static async create() {
|
||||||
|
const milieux = await game.system.rdd.environnement.milieux();
|
||||||
|
const parameters = {
|
||||||
|
milieux: milieux,
|
||||||
|
filterMilieux: $filterMilieux(milieux),
|
||||||
|
filterGroups: duplicate(FILTER_GROUPS).filter(it => it.group),
|
||||||
|
}
|
||||||
|
const options = {}
|
||||||
|
$loadFilters(parameters);
|
||||||
|
|
||||||
|
new FenetreRechercheTirage(parameters, options).render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(parameters, options) {
|
||||||
|
super(options);
|
||||||
|
this.parameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData() {
|
||||||
|
return mergeObject(await super.getData(), this.parameters)
|
||||||
|
}
|
||||||
|
|
||||||
|
_canDragStart() { return true; }
|
||||||
|
_onDragStart(event) { }
|
||||||
|
|
||||||
|
_getHeaderButtons() {
|
||||||
|
let buttons = super._getHeaderButtons();
|
||||||
|
if (game.user.isGM) {
|
||||||
|
buttons.unshift({
|
||||||
|
class: "configurer",
|
||||||
|
label: "Configurer",
|
||||||
|
icon: "fas fa-cogs",
|
||||||
|
onclick: ev => this.configurer()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html = html;
|
||||||
|
|
||||||
|
this.showFilterGroup(this.html, false);
|
||||||
|
|
||||||
|
this.html.find("a.section-filters-toggle").click(event => {
|
||||||
|
const groupDiv = this.html.find(event.currentTarget)?.parents('div.section-filters-root').first();
|
||||||
|
const visible = groupDiv.find('div.section-filters-content').first().is(":visible");
|
||||||
|
this.showFilterGroup(groupDiv, !visible)
|
||||||
|
});
|
||||||
|
|
||||||
|
this.html.find("input:is(.activate-filter-group,.activate-filter-milieu)").change(event => this.changeListeFiltresActifs())
|
||||||
|
|
||||||
|
this.html.find("a.supprimer-filtres").click(async event => this.supprimerFiltres())
|
||||||
|
|
||||||
|
this.html.find("a.recherche-filtres").click(async event => await this.recherche())
|
||||||
|
|
||||||
|
this.html.find("a.tirage-filtres").click(async event => {
|
||||||
|
const table = await this.buildTable();
|
||||||
|
const row = await CompendiumTableHelpers.getRandom(table, 'Item')
|
||||||
|
await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item');
|
||||||
|
})
|
||||||
|
|
||||||
|
// this.html.find('.recherche')
|
||||||
|
// .each((index, field) => {
|
||||||
|
// if (this.options.recherche) {
|
||||||
|
// field.focus();
|
||||||
|
// field.setSelectionRange(this.options.recherche.start, this.options.recherche.end);
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .keyup(async event => {
|
||||||
|
// const nouvelleRecherche = this._optionRecherche(event.currentTarget);
|
||||||
|
// if (this.options.recherche?.text != nouvelleRecherche?.text) {
|
||||||
|
// this.options.recherche = nouvelleRecherche;
|
||||||
|
// if (this.timerRecherche) {
|
||||||
|
// clearTimeout(this.timerRecherche);
|
||||||
|
// }
|
||||||
|
// this.timerRecherche = setTimeout(() => {
|
||||||
|
// this.timerRecherche = undefined;
|
||||||
|
// this.render(true);
|
||||||
|
// }, 500);
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// .change(async event =>
|
||||||
|
// this.options.recherche = this._optionRecherche(event.currentTarget)
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
showFilterGroup(groupDiv, show) {
|
||||||
|
if (groupDiv) {
|
||||||
|
HtmlUtility.showControlWhen(groupDiv.find('div.section-filters-content'), show);
|
||||||
|
HtmlUtility.showControlWhen(groupDiv.find('i.section-filters-hide'), show);
|
||||||
|
HtmlUtility.showControlWhen(groupDiv.find('i.section-filters-show'), !show);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
supprimerFiltres() {
|
||||||
|
this.html.find('input:is(.activate-filter-group,.activate-filter-milieu)').prop("checked", false);
|
||||||
|
this.html.find('div.liste-resultats-recherche').html('');
|
||||||
|
this.html.find('.section-filters-text input.recherche').val('');
|
||||||
|
}
|
||||||
|
|
||||||
|
async recherche() {
|
||||||
|
const table = await this.buildTable();
|
||||||
|
const htmlResultats = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs`, { resultats: table });
|
||||||
|
this.html.find('div.liste-resultats-recherche').html(htmlResultats);
|
||||||
|
this._dragDrop.forEach(dragDropHandler => dragDropHandler.bind(this.element[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildTable() {
|
||||||
|
const milieux = this.getSelectedMilieux();
|
||||||
|
const filterItemMilieux = this.buildCheckedGroupFilter(milieux);
|
||||||
|
const filter = it => filterItemMilieux(it, milieux);
|
||||||
|
const itemFrequence = it => it.getFrequence(milieux);
|
||||||
|
return await game.system.rdd.environnement.buildTable(itemFrequence, filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
buildMilieuxFilter(milieux) {
|
||||||
|
if (milieux) {
|
||||||
|
return this.buildOrFilter(this.parameters.filterMilieux.filter(it => milieux.includes(it.code)).map(f => f.check));
|
||||||
|
}
|
||||||
|
return (it, mi) => true;
|
||||||
|
}
|
||||||
|
buildFilterRechercheName() {
|
||||||
|
const recherche = this.html.find('.section-filters-text input.recherche').val();
|
||||||
|
if (recherche) {
|
||||||
|
return (it, mi) => Grammar.includesLowerCaseNoAccent(it.name, recherche);
|
||||||
|
}
|
||||||
|
return (it, mi) => true;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildCheckedGroupFilter(milieux) {
|
||||||
|
const filtersList = this.getGroupCheckedFilters()
|
||||||
|
.map(gf => this.buildOrFilter(gf.filters.map(f => f.check)));
|
||||||
|
filtersList.push(this.buildMilieuxFilter(milieux));
|
||||||
|
filtersList.push(this.buildFilterRechercheName());
|
||||||
|
return this.buildAndFilter(filtersList)
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAndFilter(filters) { return filters.reduce((f1, f2) => { return (it, mi) => f1(it, mi) && f2(it, mi); }); }
|
||||||
|
buildOrFilter(filters) { return filters.reduce((f1, f2) => { return (it, mi) => f1(it, mi) || f2(it, mi); }); }
|
||||||
|
|
||||||
|
changeListeFiltresActifs() {
|
||||||
|
const milieux = this.getSelectedMilieux();
|
||||||
|
const summariesList = this.getGroupCheckedFilters()
|
||||||
|
.map(gf => {
|
||||||
|
return gf.group.label + ': ' + gf.filters
|
||||||
|
.map(f => f.label)
|
||||||
|
.reduce(Misc.joining(', '))
|
||||||
|
});
|
||||||
|
if (milieux) {
|
||||||
|
summariesList.push('Milieux: ' + this.parameters.filterMilieux.filter(f => milieux.includes(f.code)).map(f => f.label).reduce(Misc.joining(', ')))
|
||||||
|
}
|
||||||
|
const fullText = summariesList.length == 0 ? "" : summariesList.reduce(Misc.joining(' - '));
|
||||||
|
this.html.find('span.liste-filtres-actifs').text(fullText);
|
||||||
|
}
|
||||||
|
|
||||||
|
getGroupCheckedFilters() {
|
||||||
|
const checkedGroupFilters = jQuery.map(this.html.find('input.activate-filter-group:checked'), it => this.html.find(it))
|
||||||
|
.map(element => {
|
||||||
|
return {
|
||||||
|
group: element.data('group'),
|
||||||
|
code: element.data('code')
|
||||||
|
};
|
||||||
|
}).filter(it => it.group);
|
||||||
|
|
||||||
|
const entries = Object.entries(Misc.classify(checkedGroupFilters, it => it.group));
|
||||||
|
return entries.map(([key, list]) => {
|
||||||
|
const group = this.parameters.filterGroups.find(g => g.group == key);
|
||||||
|
const filters = list.map(it => group.filters.find(f => it.code == f.code));
|
||||||
|
return { group, filters };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getSelectedMilieux() {
|
||||||
|
const milieux = jQuery.map(this.html.find('input.activate-filter-milieu:checked'), it => {
|
||||||
|
return this.html.find(it).data('code');
|
||||||
|
});
|
||||||
|
return milieux.length == 0 ? undefined : milieux
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async configurer() {
|
||||||
|
FenetreRechercheConfiguration.create();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FenetreRechercheConfiguration extends Dialog {
|
||||||
|
static async create() {
|
||||||
|
const configuration = {
|
||||||
|
compendiums: game.packs.filter(it => it.metadata.type == 'Item').map(it => it.metadata)
|
||||||
|
.map(it => mergeObject({ selected: game.system.rdd.environnement.compendiums.includes(it.id) }, it))
|
||||||
|
}
|
||||||
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/tirage/fenetre-recherche-configuration.hbs", configuration);
|
||||||
|
new FenetreRechercheConfiguration(html).render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(html) {
|
||||||
|
const options = {
|
||||||
|
classes: ["fenetre-recherche-configuration"],
|
||||||
|
width: 600,
|
||||||
|
height: 'fit-content',
|
||||||
|
'max-height': 600,
|
||||||
|
height: 'fit-content',
|
||||||
|
'z-index': 99999
|
||||||
|
};
|
||||||
|
const conf = {
|
||||||
|
title: 'Configuration de la recherche',
|
||||||
|
content: html,
|
||||||
|
buttons: {
|
||||||
|
"Sauvegarder": { label: "Sauvegarder", callback: async it => { await this.sauvegarder(); } }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
super(conf, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
this.html = html;
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html.find("button.configuration-save").click(event => this.sauvegarder())
|
||||||
|
}
|
||||||
|
|
||||||
|
async sauvegarder() {
|
||||||
|
const compendiumIds = jQuery.map(this.html.find("input.select-compendium:checked"), it => {
|
||||||
|
return this.html.find(it).data('id');
|
||||||
|
});
|
||||||
|
await game.system.rdd.environnement.saveCompendiums(compendiumIds);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,10 +12,10 @@ export class TMRRencontres {
|
|||||||
static init() {
|
static init() {
|
||||||
const tmrRencontre = new TMRRencontres();
|
const tmrRencontre = new TMRRencontres();
|
||||||
game.system.rdd.rencontresTMR = tmrRencontre;
|
game.system.rdd.rencontresTMR = tmrRencontre;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(){
|
constructor() {
|
||||||
this.table = new CompendiumTable('rencontres', 'Item', 'rencontre', Misc.ascending(it => it.system.ordreTri));
|
this.table = new CompendiumTable('rencontres', 'Item', 'rencontre', Misc.ascending(it => it.system.ordreTri));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,24 +59,16 @@ export class TMRRencontres {
|
|||||||
return rencontre.clone({
|
return rencontre.clone({
|
||||||
'system.force': await RdDDice.rollTotal(rencontre.system.formule),
|
'system.force': await RdDDice.rollTotal(rencontre.system.formule),
|
||||||
'system.coord': tmr?.coord,
|
'system.coord': tmr?.coord,
|
||||||
'system.date': game.system.rdd.calendrier.getDateFromIndex(),
|
'system.date': game.system.rdd.calendrier.dateCourante(),
|
||||||
'system.heure': game.system.rdd.calendrier.getCurrentHeure()
|
'system.heure': game.system.rdd.calendrier.heureCourante().key
|
||||||
}, { save: false });
|
}, { save: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
async calculRencontre(rencontre, tmr = undefined) {
|
async calculRencontre(rencontre, tmr = undefined) {
|
||||||
if (rencontre.system.coord == "") {
|
rencontre.system.coord = rencontre.system.coord ?? tmr?.coord;
|
||||||
rencontre.system.coord = tmr?.coord;
|
rencontre.system.force = rencontre.system.force ?? await RdDDice.rollTotal(rencontre.system.formule);
|
||||||
}
|
rencontre.system.date = rencontre.system.date ?? game.system.rdd.calendrier.dateCourante();
|
||||||
if (rencontre.system.force == 0) {
|
rencontre.system.heure = rencontre.system.heure ?? game.system.rdd.calendrier.heureCourante().key;
|
||||||
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;
|
return rencontre;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,7 +102,7 @@ export class TMRRencontres {
|
|||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async $chatRolledRencontre(row, rencontre,tmr) {
|
async $chatRolledRencontre(row, rencontre, tmr) {
|
||||||
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table-roll-rencontre.html',
|
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table-roll-rencontre.html',
|
||||||
{
|
{
|
||||||
roll: row.roll,
|
roll: row.roll,
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
{"name":"Arme d’hast","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":4,"equipe":false,"dommages":"4","force":"12","resistance":8,"competence":"Arme d'hast","cout":10,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/hast.webp","effects":[],"_id":"U6qli6TPbzj8tUdH"}
|
|
||||||
{"name":"Bâton","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"1","force":"9","resistance":8,"competence":"Masse à 2 mains","cout":0.5,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/baton.webp","effects":[],"_id":"wyiy7aLaP8jnzkFn"}
|
|
||||||
{"name":"Bouclier léger","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"0","force":"8","resistance":13,"competence":"Bouclier","cout":4,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_petit.webp","effects":[],"_id":"eK28jEeQiJdd93L3"}
|
|
||||||
{"name":"Bouclier lourd","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"0","force":"13","resistance":20,"competence":"Bouclier","cout":8,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_grand.webp","effects":[],"_id":"7B9sKLf4ipRyyEjF"}
|
|
||||||
{"name":"Bouclier moyen","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"0","force":"11","resistance":15,"competence":"Bouclier","cout":6,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_moyen.webp","effects":[],"_id":"1O7IJiQSDYxJ5VsD"}
|
|
||||||
{"name":"Cuir / Metal","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>Cuir épais clouté, ou petites plaquettes, écailles ou anneaux de fer cousus sur le cuir. Pectoral ou cotte de cuir/métal + jupon ou cuissards de cuir / métal sur culottes de cuir souple + bottes de cuir / métal + casque de métal.</p>\n<p> </p>","quantite":1,"encombrement":4,"equipe":false,"protection":4,"deterioration":0,"malus":-2,"cout":20},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_metal.webp","effects":[],"_id":"fDwsTMuug0Z5BdaA"}
|
|
||||||
{"name":"Cuir Epais","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>Cuir très épais comme le cuir de botte. Pectoral de cuir épais + jupon de bandes ou de tresses de cuir ou cuissards de cuir épais sur culottes de cuir souple + bottes dures + casque de cuir.</p>\n<p> </p>","quantite":1,"encombrement":2,"equipe":false,"protection":3,"deterioration":0,"malus":-1,"cout":10},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_epais.webp","effects":[],"_id":"szOThadvQvFcS79R"}
|
|
||||||
{"name":"Cuir Souple","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>Même épaisseur que nos modernes blousons de cuir. Pourpoint ou cotte de cuir souple + culottes de cuir souple + bottes de cuir souple.</p>\n<p> </p>","quantite":1,"encombrement":0,"equipe":false,"protection":2,"deterioration":0,"malus":0,"cout":6},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_souple.webp","effects":[],"_id":"b0f08L5CDeFIMluC"}
|
|
||||||
{"name":"Dague","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":0.5,"equipe":false,"dommages":"1","force":"7","resistance":8,"competence":"Dague","cout":3,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{"core":{"sheetClass":""}},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/dague.webp","effects":[],"_id":"CGYOJbaKtYvF2qa9"}
|
|
||||||
{"name":"Double dragonne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>Apparue vers la fin du Second Âge, c’était<em> une grande épée à deux mains</em>. Encombrante et prohibant le bouclier, c’était avant tout une épée de duel et de frime.</p>","quantite":1,"encombrement":4,"equipe":false,"dommages":"5","force":"13","resistance":13,"competence":"Epée à 2 mains","cout":50,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/double_dragonne.webp","effects":[],"_id":"6s5QjArwz9w9JIGL"}
|
|
||||||
{"name":"Drap Matelassé","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>Deux épaisseurs de drap surpiquées, avec rembourrage de laine.</p>\n<p>Pourpoint ou cotte de drap matelassé + culottes de drap matelassé + bottes de cuir souple. Le pourpoint est une sorte de veste ; la cotte est une sorte de tunique, lacée sur la poitrine, et descendant jusqu’aux genoux, façon Robin des Bois.</p>\n<p> </p>","quantite":1,"encombrement":0,"equipe":false,"protection":1,"deterioration":0,"malus":0,"cout":4},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/drap_matelasse.webp","effects":[],"_id":"vQ494sD9FgFI08kZ"}
|
|
||||||
{"name":"Épée bâtarde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>Comme son nom l’indique, c’est une <em>bâtarde </em>de l'épée longue et de l'épée sorde, à la fois longue et large, pouvant s’utiliser à une ou deux mains.</p>","quantite":1,"encombrement":3,"equipe":false,"dommages":"4/5","force":"13/12","resistance":14,"competence":"Epée à 1 main","cout":30,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_batarde.webp","effects":[],"_id":"KmfftnkUsPQD6fV0"}
|
|
||||||
{"name":"Épée cyane","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>Long <em>cimeterre </em>à l’acier bleuté, exclusivement fabriqué par les Cyans ou Hommes bleus.</p>","quantite":1,"encombrement":2,"equipe":false,"dommages":"3","force":"11","resistance":12,"competence":"Epée à 1 main","cout":25,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_cyane.webp","effects":[],"_id":"ijCebH1Pr3LmzdOj"}
|
|
||||||
{"name":"Épée demi-dragonne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":null,"quantite":1,"encombrement":1.5,"equipe":false,"dommages":"2","force":"10","resistance":10,"competence":"Epée à 1 main","cout":15,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{"core":{"sourceId":"Item.ErwaSLcGryAbYjkm"}},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/demi_dragonne.webp","effects":[],"_id":"IlA16EWR1x5ZBckA"}
|
|
||||||
{"name":"Épée dragonne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>C’est une épée <em>longue</em>, plus robuste que l’esparlongue, pouvant également frapper de taille.</p>","quantite":1,"encombrement":2,"equipe":false,"dommages":"3","force":"11","resistance":12,"competence":"Epée à 1 main","cout":20,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_dragonne.webp","effects":[],"_id":"3Wk5dzp3M7Das6wh"}
|
|
||||||
{"name":"Épée gnome","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>C’est une épée <em>courte</em>, essentiellement fabriquée et portée par les Gnomes au Second Âge.</p>","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","force":"8","resistance":12,"competence":"Epée à 1 main","cout":12,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp","effects":[],"_id":"WurdjqJ8zMiXNdiW"}
|
|
||||||
{"name":"Épée sorde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>C’est une épée plus courte que la dragonne, mais plus <em>large</em>. Elle peut s’utiliser à une ou deux mains. Sa grande solidité en fait l’épée de prédilection des gardes et des soldats.</p>\n<p>C’est probablement à elle que le <em>Guerrier Sorde</em> doit son nom (à moins que ce ne soit l’inverse).</p>","quantite":1,"encombrement":2,"equipe":false,"dommages":"3/4","force":"12/11","resistance":15,"competence":"Epée à 1 main","cout":20,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_sord.webp","effects":[],"_id":"cFnFQrQIPgyZRWdo"}
|
|
||||||
{"name":"Esparlongue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>C’est une épée semblable à la <em>rapière</em>, longue et ne frappant uniquement d’estoc. Elle doit son nom à ce qu’elle était particulièrement en vogue, au Second Âge, dans la cité d’Esparlongue. En ce début du Troisième Âge, toutefois, on lui substitue le plus souvent la <strong>demi-dragonne</strong>, épée très voisine, ne frappant pareillement que d’estoc, mais plus résistante (résistance 10) et moins coûteuse (15 sols) ; son bonus aux dommages (+2) est identique.</p>","quantite":1,"encombrement":1.5,"equipe":false,"dommages":"2","force":"10","resistance":9,"competence":"Epée à 1 main","cout":20,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/esparlongue.webp","effects":[],"_id":"t3LZDSaQ6AiloImA"}
|
|
||||||
{"name":"Fléau léger","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"3","force":"12","resistance":10,"competence":"Fléau","cout":12,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/fleau_leger.webp","effects":[],"_id":"J4PpWO4OZ6JPaAUB"}
|
|
||||||
{"name":"Fléau lourd","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"4","force":"13","resistance":10,"competence":"Fléau","cout":15,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/fleau_lourd.webp","effects":[],"_id":"HRLrRhAF4Hkfbqjh"}
|
|
||||||
{"name":"Gourdin","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"1","force":"7","resistance":8,"competence":"Masse à 1 main","cout":0,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/gourdin.webp","effects":[],"_id":"PoTI2z0Wr4hxiLpQ"}
|
|
||||||
{"name":"Grande hache","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"4","force":"13","resistance":8,"competence":"Hache à 2 mains","cout":15,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/grande_hache.webp","effects":[],"_id":"hVgd4APvAW8sbXf0"}
|
|
||||||
{"name":"Hache de bataille","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"3/4","force":"12/11","resistance":8,"competence":"Hache à 1 main","cout":15,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/hache_bataille.webp","effects":[],"_id":"9jbjDpbddL2Ep09s"}
|
|
||||||
{"name":"Hachette","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","force":"8","resistance":6,"competence":"Hache à 1 main","cout":4,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/systems/foundryvtt-reve-de-dragon/icons/objets/hachette.webp","effects":[],"_id":"TKyv5S3VNaOLOWJw"}
|
|
||||||
{"name":"Javeline","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"1","force":"7","resistance":5,"competence":"Lance","cout":1,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/javeline.webp","effects":[],"_id":"Ri5QtS98FTfgHk2N"}
|
|
||||||
{"name":"Lance courte","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"2","force":"8","resistance":5,"competence":"Lance","cout":3,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/lance.webp","effects":[],"_id":"viHilj5hAHZqWuli"}
|
|
||||||
{"name":"Mailles de Fer","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>Grand haubert de mailles avec capuche À enfiler sur une cotte de cuir souple ou de drap matelassé) + bottes de cuir / métal.</p>\n<p> </p>","quantite":1,"encombrement":6,"equipe":false,"protection":5,"deterioration":null,"malus":-4,"cout":50},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/mailles.webp","effects":[],"_id":"KQZIK8ltQ3sQiDGe"}
|
|
||||||
{"name":"Marteau","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":0.3,"equipe":false,"dommages":"2","force":"7","resistance":8,"competence":"Masse à 1 main","cout":1,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/systems/foundryvtt-reve-de-dragon/icons/objets/marteau.webp","effects":[],"_id":"i26px61PjvPlOiJW"}
|
|
||||||
{"name":"Masse lourde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"3/4","force":"12/11","resistance":10,"competence":"Masse à 1 main","cout":4,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/masse_lourde.webp","effects":[],"_id":"7xFe41JZIVNMLv1U"}
|
|
||||||
{"name":"Massette","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","force":"9","resistance":8,"competence":"Masse à 1 main","cout":2,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/massette.webp","effects":[],"_id":"wK5sGduzSvY3XxMF"}
|
|
||||||
{"name":"Plaques de Fer","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>L'armure classique du chevalier. Armure complète de plaques (heaume, cuirasse, épaulières, cubitières, ventrière, cuissards, jambières).</p>\n<p> </p>","quantite":1,"encombrement":8,"equipe":false,"protection":6,"deterioration":0,"malus":-6,"cout":100},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp","effects":[],"_id":"S3bLtbXe6BzEFCjt"}
|
|
||||||
{"name":"Rasoir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"dommages":"1","force":"0","resistance":0,"competence":"Dague","cout":2,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/systems/foundryvtt-reve-de-dragon/icons/objets/rasoir.webp","effects":[],"_id":"9UFxKeFJv79QSzhz"}
|
|
||||||
@@ -1,49 +1,49 @@
|
|||||||
{"name":"Moussecaille","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":6,"ingredients":"<ul>\n<li>4 grosses cailles (1 sust chaque)</li>\n<li>3 livres de mousseroles</li>\n<li>4 échalotes</li>\n<li>1 racine de réfèble</li>\n<li>1 schouillat de miel</li>\n<li>10 schouillats de beurre</li>\n<li>2 doigts d’huile</li>\n<li>5 schouillats de farine de blédièze</li>\n<li>eau</li>\n<li>sel</li>\n<li>4 brins de klampine</li>\n<li>4 brins de luciane</li>\n<li>1 brin de mentharde</li>\n<li>4 brins de pèpre</li>\n</ul>","duree":"80 minutes","sust":8,"description":"<p>Civet de cailles aux mousseroles.</p>\n<p>La mousserole est un petit champignon rose, très abondant après la pluie (commun). Pratiquement, cette recette peut s’appliquer à tout gibier à plume préparé aux champignons.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_6.webp","effects":[],"_id":"240HPtZsgZQERFMF"}
|
{"name":"Moussecaille","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.240HPtZsgZQERFMF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_6.webp","effects":[],"_id":"240HPtZsgZQERFMF","system":{"description":"<p>Civet de cailles aux mousseroles.</p>\n<p>La mousserole est un petit champignon rose, très abondant après la pluie (commun). Pratiquement, cette recette peut s’appliquer à tout gibier à plume préparé aux champignons.</p>","descriptionmj":"","niveau":6,"ingredients":"<ul>\n<li>4 grosses cailles (1 sust chaque)</li>\n<li>3 livres de mousseroles</li>\n<li>4 échalotes</li>\n<li>1 racine de réfèble</li>\n<li>1 schouillat de miel</li>\n<li>10 schouillats de beurre</li>\n<li>2 doigts d’huile</li>\n<li>5 schouillats de farine de blédièze</li>\n<li>eau</li>\n<li>sel</li>\n<li>4 brins de klampine</li>\n<li>4 brins de luciane</li>\n<li>1 brin de mentharde</li>\n<li>4 brins de pèpre</li>\n</ul>","duree":"80 minutes","sust":8,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870029,"modifiedTime":1671048281603,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Panaris et Phlegmon","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":7,"description":"<p>Romance sur la fatalité qui sépare deux amants et que seule la mort réunit.</p>\n<p>À la fin, la belle Panaris est transformée en carafe et le gentil Phlegmon en bouchon de cristal. L’empereur, à qui échoit le flacon, les rassemble symboliquement.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_7.webp","effects":[],"_id":"36YGDFJBxekzEvBw"}
|
{"name":"Panaris et Phlegmon","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.36YGDFJBxekzEvBw"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_7.webp","effects":[],"_id":"36YGDFJBxekzEvBw","system":{"description":"<p>Romance sur la fatalité qui sépare deux amants et que seule la mort réunit.</p>\n<p>À la fin, la belle Panaris est transformée en carafe et le gentil Phlegmon en bouchon de cristal. L’empereur, à qui échoit le flacon, les rassemble symboliquement.</p>","descriptionmj":"","niveau":7,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870029,"modifiedTime":1671048281603,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La danse des sept rêves","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":6,"description":"<p>Véritable ballet, la danse des sept rêves est une chorégraphie dramatique élaborée.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_8.webp","effects":[],"_id":"4mhiTAEhwDh7S3i0"}
|
{"name":"La danse des sept rêves","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.4mhiTAEhwDh7S3i0"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_8.webp","effects":[],"_id":"4mhiTAEhwDh7S3i0","system":{"description":"<p>Véritable ballet, la danse des sept rêves est une chorégraphie dramatique élaborée.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281604,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Les fléchettes","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"adressehasard","base":-6,"caraccomp":"Lancer","description":"<p>Jeu d’adresse consistant à viser une cible avec des fléchettes.</p>\n<p>Pour simuler une partie, faire tirer à chaque participant 5 jets de Lancer/Jeu à zéro et additionner les points de tâche obtenus. Le plus grand nombre gagne.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_flechettes.webp","effects":[],"_id":"8jOKQkuS6RJyM3uD"}
|
{"name":"Les fléchettes","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.8jOKQkuS6RJyM3uD"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_flechettes.webp","effects":[],"_id":"8jOKQkuS6RJyM3uD","system":{"description":"<p>Jeu d’adresse consistant à viser une cible avec des fléchettes.</p>\n<p>Pour simuler une partie, faire tirer à chaque participant 5 jets de Lancer/Jeu à zéro et additionner les points de tâche obtenus. Le plus grand nombre gagne.</p>","descriptionmj":"","type":"adressehasard","base":-6,"caraccomp":"Lancer","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281604,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La peccadille","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":false,"apparence":true,"niveau":2,"description":"<p>La peccadille se danse à deux, comme la valse ou le tango. Plus lente et moins rythmée que les deux premières, elle comporte quatre figures :</p>\n<p>1) les cavaliers se tiennent par les mains</p>\n<p>2) ils se tiennent par la taille</p>\n<p>3) figure libre, improvisée par celui ou celle qui a invité l’autre</p>\n<p>4) les deux visages doivent se rapprocher de façon à se toucher par le bout du nez à l’exclusion de toute autre partie du corps.</p>\n<p>Et l’on recommence.</p>\n<p>L’intérêt de cette danse réside dans sa figure libre, sobre ou osée, et sa difficulté dans le nez à nez.</p>\n<p>Il arrive lors de cette figure que, emportés par le mouvement, les visages se heurtent violemment, ce qui produit toujours une mauvaise impression chez le partenaire.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_2.webp","effects":[],"_id":"8p4pMXbgY4S5fZjJ"}
|
{"name":"La peccadille","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.8p4pMXbgY4S5fZjJ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_2.webp","effects":[],"_id":"8p4pMXbgY4S5fZjJ","system":{"description":"<p>La peccadille se danse à deux, comme la valse ou le tango. Plus lente et moins rythmée que les deux premières, elle comporte quatre figures :</p>\n<p>1) les cavaliers se tiennent par les mains</p>\n<p>2) ils se tiennent par la taille</p>\n<p>3) figure libre, improvisée par celui ou celle qui a invité l’autre</p>\n<p>4) les deux visages doivent se rapprocher de façon à se toucher par le bout du nez à l’exclusion de toute autre partie du corps.</p>\n<p>Et l’on recommence.</p>\n<p>L’intérêt de cette danse réside dans sa figure libre, sobre ou osée, et sa difficulté dans le nez à nez.</p>\n<p>Il arrive lors de cette figure que, emportés par le mouvement, les visages se heurtent violemment, ce qui produit toujours une mauvaise impression chez le partenaire.</p>","descriptionmj":"","type":"recreative","agilite":false,"apparence":true,"niveau":2,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281604,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Les dragons","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"reflexion","base":-8,"caraccomp":"Intellect","description":"<p>Les dragons sont les échecs draconics.</p>\n<p>Plus complexes et soumis à beaucoup plus de variantes que nos échecs, les dragons se jouent sur un plateau de 7 x 7 cases. Chaque joueur possède 14 pièces : le voyageur, le haut-rêvant, la pucelle, le groin, le ménestrel, l’archer, la maison, et 7 arbres.</p>\n<p>Les arbres sont l’équivalent des pions et servent à constituer les forêts. Les joueurs ne jouent pas l’un en face de l’autre, mais côte à côte, avec l’échiquier devant eux. Il y a ainsi le joueur de droite qui plante la forêt dite dextriote, et le joueur de gauche qui plante la forêt sinistrante. Quelle que soit la variante jouée, l’échiquier commence vide, les joueurs introduisant leurs pièces, arbres ou autres, l’un après l’autre.</p>\n<p>Selon les variantes, les pièces ne se déplacent pas de la même façon. Les arbres ne prennent ni ne se déplacent jamais. Ils servent d’obstacle aux lignes de déplacement des autres pièces. Seuls les haut-rêvants peuvent les prendre dans certaines variantes.</p>\n<p>Les maisons, également fixes, ne peuvent être prises que quand elles sont vides. Selon les variantes, elles peuvent contenir de deux à quatre autres pièces (qui coexistent sur la même case), sauf des arbres. Dans la maison les pièces sont protégées, on ne peut les prendre. Une variante permet d’agrandir la maison en sacrifiant un arbre.</p>\n<p>Selon une autre, les archers peuvent augmenter leur nombre de flèches en sacrifiant également un arbre.</p>\n<p>Dans la variante traditionnelle, la plus ancienne, le but du jeu est d’investir la maison adverse. Cela suppose qu’elle soit vide. Il faut préalablement éliminer ou neutraliser les pièces en dehors, jusqu’à obliger les occupants de la maison à sortir (comme aux échecs, on ne peut passer son coup, on doit effectuer un mouvement).</p>\n<p>Dans des variantes plus récentes, plus faciles, le but est de capturer une certaine pièce adverse, généralement le groin ou la pucelle (qui joue l’équivalent du roi de nos échecs). Une variante très populaire oblige que ce soit le groin qui capture la pucelle.</p>\n<p>La durée d’une partie de dragons est en moyenne d’une heure.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_calculs.webp","effects":[],"_id":"AVAMD5C2mxuOfwV4"}
|
{"name":"Les dragons","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.AVAMD5C2mxuOfwV4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_calculs.webp","effects":[],"_id":"AVAMD5C2mxuOfwV4","system":{"description":"<p>Les dragons sont les échecs draconics.</p>\n<p>Plus complexes et soumis à beaucoup plus de variantes que nos échecs, les dragons se jouent sur un plateau de 7 x 7 cases. Chaque joueur possède 14 pièces : le voyageur, le haut-rêvant, la pucelle, le groin, le ménestrel, l’archer, la maison, et 7 arbres.</p>\n<p>Les arbres sont l’équivalent des pions et servent à constituer les forêts. Les joueurs ne jouent pas l’un en face de l’autre, mais côte à côte, avec l’échiquier devant eux. Il y a ainsi le joueur de droite qui plante la forêt dite dextriote, et le joueur de gauche qui plante la forêt sinistrante. Quelle que soit la variante jouée, l’échiquier commence vide, les joueurs introduisant leurs pièces, arbres ou autres, l’un après l’autre.</p>\n<p>Selon les variantes, les pièces ne se déplacent pas de la même façon. Les arbres ne prennent ni ne se déplacent jamais. Ils servent d’obstacle aux lignes de déplacement des autres pièces. Seuls les haut-rêvants peuvent les prendre dans certaines variantes.</p>\n<p>Les maisons, également fixes, ne peuvent être prises que quand elles sont vides. Selon les variantes, elles peuvent contenir de deux à quatre autres pièces (qui coexistent sur la même case), sauf des arbres. Dans la maison les pièces sont protégées, on ne peut les prendre. Une variante permet d’agrandir la maison en sacrifiant un arbre.</p>\n<p>Selon une autre, les archers peuvent augmenter leur nombre de flèches en sacrifiant également un arbre.</p>\n<p>Dans la variante traditionnelle, la plus ancienne, le but du jeu est d’investir la maison adverse. Cela suppose qu’elle soit vide. Il faut préalablement éliminer ou neutraliser les pièces en dehors, jusqu’à obliger les occupants de la maison à sortir (comme aux échecs, on ne peut passer son coup, on doit effectuer un mouvement).</p>\n<p>Dans des variantes plus récentes, plus faciles, le but est de capturer une certaine pièce adverse, généralement le groin ou la pucelle (qui joue l’équivalent du roi de nos échecs). Une variante très populaire oblige que ce soit le groin qui capture la pucelle.</p>\n<p>La durée d’une partie de dragons est en moyenne d’une heure.</p>","descriptionmj":"","type":"reflexion","base":-8,"caraccomp":"Intellect","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281605,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La mort d’Amarak","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":6,"description":"<p>Épopée à gros budget et effets spéciaux spectaculaires.</p>\n<p>Amarak, ayant bu une potion de gigantisme, meurt en se cognant la tête dans la lune.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_6.webp","effects":[],"_id":"C5smOdHzrDHlrrZq"}
|
{"name":"La mort d’Amarak","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.C5smOdHzrDHlrrZq"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_6.webp","effects":[],"_id":"C5smOdHzrDHlrrZq","system":{"description":"<p>Épopée à gros budget et effets spéciaux spectaculaires.</p>\n<p>Amarak, ayant bu une potion de gigantisme, meurt en se cognant la tête dans la lune.</p>","descriptionmj":"","niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281605,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La princesse endormie","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":7,"description":"<p>Ballade sur une princesse qui se pique le doigt et dort très longtemps suite à un maléfice.</p>\n<p>Les derniers couplets sont malheureusement oubliés, de sorte que la chanson ne finit pas.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_7.webp","effects":[],"_id":"CBpwK9udfdzlWbfb"}
|
{"name":"La princesse endormie","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.CBpwK9udfdzlWbfb"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_7.webp","effects":[],"_id":"CBpwK9udfdzlWbfb","system":{"description":"<p>Ballade sur une princesse qui se pique le doigt et dort très longtemps suite à un maléfice.</p>\n<p>Les derniers couplets sont malheureusement oubliés, de sorte que la chanson ne finit pas.</p>","descriptionmj":"","niveau":7,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281605,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Le mal rêvé","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":4,"description":"<p>Complainte sur la destinée misérable d’un homme qui avait les oreilles à la place des genoux.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_4.webp","effects":[],"_id":"FcTMJE5Wfd02axxd"}
|
{"name":"Le mal rêvé","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.FcTMJE5Wfd02axxd"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_4.webp","effects":[],"_id":"FcTMJE5Wfd02axxd","system":{"description":"<p>Complainte sur la destinée misérable d’un homme qui avait les oreilles à la place des genoux.</p>","descriptionmj":"","niveau":4,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870031,"modifiedTime":1671048281605,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La plumette","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"adressehasard","base":-4,"caraccomp":"Dextérité / Volonté","description":"<p>Jeu d’adresse et de volonté, la plumette se joue à deux, chacun chatouillant le visage de l’autre avec une plume. Les visages doivent rester imperturbables.</p>\n<p>Le premier qui trahit un signe quelconque (rire, éternuement, grimace) a perdu.</p>\n<p>Pour simuler une partie, utiliser les règles de combat, chacun à tour de rôle attaquant ou tentant de parer l’adversaire.</p>\n<p>Pour attaquer, utiliser DEXTÉRITÉ/Jeu difficulté libre et pour parer VOLONTÉ/Jeu à la difficulté de l’attaque. Le vainqueur est le premier à réussir une attaque non parée.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_plumette.webp","effects":[],"_id":"HyOXCAtpaP7eaHGj"}
|
{"name":"La plumette","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.HyOXCAtpaP7eaHGj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_plumette.webp","effects":[],"_id":"HyOXCAtpaP7eaHGj","system":{"description":"<p>Jeu d’adresse et de volonté, la plumette se joue à deux, chacun chatouillant le visage de l’autre avec une plume. Les visages doivent rester imperturbables.</p>\n<p>Le premier qui trahit un signe quelconque (rire, éternuement, grimace) a perdu.</p>\n<p>Pour simuler une partie, utiliser les règles de combat, chacun à tour de rôle attaquant ou tentant de parer l’adversaire.</p>\n<p>Pour attaquer, utiliser DEXTÉRITÉ/Jeu difficulté libre et pour parer VOLONTÉ/Jeu à la difficulté de l’attaque. Le vainqueur est le premier à réussir une attaque non parée.</p>","descriptionmj":"","type":"adressehasard","base":-4,"caraccomp":"Dextérité / Volonté","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870032,"modifiedTime":1671048281605,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La bergamasque","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":false,"apparence":true,"niveau":5,"description":"<p>La bergamasque reprend le principe de la sarabande, mais sur un rythme plus vif et des figures plus compliquées.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_5.webp","effects":[],"_id":"KJ0Ck2G2t4lYIKJH"}
|
{"name":"La bergamasque","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.KJ0Ck2G2t4lYIKJH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_5.webp","effects":[],"_id":"KJ0Ck2G2t4lYIKJH","system":{"description":"<p>La bergamasque reprend le principe de la sarabande, mais sur un rythme plus vif et des figures plus compliquées.</p>","descriptionmj":"","type":"recreative","agilite":false,"apparence":true,"niveau":5,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870032,"modifiedTime":1671048281606,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Les calculs","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"reflexion","base":-6,"caraccomp":"Intellect","description":"<p>Ce jeu se pratique avec des calculs, c’est à-dire des petits cailloux, que l’on pose alternativement sur une surface grillée.</p>\n<p>La stratégie est à mi-chemin entre le go et le morpion.</p>\n<p>Très pratiqué, ce jeu peut être facilement improvisé en traçant la grille à la craie sur une table, ou à l’extérieur, sur du sable lisse.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_calculs.webp","effects":[],"_id":"MixMWkfRpEN51QuP"}
|
{"name":"Les calculs","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.MixMWkfRpEN51QuP"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_calculs.webp","effects":[],"_id":"MixMWkfRpEN51QuP","system":{"description":"<p>Ce jeu se pratique avec des calculs, c’est à-dire des petits cailloux, que l’on pose alternativement sur une surface grillée.</p>\n<p>La stratégie est à mi-chemin entre le go et le morpion.</p>\n<p>Très pratiqué, ce jeu peut être facilement improvisé en traçant la grille à la craie sur une table, ou à l’extérieur, sur du sable lisse.</p>","descriptionmj":"","type":"reflexion","base":-6,"caraccomp":"Intellect","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870032,"modifiedTime":1671048281606,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La serpentine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":1,"description":"<p>Danse basique, lente ou vive, ondulante et serpentine.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_1.webp","effects":[],"_id":"N7bgcR8OEh6MpfiF"}
|
{"name":"La serpentine","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.N7bgcR8OEh6MpfiF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_1.webp","effects":[],"_id":"N7bgcR8OEh6MpfiF","system":{"description":"<p>Danse basique, lente ou vive, ondulante et serpentine.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":1,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870032,"modifiedTime":1671048281606,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Rêve de Dragon","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":8,"description":"<p>Récitatif, dont la moralité se résume ainsi : puisque tout n’est qu’un rêve, allons dormir.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_8.webp","effects":[],"_id":"OTRi9mHhIANUnPA7"}
|
{"name":"Rêve de Dragon","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.OTRi9mHhIANUnPA7"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_8.webp","effects":[],"_id":"OTRi9mHhIANUnPA7","system":{"description":"<p>Récitatif, dont la moralité se résume ainsi : puisque tout n’est qu’un rêve, allons dormir.</p>","descriptionmj":"","niveau":8,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870033,"modifiedTime":1671048281607,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Choucroume","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":2,"ingredients":"<ul>\n<li>1 livre de chou émincé</li>\n<li>2 doigts d’huile</li>\n<li>1 pinte de bière</li>\n<li>sel</li>\n<li>8 brins d’aromates (béjaune, luciane)</li>\n</ul>\n<p> </p>\n<p>Une variante appelée choucroume liquide utilise le double de bière (2 pintes) et se consomme froide.</p>","duree":"30 minutes","sust":8,"description":"<p>Variété de bloutade au chou, cuite dans de la bière.</p>\n<p>Émincer finement le chou et le faire revenir dans l’huile.</p>\n<p>Ajouter la bière, le sel, les aromates, puis cuire sans cesser de touiller comme pour une bloutade ordinaire.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_2.webp","effects":[],"_id":"POuOV6xoPnO0b9OQ"}
|
{"name":"Choucroume","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.POuOV6xoPnO0b9OQ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_2.webp","effects":[],"_id":"POuOV6xoPnO0b9OQ","system":{"description":"<p>Variété de bloutade au chou, cuite dans de la bière.</p>\n<p>Émincer finement le chou et le faire revenir dans l’huile.</p>\n<p>Ajouter la bière, le sel, les aromates, puis cuire sans cesser de touiller comme pour une bloutade ordinaire.</p>","descriptionmj":"","niveau":2,"ingredients":"<ul>\n<li>1 livre de chou émincé</li>\n<li>2 doigts d’huile</li>\n<li>1 pinte de bière</li>\n<li>sel</li>\n<li>8 brins d’aromates (béjaune, luciane)</li>\n</ul>\n<p> </p>\n<p>Une variante appelée choucroume liquide utilise le double de bière (2 pintes) et se consomme froide.</p>","duree":"30 minutes","sust":8,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870033,"modifiedTime":1671048281607,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La turlutaine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":false,"apparence":true,"niveau":3,"description":"<p>Sarabande simplifiée dansée par les villageois, moins lente et moins guindée que cette dernière.</p>\n<p>On danse tantôt en groupe, tantôt par couples, avec changements de partenaire.</p>\n<p>Au moment de la séparation pour reformer le groupe, les partenaires s’envoient des baisers du bout des doigts.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_3.webp","effects":[],"_id":"Q5Lx4WWKWGFjF9cX"}
|
{"name":"La turlutaine","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.Q5Lx4WWKWGFjF9cX"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_3.webp","effects":[],"_id":"Q5Lx4WWKWGFjF9cX","system":{"description":"<p>Sarabande simplifiée dansée par les villageois, moins lente et moins guindée que cette dernière.</p>\n<p>On danse tantôt en groupe, tantôt par couples, avec changements de partenaire.</p>\n<p>Au moment de la séparation pour reformer le groupe, les partenaires s’envoient des baisers du bout des doigts.</p>","descriptionmj":"","type":"recreative","agilite":false,"apparence":true,"niveau":3,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870033,"modifiedTime":1671048281607,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Le bourrichon","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":true,"apparence":true,"niveau":0,"description":"<p>Le bourrichon est une sorte de farandole joyeuse et rythmée où un grand nombre de danseurs évoluent en se tenant par la main. Les figures sont libres, l’essentiel étant de garder le rythme.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_0.webp","effects":[],"_id":"QvMNog5MF3vDIBGR"}
|
{"name":"Le bourrichon","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.QvMNog5MF3vDIBGR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_0.webp","effects":[],"_id":"QvMNog5MF3vDIBGR","system":{"description":"<p>Le bourrichon est une sorte de farandole joyeuse et rythmée où un grand nombre de danseurs évoluent en se tenant par la main. Les figures sont libres, l’essentiel étant de garder le rythme.</p>","descriptionmj":"","type":"recreative","agilite":true,"apparence":true,"niveau":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870033,"modifiedTime":1671048281607,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Grabuge","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":3,"ingredients":"<ul>\n<li>1 livre de tomari</li>\n<li>1 livre de poisson (mer ou eau douce)</li>\n<li>2 poireaux</li>\n<li>6 oignons</li>\n<li>1 laitue</li>\n<li>2 schouillats de beurre</li>\n<li>2 doigts d’huile</li>\n<li>1 doigt de vinaigre</li>\n<li>eau</li>\n<li>sel</li>\n<li>6 brins de luciane</li>\n<li>6 brins de klampine</li>\n<li>8 brins de pif-paf</li>\n</ul>","duree":"60 minutes","sust":12,"description":"<p>Plat de tomari, de plures et de poisson mijoté au pif-paf.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_3.webp","effects":[],"_id":"RvsPbA1ehQgRvGu6"}
|
{"name":"Grabuge","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.RvsPbA1ehQgRvGu6"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_3.webp","effects":[],"_id":"RvsPbA1ehQgRvGu6","system":{"description":"<p>Plat de tomari, de plures et de poisson mijoté au pif-paf.</p>","descriptionmj":"","niveau":3,"ingredients":"<ul>\n<li>1 livre de tomari</li>\n<li>1 livre de poisson (mer ou eau douce)</li>\n<li>2 poireaux</li>\n<li>6 oignons</li>\n<li>1 laitue</li>\n<li>2 schouillats de beurre</li>\n<li>2 doigts d’huile</li>\n<li>1 doigt de vinaigre</li>\n<li>eau</li>\n<li>sel</li>\n<li>6 brins de luciane</li>\n<li>6 brins de klampine</li>\n<li>8 brins de pif-paf</li>\n</ul>","duree":"60 minutes","sust":12,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870033,"modifiedTime":1671048281608,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La danse du feu","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":5,"description":"<p>La danse du feu se danse usuellement de nuit et près d’un feu.</p>\n<p>Lente, aux mouvements plus suggérés que marqués, elle est imitative des flammes, comme si le danseur avait le feu pour partenaire.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_5.webp","effects":[],"_id":"UBVYoQmilTmkqppd"}
|
{"name":"La danse du feu","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.UBVYoQmilTmkqppd"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_5.webp","effects":[],"_id":"UBVYoQmilTmkqppd","system":{"description":"<p>La danse du feu se danse usuellement de nuit et près d’un feu.</p>\n<p>Lente, aux mouvements plus suggérés que marqués, elle est imitative des flammes, comme si le danseur avait le feu pour partenaire.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":5,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281608,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La danse du voile","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":6,"description":"<p>De caractère libre, tantôt altière comme la souveraine ou déhanchée comme la callipyge, cette danse utilise un voile comme accessoire (pièce de tissu, châle, écharpe, etc.).</p>\n<p>Son intérêt réside dans les mouvements du voile avec lesquels s’harmonisent ceux de la danseuse.</p>\n<p>Peu pratiquée par les hommes.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_6.webp","effects":[],"_id":"Ui1bMMBBdxMb2AZ2"}
|
{"name":"La danse du voile","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.Ui1bMMBBdxMb2AZ2"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_6.webp","effects":[],"_id":"Ui1bMMBBdxMb2AZ2","system":{"description":"<p>De caractère libre, tantôt altière comme la souveraine ou déhanchée comme la callipyge, cette danse utilise un voile comme accessoire (pièce de tissu, châle, écharpe, etc.).</p>\n<p>Son intérêt réside dans les mouvements du voile avec lesquels s’harmonisent ceux de la danseuse.</p>\n<p>Peu pratiquée par les hommes.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281608,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Fleur de haut-rêve","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":1,"description":"<p>Romance à l’eau de rose sur les malheurs d’une jeune haut-rêvante.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"Y5rAtXL0WxOqqbZs"}
|
{"name":"Fleur de haut-rêve","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.Y5rAtXL0WxOqqbZs"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"Y5rAtXL0WxOqqbZs","system":{"description":"<p>Romance à l’eau de rose sur les malheurs d’une jeune haut-rêvante.</p>","descriptionmj":"","niveau":1,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La souveraine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":4,"description":"<p>Danse très lente, sobre, hiératique, plus caractérisée par ses poses que par ses mouvements.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_4.webp","effects":[],"_id":"Y791UctCHALnBgjO"}
|
{"name":"La souveraine","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.Y791UctCHALnBgjO"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_4.webp","effects":[],"_id":"Y791UctCHALnBgjO","system":{"description":"<p>Danse très lente, sobre, hiératique, plus caractérisée par ses poses que par ses mouvements.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":4,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Bras de fer","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"adressehasard","base":-4,"caraccomp":"Force","description":"<p>Pour attaquer, utiliser Force/Jeu difficulté libre. Pour parer, l'opposant joue pareillement Force/Jeu à la difficulté de l’attaque.</p>\n<p>Le vainqueur est le premier à réussir une attaque non parée.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_brasdefer.webp","effects":[],"_id":"ZJvL0e5hjuws7mIH"}
|
{"name":"Bras de fer","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.ZJvL0e5hjuws7mIH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_brasdefer.webp","effects":[],"_id":"ZJvL0e5hjuws7mIH","system":{"description":"<p>Pour attaquer, utiliser Force/Jeu difficulté libre. Pour parer, l'opposant joue pareillement Force/Jeu à la difficulté de l’attaque.</p>\n<p>Le vainqueur est le premier à réussir une attaque non parée.</p>","descriptionmj":"","type":"adressehasard","base":-4,"caraccomp":"Force","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La chèvre rose","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":3,"description":"<p>Ballade comique sur une chèvre de la couleur en question, qui s’avère finalement être une princesse métamorphosée par un maléfice.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_3.webp","effects":[],"_id":"aB78Io55m2kXDjwQ"}
|
{"name":"La chèvre rose","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.aB78Io55m2kXDjwQ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_3.webp","effects":[],"_id":"aB78Io55m2kXDjwQ","system":{"description":"<p>Ballade comique sur une chèvre de la couleur en question, qui s’avère finalement être une princesse métamorphosée par un maléfice.</p>","descriptionmj":"","niveau":3,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Tripotée","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":2,"ingredients":"<ul>\n<li>1/2 livre de cosses</li>\n<li>1/2 livre de porte-pépins</li>\n<li>1/2 livre de racines</li>\n<li>eau</li>\n<li>5 schouillats de farine de blédièze</li>\n<li>3 schouillats de farine de bloute</li>\n<li>4 brins de béjaune</li>\n<li>2 brins de muscaline</li>\n<li>2 brins de pèpre</li>\n</ul>","duree":"40 minutes","sust":6,"description":"<p>Soupe végétarienne comprenant des légumes de chacune des trois sortes. Selon les légumes utilisés, la tripotée peut avoir de multiples variantes, la plus courante étant pois-quaroce-turneps.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_2.webp","effects":[],"_id":"aWfeLfT1kM2cCrNn"}
|
{"name":"Tripotée","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.aWfeLfT1kM2cCrNn"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_2.webp","effects":[],"_id":"aWfeLfT1kM2cCrNn","system":{"description":"<p>Soupe végétarienne comprenant des légumes de chacune des trois sortes. Selon les légumes utilisés, la tripotée peut avoir de multiples variantes, la plus courante étant pois-quaroce-turneps.</p>","descriptionmj":"","niveau":2,"ingredients":"<ul>\n<li>1/2 livre de cosses</li>\n<li>1/2 livre de porte-pépins</li>\n<li>1/2 livre de racines</li>\n<li>eau</li>\n<li>5 schouillats de farine de blédièze</li>\n<li>3 schouillats de farine de bloute</li>\n<li>4 brins de béjaune</li>\n<li>2 brins de muscaline</li>\n<li>2 brins de pèpre</li>\n</ul>","duree":"40 minutes","sust":6,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870035,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Tiens, v’là les Groins !","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":0,"description":"<p>Chanson de marche peu rafinée, comme en témoigne le refrain :</p>\n<blockquote>\n<p>« Tiens, v’là les Groins !</p>\n<p>Ça y’en a eux qui faire du foin !</p>\n<p>Quand y’en a près, y’en a pas loin !</p>\n<p>Tiens, v’là les Groins ! »</p>\n</blockquote>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"dwSY0ImswRHUSuRQ"}
|
{"name":"Tiens, v’là les Groins !","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.dwSY0ImswRHUSuRQ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"dwSY0ImswRHUSuRQ","system":{"description":"<p>Chanson de marche peu rafinée, comme en témoigne le refrain :</p>\n<blockquote>\n<p>« Tiens, v’là les Groins !</p>\n<p>Ça y’en a eux qui faire du foin !</p>\n<p>Quand y’en a près, y’en a pas loin !</p>\n<p>Tiens, v’là les Groins ! »</p>\n</blockquote>","descriptionmj":"","niveau":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870035,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La volée","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":true,"apparence":true,"niveau":6,"description":"<p>Danse villageoise, la volée est une farandole rapide incluant des sauts et des figures quasi acrobatiques, ainsi que des moments rapprochés à deux (comme la peccadille). Elle est évidemment réservée aux bons danseurs, et particulièrement exténuante.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_6.webp","effects":[],"_id":"ehAslJ16qKJDrTqt"}
|
{"name":"La volée","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.ehAslJ16qKJDrTqt"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_6.webp","effects":[],"_id":"ehAslJ16qKJDrTqt","system":{"description":"<p>Danse villageoise, la volée est une farandole rapide incluant des sauts et des figures quasi acrobatiques, ainsi que des moments rapprochés à deux (comme la peccadille). Elle est évidemment réservée aux bons danseurs, et particulièrement exténuante.</p>","descriptionmj":"","type":"recreative","agilite":true,"apparence":true,"niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870035,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"jOL4buV3m3nHr8v7","name":"Le doublon","type":"jeu","img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_doublon.webp","data":{"type":"de","base":0,"caraccomp":"Chance","reference":"","description":"<p>Jeu de pur hasard consistant à obtenir un double avec deux dés.</p>\n<p>Si plusieurs joueurs y parviennent, le plus haut gagne ; si aucun n’y parvient, le coup est nul et les mises restent au pot.</p>\n<p>Pour simuler une partie de doublon, faire simplement tirer des jets de CHANCE à zéro (ajustés astrologiquement), mais sans compétence, pas même Jeu, et comparer les résultats (échec, réussite normale, significative, etc.) : le meilleur gagne. À égalité de réussites, le coup est nul.</p>"},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"rYShh2P1DNavdoBD":3},"flags":{}}
|
{"_id":"jOL4buV3m3nHr8v7","name":"Le doublon","type":"jeu","img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_doublon.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.jOL4buV3m3nHr8v7"}},"system":{"description":"<p>Jeu de pur hasard consistant à obtenir un double avec deux dés.</p>\n<p>Si plusieurs joueurs y parviennent, le plus haut gagne ; si aucun n’y parvient, le coup est nul et les mises restent au pot.</p>\n<p>Pour simuler une partie de doublon, faire simplement tirer des jets de CHANCE à zéro (ajustés astrologiquement), mais sans compétence, pas même Jeu, et comparer les résultats (échec, réussite normale, significative, etc.) : le meilleur gagne. À égalité de réussites, le coup est nul.</p>","descriptionmj":"","type":"de","base":0,"caraccomp":"Chance","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870036,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Le rossignol d’Ostarlath","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":8,"description":"<p>Romance où les paroles, peu importantes, sont essentiellement un exercice de vocalises.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_8.webp","effects":[],"_id":"jUsy5PTDwBgDrRnq"}
|
{"name":"Le rossignol d’Ostarlath","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.jUsy5PTDwBgDrRnq"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_8.webp","effects":[],"_id":"jUsy5PTDwBgDrRnq","system":{"description":"<p>Romance où les paroles, peu importantes, sont essentiellement un exercice de vocalises.</p>","descriptionmj":"","niveau":8,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870037,"modifiedTime":1671048281610,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Le roi des ours","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":3,"description":"<p>Sanglante épopée sur un thème identique* : maléfice, métamorphose et superbe vengeance finale.</p>\n<p> </p>\n<p><em>*voir \"La chèvre rose\"</em></p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_3.webp","effects":[],"_id":"jUxckTsggDZBgn2W"}
|
{"name":"Le roi des ours","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.jUxckTsggDZBgn2W"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_3.webp","effects":[],"_id":"jUxckTsggDZBgn2W","system":{"description":"<p>Sanglante épopée sur un thème identique* : maléfice, métamorphose et superbe vengeance finale.</p>\n<p> </p>\n<p><em>*voir \"La chèvre rose\"</em></p>","descriptionmj":"","niveau":3,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870037,"modifiedTime":1671048281610,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La route est longue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":0,"description":"<p>Chanson de marche aux couplets répétitifs.</p>\n<blockquote>\n<p>« Une lieue sans cheval, ça use, ça use</p>\n<p>Une lieue sans cheval, ça use les sandales !»</p>\n</blockquote>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"jyPBU95uPhIhsdpa"}
|
{"name":"La route est longue","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.jyPBU95uPhIhsdpa"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"jyPBU95uPhIhsdpa","system":{"description":"<p>Chanson de marche aux couplets répétitifs.</p>\n<blockquote>\n<p>« Une lieue sans cheval, ça use, ça use</p>\n<p>Une lieue sans cheval, ça use les sandales !»</p>\n</blockquote>","descriptionmj":"","niveau":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870037,"modifiedTime":1671048281610,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La danse du couteau","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":6,"description":"<p>Plus masculine que féminine, cette danse utilise un couteau (dague) comme accessoire.</p>\n<p>Elle est imitative d’un combat.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_6.webp","effects":[],"_id":"k9EELSV0DrurUt1e"}
|
{"name":"La danse du couteau","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.k9EELSV0DrurUt1e"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_6.webp","effects":[],"_id":"k9EELSV0DrurUt1e","system":{"description":"<p>Plus masculine que féminine, cette danse utilise un couteau (dague) comme accessoire.</p>\n<p>Elle est imitative d’un combat.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870037,"modifiedTime":1671048281610,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"L’amour est morte","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":5,"description":"<p>Romance sentimentale d’une tristesse à faire pleurer les cailloux.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_5.webp","effects":[],"_id":"kCU7A8fMczERjizY"}
|
{"name":"L’amour est morte","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.kCU7A8fMczERjizY"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_5.webp","effects":[],"_id":"kCU7A8fMczERjizY","system":{"description":"<p>Romance sentimentale d’une tristesse à faire pleurer les cailloux.</p>","descriptionmj":"","niveau":5,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870037,"modifiedTime":1671048281610,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Amandjara","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":2,"description":"<p>Sérénade sur la légendaire cité d’Amandjara,</p>\n<p>« Perle du désert bleu, sur qui la lune fait les doux yeux ... »</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_2.webp","effects":[],"_id":"kiIlPL5XANy5OgYn"}
|
{"name":"Amandjara","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.kiIlPL5XANy5OgYn"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_2.webp","effects":[],"_id":"kiIlPL5XANy5OgYn","system":{"description":"<p>Sérénade sur la légendaire cité d’Amandjara,</p>\n<p>« Perle du désert bleu, sur qui la lune fait les doux yeux ... »</p>","descriptionmj":"","niveau":2,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870038,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Bloutade","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":1,"ingredients":"<ul>\n<li>1 livre de farine de bloute*</li>\n<li>1/2 livre de viande de porc ou de padongre coupée en petits morceaux</li>\n<li>2 doigts d’huile</li>\n<li>eau,</li>\n<li>sel</li>\n<li>8 brins d’aromates (béjaune, luciane)</li>\n</ul>","duree":"30 minutes","sust":8,"description":"<p>Purée de farine de bloute.</p>\n<p> </p>\n<p><strong>Bloute</strong></p>\n<p>Avec le tomari ou le blédièze, la bloute est à la base de l’alimentation dans un grand nombre d’endroits. C’est un tubercule de forme et de couleur voisins de notre manioc, à la chair gélatineuse et fade. Totalement immangeables telles quelles, les bloutes sont mises à sécher sur des claies, puis broyées en farine. Ce n’est qu’ainsi qu’on peut les consommer. La farine de bloute entre dans la confection des brouets et des ragoûts, notamment de la bloutade. Ainsi cuite, elle ressemble à du tapioca.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_1.webp","effects":[],"_id":"lv6AiGYIjtqHhn7u"}
|
{"name":"Bloutade","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.lv6AiGYIjtqHhn7u"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_1.webp","effects":[],"_id":"lv6AiGYIjtqHhn7u","system":{"description":"<p>Purée de farine de bloute.</p>\n<p> </p>\n<p><strong>Bloute</strong></p>\n<p>Avec le tomari ou le blédièze, la bloute est à la base de l’alimentation dans un grand nombre d’endroits. C’est un tubercule de forme et de couleur voisins de notre manioc, à la chair gélatineuse et fade. Totalement immangeables telles quelles, les bloutes sont mises à sécher sur des claies, puis broyées en farine. Ce n’est qu’ainsi qu’on peut les consommer. La farine de bloute entre dans la confection des brouets et des ragoûts, notamment de la bloutade. Ainsi cuite, elle ressemble à du tapioca.</p>","descriptionmj":"","niveau":1,"ingredients":"<ul>\n<li>1 livre de farine de bloute*</li>\n<li>1/2 livre de viande de porc ou de padongre coupée en petits morceaux</li>\n<li>2 doigts d’huile</li>\n<li>eau,</li>\n<li>sel</li>\n<li>8 brins d’aromates (béjaune, luciane)</li>\n</ul>","duree":"30 minutes","sust":8,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870038,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Le tisonnier","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"carte","base":-4,"caraccomp":"Chance / Empathie","description":"<p>On commence par se mettre d’accord sur la valeur hiérarchique des symboles et des combinaisons possibles, puis le jeu consiste, à chaque distribution de cartes, à miser selon un système de surenchères jusqu’à ce que les cartes soient dévoilées.</p>\n<p>La combinaison la plus forte emporte alors les mises.</p>\n<p>Le jeu demande de la chance, sans laquelle il est difficile de gagner à long terme, mais tout autant de l’empathie pour bluffer lors des surenchères.</p>\n<p>Pour simuler une partie, jouer un jet de CHANCE à zéro (ajusté astrologiquement), suivi d’un jet d’EMPATHIE/Jeu à zéro, et additionner les points de tâche obtenus par les deux jets. Le vainqueur est celui qui en totalise le plus.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_tisonnier.webp","effects":[],"_id":"mRzHzrubRkyqHUTC"}
|
{"name":"Le tisonnier","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.mRzHzrubRkyqHUTC"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_tisonnier.webp","effects":[],"_id":"mRzHzrubRkyqHUTC","system":{"description":"<p>On commence par se mettre d’accord sur la valeur hiérarchique des symboles et des combinaisons possibles, puis le jeu consiste, à chaque distribution de cartes, à miser selon un système de surenchères jusqu’à ce que les cartes soient dévoilées.</p>\n<p>La combinaison la plus forte emporte alors les mises.</p>\n<p>Le jeu demande de la chance, sans laquelle il est difficile de gagner à long terme, mais tout autant de l’empathie pour bluffer lors des surenchères.</p>\n<p>Pour simuler une partie, jouer un jet de CHANCE à zéro (ajusté astrologiquement), suivi d’un jet d’EMPATHIE/Jeu à zéro, et additionner les points de tâche obtenus par les deux jets. Le vainqueur est celui qui en totalise le plus.</p>","descriptionmj":"","type":"carte","base":-4,"caraccomp":"Chance / Empathie","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870038,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Plume de zyglute","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":4,"description":"<p>Sérénade.</p>\n<p>Belle musique, mais paroles d’une rare stupidité :</p>\n<blockquote>\n<p>« Coin-coin, glou-glou, c’est qui ? c’est vous ? »</p>\n</blockquote>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_4.webp","effects":[],"_id":"nCFFhbL54WXU0FFi"}
|
{"name":"Plume de zyglute","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.nCFFhbL54WXU0FFi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_4.webp","effects":[],"_id":"nCFFhbL54WXU0FFi","system":{"description":"<p>Sérénade.</p>\n<p>Belle musique, mais paroles d’une rare stupidité :</p>\n<blockquote>\n<p>« Coin-coin, glou-glou, c’est qui ? c’est vous ? »</p>\n</blockquote>","descriptionmj":"","niveau":4,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870038,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"L’auberge noire","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":5,"description":"<p>Complainte macabre sur un aubergiste qui assassine ses clients avec la râpe à fromage.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_5.webp","effects":[],"_id":"srNKj5s0TOw7VDQ4"}
|
{"name":"L’auberge noire","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.srNKj5s0TOw7VDQ4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_5.webp","effects":[],"_id":"srNKj5s0TOw7VDQ4","system":{"description":"<p>Complainte macabre sur un aubergiste qui assassine ses clients avec la râpe à fromage.</p>","descriptionmj":"","niveau":5,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870038,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Ma chope est vide !","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":0,"description":"<p>Chanson à boire peu raffinée.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"uGVOeSq2ZKMG8VjU"}
|
{"name":"Ma chope est vide !","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.uGVOeSq2ZKMG8VjU"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"uGVOeSq2ZKMG8VjU","system":{"description":"<p>Chanson à boire peu raffinée.</p>","descriptionmj":"","niveau":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870039,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La callipyge","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":2,"description":"<p>Comme la serpentine, avec des effets plus marqués, essentiellement basée sur les mouvements du bassin. La callipyge n’est généralement dansée que par les femmes.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_2.webp","effects":[],"_id":"uf7a9D5RYw7gOi36"}
|
{"name":"La callipyge","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.uf7a9D5RYw7gOi36"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_2.webp","effects":[],"_id":"uf7a9D5RYw7gOi36","system":{"description":"<p>Comme la serpentine, avec des effets plus marqués, essentiellement basée sur les mouvements du bassin. La callipyge n’est généralement dansée que par les femmes.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":2,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870039,"modifiedTime":1671048281612,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La gambade","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":true,"apparence":true,"niveau":1,"description":"<p>Gigue endiablée, proche du bourrichon, mais avec des figures un peu moins sommaires.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_1.webp","effects":[],"_id":"uxdljYU7TlC2F6oA"}
|
{"name":"La gambade","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.uxdljYU7TlC2F6oA"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_1.webp","effects":[],"_id":"uxdljYU7TlC2F6oA","system":{"description":"<p>Gigue endiablée, proche du bourrichon, mais avec des figures un peu moins sommaires.</p>","descriptionmj":"","type":"recreative","agilite":true,"apparence":true,"niveau":1,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870039,"modifiedTime":1671048281612,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Trompe de padongre à la mentharde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":4,"ingredients":"<ul>\n<li>1 belle trompe de padongre (10 sust)</li>\n<li>25 schouillats de miel</li>\n<li>1 livre de beurre</li>\n<li>1 pinte de lait</li>\n<li>20 brins de mentharde</li>\n<li>sel</li>\n</ul>","duree":"90 minutes","sust":12,"description":"<p>Enduite de miel, de beurre et entourée de feuilles de mentharde fraîches, la trompe de padongre doit être cuite au four et arrosée régulièrement de lait. Toute la difficulté réside dans la cuisson.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_4.webp","effects":[],"_id":"uzSivEs6SFEGVoI0"}
|
{"name":"Trompe de padongre à la mentharde","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.uzSivEs6SFEGVoI0"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_4.webp","effects":[],"_id":"uzSivEs6SFEGVoI0","system":{"description":"<p>Enduite de miel, de beurre et entourée de feuilles de mentharde fraîches, la trompe de padongre doit être cuite au four et arrosée régulièrement de lait. Toute la difficulté réside dans la cuisson.</p>","descriptionmj":"","niveau":4,"ingredients":"<ul>\n<li>1 belle trompe de padongre (10 sust)</li>\n<li>25 schouillats de miel</li>\n<li>1 livre de beurre</li>\n<li>1 pinte de lait</li>\n<li>20 brins de mentharde</li>\n<li>sel</li>\n</ul>","duree":"90 minutes","sust":12,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870039,"modifiedTime":1671048281613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La triplette","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"de","base":0,"caraccomp":"Chance","description":"<p>Autre jeu de hasard, la triplette est un jeu de dés de combinaisons se jouant avec trois dés (sorte de 421).</p>\n<p>Pour simuler une partie de triplette, déterminer l’ordre dans lequel jouent les participants. Le premier à jouer peut tenter de un à trois jets de CHANCE à zéro (ajustés astrologiquement comme pour le doublon), et additionner les points de tâche obtenus.</p>\n<p>Attention aux échecs qui donnent des points négatifs ! Il peut être plus judicieux de se contenter d’un seul jet bien réussi.</p>\n<p>Les joueurs suivants, en effet, pourront à leur tour tenter le même nombre de jets de CHANCE ou moins, mais pas davantage. Le plus grand nombre de points gagne finalement.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_doublon.webp","effects":[],"_id":"vYPjOjd3vSAvjL76"}
|
{"name":"La triplette","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.vYPjOjd3vSAvjL76"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_doublon.webp","effects":[],"_id":"vYPjOjd3vSAvjL76","system":{"description":"<p>Autre jeu de hasard, la triplette est un jeu de dés de combinaisons se jouant avec trois dés (sorte de 421).</p>\n<p>Pour simuler une partie de triplette, déterminer l’ordre dans lequel jouent les participants. Le premier à jouer peut tenter de un à trois jets de CHANCE à zéro (ajustés astrologiquement comme pour le doublon), et additionner les points de tâche obtenus.</p>\n<p>Attention aux échecs qui donnent des points négatifs ! Il peut être plus judicieux de se contenter d’un seul jet bien réussi.</p>\n<p>Les joueurs suivants, en effet, pourront à leur tour tenter le même nombre de jets de CHANCE ou moins, mais pas davantage. Le plus grand nombre de points gagne finalement.</p>","descriptionmj":"","type":"de","base":0,"caraccomp":"Chance","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870040,"modifiedTime":1671048281613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Le voyageur","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":1,"description":"<p>Ballade sur les tribulations d’un voyageur.</p>\n<p>Interminable, cette chanson possède plus de cent couplets.</p>\n<p> </p>\n<p><em>Déterminer en tirant 1d100 le nombre de couplets connus.</em></p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"vlqX5BC9recz2kM2"}
|
{"name":"Le voyageur","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.vlqX5BC9recz2kM2"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"vlqX5BC9recz2kM2","system":{"description":"<p>Ballade sur les tribulations d’un voyageur.</p>\n<p>Interminable, cette chanson possède plus de cent couplets.</p>\n<p> </p>\n<p><em>Déterminer en tirant 1d100 le nombre de couplets connus.</em></p>","descriptionmj":"","niveau":1,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870040,"modifiedTime":1671048281613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La pétasse","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"adressehasard","base":-6,"caraccomp":"Lancer","description":"<p>Jeu d’adresse combinant boules et quilles.</p>\n<p>Chaque joueur dispose de plusieurs quilles, appelées pétasses, et de boules de bois, appelées tronchets. Le jeu connaît de nombreuses variantes, mais le principe général est le même : culbuter les pétasses des adversaires en évitant de se faire troncher les siennes.</p>\n<p>Pour simuler une partie, faire tirer à chaque participant 5 jets de Lancer/Jeu à zéro et additionner les points de tâche obtenus. Le plus grand nombre gagne.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_petasse.webp","effects":[],"_id":"vo8GoXIBNWp1GY12"}
|
{"name":"La pétasse","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.vo8GoXIBNWp1GY12"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_petasse.webp","effects":[],"_id":"vo8GoXIBNWp1GY12","system":{"description":"<p>Jeu d’adresse combinant boules et quilles.</p>\n<p>Chaque joueur dispose de plusieurs quilles, appelées pétasses, et de boules de bois, appelées tronchets. Le jeu connaît de nombreuses variantes, mais le principe général est le même : culbuter les pétasses des adversaires en évitant de se faire troncher les siennes.</p>\n<p>Pour simuler une partie, faire tirer à chaque participant 5 jets de Lancer/Jeu à zéro et additionner les points de tâche obtenus. Le plus grand nombre gagne.</p>","descriptionmj":"","type":"adressehasard","base":-6,"caraccomp":"Lancer","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870040,"modifiedTime":1671048281613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"La sarabande","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":false,"apparence":true,"niveau":4,"description":"<p>Peu pratiquée dans les villages, la sarabande est une danse de cour, lente et solennelle, alternant groupe et couples, comme la turlutaine dont elle est une version «sérieuse».</p>\n<p>Les changements de partenaire s’accompagnent de profondes révérences.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_4.webp","effects":[],"_id":"wf1jpIZmrB5LfK93"}
|
{"name":"La sarabande","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.wf1jpIZmrB5LfK93"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_4.webp","effects":[],"_id":"wf1jpIZmrB5LfK93","system":{"description":"<p>Peu pratiquée dans les villages, la sarabande est une danse de cour, lente et solennelle, alternant groupe et couples, comme la turlutaine dont elle est une version «sérieuse».</p>\n<p>Les changements de partenaire s’accompagnent de profondes révérences.</p>","descriptionmj":"","type":"recreative","agilite":false,"apparence":true,"niveau":4,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870042,"modifiedTime":1671048281613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Le retour du baron gris","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":2,"description":"<p>Épopée pleine de cavalcades, de trahisons, de batailles et de cervelles éclatées.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_2.webp","effects":[],"_id":"xjITZoom3Azu9NQa"}
|
{"name":"Le retour du baron gris","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.xjITZoom3Azu9NQa"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_2.webp","effects":[],"_id":"xjITZoom3Azu9NQa","system":{"description":"<p>Épopée pleine de cavalcades, de trahisons, de batailles et de cervelles éclatées.</p>","descriptionmj":"","niveau":2,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870042,"modifiedTime":1671048281614,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"L’heure de la Lyre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":1,"description":"<p>Berceuse sur le thème de la nuit qui descend.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"yLcvnrbqIKS4ezj7"}
|
{"name":"L’heure de la Lyre","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.yLcvnrbqIKS4ezj7"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"yLcvnrbqIKS4ezj7","system":{"description":"<p>Berceuse sur le thème de la nuit qui descend.</p>","descriptionmj":"","niveau":1,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870043,"modifiedTime":1671048281614,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Le cavalier de sombre neige","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":6,"description":"<p>Épopée pleine de suspense et de terreur, où le soleil est rouge, la lune violette et la neige noire.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_6.webp","effects":[],"_id":"zRQ5WnPI483CKm9Q"}
|
{"name":"Le cavalier de sombre neige","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.zRQ5WnPI483CKm9Q"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_6.webp","effects":[],"_id":"zRQ5WnPI483CKm9Q","system":{"description":"<p>Épopée pleine de suspense et de terreur, où le soleil est rouge, la lune violette et la neige noire.</p>","descriptionmj":"","niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870043,"modifiedTime":1671048281614,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
{"_id":"0zRL8bOpCXNQnIR4","name":"Ruade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.0zRL8bOpCXNQnIR4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":4,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"0zRL8bOpCXNQnIR4","name":"Ruade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.0zRL8bOpCXNQnIR4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"description":null,"descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":4,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702692,"modifiedTime":1671048288982,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"4GmpkphbsmQjvVVK","name":"Escalade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.4GmpkphbsmQjvVVK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"4GmpkphbsmQjvVVK","name":"Escalade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.4GmpkphbsmQjvVVK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702692,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"6DK46pyO0hzEuuUg","name":"Morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.6DK46pyO0hzEuuUg"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"generale","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"6DK46pyO0hzEuuUg","name":"Morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.6DK46pyO0hzEuuUg"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"generale","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702692,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":14,"iscombat":true,"isparade":false,"ispossession":true,"dommages":0,"description":"<p>L'entité tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie":"melee"},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624948267,"modifiedTime":1663625011162,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"9u16zxXRurCtxuOX","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
|
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"description":"<p>L'entité tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie_parade":"","niveau":2,"default_diffLibre":0,"categorie":"draconic","carac_value":14,"iscombat":true,"isnaturelle":true,"ispossession":true,"dommages":0,"isparade":false},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624976822,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"9u16zxXRurCtxuOX","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
|
||||||
{"_id":"BjqRrGtHtTzuNpZB","name":"Griffes et Crocs","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"BjqRrGtHtTzuNpZB","name":"Griffes et Crocs","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702692,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"CYpxxf1uTa78NWR9","name":"Esquive","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.CYpxxf1uTa78NWR9"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"CYpxxf1uTa78NWR9","name":"Esquive","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.CYpxxf1uTa78NWR9"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702692,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"JTuBQCPdumw3DfxH","name":"Crête","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.JTuBQCPdumw3DfxH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-crete.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":3,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"JTuBQCPdumw3DfxH","name":"Crête","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.JTuBQCPdumw3DfxH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-crete.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":3,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"Kt7WlB5Ui97X211z","name":"Vol","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Kt7WlB5Ui97X211z"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-vol.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"Kt7WlB5Ui97X211z","name":"Vol","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Kt7WlB5Ui97X211z"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-vol.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"LWQHz5ymNBzh6ZEr","name":"Cornes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.LWQHz5ymNBzh6ZEr"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-corne.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"LWQHz5ymNBzh6ZEr","name":"Cornes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.LWQHz5ymNBzh6ZEr"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-corne.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"NctG7suzvGE7ZZzj","name":"Bras-bouches","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.NctG7suzvGE7ZZzj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-brasbouche.webp","effects":[],"system":{"categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"NctG7suzvGE7ZZzj","name":"Bras-bouches","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.NctG7suzvGE7ZZzj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-brasbouche.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"OzHBowOMADRwcVXR","name":"Pierre Tenue","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.OzHBowOMADRwcVXR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierretenue.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"OzHBowOMADRwcVXR","name":"Pierre Tenue","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.OzHBowOMADRwcVXR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierretenue.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":false,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"PCwbR6lghjydTj93","name":"Grande morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.PCwbR6lghjydTj93"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"PCwbR6lghjydTj93","name":"Grande morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.PCwbR6lghjydTj93"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"PrVuVpwuYaZtwRUi","name":"Piétinement","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.PrVuVpwuYaZtwRUi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":4,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"PrVuVpwuYaZtwRUi","name":"Piétinement","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.PrVuVpwuYaZtwRUi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"description":null,"descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":4,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"RAnasKnoA3OQgwfv","name":"Pinces","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.RAnasKnoA3OQgwfv"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pinces.webp","effects":[],"system":{"categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":3,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"RAnasKnoA3OQgwfv","name":"Pinces","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.RAnasKnoA3OQgwfv"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pinces.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":3,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"XgfRxSj8Ty1d3JFM","name":"Mandibules","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.XgfRxSj8Ty1d3JFM"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-mandibules.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","carac-value":null,"categorie":"generale","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"XgfRxSj8Ty1d3JFM","name":"Mandibules","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.XgfRxSj8Ty1d3JFM"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-mandibules.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"generale","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false,"carac-value":null},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"Zpl2Bi451vB3r91W","name":"Coup de pied","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Zpl2Bi451vB3r91W"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-coup_de_pied.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":3,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"Zpl2Bi451vB3r91W","name":"Coup de pied","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Zpl2Bi451vB3r91W"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-coup_de_pied.webp","effects":[],"system":{"description":null,"descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":3,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":14,"iscombat":true,"isparade":false,"ispossession":true,"dommages":0,"description":"<p>L'entité tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie":"draconic"},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624976822,"modifiedTime":1663625011162,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"duVgxI3Cdko0KzAj","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
|
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":14,"iscombat":true,"isparade":false,"ispossession":true,"dommages":0,"description":"<p>L'entité tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie":"draconic"},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624976822,"modifiedTime":1663625011162,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"duVgxI3Cdko0KzAj","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
|
||||||
{"_id":"efl1HdDSKpBfImQ1","name":"Pierre Lancée","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.efl1HdDSKpBfImQ1"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierrelancee.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"lancer","isnaturelle":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"efl1HdDSKpBfImQ1","name":"Pierre Lancée","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.efl1HdDSKpBfImQ1"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierrelancee.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"lancer","carac_value":0,"iscombat":true,"isnaturelle":false,"ispossession":false,"dommages":1,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"h9ASt4vrvEgxfj7j","name":"Tronçonneuse","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.h9ASt4vrvEgxfj7j"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-tronconneuse.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":10,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"h9ASt4vrvEgxfj7j","name":"Tronçonneuse","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.h9ASt4vrvEgxfj7j"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-tronconneuse.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":10,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"jhua9kkCs55OV7Yl","name":"Grandes griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.jhua9kkCs55OV7Yl"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"jhua9kkCs55OV7Yl","name":"Grandes griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.jhua9kkCs55OV7Yl"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"lzEdMrKXbOYrWG5S","name":"Vigilance","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.lzEdMrKXbOYrWG5S"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"lzEdMrKXbOYrWG5S","name":"Vigilance","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.lzEdMrKXbOYrWG5S"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"ndNshntOYb1JFNqi","name":"Serres","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.ndNshntOYb1JFNqi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-serres.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"ndNshntOYb1JFNqi","name":"Serres","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.ndNshntOYb1JFNqi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-serres.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"os88Rsp7mBkahqmh","name":"Bec","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.os88Rsp7mBkahqmh"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"os88Rsp7mBkahqmh","name":"Bec","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.os88Rsp7mBkahqmh"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"qilRzXpVaGceNmQp","name":"Dague","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.qilRzXpVaGceNmQp"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dague.webp","effects":[],"system":{"categorie_parade":"dagues","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"qilRzXpVaGceNmQp","name":"Dague","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.qilRzXpVaGceNmQp"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dague.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"dagues","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":false,"ispossession":false,"dommages":1,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"qrd9AoZzFgyzFBxz","name":"Griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.qrd9AoZzFgyzFBxz"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"qrd9AoZzFgyzFBxz","name":"Griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.qrd9AoZzFgyzFBxz"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"isparade":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"sUdXhpuVVOAlcVpo","name":"Pickpocket","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.sUdXhpuVVOAlcVpo"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_pickpocket.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"sUdXhpuVVOAlcVpo","name":"Pickpocket","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.sUdXhpuVVOAlcVpo"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_pickpocket.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288985,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"shsUV8UpU18c0RJK","name":"Course","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.shsUV8UpU18c0RJK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"shsUV8UpU18c0RJK","name":"Course","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.shsUV8UpU18c0RJK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288985,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"yBUVTjTXYfwvzusb","name":"Saut","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yBUVTjTXYfwvzusb"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":"","categorie":"generale"},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"yBUVTjTXYfwvzusb","name":"Saut","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yBUVTjTXYfwvzusb"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"generale","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288985,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"yDHZfK4RmwQW4YaW","name":"Discrétion","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yDHZfK4RmwQW4YaW"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"yDHZfK4RmwQW4YaW","name":"Discrétion","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yDHZfK4RmwQW4YaW"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288985,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
{"_id":"0Ms9iKxqigNNpZEx","name":"Esquive","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":false,"dommages":0,"description":"","categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","effects":[]}
|
{"_id":"0Ms9iKxqigNNpZEx","name":"Esquive","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.0Ms9iKxqigNNpZEx"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895714,"modifiedTime":1671048307066,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"18wcei5hlEInsBFO","name":"Attaque","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":0,"description":"","carac-value":null,"categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[]}
|
{"_id":"18wcei5hlEInsBFO","name":"Attaque","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.18wcei5hlEInsBFO"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":0,"carac-value":null,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895715,"modifiedTime":1671048307066,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"3Crwg8cx2JOb697T","name":"Parade","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":false,"dommages":0,"description":"","carac-value":null,"categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","effects":[]}
|
{"_id":"3Crwg8cx2JOb697T","name":"Parade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.3Crwg8cx2JOb697T"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"carac-value":null,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895715,"modifiedTime":1671048307066,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"6eWCVDYLXXO1Z48D","name":"Grandes griffes","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"categorie_parade":"sans-armes","niveau":0,"carac_value":0,"iscombat":true,"isparade":false,"dommages":2,"description":""},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[]}
|
{"_id":"6eWCVDYLXXO1Z48D","name":"Grandes griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895715,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"9Y83OsQgeyR5oCdH","name":"Griffes","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","carac-value":null,"categorie_parade":"sans-armes","isparade":false},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[]}
|
{"_id":"9Y83OsQgeyR5oCdH","name":"Griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"carac-value":null,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895715,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"D9cBJ3EJPYLnABiJ","name":"Tentacules","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"categorie_parade":"boucliers","niveau":0,"carac_value":0,"iscombat":true,"isparade":true,"dommages":2,"description":"<p>Attaque ou parade avec un tentacule.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-tentacule.webp","effects":[]}
|
{"_id":"D9cBJ3EJPYLnABiJ","name":"Tentacules","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.D9cBJ3EJPYLnABiJ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-tentacule.webp","effects":[],"system":{"description":"<p>Attaque ou parade avec un tentacule.</p>","descriptionmj":"","categorie_parade":"boucliers","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"QGULMUoC9JXFze0r","name":"Bouclier Lourd","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":0,"description":"","carac-value":null,"categorie_parade":"boucliers","isparade":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_bouclier.webp","effects":[]}
|
{"_id":"QGULMUoC9JXFze0r","name":"Bouclier Lourd","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.QGULMUoC9JXFze0r"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_bouclier.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"boucliers","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":0,"carac-value":null,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"WsYnwR8GcOxfuCI0","name":"Bras-Galet","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","carac-value":null,"categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","effects":[]}
|
{"_id":"WsYnwR8GcOxfuCI0","name":"Bras-Galet","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.WsYnwR8GcOxfuCI0"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"carac-value":null,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"c0I93Q53i4ZmxpyT","name":"Corps à Corps","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":0,"description":"","categorie_parade":"sans-armes","isparade":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp","effects":[]}
|
{"_id":"c0I93Q53i4ZmxpyT","name":"Corps à Corps","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"d5SZ09sFaG3cL2Rg","name":"Bec","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":0,"description":"","categorie_parade":"","isparade":false},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.os88Rsp7mBkahqmh"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp","effects":[]}
|
{"_id":"d5SZ09sFaG3cL2Rg","name":"Bec","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.os88Rsp7mBkahqmh"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"db8E8HwROw1ZcwRR","name":"Crocs","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","carac-value":null,"categorie_parade":"","isparade":false},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.NctG7suzvGE7ZZzj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-brasbouche.webp","effects":[]}
|
{"_id":"db8E8HwROw1ZcwRR","name":"Crocs","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.NctG7suzvGE7ZZzj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-brasbouche.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"carac-value":null,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"gPOQd9NI7AFH0whX","name":"Epée Bâtarde","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":4,"description":"","carac-value":null,"categorie_parade":"epees-lourdes","isparade":true},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-humanoides.YTKld5ggDsHqwYoR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_epee_1_main.webp","effects":[]}
|
{"_id":"gPOQd9NI7AFH0whX","name":"Epée Bâtarde","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-humanoides.YTKld5ggDsHqwYoR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_epee_1_main.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":4,"carac-value":null,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895717,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"j1xHCzfIeYKgXxoH","name":"Morsure","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[]}
|
{"_id":"j1xHCzfIeYKgXxoH","name":"Morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.j1xHCzfIeYKgXxoH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895717,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"_id":"lDZ3qUPKN35ob5TH","name":"Grande morsure","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"categorie_parade":"","niveau":0,"carac_value":0,"iscombat":true,"isparade":false,"dommages":2,"description":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[]}
|
{"_id":"lDZ3qUPKN35ob5TH","name":"Grande morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.lDZ3qUPKN35ob5TH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895717,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||||
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":-4,"categorie":"melee","carac_value":14,"iscombat":true,"isnaturelle":true,"ispossession":true,"dommages":0,"description":"<p>L'entité tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","isparade":false},"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.22","coreVersion":"10.286","createdTime":1663624976822,"modifiedTime":1664918524164,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"folder":null,"sort":0,"_id":"wDHR5UHWq568lfGa"}
|
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"description":"<p>L'entité tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie_parade":"","niveau":2,"default_diffLibre":-4,"categorie":"melee","carac_value":14,"iscombat":true,"isnaturelle":true,"ispossession":true,"dommages":0,"isparade":false},"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624976822,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"folder":null,"sort":0,"_id":"wDHR5UHWq568lfGa"}
|
||||||
|
|||||||