Compare commits
180 Commits
Author | SHA1 | Date | |
---|---|---|---|
c515e9bc66 | |||
b2e7a8a6e1 | |||
09045c0d53 | |||
4c4e1e8419 | |||
66bcc51102 | |||
32844bbf3c | |||
21d6f14b68 | |||
87a0bece5e | |||
e0f83e9be2 | |||
01c1978ccd | |||
47ae157781 | |||
0c092b9099 | |||
a6d1a84b13 | |||
82e8954d5c | |||
249850558b | |||
45b10f2c6b | |||
d39dac3bf9 | |||
1f5e8c084b | |||
0864721bc5 | |||
4c5685c20b | |||
a618200417 | |||
62eb6482d0 | |||
9b8ea03067 | |||
8090d0280d | |||
c31202fbd3 | |||
146c8d184c | |||
c251727dea | |||
19f5e2af59 | |||
8b2f02d4b0 | |||
03b88a269a | |||
32d016b9ad | |||
a0c1d063f1 | |||
1e5446fcde | |||
f76e0db046 | |||
b7c816129b | |||
c786757db0 | |||
78d4b48aae | |||
0a9e8e0ac6 | |||
5443cb52bb | |||
b232a8fa0c | |||
a68aa29b53 | |||
ccb9cd73f4 | |||
723d1e6b99 | |||
40f99da8ac | |||
76865d24d2 | |||
020824af7e | |||
cc8f432746 | |||
6435ce70da | |||
db9cbc693a | |||
b202352979 | |||
7ddedea204 | |||
2bca036d53 | |||
8f08f95dbf | |||
b5581ff9fb | |||
e06ae1937a | |||
0f7e1ef553 | |||
51afd9020c | |||
1bc5e06147 | |||
7f3a575349 | |||
c26ba66722 | |||
cb105dd311 | |||
76c88e530e | |||
03839397ce | |||
74ddc8893a | |||
790aa950c3 | |||
4672a3a7d6 | |||
2a8ab5e1ce | |||
4aaa72ed1a | |||
f087b61c27 | |||
96c6936c3e | |||
7d27d7d9f9 | |||
0d7ba3be69 | |||
8670456d9a | |||
b2c7ff4927 | |||
680fbee090 | |||
5c6a01b9f4 | |||
d45f5d625a | |||
2b1a9151d7 | |||
3335c41c27 | |||
329ae475d9 | |||
72f8c83caf | |||
d353b6ccaf | |||
a122a2e421 | |||
2465af4413 | |||
817c5d30ad | |||
87440cf7f9 | |||
965e45cead | |||
ac8610cd6c | |||
08cf1f49e1 | |||
4925cee756 | |||
43acbfb443 | |||
9a6fb1a850 | |||
42fb0c0b5e | |||
fa2b125459 | |||
e8d0748688 | |||
2972504640 | |||
3582fa9c8a | |||
d5277137dd | |||
dae852a1e0 | |||
1ea6b66483 | |||
d35f3ce5a2 | |||
bf9e74ef7c | |||
fd73b2c7af | |||
3aa13511cd | |||
94cebbb9e5 | |||
2a1495927f | |||
8d42871988 | |||
868ed01723 | |||
65c90c5bd4 | |||
c16101428a | |||
77d5646497 | |||
1c0c775de3 | |||
e8a59b56a4 | |||
39f6307058 | |||
a532a989d6 | |||
a802307dac | |||
d95a0ebfc1 | |||
25d7a447a8 | |||
2b6d1d8de1 | |||
de922e2605 | |||
dbad358d7a | |||
218f38e044 | |||
441259efb6 | |||
c99ac0675a | |||
d5fbca4778 | |||
c509e23513 | |||
50c336cda7 | |||
34e12cd701 | |||
bbd38bd618 | |||
3f4d52487d | |||
944dd103d2 | |||
e71c03abb0 | |||
17d863482d | |||
dcc450db63 | |||
6025f5d1de | |||
0b898b1ee7 | |||
1ad457f25f | |||
5e8c01935c | |||
0b7ec59822 | |||
a44904ebc0 | |||
a86ac0ffa2 | |||
0b3b1c66bd | |||
f26ae24d13 | |||
5207df0223 | |||
10ddcf031e | |||
830f4fde9a | |||
98de1a6922 | |||
dab371578d | |||
c58c9636d2 | |||
7f811ae249 | |||
396f73ec22 | |||
1de15d0b32 | |||
57ec6403bb | |||
372eb6d334 | |||
bc45ffa7bb | |||
b5e2f892a5 | |||
c28e8d4c9b | |||
658e4f45aa | |||
fdb1aec36a | |||
4a76221f07 | |||
300419cbad | |||
620b34443d | |||
432098f9c5 | |||
e1b10bc489 | |||
b4281afba8 | |||
ffd7b0b0c1 | |||
c281551603 | |||
5e9f1cd8a6 | |||
9245c7da44 | |||
1d69e1dc5a | |||
ec0e1ac257 | |||
aec5d6f239 | |||
e09bdadba7 | |||
7e252cf6ae | |||
38adf22e82 | |||
da7d67b3d7 | |||
948f707340 | |||
cfe99ec188 | |||
d85396db0f | |||
950e050051 |
BIN
fonts/goudyacc.woff
Normal file
BIN
fonts/heuresdraconiques2.ttf
Normal file
BIN
fonts/heuresdraconiques2.woff
Normal file
BIN
fonts/heuresdraconiques2.woff2
Normal file
BIN
icons/creatures/aligate_t.webp
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
icons/creatures/araflate_t.webp
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
icons/creatures/bandersnatch_t.webp
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
icons/creatures/bramart_t.webp
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
icons/creatures/brolute_t.webp
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
icons/creatures/chamule_t.webp
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
icons/creatures/cheval_t.webp
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
icons/creatures/chiard_t.webp
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
icons/creatures/chien_t.webp
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
icons/creatures/chrasme_t.webp
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
icons/creatures/cornicochon_t.webp
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
icons/creatures/dong_t.webp
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
icons/creatures/drakkule_t.webp
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
icons/creatures/felorn_t.webp
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
icons/creatures/harpie_t.webp
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
icons/heures/de-heures.webp
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
icons/heures/hd01.webp
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
icons/heures/hd02.webp
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
icons/heures/hd03.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
icons/heures/hd04.webp
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
icons/heures/hd05.webp
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
icons/heures/hd06.webp
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
icons/heures/hd07.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
icons/heures/hd08.webp
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
icons/heures/hd09.webp
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
icons/heures/hd10.webp
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
icons/heures/hd11.webp
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/heures/hd12.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
icons/tmr/gift.webp
Normal file
After Width: | Height: | Size: 528 B |
BIN
icons/tmr/pelerin.webp
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
icons/tmr/scroll.webp
Normal file
After Width: | Height: | Size: 7.9 KiB |
BIN
icons/tmr/treasure-chest.webp
Normal file
After Width: | Height: | Size: 5.1 KiB |
BIN
icons/tmr/wave.webp
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
icons/voyageurs/token_alchimiste.webp
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
icons/voyageurs/token_baladin.webp
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
icons/voyageurs/token_bois.webp
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
icons/voyageurs/token_combattant_choc.webp
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
icons/voyageurs/token_courreur.webp
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
icons/voyageurs/token_courreur_mer.webp
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
icons/voyageurs/token_dilettante.webp
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
icons/voyageurs/token_etranger.webp
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
icons/voyageurs/token_hr_cuisinier.webp
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
icons/voyageurs/token_hr_dilettante.webp
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
icons/voyageurs/token_hr_erudit.webp
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
icons/voyageurs/token_hr_muscle.webp
Normal file
After Width: | Height: | Size: 18 KiB |
@ -7,6 +7,7 @@
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { RdDActorSheet } from "./actor-sheet.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDActorCreatureSheet extends RdDActorSheet {
|
||||
@ -25,41 +26,25 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getData() {
|
||||
let data = super.getData();
|
||||
console.log("Creature : ", data);
|
||||
|
||||
data.itemsByType = {};
|
||||
for (const item of data.items) {
|
||||
let list = data.itemsByType[item.type];
|
||||
if (!list) {
|
||||
list = [];
|
||||
data.itemsByType[item.type] = list;
|
||||
}
|
||||
list.push(item);
|
||||
async getData() {
|
||||
let formData = await super.getData();
|
||||
console.log("Creature : ", formData);
|
||||
formData.calc = {
|
||||
caracTotal: RdDCarac.computeTotal(formData.data.carac),
|
||||
resumeBlessures: this.actor.computeResumeBlessure(formData.data.blessures),
|
||||
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
||||
}
|
||||
formData.calc.surEncombrementMessage = (formData.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : "";
|
||||
formData.options.isGM = game.user.isGM;
|
||||
|
||||
// Compute current carac sum
|
||||
let sum = 0;
|
||||
Object.values(data.data.carac).forEach(carac => { if (!carac.derivee) { sum += parseInt(carac.value) } });
|
||||
data.data.caracSum = sum;
|
||||
formData.data.competencecreature = formData.itemsByType["competencecreature"];
|
||||
|
||||
data.data.carac.taille.isTaille = true; // To avoid button link;
|
||||
data.data.blessures.resume = this.actor.computeResumeBlessure(data.data.blessures);
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||
RdDUtility.buildArbreDeConteneur(this, formData);
|
||||
|
||||
data.data.isGM = game.user.isGM;
|
||||
console.log("Creature : ", this.objetVersConteneur, formData);
|
||||
|
||||
data.data.competencecreature = data.itemsByType["competencecreature"];
|
||||
|
||||
this.actor.computeEncombrementTotalEtMalusArmure();
|
||||
RdDUtility.filterItemsPerTypeForSheet(data);
|
||||
RdDUtility.buildArbreDeConteneur(this, data);
|
||||
data.data.encTotal = this.actor.encTotal;
|
||||
data.data.isGM = game.user.isGM;
|
||||
|
||||
console.log("Creature : ", this.objetVersConteneur, data);
|
||||
|
||||
return data;
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -4,6 +4,7 @@
|
||||
*/
|
||||
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDActorEntiteSheet extends ActorSheet {
|
||||
@ -29,24 +30,18 @@ export class RdDActorEntiteSheet extends ActorSheet {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getData() {
|
||||
let data = super.getData();
|
||||
async getData() {
|
||||
let formData = super.getData();
|
||||
|
||||
data.itemsByType = {};
|
||||
for (const item of data.items) {
|
||||
let list = data.itemsByType[item.type];
|
||||
if (!list) {
|
||||
list = [];
|
||||
data.itemsByType[item.type] = list;
|
||||
}
|
||||
list.push(item);
|
||||
}
|
||||
formData.itemsByType = Misc.classify(formData.items);
|
||||
|
||||
data.data.carac.taille.isTaille = true; // To avoid button link;
|
||||
data.data.competencecreature = data.itemsByType["competencecreature"];
|
||||
data.data.isGM = game.user.isGM;
|
||||
formData.options.isGM = game.user.isGM;
|
||||
|
||||
return data;
|
||||
formData.data.carac.taille.isTaille = true; // To avoid button link;
|
||||
formData.data.competencecreature = formData.itemsByType["competencecreature"];
|
||||
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -10,6 +10,7 @@ import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDCombatManager } from "./rdd-combat.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDActorSheet extends ActorSheet {
|
||||
@ -31,120 +32,115 @@ export class RdDActorSheet extends ActorSheet {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getData() {
|
||||
let data = super.getData();
|
||||
if ( data.actor.type == 'creature' || data.actor.type == 'humanoide') return data; // Shortcut
|
||||
async getData() {
|
||||
let formData = super.getData();
|
||||
// -------------- version 0.7.9
|
||||
// let formData = {
|
||||
// cssClass: this.entity.owner ? "editable" : "locked",
|
||||
// editable: this.isEditable,
|
||||
// entity: duplicate(this.entity.data),
|
||||
// limited: this.entity.limited,
|
||||
// options: this.options,
|
||||
// owner: this.entity.owner,
|
||||
// title: this.title
|
||||
// }
|
||||
// // Entity data
|
||||
// formData.actor = formData.entity;
|
||||
// formData.data = formData.entity.data;
|
||||
|
||||
data.data.editCaracComp = this.options.editCaracComp;
|
||||
data.data.showCompNiveauBase = this.options.showCompNiveauBase;
|
||||
data.data.montrerArchetype = this.options.montrerArchetype;
|
||||
// // Owned items
|
||||
// formData.items = formData.actor.items;
|
||||
// formData.items.sort((a, b) => (a.sort || 0) - (b.sort || 0));
|
||||
|
||||
data.itemsByType = Misc.classify(data.items);
|
||||
formData.itemsByType = Misc.classify(formData.items);
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||
|
||||
// Competence per category
|
||||
data.data.comptageArchetype = RdDUtility.getLimitesArchetypes();
|
||||
data.data.competenceXPTotal = 0;
|
||||
data.competenceByCategory = Misc.classify(
|
||||
data.itemsByType.competence,
|
||||
item => item.data.categorie,
|
||||
item => {
|
||||
let archetypeKey = (item.data.niveau_archetype < 0) ? 0 : item.data.niveau_archetype;
|
||||
if (data.data.comptageArchetype[archetypeKey] == undefined) {
|
||||
data.data.comptageArchetype[archetypeKey] = { "niveau": archetypeKey, "nombreMax": 0, "nombre": 0};
|
||||
}
|
||||
data.data.comptageArchetype[archetypeKey].nombre = (data.data.comptageArchetype[archetypeKey]?.nombre??0) + 1; //Comptage archetype
|
||||
item.data.xpNext = RdDItemCompetence.getCompetenceNextXp(item.data.niveau);
|
||||
item.data.isLevelUp = item.data.xp >= item.data.xpNext; // Flag de niveau à MAJ
|
||||
//this.actor.checkCompetenceXP(item.name); // Petite vérification experience
|
||||
item.data.showCompetence = !data.data.showCompNiveauBase || (Number(item.data.niveau) != Number(RdDUtility.getLevelCategory(item.data.categorie)));
|
||||
// Ignorer les compétences 'troncs' à ce stade
|
||||
data.data.competenceXPTotal += RdDItemCompetence.computeCompetenceXPCost(item);
|
||||
return item;
|
||||
});
|
||||
data.data.competenceXPTotal -= RdDItemCompetence.computeEconomieCompetenceTroncXP(data.itemsByType.competence);
|
||||
formData.options.isGM = game.user.isGM;
|
||||
|
||||
// Compute current carac sum
|
||||
let sum = 0;
|
||||
for (let caracName in data.data.carac) {
|
||||
let currentCarac = data.data.carac[caracName];
|
||||
if (!currentCarac.derivee) {
|
||||
sum += parseInt(currentCarac.value);
|
||||
}
|
||||
currentCarac.xpNext = RdDUtility.getCaracNextXp(currentCarac.value);
|
||||
currentCarac.isLevelUp = (currentCarac.xp >= currentCarac.xpNext);
|
||||
}
|
||||
sum += (data.data.beaute >= 0) ? (data.data.beaute - 10) : 0;
|
||||
data.data.caracSum = sum;
|
||||
// la taille est la taille: on ne peut pas l'utiliser pour un jet
|
||||
formData.data.carac.taille.isTaille = true;
|
||||
|
||||
// Force empty arme, at least for Esquive
|
||||
if (data.itemsByType.arme == undefined) data.itemsByType.arme = [];
|
||||
for (const arme of data.itemsByType.arme) {
|
||||
arme.data.niveau = 0; // Per default, TODO to be fixed
|
||||
for (const melee of data.competenceByCategory.melee) {
|
||||
if (melee.name == arme.data.competence)
|
||||
arme.data.niveau = melee.data.niveau
|
||||
}
|
||||
for (const tir of data.competenceByCategory.tir) {
|
||||
if (tir.name == arme.data.competence)
|
||||
arme.data.niveau = tir.data.niveau
|
||||
}
|
||||
for (const lancer of data.competenceByCategory.lancer) {
|
||||
if (lancer.name == arme.data.competence)
|
||||
arme.data.niveau = lancer.data.niveau
|
||||
}
|
||||
}
|
||||
if (this.actor.data.type == 'creature') return formData; // Shortcut
|
||||
|
||||
// To avoid armour and so on...
|
||||
data.data.combat = duplicate(RdDUtility.checkNull(data.itemsByType['arme']));
|
||||
data.data.combat = RdDCombatManager.finalizeArmeList(data.data.combat, data.itemsByType.competence, data.data.carac);
|
||||
formData.competenceByCategory = Misc.classify(formData.data.competences, it => it.data.categorie);
|
||||
|
||||
data.esquive = { name: "Esquive", niveau: data.competenceByCategory?.melee.find(it => it.name == 'Esquive')?.data.niveau ?? -6};
|
||||
let corpsACorps = data.competenceByCategory?.melee.find(it => it.name == 'Corps à corps');
|
||||
if (corpsACorps) {
|
||||
let cc_init = RdDCombatManager.calculInitiative(corpsACorps.data.niveau, data.data.carac['melee'].value);
|
||||
data.data.combat.push(RdDItemArme.mainsNues({ niveau: corpsACorps.data.niveau, initiative: cc_init }));
|
||||
}
|
||||
this.armesList = duplicate(data.data.combat);
|
||||
formData.calc = {
|
||||
comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.data.competences),
|
||||
competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.data.competences),
|
||||
caracTotal: RdDCarac.computeTotal(formData.data.carac, formData.data.beaute),
|
||||
// Mise à jour de l'encombrement total et du prix de l'équipement
|
||||
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
||||
prixTotalEquipement: await this.actor.computePrixTotalEquipement(),
|
||||
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
|
||||
fatigue: {
|
||||
malus: RdDUtility.calculMalusFatigue(formData.data.sante.fatigue.value, formData.data.sante.endurance.max),
|
||||
html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(formData.data.sante.fatigue.value, formData.data.sante.endurance.max).html() + "</table>"
|
||||
},
|
||||
resumeBlessures: this.actor.computeResumeBlessure(formData.data.blessures),
|
||||
};
|
||||
formData.calc.surEncombrementMessage = (formData.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : "";
|
||||
|
||||
data.data.carac.taille.isTaille = true; // To avoid button link;
|
||||
data.data.compteurs.chance.isChance = true;
|
||||
data.data.blessures.resume = this.actor.computeResumeBlessure(data.data.blessures);
|
||||
formData.data.competences.forEach(item => {
|
||||
item.visible = !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item);
|
||||
RdDItemCompetence.levelUp(item);
|
||||
});
|
||||
|
||||
Object.values(formData.data.carac).forEach(c => {
|
||||
RdDCarac.levelUp(c);
|
||||
});
|
||||
|
||||
|
||||
// toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
|
||||
formData.data.combat = duplicate(formData.itemsByType.arme ?? []);
|
||||
RdDItemArme.computeNiveauArmes(formData.data.combat, formData.data.competences);
|
||||
RdDItemArme.ajoutCorpsACorps(formData.data.combat, formData.data.competences, formData.data.carac );
|
||||
formData.esquive = RdDItemCompetence.getEsquive(formData.data.competences);
|
||||
formData.data.combat = RdDCombatManager.finalizeArmeList(formData.data.combat, formData.itemsByType.competence, formData.data.carac);
|
||||
|
||||
|
||||
this.armesList = formData.data.combat;
|
||||
|
||||
// Mise à jour de l'encombrement total et du prix de l'équipement
|
||||
this.actor.computeEncombrementTotalEtMalusArmure();
|
||||
this.actor.computePrixTotalEquipement();
|
||||
|
||||
// Common data
|
||||
data.data.competenceByCategory = data.competenceByCategory;
|
||||
data.data.encTotal = this.actor.encTotal;
|
||||
data.data.prixTotalEquipement = this.actor.prixTotalEquipement;
|
||||
data.data.surprise = RdDBonus.find(this.actor.getSurprise(false)).descr;
|
||||
data.data.isGM = game.user.isGM;
|
||||
data.ajustementsConditions = CONFIG.RDD.ajustementsConditions;
|
||||
data.difficultesLibres = CONFIG.RDD.difficultesLibres;
|
||||
formData.data.competenceByCategory = formData.competenceByCategory;
|
||||
formData.data.isGM = game.user.isGM;
|
||||
formData.ajustementsConditions = CONFIG.RDD.ajustementsConditions;
|
||||
formData.difficultesLibres = CONFIG.RDD.difficultesLibres;
|
||||
|
||||
// low is normal, this the base used to compute the grid.
|
||||
data.data.fatigue = {
|
||||
malus: RdDUtility.calculMalusFatigue(data.data.sante.fatigue.value, data.data.sante.endurance.max),
|
||||
html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(data.data.sante.fatigue.value, data.data.sante.endurance.max).html() + "</table>"
|
||||
formData.data.fatigue = {
|
||||
malus: RdDUtility.calculMalusFatigue(formData.data.sante.fatigue.value, formData.data.sante.endurance.max),
|
||||
html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(formData.data.sante.fatigue.value, formData.data.sante.endurance.max).html() + "</table>"
|
||||
}
|
||||
|
||||
RdDUtility.filterItemsPerTypeForSheet(data);
|
||||
data.data.sortReserve = data.data.reve.reserve.list;
|
||||
data.data.rencontres = duplicate(data.data.reve.rencontre.list);
|
||||
data.data.caseSpeciales = data.itemsByType['casetmr'];
|
||||
RdDUtility.buildArbreDeConteneur(this, data);
|
||||
data.data.surEncombrementMessage = (data.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : "";
|
||||
data.data.vehiculesList = this.actor.buildVehiculesList();
|
||||
data.data.monturesList = this.actor.buildMonturesList();
|
||||
data.data.suivantsList = this.actor.buildSuivantsList();
|
||||
return data;
|
||||
formData.hautreve = {
|
||||
sortsReserve: formData.data.reve.reserve.list,
|
||||
rencontres: duplicate(formData.data.reve.rencontre.list),
|
||||
casesTmr: formData.itemsByType.casetmr
|
||||
}
|
||||
|
||||
RdDUtility.buildArbreDeConteneur(this, formData);
|
||||
formData.subacteurs = {
|
||||
vehicules: this.actor.listeVehicules(),
|
||||
montures: this.actor.listeMontures(),
|
||||
suivants: this.actor.listeSuivants()
|
||||
}
|
||||
if (this.actor.getBestDraconic().data.niveau > -11 && !this.actor.isHautRevant()) {
|
||||
ui.notifications.error(`${this.actor.name} a des compétences draconiques, mais pas le don de Haut-Rêve!
|
||||
<br>Ajoutez-lui la tête "Don de Haut-Rêve" pour lui permettre d'utiliser ses compétences et d'accéder aux terres médianes du rêve`);
|
||||
}
|
||||
return formData;
|
||||
}
|
||||
|
||||
isCompetenceAffichable(competence) {
|
||||
return !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(competence);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _onDrop(event) {
|
||||
let toSuper = await RdDUtility.processItemDropEvent(this, event);
|
||||
if ( toSuper) {
|
||||
if (toSuper) {
|
||||
super._onDrop(event);
|
||||
}
|
||||
}
|
||||
@ -156,16 +152,16 @@ export class RdDActorSheet extends ActorSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async creerObjet() {
|
||||
let itemType = $("#creer-equipement").val();
|
||||
let itemType = $(".item-type").val();
|
||||
await this.actor.createOwnedItem({ name: 'Nouveau ' + itemType, type: itemType }, { renderSheet: true });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async selectObjetType() {
|
||||
let itemType = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "monnaie"];
|
||||
let options = '<span class="competence-label">Selectionnez le type d\'équipement</span><select id="creer-equipement">';
|
||||
for (let typeName of itemType) {
|
||||
options += '<option value="' + typeName + '">' + typeName + '</option>'
|
||||
let typeObjets = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "monnaie"];
|
||||
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({
|
||||
@ -182,6 +178,27 @@ export class RdDActorSheet extends ActorSheet {
|
||||
d.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async selectTypeOeuvre() {
|
||||
let typeOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu" ];
|
||||
let options = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
|
||||
for (let typeName of typeOeuvres) {
|
||||
options += `<option value="${typeName}">${typeName}</option>`
|
||||
}
|
||||
options += '</select>';
|
||||
let d = new Dialog({
|
||||
title: "Créer une oeuvre",
|
||||
content: options,
|
||||
buttons: {
|
||||
one: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: "Créer l'oeuvre",
|
||||
callback: () => this.creerObjet()
|
||||
}
|
||||
}
|
||||
});
|
||||
d.render(true);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
@ -229,12 +246,15 @@ export class RdDActorSheet extends ActorSheet {
|
||||
ev.preventDefault();
|
||||
}
|
||||
});
|
||||
html.find('#creer-tache').click(ev => {
|
||||
html.find('.creer-tache').click(ev => {
|
||||
this.createEmptyTache();
|
||||
});
|
||||
html.find('#creer-un-objet').click(ev => {
|
||||
html.find('.creer-un-objet').click(ev => {
|
||||
this.selectObjetType();
|
||||
});
|
||||
html.find('.creer-une-oeuvre').click(ev => {
|
||||
this.selectTypeOeuvre();
|
||||
});
|
||||
html.find('#nettoyer-conteneurs').click(ev => {
|
||||
this.actor.nettoyerConteneurs();
|
||||
});
|
||||
@ -275,11 +295,11 @@ export class RdDActorSheet extends ActorSheet {
|
||||
this.actor.rollCarac(caracName.toLowerCase());
|
||||
});
|
||||
|
||||
html.find('#chance-actuelle').click((event) => {
|
||||
html.find('.chance-actuelle').click((event) => {
|
||||
this.actor.rollCarac('chance-actuelle');
|
||||
});
|
||||
|
||||
html.find('#chance-appel').click((event) => {
|
||||
html.find('.chance-appel').click((event) => {
|
||||
this.actor.rollAppelChance();
|
||||
});
|
||||
|
||||
@ -335,8 +355,8 @@ export class RdDActorSheet extends ActorSheet {
|
||||
html.find('.subacteur-label a').click((event) => {
|
||||
const li = $(event.currentTarget).parents(".item");
|
||||
let actorId = li.data('actor-id');
|
||||
let actor = game.actors.get( actorId) ;
|
||||
if ( actor ) {
|
||||
let actor = game.actors.get(actorId);
|
||||
if (actor) {
|
||||
actor.sheet.render(true);
|
||||
}
|
||||
});
|
||||
@ -461,9 +481,7 @@ export class RdDActorSheet extends ActorSheet {
|
||||
// On pts de reve change
|
||||
html.find('.pointsreve-value').change((event) => {
|
||||
let reveValue = event.currentTarget.value;
|
||||
let reve = duplicate(this.actor.data.data.reve.reve);
|
||||
reve.value = reveValue;
|
||||
this.actor.update({ "data.reve.reve": reve });
|
||||
this.actor.update({ "data.reve.reve.value": reveValue });
|
||||
});
|
||||
|
||||
// On seuil de reve change
|
||||
@ -473,7 +491,7 @@ export class RdDActorSheet extends ActorSheet {
|
||||
});
|
||||
|
||||
html.find('#attribut-protection-edit').change((event) => {
|
||||
this.actor.updateProtectionValue(event.currentTarget.attributes.name.value, parseInt(event.target.value));
|
||||
this.actor.updateAttributeValue(event.currentTarget.attributes.name.value, parseInt(event.target.value));
|
||||
});
|
||||
|
||||
// On stress change
|
||||
@ -485,19 +503,19 @@ export class RdDActorSheet extends ActorSheet {
|
||||
html.find('#ethylisme').change((event) => {
|
||||
this.actor.setEthylisme(parseInt(event.target.value));
|
||||
});
|
||||
html.find('#stress-test').click((event) => {
|
||||
html.find('.stress-test').click((event) => {
|
||||
this.actor.transformerStress();
|
||||
this.render(true);
|
||||
});
|
||||
html.find('#moral-malheureux').click((event) => {
|
||||
html.find('.moral-malheureux').click((event) => {
|
||||
this.actor.jetDeMoral('malheureuse');
|
||||
this.render(true);
|
||||
});
|
||||
html.find('#moral-neutre').click((event) => {
|
||||
html.find('.moral-neutre').click((event) => {
|
||||
this.actor.jetDeMoral('neutre');
|
||||
this.render(true);
|
||||
});
|
||||
html.find('#moral-heureux').click((event) => {
|
||||
html.find('.moral-heureux').click((event) => {
|
||||
this.actor.jetDeMoral('heureuse');
|
||||
this.render(true);
|
||||
});
|
||||
|
@ -33,21 +33,24 @@ export class RdDActorVehiculeSheet extends ActorSheet {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getData() {
|
||||
let data = super.getData();
|
||||
async getData() {
|
||||
let formData = super.getData();
|
||||
|
||||
data.itemsByType = Misc.classify(data.items);
|
||||
formData.itemsByType = Misc.classify(formData.items);
|
||||
|
||||
RdDUtility.filterItemsPerTypeForSheet(data);
|
||||
RdDUtility.buildArbreDeConteneur(this, data);
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||
RdDUtility.buildArbreDeConteneur(this, formData);
|
||||
|
||||
this.actor.computeEncombrementTotalEtMalusArmure();
|
||||
data.data.isGM = game.user.isGM;
|
||||
data.data.surEncombrementMessage = (this.encTotal > data.capacite_encombrement) ? "Sur-Encombrement!" : "";
|
||||
formData.options.isGM = game.user.isGM;
|
||||
|
||||
console.log("DATA", data);
|
||||
formData.calc ={
|
||||
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
||||
}
|
||||
formData.calc.surEncombrementMessage = formData.calc.encTotal > formData.data.capacite_encombrement ? "Sur-Encombrement!" : "",
|
||||
|
||||
return data;
|
||||
console.log("DATA", formData);
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
1089
module/actor.js
@ -1,3 +1,4 @@
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
/**
|
||||
* Class providing helper methods to get the list of users, and
|
||||
@ -7,32 +8,27 @@ export class ChatUtility {
|
||||
/* -------------------------------------------- */
|
||||
static onSocketMessage(sockmsg) {
|
||||
switch (sockmsg.msg) {
|
||||
case "msg_delete_chat_message": return ChatUtility.onRemoveMessages(sockmsg.part, sockmsg.gmId);
|
||||
case "msg_delete_chat_message": return ChatUtility.onRemoveMessages(sockmsg.part);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onRemoveMessages(part, gmId) {
|
||||
if (game.user._id == gmId) {
|
||||
static onRemoveMessages(part) {
|
||||
if (Misc.isElectedUser()) {
|
||||
const toDelete = game.messages.filter(it => it.data.content.includes(part));
|
||||
toDelete.forEach(it => it.delete());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static removeChatMessageContaining(part) {
|
||||
const gmId = game.user.isGM ? game.user._id : game.users.entities.find(u => u.isGM)?.id;
|
||||
|
||||
if (!gmId || game.user.isGM) {
|
||||
ChatUtility.onRemoveMessages(part, game.user._id);
|
||||
if (Misc.isElectedUser()) {
|
||||
ChatUtility.onRemoveMessages(part);
|
||||
}
|
||||
else {
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", {
|
||||
msg: "msg_delete_chat_message", data: {
|
||||
part:part,
|
||||
gmId: gmId,
|
||||
}});
|
||||
msg: "msg_delete_chat_message", data: { part: part }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
1
module/constants.js
Normal file
@ -0,0 +1 @@
|
||||
export const SYSTEM_RDD = "foundryvtt-reve-de-dragon";
|
@ -1,27 +0,0 @@
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
|
||||
export class DeDraconique extends Roll{
|
||||
|
||||
static async ddr(rollMode=undefined) {
|
||||
let ddr = new DeDraconique().evaluate();
|
||||
await RdDDice.show(ddr, rollMode);
|
||||
return ddr;
|
||||
}
|
||||
|
||||
constructor(){
|
||||
super("1d8x8 - 0")
|
||||
}
|
||||
|
||||
evaluate() {
|
||||
super.evaluate();
|
||||
const rerolls = Math.ceil(this.total / 8);
|
||||
this.terms[this.terms.length - 1] = rerolls;
|
||||
this.results[this.results.length - 1] = rerolls;
|
||||
this._total -= rerolls;
|
||||
return this;
|
||||
}
|
||||
|
||||
async render(chatOptions) {
|
||||
return super.render(chatOptions)
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@ export class Grammar {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static articleDetermine(genre) {
|
||||
switch (toLowerCaseNoAccent(genre)) {
|
||||
switch (Grammar.toLowerCaseNoAccent(genre)) {
|
||||
case 'f': case 'feminin': return 'la';
|
||||
case 'p': case 'mp': case 'fp': case 'pluriel': return 'les';
|
||||
default:
|
||||
@ -35,8 +35,8 @@ export class Grammar {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static articleIndétermine(genre) {
|
||||
switch (toLowerCaseNoAccent(genre)) {
|
||||
static articleIndetermine(genre) {
|
||||
switch (Grammar.toLowerCaseNoAccent(genre)) {
|
||||
case 'f': case 'feminin': return 'une';
|
||||
case 'p': case 'fp': case 'mp': case 'pluriel': return 'des';
|
||||
case 'n': case 'neutre': return 'du'
|
||||
@ -58,7 +58,7 @@ export class Grammar {
|
||||
* @param {...any} mots
|
||||
*/
|
||||
static accord(genre, ...mots) {
|
||||
switch (toLowerCaseNoAccent(genre)) {
|
||||
switch (Grammar.toLowerCaseNoAccent(genre)) {
|
||||
default:
|
||||
case 'n': case 'neutre':
|
||||
case 'm': case 'masculin': return mots[0];
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDCombatManager } from "./rdd-combat.js";
|
||||
|
||||
const nomCategorieParade = {
|
||||
"sans-armes": "Sans arme / armes naturelles",
|
||||
@ -16,20 +18,33 @@ const nomCategorieParade = {
|
||||
/* -------------------------------------------- */
|
||||
export class RdDItemArme extends Item {
|
||||
|
||||
static isArme(item) {
|
||||
return (item.type == 'competencecreature' && item.data.iscombat) || item.type == 'arme';
|
||||
static isArme(itemData) {
|
||||
itemData = Misc.data(itemData);
|
||||
return (itemData.type == 'competencecreature' && itemData.data.iscombat) || itemData.type == 'arme';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getArmeData(item) {
|
||||
switch (item ? item.data.type : '') {
|
||||
case 'arme': return item.data;
|
||||
static getArmeData(armeData) {
|
||||
armeData = Misc.data(armeData);
|
||||
switch (armeData ? armeData.type : '') {
|
||||
case 'arme': return armeData;
|
||||
case 'competencecreature':
|
||||
return RdDItemCompetenceCreature.toArme(item.data);
|
||||
return RdDItemCompetenceCreature.toArme(armeData);
|
||||
}
|
||||
return RdDItemArme.mainsNues();
|
||||
}
|
||||
|
||||
static computeNiveauArmes(armes, competences) {
|
||||
for (const arme of armes) {
|
||||
arme.data.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
|
||||
}
|
||||
}
|
||||
|
||||
static niveauCompetenceArme(arme, competences) {
|
||||
const compArme = competences.find(it => it.name == arme.data.competence);
|
||||
return compArme?.data.niveau ?? -8;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getNomCategorieParade(arme) {
|
||||
const categorie = arme?.data ? RdDItemArme.getCategorieParade(arme) : arme;
|
||||
@ -38,7 +53,7 @@ export class RdDItemArme extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static needArmeResist(armeAttaque, armeParade) {
|
||||
if (!armeAttaque || !armeParade){
|
||||
if (!armeAttaque || !armeParade) {
|
||||
return false;
|
||||
}
|
||||
// Epées parant une arme de bois (cf. page 115 ), une résistance est nécessaire
|
||||
@ -49,21 +64,22 @@ export class RdDItemArme extends Item {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCategorieParade(arme) {
|
||||
if (arme.data.categorie_parade) {
|
||||
return arme.data.categorie_parade;
|
||||
static getCategorieParade(armeData) {
|
||||
armeData = Misc.data(armeData);
|
||||
if (armeData.data.categorie_parade) {
|
||||
return armeData.data.categorie_parade;
|
||||
}
|
||||
// pour compatibilité avec des personnages existants
|
||||
if (arme.type == 'competencecreature' || arme.data.categorie == 'creature' ) {
|
||||
return arme.data.categorie_parade || (arme.data.isparade ? 'sans-armes' : '');
|
||||
if (armeData.type == 'competencecreature' || armeData.data.categorie == 'creature') {
|
||||
return armeData.data.categorie_parade || (armeData.data.isparade ? 'sans-armes' : '');
|
||||
}
|
||||
if (!arme.type.match(/arme|competencecreature/)) {
|
||||
if (!armeData.type.match(/arme|competencecreature/)) {
|
||||
return '';
|
||||
}
|
||||
if (arme.data.competence == undefined) {
|
||||
if (armeData.data.competence == undefined) {
|
||||
return 'competencecreature';
|
||||
}
|
||||
let compname = arme.data.competence.toLowerCase();
|
||||
let compname = armeData.data.competence.toLowerCase();
|
||||
if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return '';
|
||||
|
||||
if (compname.match('hache')) return 'haches';
|
||||
@ -72,9 +88,9 @@ export class RdDItemArme extends Item {
|
||||
if (compname.match('bouclier')) return 'boucliers';
|
||||
if (compname.match('masse')) return 'masses';
|
||||
if (compname.match('epée') || compname.match('épée')) {
|
||||
if (arme.name.toLowerCase().match(/(gnome)/))
|
||||
if (armeData.name.toLowerCase().match(/(gnome)/))
|
||||
return 'epees-courtes';
|
||||
if (arme.name.toLowerCase().match(/((e|é)pée dragone|esparlongue|demi-dragonne)/))
|
||||
if (armeData.name.toLowerCase().match(/((e|é)pée dragone|esparlongue|demi-dragonne)/))
|
||||
return 'epees-longues';
|
||||
return 'epees-lourdes';
|
||||
}
|
||||
@ -86,7 +102,7 @@ export class RdDItemArme extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static needParadeSignificative(armeAttaque, armeParade) {
|
||||
if (!armeAttaque || !armeParade){
|
||||
if (!armeAttaque || !armeParade) {
|
||||
return false;
|
||||
}
|
||||
// categories d'armes à la parade (cf. page 115 )
|
||||
@ -119,36 +135,44 @@ export class RdDItemArme extends Item {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static armeUneOuDeuxMains(arme, aUneMain) {
|
||||
if (arme) {
|
||||
arme.data.unemain = arme.data.unemain || !arme.data.deuxmains;
|
||||
const uneOuDeuxMains = arme.data.unemain && arme.data.deuxmains;
|
||||
const containsSlash = !Number.isInteger(arme.data.dommages) && arme.data.dommages.includes("/");
|
||||
static armeUneOuDeuxMains(armeData, aUneMain) {
|
||||
armeData = Misc.data(armeData);
|
||||
if (armeData) {
|
||||
armeData.data.unemain = armeData.data.unemain || !armeData.data.deuxmains;
|
||||
const uneOuDeuxMains = armeData.data.unemain && armeData.data.deuxmains;
|
||||
const containsSlash = !Number.isInteger(armeData.data.dommages) && armeData.data.dommages.includes("/");
|
||||
if (containsSlash) { // Sanity check
|
||||
arme = duplicate(arme);
|
||||
armeData = duplicate(armeData);
|
||||
|
||||
const tableauDegats = arme.data.dommages.split("/");
|
||||
const tableauDegats = armeData.data.dommages.split("/");
|
||||
if (aUneMain)
|
||||
arme.data.dommagesReels = Number(tableauDegats[0]);
|
||||
armeData.data.dommagesReels = Number(tableauDegats[0]);
|
||||
else // 2 mains
|
||||
arme.data.dommagesReels = Number(tableauDegats[1]);
|
||||
armeData.data.dommagesReels = Number(tableauDegats[1]);
|
||||
}
|
||||
else {
|
||||
arme.data.dommagesReels = Number(arme.data.dommages);
|
||||
armeData.data.dommagesReels = Number(armeData.data.dommages);
|
||||
}
|
||||
|
||||
if (uneOuDeuxMains != containsSlash) {
|
||||
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 " + armeData.name + " ne sont pas corrects (ie sous la forme X/Y)");
|
||||
}
|
||||
}
|
||||
return arme;
|
||||
return armeData;
|
||||
}
|
||||
|
||||
static isArmeUtilisable(item) {
|
||||
return item.type == 'arme' && (item.data.resistance > 0 || item.data.portee_courte>0);
|
||||
static isArmeUtilisable(itemData) {
|
||||
itemData = Misc.data(itemData);
|
||||
return itemData.type == 'arme' && itemData.data.equipe && (itemData.data.resistance > 0 || itemData.data.portee_courte > 0);
|
||||
}
|
||||
|
||||
static mainsNues(actorData={}) {
|
||||
static ajoutCorpsACorps(armes, competences, carac) {
|
||||
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { data: { niveau: -6 } };
|
||||
let init = RdDCombatManager.calculInitiative(corpsACorps.data.niveau, carac['melee'].value);
|
||||
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.data.niveau, initiative: init }));
|
||||
}
|
||||
|
||||
static mainsNues(actorData = {}) {
|
||||
const mainsNues = {
|
||||
name: 'Mains nues',
|
||||
data: {
|
||||
@ -163,7 +187,7 @@ export class RdDItemArme extends Item {
|
||||
}
|
||||
};
|
||||
if (actorData) {
|
||||
mergeObject( mainsNues.data, actorData, {overwrite:false});
|
||||
mergeObject(mainsNues.data, actorData, { overwrite: false });
|
||||
}
|
||||
return mainsNues
|
||||
}
|
||||
|
@ -1,9 +1,45 @@
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
const competenceTroncs = [["Esquive", "Dague", "Corps à corps"],
|
||||
["Epée à 1 main", "Epée à 2 mains", "Hache à 1 main", "Hache à 2 mains", "Lance", "Masse à 1 main", "Masse à 2 mains"]];
|
||||
|
||||
const competence_xp_par_niveau = [5, 5, 5, 10, 10, 10, 10, 15, 15, 15, 15, 20, 20, 20, 20, 30, 30, 40, 40, 60, 60, 100, 100, 100, 100, 100, 100, 100, 100, 100];
|
||||
const competence_niveau_max = competence_xp_par_niveau.length - 10;
|
||||
/* -------------------------------------------- */
|
||||
const limitesArchetypes = [
|
||||
{ "niveau": 0, "nombreMax": 100, "nombre": 0 },
|
||||
{ "niveau": 1, "nombreMax": 10, "nombre": 0 },
|
||||
{ "niveau": 2, "nombreMax": 9, "nombre": 0 },
|
||||
{ "niveau": 3, "nombreMax": 8, "nombre": 0 },
|
||||
{ "niveau": 4, "nombreMax": 7, "nombre": 0 },
|
||||
{ "niveau": 5, "nombreMax": 6, "nombre": 0 },
|
||||
{ "niveau": 6, "nombreMax": 5, "nombre": 0 },
|
||||
{ "niveau": 7, "nombreMax": 4, "nombre": 0 },
|
||||
{ "niveau": 8, "nombreMax": 3, "nombre": 0 },
|
||||
{ "niveau": 9, "nombreMax": 2, "nombre": 0 },
|
||||
{ "niveau": 10, "nombreMax": 1, "nombre": 0 },
|
||||
{ "niveau": 11, "nombreMax": 1, "nombre": 0 }
|
||||
];
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const categorieCompetences = {
|
||||
"generale": { base: "-4", label: "Générales" },
|
||||
"particuliere": { base: "-8", label: "Particulières" },
|
||||
"specialisee": { base: "-11", label: "Spécialisées" },
|
||||
"connaissance": { base: "-11", label: "Connaissances" },
|
||||
"draconic": { base: "-11", label: "Draconics" },
|
||||
"melee": { base: "-6", label: "Mêlée" },
|
||||
"tir": { base: "-8", label: "Tir" },
|
||||
"lancer": { base: "-8", label: "Lancer" }
|
||||
}
|
||||
|
||||
const compendiumCompetences = {
|
||||
"personnage": "foundryvtt-reve-de-dragon.competences",
|
||||
"creature": "foundryvtt-reve-de-dragon.competences-creatures",
|
||||
"entite": "foundryvtt-reve-de-dragon.competences-entites"
|
||||
};
|
||||
|
||||
|
||||
function _buildCumulXP() {
|
||||
let cumulXP = { "-11": 0 };
|
||||
@ -20,11 +56,29 @@ const competence_xp_cumul = _buildCumulXP();
|
||||
|
||||
export class RdDItemCompetence extends Item {
|
||||
|
||||
static actorCompendium(actorType) {
|
||||
return compendiumCompetences[actorType];
|
||||
}
|
||||
|
||||
static getCategorieCompetences() {
|
||||
return categorieCompetences;
|
||||
}
|
||||
static getNiveauBase(category) {
|
||||
return categorieCompetences[category].base;
|
||||
}
|
||||
static getLabelCategorie(category) {
|
||||
return categorieCompetences[category].label;
|
||||
}
|
||||
|
||||
static getEsquive(competences) {
|
||||
return { name: 'Esquive', niveau: RdDItemCompetence.findCompetence(competences, 'Esquive')?.data.niveau ?? -6 };
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCompetenceArme(competence) {
|
||||
switch (competence.data.categorie) {
|
||||
case 'melee':
|
||||
return competence.name.toLowerCase() != 'esquive';
|
||||
return competence.name != 'Esquive';
|
||||
case 'tir':
|
||||
case 'lancer':
|
||||
return true;
|
||||
@ -55,11 +109,49 @@ export class RdDItemCompetence extends Item {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeTotalXP(competences) {
|
||||
const total = competences.map(c => RdDItemCompetence.computeXP(c))
|
||||
.reduce((a, b) => a + b, 0);
|
||||
const economieTronc = RdDItemCompetence.computeEconomieXPTronc(competences);
|
||||
return total - economieTronc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeXP(competence) {
|
||||
const factor = competence.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double !
|
||||
const xpNiveau = RdDItemCompetence.computeDeltaXP(competence.data.base, competence.data.niveau ?? competence.data.base);
|
||||
const xp = competence.data.xp ?? 0;
|
||||
const xpSort = competence.data.xp_sort ?? 0;
|
||||
return factor * (xpNiveau + xp) + xpSort;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeEconomieXPTronc(competences) {
|
||||
return competenceTroncs.map(
|
||||
list => list.map(name => RdDItemCompetence.findCompetence(competences, name))
|
||||
// calcul du coût xp jusqu'au niveau 0 maximum
|
||||
.map(it => RdDItemCompetence.computeDeltaXP(it?.data.base ?? -11, Math.min(it?.data.niveau ?? -11, 0)))
|
||||
.sort(Misc.ascending())
|
||||
.splice(0, list.length-1) // prendre toutes les valeurs sauf l'une des plus élevées
|
||||
.reduce(Misc.sum(), 0)
|
||||
).reduce(Misc.sum(), 0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeDeltaXP(from, to) {
|
||||
RdDItemCompetence._valideNiveau(from);
|
||||
RdDItemCompetence._valideNiveau(to);
|
||||
return competence_xp_cumul[to] - competence_xp_cumul[from];
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeCompetenceXPCost(competence) {
|
||||
let xp = RdDItemCompetence.getDeltaXp(competence.data.base, competence.data.niveau ?? competence.data.base);
|
||||
xp += competence.data.xp ?? 0;
|
||||
if ( competence.name.includes('Thanatos') ) xp *= 2; /// Thanatos compte double !
|
||||
if (competence.name.includes('Thanatos')) xp *= 2; /// Thanatos compte double !
|
||||
xp += competence.data.xp_sort ?? 0;
|
||||
return xp;
|
||||
}
|
||||
@ -69,19 +161,45 @@ export class RdDItemCompetence extends Item {
|
||||
let economie = 0;
|
||||
for (let troncList of competenceTroncs) {
|
||||
let list = troncList.map(name => RdDItemCompetence.findCompetence(competences, name))
|
||||
.sort( (c1, c2) => c2.data.niveau - c1.data.niveau); // tri du plus haut au plus bas
|
||||
list.splice(0,1); // ignorer la plus élevée
|
||||
.sort((c1, c2) => c2.data.niveau - c1.data.niveau); // tri du plus haut au plus bas
|
||||
list.splice(0, 1); // ignorer la plus élevée
|
||||
list.forEach(c => {
|
||||
economie += RdDItemCompetence.getDeltaXp(c.data.base, Math.min(c.data.niveau, 0) );
|
||||
economie += RdDItemCompetence.getDeltaXp(c.data.base, Math.min(c.data.niveau, 0));
|
||||
});
|
||||
}
|
||||
return economie;
|
||||
}
|
||||
|
||||
static levelUp(itemData) {
|
||||
itemData.data.xpNext = RdDItemCompetence.getCompetenceNextXp(itemData.data.niveau);
|
||||
itemData.data.isLevelUp = itemData.data.xp >= itemData.data.xpNext;
|
||||
}
|
||||
|
||||
static isVisible(itemData) {
|
||||
return Number(itemData.data.niveau) != RdDItemCompetence.getNiveauBase(itemData.data.categorie);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isNiveauBase(itemData) {
|
||||
return Number(itemData.data.niveau) == RdDItemCompetence.getNiveauBase(itemData.data.categorie);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static findCompetence(list, name) {
|
||||
name = name.toLowerCase();
|
||||
return list.find(item => item.name.toLowerCase() == name && (item.type == "competence" || item.type == "competencecreature"))
|
||||
name = Grammar.toLowerCaseNoAccent(name);
|
||||
const competences = list.filter(it => Grammar.toLowerCaseNoAccent(it.name).includes(name) && (it.type == "competence" || it.type == "competencecreature"));
|
||||
if (competences.length == 0) {
|
||||
return undefined;
|
||||
}
|
||||
let competence = competences.find(it => Grammar.toLowerCaseNoAccent(it.name) == name);
|
||||
if (competence) {
|
||||
return competence;
|
||||
}
|
||||
if (competences.length>1) {
|
||||
const names = competences.map(it => it.name).reduce((a, b) => `${a}<br>${b}`);
|
||||
ui.notifications.info(`Plusieurs compétences possibles:<br>${names}<br>La première sera choisie: ${competences[0].name}`);
|
||||
}
|
||||
return competences[0];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -103,10 +221,26 @@ export class RdDItemCompetence extends Item {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _valideNiveau(niveau){
|
||||
static _valideNiveau(niveau) {
|
||||
if (niveau < -11 || niveau > competence_niveau_max) {
|
||||
console.warn("Niveau en dehors des niveaux de compétences: [-11, " + competence_niveau_max + "]", niveau)
|
||||
console.warn(`Niveau ${niveau} en dehors des niveaux de compétences: [-11, ${competence_niveau_max} ]`);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeResumeArchetype(competences) {
|
||||
const archetype = RdDItemCompetence.getLimitesArchetypes();
|
||||
competences.forEach(it => {
|
||||
let niveau = Math.max(0, it.data.niveau_archetype);
|
||||
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
|
||||
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;
|
||||
});
|
||||
return archetype;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getLimitesArchetypes() {
|
||||
return duplicate(limitesArchetypes);
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDItemCompetenceCreature extends Item {
|
||||
|
||||
@ -15,31 +17,34 @@ export class RdDItemCompetenceCreature extends Item {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static toArme(item) {
|
||||
if (RdDItemCompetenceCreature.isCompetenceAttaque(item)) {
|
||||
let arme = { name: item.name, data: duplicate(item.data) };
|
||||
static toArme(itemData) {
|
||||
if (RdDItemCompetenceCreature.isCompetenceAttaque(itemData)) {
|
||||
let arme = duplicate(Misc.data(itemData));
|
||||
mergeObject(arme.data,
|
||||
{
|
||||
competence: item.name,
|
||||
competence: arme.name,
|
||||
resistance: 100,
|
||||
equipe: true,
|
||||
dommagesReels: arme.data.dommages,
|
||||
penetration: 0,
|
||||
force: 0,
|
||||
rapide: true
|
||||
});
|
||||
return arme;
|
||||
}
|
||||
console.error("RdDItemCompetenceCreature.toArme(", item, ") : impossible de transformer l'Item en arme");
|
||||
console.error("RdDItemCompetenceCreature.toArme(", itemData, ") : impossible de transformer l'Item en arme");
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCompetenceAttaque(item) {
|
||||
return item.type == 'competencecreature' && item.data.iscombat;
|
||||
static isCompetenceAttaque(itemData) {
|
||||
itemData = Misc.data(itemData);
|
||||
return itemData.type == 'competencecreature' && itemData.data.iscombat;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCompetenceParade(item) {
|
||||
return item.type == 'competencecreature' && item.data.isparade;
|
||||
static isCompetenceParade(itemData) {
|
||||
itemData = Misc.data(itemData);
|
||||
return itemData.type == 'competencecreature' && itemData.data.isparade;
|
||||
}
|
||||
}
|
||||
|
40
module/item-monnaie.js
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
const monnaiesData = [
|
||||
{
|
||||
_id: randomID(16), name: "Etain (1 denier)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
|
||||
data: { quantite: 0, valeur_deniers: 1, encombrement: 0.001, description: "" }
|
||||
},
|
||||
{
|
||||
_id: randomID(16), name: "Bronze (10 deniers)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp",
|
||||
data: { quantite: 0, valeur_deniers: 10, encombrement: 0.002, description: "" }
|
||||
},
|
||||
{
|
||||
_id: randomID(16), name: "Argent (1 sol)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp",
|
||||
data: { quantite: 0, valeur_deniers: 100, encombrement: 0.003, description: "" }
|
||||
},
|
||||
{
|
||||
_id: randomID(16), name: "Or (10 sols)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
|
||||
data: { quantite: 0, valeur_deniers: 1000, encombrement: 0.004, description: "" }
|
||||
}
|
||||
]
|
||||
|
||||
export class Monnaie {
|
||||
|
||||
static monnaiesData() {
|
||||
return monnaiesData;
|
||||
}
|
||||
|
||||
static filtrerMonnaies(items) {
|
||||
return items.filter(it => it.type == 'monnaie');
|
||||
}
|
||||
|
||||
static monnaiesManquantes(items) {
|
||||
const valeurs = Monnaie.filtrerMonnaies(items)
|
||||
.map(it => it.data.valeur_deniers)
|
||||
return duplicate(monnaiesData.filter(monnaie => !valeurs.find(v => v != monnaie.data.valeur_deniers)));
|
||||
}
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -7,7 +8,8 @@ export class RdDItem extends Item {
|
||||
async postItem() {
|
||||
console.log(this);
|
||||
const properties = this[`_${this.data.type}ChatData`]();
|
||||
let chatData = duplicate(this.data);
|
||||
const itemData = Misc.data(this);
|
||||
let chatData = duplicate(itemData);
|
||||
chatData["properties"] = properties
|
||||
|
||||
//Check if the posted item should have availability/pay buttons
|
||||
@ -49,17 +51,17 @@ export class RdDItem extends Item {
|
||||
{
|
||||
if (this.isOwned)
|
||||
{
|
||||
if (this.data.data.quantite == 0)
|
||||
if (itemData.data.quantite == 0)
|
||||
dialogResult[0] = -1
|
||||
else if (this.data.data.quantite < dialogResult[0])
|
||||
else if (itemData.data.quantite < dialogResult[0])
|
||||
{
|
||||
dialogResult[0] = this.data.data.quantite;
|
||||
dialogResult[0] = itemData.data.quantite;
|
||||
ui.notifications.notify(`Impossible de poster plus que ce que vous avez. La quantité à été réduite à ${dialogResult[0]}.`)
|
||||
this.update({"data.quantite" : 0})
|
||||
}
|
||||
else {
|
||||
ui.notifications.notify(`Quantité réduite par ${dialogResult[0]}.`)
|
||||
this.update({"data.quantite" : this.data.data.quantite - dialogResult[0]})
|
||||
this.update({"data.quantite" : itemData.data.quantite - dialogResult[0]})
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,7 +86,7 @@ export class RdDItem extends Item {
|
||||
chatData.jsondata = JSON.stringify(
|
||||
{
|
||||
compendium : "postedItem",
|
||||
payload: this.data,
|
||||
payload: itemData,
|
||||
});
|
||||
|
||||
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-item.html', chatData).then(html => {
|
||||
@ -95,217 +97,217 @@ export class RdDItem extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_objetChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Encombrement</b>: ${data.encombrement}`
|
||||
`<b>Encombrement</b>: ${rddData.encombrement}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_armeChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Compétence</b>: ${data.competence}`,
|
||||
`<b>Dommages</b>: ${data.dommages}`,
|
||||
`<b>Force minimum</b>: ${data.force}`,
|
||||
`<b>Resistance</b>: ${data.resistance}`,
|
||||
`<b>Encombrement</b>: ${data.encombrement}`
|
||||
`<b>Compétence</b>: ${rddData.competence}`,
|
||||
`<b>Dommages</b>: ${rddData.dommages}`,
|
||||
`<b>Force minimum</b>: ${rddData.force}`,
|
||||
`<b>Resistance</b>: ${rddData.resistance}`,
|
||||
`<b>Encombrement</b>: ${rddData.encombrement}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_conteneurChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Capacité</b>: ${data.capacite} Enc.`,
|
||||
`<b>Encombrement</b>: ${data.encombrement}`
|
||||
`<b>Capacité</b>: ${rddData.capacite} Enc.`,
|
||||
`<b>Encombrement</b>: ${rddData.encombrement}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_munitionChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Encombrement</b>: ${data.encombrement}`
|
||||
`<b>Encombrement</b>: ${rddData.encombrement}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_armureChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Protection</b>: ${data.protection}`,
|
||||
`<b>Détérioration</b>: ${data.deterioration}`,
|
||||
`<b>Malus armure</b>: ${data.malus}`,
|
||||
`<b>Encombrement</b>: ${data.encombrement}`
|
||||
`<b>Protection</b>: ${rddData.protection}`,
|
||||
`<b>Détérioration</b>: ${rddData.deterioration}`,
|
||||
`<b>Malus armure</b>: ${rddData.malus}`,
|
||||
`<b>Encombrement</b>: ${rddData.encombrement}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_competenceChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Catégorie</b>: ${data.categorie}`,
|
||||
`<b>Niveau</b>: ${data.niveau}`,
|
||||
`<b>Caractéristique par défaut</b>: ${data.carac_defaut}`,
|
||||
`<b>XP</b>: ${data.xp}`
|
||||
`<b>Catégorie</b>: ${rddData.categorie}`,
|
||||
`<b>Niveau</b>: ${rddData.niveau}`,
|
||||
`<b>Caractéristique par défaut</b>: ${rddData.carac_defaut}`,
|
||||
`<b>XP</b>: ${rddData.xp}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_competencecreatureChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Catégorie</b>: ${data.categorie}`,
|
||||
`<b>Niveau</b>: ${data.niveau}`,
|
||||
`<b>Caractéristique</b>: ${data.carac_value}`,
|
||||
`<b>XP</b>: ${data.xp}`
|
||||
`<b>Catégorie</b>: ${rddData.categorie}`,
|
||||
`<b>Niveau</b>: ${rddData.niveau}`,
|
||||
`<b>Caractéristique</b>: ${rddData.carac_value}`,
|
||||
`<b>XP</b>: ${rddData.xp}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_sortChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Draconic</b>: ${data.draconic}`,
|
||||
`<b>Difficulté</b>: ${data.difficulte}`,
|
||||
`<b>Case TMR</b>: ${data.caseTMR}`,
|
||||
`<b>Points de Rêve</b>: ${data.ptreve}`
|
||||
`<b>Draconic</b>: ${rddData.draconic}`,
|
||||
`<b>Difficulté</b>: ${rddData.difficulte}`,
|
||||
`<b>Case TMR</b>: ${rddData.caseTMR}`,
|
||||
`<b>Points de Rêve</b>: ${rddData.ptreve}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_herbeChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Milieu</b>: ${data.milieu}`,
|
||||
`<b>Rareté</b>: ${data.rarete}`,
|
||||
`<b>Catégorie</b>: ${data.categorie}`,
|
||||
`<b>Milieu</b>: ${rddData.milieu}`,
|
||||
`<b>Rareté</b>: ${rddData.rarete}`,
|
||||
`<b>Catégorie</b>: ${rddData.categorie}`,
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_ingredientChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Milieu</b>: ${data.milieu}`,
|
||||
`<b>Rareté</b>: ${data.rarete}`,
|
||||
`<b>Catégorie</b>: ${data.categorie}`,
|
||||
`<b>Milieu</b>: ${rddData.milieu}`,
|
||||
`<b>Rareté</b>: ${rddData.rarete}`,
|
||||
`<b>Catégorie</b>: ${rddData.categorie}`,
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_tacheChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Caractéristique</b>: ${data.carac}`,
|
||||
`<b>Compétence</b>: ${data.competence}`,
|
||||
`<b>Périodicité</b>: ${data.periodicite}`,
|
||||
`<b>Fatigue</b>: ${data.fatigue}`,
|
||||
`<b>Difficulté</b>: ${data.difficulte}`,
|
||||
`<b>Points de Tâche</b>: ${data.points_de_tache}`,
|
||||
`<b>Points de Tâche atteints</b>: ${data.points_de_tache_courant}`
|
||||
`<b>Caractéristique</b>: ${rddData.carac}`,
|
||||
`<b>Compétence</b>: ${rddData.competence}`,
|
||||
`<b>Périodicité</b>: ${rddData.periodicite}`,
|
||||
`<b>Fatigue</b>: ${rddData.fatigue}`,
|
||||
`<b>Difficulté</b>: ${rddData.difficulte}`,
|
||||
`<b>Points de Tâche</b>: ${rddData.points_de_tache}`,
|
||||
`<b>Points de Tâche atteints</b>: ${rddData.points_de_tache_courant}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_livreChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Compétence</b>: ${data.competence}`,
|
||||
`<b>Auteur</b>: ${data.auteur}`,
|
||||
`<b>Difficulté</b>: ${data.difficulte}`,
|
||||
`<b>Points de Tâche</b>: ${data.points_de_tache}`,
|
||||
`<b>Encombrement</b>: ${data.encombrement}`
|
||||
`<b>Compétence</b>: ${rddData.competence}`,
|
||||
`<b>Auteur</b>: ${rddData.auteur}`,
|
||||
`<b>Difficulté</b>: ${rddData.difficulte}`,
|
||||
`<b>Points de Tâche</b>: ${rddData.points_de_tache}`,
|
||||
`<b>Encombrement</b>: ${rddData.encombrement}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_potionChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Rareté</b>: ${data.rarete}`,
|
||||
`<b>Catégorie</b>: ${data.categorie}`,
|
||||
`<b>Encombrement</b>: ${data.encombrement}`,
|
||||
`<b>Rareté</b>: ${rddData.rarete}`,
|
||||
`<b>Catégorie</b>: ${rddData.categorie}`,
|
||||
`<b>Encombrement</b>: ${rddData.encombrement}`,
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_queueChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Refoulement</b>: ${data.refoulement}`
|
||||
`<b>Refoulement</b>: ${rddData.refoulement}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_ombreChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Refoulement</b>: ${data.refoulement}`
|
||||
`<b>Refoulement</b>: ${rddData.refoulement}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_souffleChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [];
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_teteChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [];
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_tarotChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Concept</b>: ${data.concept}`,
|
||||
`<b>Aspect</b>: ${data.aspect}`,
|
||||
`<b>Concept</b>: ${rddData.concept}`,
|
||||
`<b>Aspect</b>: ${rddData.aspect}`,
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_nombreastralChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Valeur</b>: ${data.value}`,
|
||||
`<b>Jour</b>: ${data.jourlabel}`,
|
||||
`<b>Valeur</b>: ${rddData.value}`,
|
||||
`<b>Jour</b>: ${rddData.jourlabel}`,
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_monnaieChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Valeur en Deniers</b>: ${data.valeur_deniers}`,
|
||||
`<b>Encombrement</b>: ${data.encombrement}`
|
||||
`<b>Valeur en Deniers</b>: ${rddData.valeur_deniers}`,
|
||||
`<b>Encombrement</b>: ${rddData.encombrement}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_meditationChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Thème</b>: ${data.theme}`,
|
||||
`<b>Compétence</b>: ${data.competence}`,
|
||||
`<b>Support</b>: ${data.support}`,
|
||||
`<b>Heure</b>: ${data.heure}`,
|
||||
`<b>Purification</b>: ${data.purification}`,
|
||||
`<b>Vêture</b>: ${data.veture}`,
|
||||
`<b>Comportement</b>: ${data.comportement}`,
|
||||
`<b>Case TMR</b>: ${data.tmr}`
|
||||
`<b>Thème</b>: ${rddData.theme}`,
|
||||
`<b>Compétence</b>: ${rddData.competence}`,
|
||||
`<b>Support</b>: ${rddData.support}`,
|
||||
`<b>Heure</b>: ${rddData.heure}`,
|
||||
`<b>Purification</b>: ${rddData.purification}`,
|
||||
`<b>Vêture</b>: ${rddData.veture}`,
|
||||
`<b>Comportement</b>: ${rddData.comportement}`,
|
||||
`<b>Case TMR</b>: ${rddData.tmr}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_casetmrChatData() {
|
||||
const data = duplicate(this.data.data);
|
||||
const rddData = Misc.data(this).data;
|
||||
let properties = [
|
||||
`<b>Coordonnée</b>: ${data.coord}`,
|
||||
`<b>Spécificité</b>: ${data.specific}`
|
||||
`<b>Coordonnée</b>: ${rddData.coord}`,
|
||||
`<b>Spécificité</b>: ${rddData.specific}`
|
||||
]
|
||||
return properties;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import { RdDUtility } from "./rdd-utility.js";
|
||||
import { RdDItem } from "./item-rdd.js";
|
||||
import { RdDAlchimie } from "./rdd-alchimie.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
/**
|
||||
* Extend the basic ItemSheet with some very simple modifications
|
||||
@ -30,7 +31,7 @@ export class RdDItemSheet extends ItemSheet {
|
||||
{
|
||||
class: "post",
|
||||
icon: "fas fa-comment",
|
||||
onclick: ev => new RdDItem(this.item.data).postItem()
|
||||
onclick: ev => new RdDItem(Misc.data(this.item)).postItem()
|
||||
})
|
||||
return buttons
|
||||
}
|
||||
@ -47,26 +48,26 @@ export class RdDItemSheet extends ItemSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
let data = super.getData();
|
||||
data.categorieCompetences = RdDUtility.getCategorieCompetences();
|
||||
if ( data.item.type == 'tache' || data.item.type == 'livre' || data.item.type == 'meditation' || data.item.type == 'oeuvre') {
|
||||
data.caracList = duplicate(game.system.model.Actor.personnage.carac);
|
||||
data.competences = await RdDUtility.loadCompendiumNames( 'foundryvtt-reve-de-dragon.competences' );
|
||||
let formData = super.getData();
|
||||
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences();
|
||||
if ( formData.item.type == 'tache' || formData.item.type == 'livre' || formData.item.type == 'meditation' || formData.item.type == 'oeuvre') {
|
||||
formData.caracList = duplicate(game.system.model.Actor.personnage.carac);
|
||||
formData.competences = await RdDUtility.loadCompendiumNames( 'foundryvtt-reve-de-dragon.competences' );
|
||||
}
|
||||
if (data.item.type == 'arme') {
|
||||
data.competences = await RdDUtility.loadCompendium( 'foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it));
|
||||
if (formData.item.type == 'arme') {
|
||||
formData.competences = await RdDUtility.loadCompendium( 'foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it));
|
||||
}
|
||||
if ( data.item.type == 'recettealchimique' ) {
|
||||
RdDAlchimie.processManipulation(data.item, this.actor && this.actor._id );
|
||||
if ( formData.item.type == 'recettealchimique' ) {
|
||||
RdDAlchimie.processManipulation(formData.item, this.actor && this.actor._id );
|
||||
}
|
||||
if ( this.actor ) {
|
||||
data.isOwned = true;
|
||||
data.actorId = this.actor._id;
|
||||
formData.isOwned = true;
|
||||
formData.actorId = this.actor._id;
|
||||
}
|
||||
data.bonusCaseList = RdDItemSort.getBonusCaseList(data, true);
|
||||
data.isGM = game.user.isGM; // Pour verrouiller certaines éditions
|
||||
formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
|
||||
formData.isGM = game.user.isGM; // Pour verrouiller certaines éditions
|
||||
|
||||
return data;
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -101,7 +102,7 @@ export class RdDItemSheet extends ItemSheet {
|
||||
if ( actor ) {
|
||||
actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData);
|
||||
} else {
|
||||
ui.notifications.info("Impossible trouver un actur pour réaliser cette tache Alchimique.");
|
||||
ui.notifications.info("Impossible de trouver un acteur pour réaliser cette tâche alchimique.");
|
||||
}
|
||||
});
|
||||
|
||||
@ -111,7 +112,7 @@ export class RdDItemSheet extends ItemSheet {
|
||||
async _onClickSelectCategorie(event) {
|
||||
event.preventDefault();
|
||||
|
||||
let level = RdDUtility.getLevelCategory(event.currentTarget.value);
|
||||
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
|
||||
this.object.data.data.base = level;
|
||||
$("#base").val( level );
|
||||
}
|
||||
|
@ -6,26 +6,42 @@
|
||||
export class Misc {
|
||||
static isFunction(v) {
|
||||
return v && {}.toString.call(v) === '[object Function]';
|
||||
}
|
||||
}
|
||||
|
||||
static upperFirst(text) {
|
||||
return text.charAt(0).toUpperCase() + text.slice(1);
|
||||
}
|
||||
|
||||
static toSignedString(number){
|
||||
static toSignedString(number) {
|
||||
const value = parseInt(number)
|
||||
const isPositiveNumber = value != NaN && value > 0;
|
||||
return isPositiveNumber ? "+"+number : number
|
||||
return isPositiveNumber ? "+" + number : number
|
||||
}
|
||||
|
||||
static sum() {
|
||||
return (a, b) => a + b;
|
||||
}
|
||||
|
||||
static ascending(orderFunction = x=>x) {
|
||||
return (a, b) => Misc.sortingBy(orderFunction(a), orderFunction(b));
|
||||
}
|
||||
|
||||
static descending(orderFunction = x=>x) {
|
||||
return (a, b) => Misc.sortingBy(orderFunction(b), orderFunction(a));
|
||||
}
|
||||
|
||||
static sortingBy(a, b) {
|
||||
if (a > b) return 1;
|
||||
if (a < b) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
static toInt(value)
|
||||
{
|
||||
if (value == undefined)
|
||||
{
|
||||
static toInt(value) {
|
||||
if (value == undefined) {
|
||||
return 0;
|
||||
}
|
||||
const parsed = parseInt(value);
|
||||
@ -47,6 +63,17 @@ export class Misc {
|
||||
return itemsBy;
|
||||
}
|
||||
|
||||
static classifyFirst(items, classifier) {
|
||||
let itemsBy = {};
|
||||
for (const item of items) {
|
||||
const classification = classifier(item);
|
||||
if (!itemsBy[classification]) {
|
||||
itemsBy[classification] = item;
|
||||
}
|
||||
}
|
||||
return itemsBy;
|
||||
}
|
||||
|
||||
static classifyInto(itemsBy, items, classifier = it => it.type, transform = it => it) {
|
||||
for (const item of items) {
|
||||
const classification = classifier(item);
|
||||
@ -67,4 +94,36 @@ export class Misc {
|
||||
return [...new Set(array)];
|
||||
}
|
||||
|
||||
static actorData(actor) {
|
||||
return Misc.data(actor);
|
||||
}
|
||||
|
||||
static itemData(item) {
|
||||
return Misc.data(item);
|
||||
}
|
||||
|
||||
static data(it) {
|
||||
if (it instanceof Item) {
|
||||
return it.data;
|
||||
}
|
||||
if (it instanceof Actor) {
|
||||
return it.data;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
static templateData(it) {
|
||||
return Misc.data(it)?.data ?? {}
|
||||
}
|
||||
|
||||
static connectedGMOrUser(ownerId = undefined) {
|
||||
if (ownerId && game.user.id == ownerId){
|
||||
return ownerId;
|
||||
}
|
||||
return (game.user.isGM ? game.user.id : game.users.entities.find(u => u.isGM && u.active)?.id) ?? game.user.id;
|
||||
}
|
||||
|
||||
static isElectedUser() {
|
||||
return game.user.id == Misc.connectedGMOrUser();
|
||||
}
|
||||
}
|
@ -50,7 +50,7 @@ const poesieHautReve = [
|
||||
},
|
||||
{
|
||||
reference: 'Denis Gerfaud',
|
||||
extrait: `Ainsi se cuccèdent les Jours et les Ages.
|
||||
extrait: `Ainsi se succèdent les Jours et les Ages.
|
||||
<br>Les jours des Dragons sont les Ages des Hommes.`
|
||||
},
|
||||
{
|
||||
|
44
module/poetique.txt
Normal file
@ -0,0 +1,44 @@
|
||||
Le courant du Fleuve
|
||||
Te domine et te Porte
|
||||
Avant que tu te moeuves
|
||||
Combat le, ou il t'emporte
|
||||
|
||||
|
||||
|
||||
A vous qui faites ripaille
|
||||
sourds aux damnés de la faim
|
||||
à vous qui livrez
|
||||
une inégale bataille
|
||||
à ceux qui vous tendent la main
|
||||
|
||||
Ils sont tout près ! - Tenons fermée
|
||||
<br>Cette salle, où nous les narguons.
|
||||
<br>Quel bruit dehors ! Hideuse armée
|
||||
<br>De vampires et de dragons !
|
||||
<br>La poutre du toit descellée
|
||||
<br>Ploie ainsi qu'une herbe mouillée,
|
||||
<br>Et la vieille porte rouillée
|
||||
<br>Tremble, à déraciner ses gonds !`),
|
||||
|
||||
https://www.poetica.fr/poeme-1423/guy-de-maupassant-le-sommeil-du-mandarin/
|
||||
|
||||
|
||||
|
||||
|
||||
Le monde est un rêve de Dragons. Nous
|
||||
ne savons pas qui sont les Dragons ni à quoi
|
||||
ils ressemblent, en dépit de l’antique iconographie qui les dépeint comme de gigantesques créatures ailées capables de cracher
|
||||
feu et flammes.
|
||||
|
||||
|
||||
|
||||
Car parmi les humains, autre nom lui est donné,
|
||||
Nom sinistre parmi tous, nom funèbre, c'est la mort!
|
||||
Un ami disparu... Thanatos est passé...
|
||||
|
||||
|
||||
Messieurs, ne crachez pas de jurons ni d'ordure
|
||||
Au visage fardé de cette pauvre impure
|
||||
Que déesse Famine a par un soir d'hiver,
|
||||
Contrainte à relever ses jupons en plein air.
|
||||
|
@ -49,20 +49,13 @@ export class RdDAlchimie {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getDifficulte( aspects ) {
|
||||
let aspectsArray = aspects.split('-');
|
||||
let diff = 0;
|
||||
let nbDifferent = 0;
|
||||
let aspectsHash = {}
|
||||
for (let colconst of aspectsArray) {
|
||||
if ( aspectsHash[colconst] ){ // Deja present, augmente difficulté de 1
|
||||
diff -= 1;
|
||||
} else {
|
||||
nbDifferent++;
|
||||
aspectsHash[colconst] = colconst; // Keep track
|
||||
}
|
||||
static getDifficulte(aspects) {
|
||||
let elements = aspects.split('-');
|
||||
let composantes = elements.length;
|
||||
let distincts = Object.keys(Misc.classifyFirst(elements, it => it)).length;
|
||||
if (distincts == 1) {
|
||||
composantes--;
|
||||
}
|
||||
diff = diff - ((nbDifferent>1) ? nbDifferent : 0); // Ca doit marcher ....
|
||||
return Math.min(0, diff); // Pour être sur
|
||||
return Math.min(0, -composantes);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ export class RdDAstrologieEditeur extends Dialog {
|
||||
constructor(html, calendrier, calendrierData) {
|
||||
|
||||
let myButtons = {
|
||||
resetButton: { label: "Re-tirer les nombres astraux", callback: html => this.resetNombreAstraux() },
|
||||
saveButton: { label: "Fermer", callback: html => this.fillData() }
|
||||
};
|
||||
|
||||
@ -21,6 +22,14 @@ export class RdDAstrologieEditeur extends Dialog {
|
||||
this.updateData( calendrierData );
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
resetNombreAstraux() {
|
||||
game.system.rdd.calendrier.resetNombreAstral();
|
||||
game.system.rdd.calendrier.rebuildListeNombreAstral();
|
||||
|
||||
game.system.rdd.calendrier.showAstrologieEditor();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
fillData( ) {
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
|
||||
/**
|
||||
@ -61,7 +62,7 @@ export class RdDAstrologieJoueur extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
requestJetAstrologie( ) {
|
||||
let data = { id: this.actor.data._id,
|
||||
carac_vue: this.actor.data.data.carac['vue'].value,
|
||||
carac_vue: Misc.data(this.actor).data.carac['vue'].value,
|
||||
etat: this.dataNombreAstral.etat,
|
||||
astrologie: this.dataNombreAstral.astrologie,
|
||||
conditions: $("#diffConditions").val(),
|
||||
|
@ -8,56 +8,58 @@ import { Grammar } from "./grammar.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const dossierIconesHeures = 'systems/foundryvtt-reve-de-dragon/icons/heures/'
|
||||
const heuresList = [ "vaisseau", "sirene", "faucon", "couronne", "dragon", "epees", "lyre", "serpent", "poissonacrobate", "araignee", "roseau", "chateaudormant" ];
|
||||
const heuresDef = { "vaisseau": { label: "Vaisseau", lettreFont: 'v', saison: "printemps", heure: 0, icon: 'hd01.svg' },
|
||||
"sirene": { label: "Sirène", lettreFont: 'S', saison: "printemps", heure: 1, icon: 'hd02.svg' },
|
||||
"faucon": { label: "Faucon", lettreFont: 'f', saison: "printemps", heure: 2, icon: 'hd03.svg' },
|
||||
"couronne": { label: "Couronne", lettreFont: 'C', saison: "ete", heure: 3, icon: 'hd04.svg' },
|
||||
"dragon": { label: "Dragon", lettreFont: 'd', saison: "ete", heure: 4, icon: 'hd05.svg' },
|
||||
"epees": { label: "Epées", lettreFont: 'e', saison: "ete", heure: 5, icon: 'hd06.svg' },
|
||||
"lyre": { label: "Lyre", lettreFont: 'l', saison: "automne", heure: 6, icon: 'hd07.svg' },
|
||||
"serpent": { label: "Serpent", lettreFont: 's', saison: "automne", heure: 7, icon: 'hd08.svg' },
|
||||
"poissonacrobate": { label: "Poisson Acrobate", lettreFont: 'p', saison: "automne", heure: 8, icon: 'hd09.svg' },
|
||||
"araignee": { label: "Araignée", lettreFont: 'a', saison: "hiver", heure: 9, icon: 'hd10.svg' },
|
||||
"roseau": { label: "Roseau", lettreFont: 'r', saison: "hiver", heure: 10, icon: 'hd11.svg' },
|
||||
"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 heuresList = ["vaisseau", "sirene", "faucon", "couronne", "dragon", "epees", "lyre", "serpent", "poissonacrobate", "araignee", "roseau", "chateaudormant"];
|
||||
const heuresDef = {
|
||||
"vaisseau": { label: "Vaisseau", lettreFont: 'v', saison: "printemps", heure: 0, icon: 'hd01.svg' },
|
||||
"sirene": { label: "Sirène", lettreFont: 'i', saison: "printemps", heure: 1, icon: 'hd02.svg' },
|
||||
"faucon": { label: "Faucon", lettreFont: 'f', saison: "printemps", heure: 2, icon: 'hd03.svg' },
|
||||
"couronne": { label: "Couronne", lettreFont: '', saison: "ete", heure: 3, icon: 'hd04.svg' },
|
||||
"dragon": { label: "Dragon", lettreFont: 'd', saison: "ete", heure: 4, icon: 'hd05.svg' },
|
||||
"epees": { label: "Epées", lettreFont: 'e', saison: "ete", heure: 5, icon: 'hd06.svg' },
|
||||
"lyre": { label: "Lyre", lettreFont: 'l', saison: "automne", heure: 6, icon: 'hd07.svg' },
|
||||
"serpent": { label: "Serpent", lettreFont: 's', saison: "automne", heure: 7, icon: 'hd08.svg' },
|
||||
"poissonacrobate": { label: "Poisson Acrobate", lettreFont: 'p', saison: "automne", heure: 8, icon: 'hd09.svg' },
|
||||
"araignee": { label: "Araignée", lettreFont: 'a', saison: "hiver", heure: 9, icon: 'hd10.svg' },
|
||||
"roseau": { label: "Roseau", lettreFont: 'r', saison: "hiver", heure: 10, icon: 'hd11.svg' },
|
||||
"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_JOUR_PAR_MOIS = 28;
|
||||
const MAX_NOMBRE_ASTRAL = 12;
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDCalendrier extends Application {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* -------------------------------------------- */
|
||||
async initCalendrier() {
|
||||
// Calendrier
|
||||
this.calendrier = duplicate(game.settings.get("foundryvtt-reve-de-dragon", "calendrier"));
|
||||
console.log("CALENDRIER", this.calendrier);
|
||||
if ( this.calendrier == undefined || this.calendrier.moisRdD == undefined) {
|
||||
this.calendrier.heureRdD = 0; // Index dans heuresList
|
||||
if (this.calendrier == undefined || this.calendrier.moisRdD == undefined) {
|
||||
this.calendrier.heureRdD = 0; // Index dans heuresList
|
||||
this.calendrier.minutesRelative = 0;
|
||||
this.calendrier.moisRdD = 0; // Index dans heuresList
|
||||
this.calendrier.jour = 0;
|
||||
if ( game.user.isGM) { // Uniquement si GM
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", this.calendrier );
|
||||
this.calendrier.moisRdD = 0; // Index dans heuresList
|
||||
this.calendrier.jour = 0;
|
||||
if (game.user.isGM) { // Uniquement si GM
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", this.calendrier);
|
||||
}
|
||||
}
|
||||
// position
|
||||
this.calendrierPos = duplicate(game.settings.get("foundryvtt-reve-de-dragon", "calendrier-pos"));
|
||||
if ( this.calendrierPos == undefined || this.calendrierPos.top == undefined) {
|
||||
this.calendrierPos.top = 200;
|
||||
this.calendrierPos.left = 200;
|
||||
if ( game.user.isGM) { // Uniquement si GM
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier-pos", this.calendrierPos );
|
||||
if (this.calendrierPos == undefined || this.calendrierPos.top == undefined) {
|
||||
this.calendrierPos.top = 200;
|
||||
this.calendrierPos.left = 200;
|
||||
if (game.user.isGM) { // Uniquement si GM
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier-pos", this.calendrierPos);
|
||||
}
|
||||
}
|
||||
// nombre astral
|
||||
if ( game.user.isGM) {
|
||||
if (game.user.isGM) {
|
||||
this.listeNombreAstral = this._loadListNombreAstral();
|
||||
this.rebuildListeNombreAstral(); // Ensure always up-to-date
|
||||
}
|
||||
@ -79,11 +81,11 @@ export class RdDCalendrier extends Application {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getDateFromIndex( index = undefined ) {
|
||||
if ( !index) index = this.getCurrentDayIndex();
|
||||
getDateFromIndex(index = undefined) {
|
||||
if (!index) index = this.getCurrentDayIndex();
|
||||
let month = Math.floor(index / 28);
|
||||
let day = (index - (month*28)) + 1;
|
||||
return day+" "+heuresList[month];
|
||||
let day = (index - (month * 28)) + 1;
|
||||
return day + " " + heuresList[month];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -92,15 +94,15 @@ export class RdDCalendrier extends Application {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getCurrentDayIndex( ) {
|
||||
getCurrentDayIndex() {
|
||||
return (this.calendrier.moisRdD * 28) + this.calendrier.jour;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getJoursSuivants( num) {
|
||||
getJoursSuivants(num) {
|
||||
let jours = [];
|
||||
let index = this.getCurrentDayIndex();
|
||||
for (let i=0; i<num; i++) {
|
||||
for (let i = 0; i < num; i++) {
|
||||
jours[i] = { label: this.getDateFromIndex(index), index: index };
|
||||
index += 1;
|
||||
}
|
||||
@ -123,21 +125,27 @@ export class RdDCalendrier extends Application {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getNombreAstral( indexDate ) {
|
||||
getNombreAstral(indexDate) {
|
||||
const liste = this.listeNombreAstral ?? this._loadListNombreAstral();
|
||||
let astralData = liste.find( (nombreAstral, i) => nombreAstral.index == indexDate );
|
||||
if (! astralData?.nombreAstral ) {
|
||||
let astralData = liste.find((nombreAstral, i) => nombreAstral.index == indexDate);
|
||||
if (!astralData?.nombreAstral) {
|
||||
this.rebuildListeNombreAstral();
|
||||
astralData = liste.find( (nombreAstral, i) => nombreAstral.index == indexDate );
|
||||
astralData = liste.find((nombreAstral, i) => nombreAstral.index == indexDate);
|
||||
}
|
||||
return astralData?.nombreAstral ?? "N/A";
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
resetNombreAstral( ) {
|
||||
this.listeNombreAstral = [];
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
rebuildListeNombreAstral() {
|
||||
let jourCourant = this.getCurrentDayIndex();
|
||||
let jourFin = jourCourant + 12;
|
||||
let newList = [0,1,2,3,4,5,6,7,8,9,10,11].map( i => this.ajouterNombreAstral(jourCourant + i));
|
||||
let newList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map(i => this.ajouterNombreAstral(jourCourant + i));
|
||||
if (this.listeNombreAstral) {
|
||||
for (const na of this.listeNombreAstral) {
|
||||
if (na && na.index >= jourCourant && na.index < jourFin) {
|
||||
@ -145,34 +153,49 @@ export class RdDCalendrier extends Application {
|
||||
}
|
||||
}
|
||||
}
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral );
|
||||
this.listeNombreAstral = newList;
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
incrementTime(minute = 0) {
|
||||
this.calendrier.minutesRelative += minute;
|
||||
if (this.calendrier.minutesRelative >= 120 ) {
|
||||
onCalendarButton(ev) {
|
||||
ev.preventDefault();
|
||||
const calendarAvance = ev.currentTarget.attributes['data-calendar-avance'];
|
||||
const calendarSet = ev.currentTarget.attributes['data-calendar-set'];
|
||||
if (calendarAvance) {
|
||||
this.incrementTime(Number(calendarAvance.value));
|
||||
}
|
||||
else if (calendarSet) {
|
||||
this.positionnerHeure(Number(calendarSet.value));
|
||||
}
|
||||
this.updateDisplay();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
incrementTime(minutes = 0) {
|
||||
this.calendrier.minutesRelative += minutes;
|
||||
if (this.calendrier.minutesRelative >= 120) {
|
||||
this.calendrier.minutesRelative -= 120;
|
||||
this.calendrier.heureRdD += 1;
|
||||
}
|
||||
if ( this.calendrier.heureRdD > 11 ) {
|
||||
if (this.calendrier.heureRdD > 11) {
|
||||
this.calendrier.heureRdD -= 12;
|
||||
this.incrementerJour();
|
||||
}
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", duplicate(this.calendrier) );
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", duplicate(this.calendrier));
|
||||
// Notification aux joueurs
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", {
|
||||
msg: "msg_sync_time",
|
||||
data: duplicate(this.calendrier)
|
||||
} );
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
incrementerJour( ) {
|
||||
incrementerJour() {
|
||||
this.calendrier.jour += 1;
|
||||
if ( this.calendrier.jour >= RDD_JOUR_PAR_MOIS) {
|
||||
if (this.calendrier.jour >= RDD_JOUR_PAR_MOIS) {
|
||||
this.calendrier.jour -= RDD_JOUR_PAR_MOIS;
|
||||
if ( this.calendrier.jour <= 0)
|
||||
if (this.calendrier.jour <= 0)
|
||||
this.calendrier.jour = 0;
|
||||
this.calendrier.moisRdD += 1;
|
||||
// Reconstruire les nombres astraux
|
||||
@ -181,97 +204,95 @@ export class RdDCalendrier extends Application {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
syncPlayerTime( calendrier ) {
|
||||
syncPlayerTime(calendrier) {
|
||||
this.calendrier = duplicate(calendrier); // Local copy update
|
||||
this.updateDisplay(); // Then update
|
||||
this.updateDisplay();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
positionnerHeure( indexHeure ) {
|
||||
if ( indexHeure <= this.calendrier.heureRdD )
|
||||
positionnerHeure(indexHeure) {
|
||||
if (indexHeure <= this.calendrier.heureRdD)
|
||||
this.incrementerJour();
|
||||
this.calendrier.heureRdD = indexHeure;
|
||||
this.calendrier.minutesRelative = 0;
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", duplicate(this.calendrier) );
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", duplicate(this.calendrier));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
fillCalendrierData( data = {} ) {
|
||||
let moisKey = heuresList[this.calendrier.moisRdD];
|
||||
fillCalendrierData(formData = {}) {
|
||||
let moisKey = heuresList[this.calendrier.moisRdD];
|
||||
let heureKey = heuresList[this.calendrier.heureRdD];
|
||||
|
||||
const mois = heuresDef[moisKey];
|
||||
const heure = heuresDef[heureKey];
|
||||
|
||||
//console.log(moisKey, heureKey);
|
||||
data.heureKey = heureKey;
|
||||
data.moisKey = moisKey;
|
||||
data.jourMois = this.calendrier.jour + 1;
|
||||
data.nomMois = mois.label; // heures et mois nommés identiques
|
||||
data.iconMois = dossierIconesHeures + mois.icon;
|
||||
data.nomHeure = heure.label;
|
||||
data.iconHeure = dossierIconesHeures + heure.icon;
|
||||
data.nomSaison = saisonsDef[mois.saison].label;
|
||||
data.minutesRelative = this.calendrier.minutesRelative;
|
||||
data.isGM = game.user.isGM;
|
||||
return data;
|
||||
formData.heureKey = heureKey;
|
||||
formData.moisKey = moisKey;
|
||||
formData.jourMois = this.calendrier.jour + 1;
|
||||
formData.nomMois = mois.label; // heures et mois nommés identiques
|
||||
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;
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getLectureAstrologieDifficulte( dateIndex ) {
|
||||
getLectureAstrologieDifficulte(dateIndex) {
|
||||
let indexNow = this.getCurrentDayIndex();
|
||||
let diffDay = dateIndex - indexNow;
|
||||
return - Math.floor(diffDay / 2);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async requestNombreAstral( request) {
|
||||
if ( game.user.isGM) { // Only GM
|
||||
console.log( request );
|
||||
let jourDiff = this.getLectureAstrologieDifficulte( request.date);
|
||||
async requestNombreAstral(request) {
|
||||
if (game.user.isGM) { // Only GM
|
||||
console.log(request);
|
||||
let jourDiff = this.getLectureAstrologieDifficulte(request.date);
|
||||
let niveau = Number(request.astrologie.data.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
|
||||
let rolled = await RdDResolutionTable.rollData({
|
||||
let rollData= {
|
||||
caracValue: request.carac_vue,
|
||||
finalLevel: niveau,
|
||||
showDice: false});
|
||||
let nbAstral = this.getNombreAstral( request.date );
|
||||
let nbAstralFaux = nbAstral;
|
||||
showDice: false
|
||||
};
|
||||
await RdDResolutionTable.rollData(rollData);
|
||||
let nbAstral = this.getNombreAstral(request.date);
|
||||
request.rolled = rollData.rolled;
|
||||
request.isValid = true;
|
||||
request.rolled = rolled;
|
||||
if ( !rolled .isSuccess ) {
|
||||
if (!request.rolled.isSuccess) {
|
||||
request.isValid = false;
|
||||
while ( nbAstralFaux == nbAstral ) {
|
||||
nbAstralFaux = new Roll("1d12").roll().total;
|
||||
}
|
||||
nbAstral = nbAstralFaux;
|
||||
let nbAstralFaux = new Roll("1d11").evaluate().total;
|
||||
nbAstral = nbAstral==nbAstralFaux ? 12 : nbAstralFaux;
|
||||
// Mise à jour des nombres astraux du joueur
|
||||
let astralData = this.listeNombreAstral.find( (nombreAstral, i) => nombreAstral.index == request.date );
|
||||
astralData.valeursFausses.push( {actorId: request.id, nombreAstral: nbAstralFaux});
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral );
|
||||
let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == request.date);
|
||||
astralData.valeursFausses.push({ actorId: request.id, nombreAstral: nbAstralFaux });
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral);
|
||||
}
|
||||
request.nbAstral = nbAstral;
|
||||
if ( game.user.isGM) {
|
||||
RdDUtility.responseNombreAstral( request );
|
||||
} else {
|
||||
if (game.user.isGM) {
|
||||
RdDUtility.responseNombreAstral(request);
|
||||
} else {
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", {
|
||||
msg: "msg_response_nombre_astral",
|
||||
data: request
|
||||
} );
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getAjustementAstrologique(heureNaissance, name='inconnu')
|
||||
{
|
||||
getAjustementAstrologique(heureNaissance, name = 'inconnu') {
|
||||
let heure = Grammar.toLowerCaseNoAccent(heureNaissance);
|
||||
if (heure && heuresDef[heure]) {
|
||||
let hn = heuresDef[heure].heure;
|
||||
let chiffreAstral = this.getCurrentNombreAstral();
|
||||
let heureCourante = this.calendrier.heureRdD;
|
||||
let ecartChance = (hn + chiffreAstral - heureCourante)%12;
|
||||
switch (ecartChance)
|
||||
{
|
||||
let ecartChance = (hn + chiffreAstral - heureCourante) % 12;
|
||||
switch (ecartChance) {
|
||||
case 0: return 4;
|
||||
case 4: case 8: return 2;
|
||||
case 6: return -4;
|
||||
@ -286,12 +307,12 @@ export class RdDCalendrier extends Application {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getData() {
|
||||
let data = super.getData();
|
||||
let formData = super.getData();
|
||||
|
||||
this.fillCalendrierData(data);
|
||||
this.fillCalendrierData(formData);
|
||||
|
||||
this.setPos( this.calendrierPos );
|
||||
return data;
|
||||
this.setPos(this.calendrierPos);
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -301,8 +322,8 @@ export class RdDCalendrier extends Application {
|
||||
let elmnt = document.getElementById("calendar-time-container");
|
||||
if (elmnt) {
|
||||
elmnt.style.bottom = null;
|
||||
let xPos = (pos.left) > window.innerWidth ? window.innerWidth-200 : pos.left;
|
||||
let yPos = (pos.top) > window.innerHeight-20 ? window.innerHeight-100 : pos.top;
|
||||
let xPos = (pos.left) > window.innerWidth ? window.innerWidth - 200 : pos.left;
|
||||
let yPos = (pos.top) > window.innerHeight - 20 ? window.innerHeight - 100 : pos.top;
|
||||
elmnt.style.top = (yPos) + "px";
|
||||
elmnt.style.left = (xPos) + "px";
|
||||
resolve();
|
||||
@ -316,125 +337,101 @@ export class RdDCalendrier extends Application {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateDisplay() {
|
||||
let data = this.fillCalendrierData( );
|
||||
// Rebuild data
|
||||
let data = this.fillCalendrierData();
|
||||
// Rebuild data
|
||||
let dateHTML = `Jour ${data.jourMois} de ${data.nomMois} (${data.nomSaison})`;
|
||||
if (game.user.isGM) {
|
||||
dateHTML = dateHTML + " - NA: "+this.getCurrentNombreAstral();
|
||||
dateHTML = dateHTML + " - NA: " + this.getCurrentNombreAstral();
|
||||
}
|
||||
for (let handle of document.getElementsByClassName("calendar-date-rdd")) {
|
||||
handle.innerHTML = dateHTML;
|
||||
}
|
||||
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
|
||||
heure.innerHTML = data.nomHeure;
|
||||
}
|
||||
for (const minute of document.getElementsByClassName("calendar-time-disp")) {
|
||||
minute.innerHTML = `${data.minutesRelative} minutes`;
|
||||
}
|
||||
for (const heureImg of document.getElementsByClassName("calendar-heure-img")) {
|
||||
heureImg.src = data.iconHeure;
|
||||
}
|
||||
document.getElementById("calendar--move-handle").innerHTML = dateHTML;
|
||||
document.getElementById("calendar-heure-texte").innerHTML = `${data.nomHeure}`;
|
||||
document.getElementById("calendar-time").innerHTML = `${data.minutesRelative} min.`;
|
||||
document.getElementById("calendar-heure-img").src = data.iconHeure;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
saveEditeur( calendrierData ) {
|
||||
saveEditeur(calendrierData) {
|
||||
this.calendrier.minutesRelative = Number(calendrierData.minutesRelative);
|
||||
this.calendrier.jour = Number(calendrierData.jourMois) - 1;
|
||||
this.calendrier.moisRdD = heuresList.findIndex(mois => mois === calendrierData.moisKey);
|
||||
this.calendrier.heureRdD = heuresList.findIndex(heure => heure === calendrierData.heureKey);; // Index dans heuresList
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", duplicate(this.calendrier) );
|
||||
this.calendrier.jour = Number(calendrierData.jourMois) - 1;
|
||||
this.calendrier.moisRdD = heuresList.findIndex(mois => mois === calendrierData.moisKey);
|
||||
this.calendrier.heureRdD = heuresList.findIndex(heure => heure === calendrierData.heureKey);; // Index dans heuresList
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", duplicate(this.calendrier));
|
||||
|
||||
this.rebuildListeNombreAstral();
|
||||
|
||||
this.updateDisplay();
|
||||
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", {
|
||||
msg: "msg_sync_time",
|
||||
data: duplicate(this.calendrier)
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async showCalendarEditor() {
|
||||
let calendrierData = duplicate( this.fillCalendrierData( ) );
|
||||
if ( this.editeur == undefined ) {
|
||||
let calendrierData = duplicate(this.fillCalendrierData());
|
||||
if (this.editeur == undefined) {
|
||||
calendrierData.jourMoisOptions = Array(28).fill().map((item, index) => 1 + index);
|
||||
calendrierData.heuresOptions = [0, 1];
|
||||
calendrierData.minutesOptions = Array(120).fill().map((item, index) => 0 + index);
|
||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', calendrierData );
|
||||
this.editeur = new RdDCalendrierEditeur(html, this, calendrierData )
|
||||
calendrierData.heuresOptions = [0, 1];
|
||||
calendrierData.minutesOptions = Array(120).fill().map((item, index) => 0 + index);
|
||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', calendrierData);
|
||||
this.editeur = new RdDCalendrierEditeur(html, this, calendrierData)
|
||||
}
|
||||
this.editeur.updateData( calendrierData );
|
||||
this.editeur.updateData(calendrierData);
|
||||
this.editeur.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async showAstrologieEditor() {
|
||||
let calendrierData = duplicate( this.fillCalendrierData( ) );
|
||||
let astrologieArray = [];
|
||||
for (let astralData of this.listeNombreAstral ) {
|
||||
astralData.humanDate = this.getDateFromIndex( astralData.index );
|
||||
let calendrierData = duplicate(this.fillCalendrierData());
|
||||
let astrologieArray = [];
|
||||
for (let astralData of this.listeNombreAstral) {
|
||||
astralData.humanDate = this.getDateFromIndex(astralData.index);
|
||||
for (let vf of astralData.valeursFausses) {
|
||||
let actor = game.actors.get( vf.actorId);
|
||||
console.log(vf.actorId, actor );
|
||||
let actor = game.actors.get(vf.actorId);
|
||||
console.log(vf.actorId, actor);
|
||||
vf.actorName = (actor) ? actor.name : "Inconnu";
|
||||
}
|
||||
astrologieArray.push( duplicate(astralData ) );
|
||||
astrologieArray.push(duplicate(astralData));
|
||||
}
|
||||
//console.log("ASTRO", astrologieArray);
|
||||
calendrierData.astrologieData = astrologieArray;
|
||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-astrologie-template.html', calendrierData );
|
||||
let astrologieEditeur = new RdDAstrologieEditeur(html, this, calendrierData )
|
||||
astrologieEditeur.updateData( calendrierData );
|
||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-astrologie-template.html', calendrierData);
|
||||
let astrologieEditeur = new RdDAstrologieEditeur(html, this, calendrierData)
|
||||
astrologieEditeur.updateData(calendrierData);
|
||||
astrologieEditeur.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
|
||||
|
||||
this.updateDisplay();
|
||||
|
||||
html.find('#calendar-btn-1min').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.incrementTime(1);
|
||||
this.updateDisplay();
|
||||
});
|
||||
html.find('#calendar-btn-5min').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.incrementTime(5);
|
||||
this.updateDisplay();
|
||||
});
|
||||
html.find('#calendar-btn-10min').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.incrementTime(10);
|
||||
this.updateDisplay();
|
||||
});
|
||||
html.find('#calendar-btn-20min').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.incrementTime(20);
|
||||
this.updateDisplay();
|
||||
});
|
||||
html.find('#calendar-btn-30min').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.incrementTime(30);
|
||||
this.updateDisplay();
|
||||
});
|
||||
html.find('#calendar-btn-1heure').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.incrementTime(120);
|
||||
this.updateDisplay();
|
||||
});
|
||||
html.find('#calendar-btn-vaisseau').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.positionnerHeure(0); // 0 -> vaisseau
|
||||
this.updateDisplay();
|
||||
});
|
||||
html.find('#calendar-btn-lyre').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.positionnerHeure(6); // 6 -> lyre
|
||||
this.updateDisplay();
|
||||
});
|
||||
html.find('#calendar-btn-edit').click(ev => {
|
||||
html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
|
||||
|
||||
html.find('.calendar-btn-edit').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.showCalendarEditor();
|
||||
});
|
||||
html.find('#astrologie-btn-edit').click(ev => {
|
||||
|
||||
html.find('.astrologie-btn-edit').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.showAstrologieEditor();
|
||||
});
|
||||
|
||||
html.find('#calendar--move-handle').mousedown(ev => {
|
||||
html.find('#calendar-move-handle').mousedown(ev => {
|
||||
ev.preventDefault();
|
||||
ev = ev || window.event;
|
||||
let isRightMB = false;
|
||||
@ -479,23 +476,27 @@ export class RdDCalendrier extends Application {
|
||||
elmnt.onmousedown = null;
|
||||
document.onmouseup = null;
|
||||
document.onmousemove = null;
|
||||
let xPos = (elmnt.offsetLeft - pos1) > window.innerWidth ? window.innerWidth-200 : (elmnt.offsetLeft - pos1);
|
||||
let yPos = (elmnt.offsetTop - pos2) > window.innerHeight-20 ? window.innerHeight-100 : (elmnt.offsetTop - pos2)
|
||||
let xPos = (elmnt.offsetLeft - pos1) > window.innerWidth ? window.innerWidth - 200 : (elmnt.offsetLeft - pos1);
|
||||
let yPos = (elmnt.offsetTop - pos2) > window.innerHeight - 20 ? window.innerHeight - 100 : (elmnt.offsetTop - pos2)
|
||||
xPos = xPos < 0 ? 0 : xPos;
|
||||
yPos = yPos < 0 ? 0 : yPos;
|
||||
if(xPos != (elmnt.offsetLeft - pos1) || yPos != (elmnt.offsetTop - pos2)){
|
||||
if (xPos != (elmnt.offsetLeft - pos1) || yPos != (elmnt.offsetTop - pos2)) {
|
||||
elmnt.style.top = (yPos) + "px";
|
||||
elmnt.style.left = (xPos) + "px";
|
||||
}
|
||||
game.system.rdd.calendrier.calendrierPos.top = yPos;
|
||||
game.system.rdd.calendrier.calendrierPos.top = yPos;
|
||||
game.system.rdd.calendrier.calendrierPos.left = xPos;
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos) );
|
||||
if (game.user.isGM) {
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(isRightMB){
|
||||
game.system.rdd.calendrier.calendrierPos.top = 200;
|
||||
} else if (isRightMB) {
|
||||
game.system.rdd.calendrier.calendrierPos.top = 200;
|
||||
game.system.rdd.calendrier.calendrierPos.left = 200;
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos) );
|
||||
if (game.user.isGM) {
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos));
|
||||
}
|
||||
this.setPos(game.system.rdd.calendrier.calendrierPos);
|
||||
}
|
||||
});
|
||||
|
@ -1,7 +1,66 @@
|
||||
import { Grammar } from "./grammar.js";
|
||||
|
||||
const tableCaracDerivee = {
|
||||
// xp: coût pour passer du niveau inférieur à ce niveau
|
||||
1: { xp: 3, poids: "moins de 1kg", plusdom: -5, sconst: 0.5, sust: 0.1 },
|
||||
2: { xp: 3, poids: "1-5", plusdom: -4, sconst: 0.5, sust: 0.3 },
|
||||
3: { xp: 4, poids: "6-10", plusdom: -3, sconst: 1, sust: 0.5, beaute: 'hideux' },
|
||||
4: { xp: 4, poids: "11-20", plusdom: -3, sconst: 1, sust: 1, beaute: 'repoussant' },
|
||||
5: { xp: 5, poids: "21-30", plusdom: -2, sconst: 1, sust: 1, beaute: 'franchement très laid' },
|
||||
6: { xp: 5, poids: "31-40", plusdom: -1, sconst: 2, sust: 2, beaute: 'laid' },
|
||||
7: { xp: 6, poids: "41-50", plusdom: -1, sconst: 2, sust: 2, beaute: 'très désavantagé' },
|
||||
8: { xp: 6, poids: "51-60", plusdom: 0, sconst: 2, sust: 2, beaute: 'désavantagé' },
|
||||
9: { xp: 7, poids: "61-65", plusdom: 0, sconst: 3, sust: 2, beaute: 'pas terrible' },
|
||||
10: { xp: 7, poids: "66-70", plusdom: 0, sconst: 3, sust: 3, beaute: 'commun' },
|
||||
11: { xp: 8, poids: "71-75", plusdom: 0, sconst: 3, sust: 3, beaute: 'pas mal' },
|
||||
12: { xp: 8, poids: "76-80", plusdom: +1, sconst: 4, sust: 3, beaute: 'avantagé' },
|
||||
13: { xp: 9, poids: "81-90", plusdom: +1, sconst: 4, sust: 3, beaute: 'mignon' },
|
||||
14: { xp: 9, poids: "91-100", plusdom: +2, sconst: 4, sust: 4, beaute: 'beau' },
|
||||
15: { xp: 10, poids: "101-110", plusdom: +2, sconst: 5, sust: 4, beaute: 'très beau' },
|
||||
16: { xp: 20, poids: "111-120", plusdom: +3, sconst: 5, sust: 4, beaute: 'éblouissant' },
|
||||
17: { xp: 30, poids: "121-131", plusdom: +3, sconst: 5, sust: 5 },
|
||||
18: { xp: 40, poids: "131-141", plusdom: +4, sconst: 6, sust: 5 },
|
||||
19: { xp: 50, poids: "141-150", plusdom: +4, sconst: 6, sust: 5 },
|
||||
20: { xp: 60, poids: "151-160", plusdom: +4, sconst: 6, sust: 6 },
|
||||
21: { xp: 70, poids: "161-180", plusdom: +5, sconst: 7, sust: 6 },
|
||||
22: { xp: 80, poids: "181-200", plusdom: +5, sconst: 7, sust: 7 },
|
||||
23: { xp: 90, poids: "201-300", plusdom: +6, sconst: 7, sust: 8 },
|
||||
24: { xp: 100, poids: "301-400", plusdom: +6, sconst: 8, sust: 9 },
|
||||
25: { xp: 110, poids: "401-500", plusdom: +7, sconst: 8, sust: 10 },
|
||||
26: { xp: 120, poids: "501-600", plusdom: +7, sconst: 8, sust: 11 },
|
||||
27: { xp: 130, poids: "601-700", plusdom: +8, sconst: 9, sust: 12 },
|
||||
28: { xp: 140, poids: "701-800", plusdom: +8, sconst: 9, sust: 13 },
|
||||
29: { xp: 150, poids: "801-900", plusdom: +9, sconst: 9, sust: 14 },
|
||||
30: { xp: 160, poids: "901-1000", plusdom: +9, sconst: 10, sust: 15 },
|
||||
31: { xp: 170, poids: "1001-1500", plusdom: +10, sconst: 10, sust: 16 },
|
||||
32: { xp: 180, poids: "1501-2000", plusdom: +11, sconst: 10, sust: 17 }
|
||||
};
|
||||
|
||||
export class RdDCarac {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static findCarac(carac, name) {
|
||||
name = Grammar.toLowerCaseNoAccent(name);
|
||||
const pairs = Object.entries(carac)
|
||||
.filter(([key, value]) => key.includes(name) || Grammar.toLowerCaseNoAccent(value.label).includes(name));
|
||||
|
||||
let c = pairs.find(([key, value]) => key == name || Grammar.toLowerCaseNoAccent(value.label) == name);
|
||||
if (c) {
|
||||
return c[1];
|
||||
}
|
||||
|
||||
pairs.sort((a, b) => a[0].length- b[0].length);
|
||||
if (pairs.length > 0) {
|
||||
c = pairs[0][1];
|
||||
if (pairs.length > 1) {
|
||||
const labels = pairs.map(pair => pair[1].label).reduce((a, b) => `${a}<br>${b}`);
|
||||
ui.notifications.info(`Plusieurs caractéristiques possibles:<br>${labels}<br>La première sera choisie: ${c.label}.`);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static isAgiliteOuDerivee(selectedCarac) {
|
||||
return selectedCarac?.label.match(/(Agilité|Dérobée)/);
|
||||
}
|
||||
@ -21,6 +80,37 @@ export class RdDCarac {
|
||||
(RdDCarac.isReve(selectedCarac) && !competence);
|
||||
}
|
||||
|
||||
|
||||
static computeTotal(carac, beaute = undefined) {
|
||||
const total = Object.values(carac).filter(c => !c.derivee)
|
||||
.map(it => parseInt(it.value))
|
||||
.reduce((a, b) => a + b, 0);
|
||||
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0);
|
||||
return total + beauteSuperieur10;
|
||||
}
|
||||
|
||||
static levelUp(it) {
|
||||
it.xpNext = RdDCarac.getCaracNextXp(it.value);
|
||||
it.isLevelUp = (it.xp >= it.xpNext);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static calculSConst(constitution) {
|
||||
return Number(tableCaracDerivee[Number(constitution)].sconst);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCaracNextXp(value) {
|
||||
const nextValue = Number(value) + 1;
|
||||
// xp est le coût pour atteindre cette valeur, on regarde donc le coût de la valeur+1
|
||||
return RdDCarac.getCaracXp(nextValue);
|
||||
}
|
||||
|
||||
static getCaracXp(targetValue) {
|
||||
return tableCaracDerivee[targetValue]?.xp ?? 200;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* L’appel à la chance n’est possible que pour recommencer les jets d’actions physiques :
|
||||
* tous les jets de combat, de FORCE, d’AGILITÉ, de DEXTÉRITÉ, de Dérobée, d’APPARENCE,
|
||||
@ -29,4 +119,38 @@ export class RdDCarac {
|
||||
static isActionPhysique(selectedCarac) {
|
||||
return Grammar.toLowerCaseNoAccent(selectedCarac?.label).match(/(apparence|force|agilite|dexterite|vue|ouie|odorat|empathie|melee|tir|lancer|derobee)/);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeCarac(data) {
|
||||
data.carac.force.value = Math.min(data.carac.force.value, parseInt(data.carac.taille.value) + 4);
|
||||
|
||||
data.carac.derobee.value = Math.floor(parseInt(((21 - data.carac.taille.value)) + parseInt(data.carac.agilite.value)) / 2);
|
||||
let bonusDomKey = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2);
|
||||
bonusDomKey = Math.min(Math.max(bonusDomKey, 0), 32); // Clamp de securite
|
||||
|
||||
let tailleData = tableCaracDerivee[bonusDomKey];
|
||||
data.attributs.plusdom.value = tailleData.plusdom;
|
||||
|
||||
data.attributs.sconst.value = RdDCarac.calculSConst(data.carac.constitution.value);
|
||||
data.attributs.sust.value = tableCaracDerivee[Number(data.carac.taille.value)].sust;
|
||||
|
||||
data.attributs.encombrement.value = (parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2;
|
||||
data.carac.melee.value = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.agilite.value)) / 2);
|
||||
data.carac.tir.value = Math.floor((parseInt(data.carac.vue.value) + parseInt(data.carac.dexterite.value)) / 2);
|
||||
data.carac.lancer.value = Math.floor((parseInt(data.carac.tir.value) + parseInt(data.carac.force.value)) / 2);
|
||||
|
||||
data.sante.vie.max = Math.ceil((parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value)) / 2);
|
||||
|
||||
data.sante.vie.value = Math.min(data.sante.vie.value, data.sante.vie.max)
|
||||
data.sante.endurance.max = Math.max(parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value), parseInt(data.sante.vie.max) + parseInt(data.carac.volonte.value));
|
||||
data.sante.endurance.value = Math.min(data.sante.endurance.value, data.sante.endurance.max);
|
||||
data.sante.fatigue.max = data.sante.endurance.max * 2;
|
||||
data.sante.fatigue.value = Math.min(data.sante.fatigue.value, data.sante.fatigue.max);
|
||||
|
||||
//Compteurs
|
||||
data.reve.reve.max = data.carac.reve.value;
|
||||
data.compteurs.chance.max = data.carac.chance.value;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -50,7 +50,12 @@ export class RdDCombatManager extends Combat {
|
||||
/* -------------------------------------------- */
|
||||
cleanSonne() {
|
||||
for (let combatant of this.data.combatants) {
|
||||
combatant.actor.verifierSonneRound(this.current.round);
|
||||
if (combatant.actor) {
|
||||
combatant.actor.verifierSonneRound(this.current.round);
|
||||
}
|
||||
else {
|
||||
ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur!`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,28 +79,30 @@ export class RdDCombatManager extends Combat {
|
||||
//if (!c) return results;
|
||||
|
||||
let rollFormula = formula; // Init per default
|
||||
console.log("RR :", rollFormula);
|
||||
if (!rollFormula) {
|
||||
let armeCombat, competence;
|
||||
if (c.actor.data.type == 'creature' || c.actor.data.type == 'entite') {
|
||||
for (const competenceItem of c.actor.data.items) {
|
||||
if (competenceItem.data.iscombat) {
|
||||
competence = duplicate(competenceItem);
|
||||
for (const competenceItemData of c.actor.data.items) {
|
||||
if (competenceItemData.data.iscombat) {
|
||||
competence = duplicate(competenceItemData);
|
||||
}
|
||||
}
|
||||
rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, competence.data.carac_value) + ")/100)";
|
||||
} else {
|
||||
for (const item of c.actor.data.items) {
|
||||
if (item.type == "arme" && item.data.equipe) {
|
||||
armeCombat = duplicate(item);
|
||||
for (const itemData of c.actor.data.items) {
|
||||
if (itemData.type == "arme" && itemData.data.equipe) {
|
||||
armeCombat = duplicate(itemData);
|
||||
}
|
||||
}
|
||||
let compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.data.competence;
|
||||
competence = RdDItemCompetence.findCompetence(c.actor.data.items, compName);
|
||||
let bonusEcaille = (armeCombat && armeCombat.data.magique) ? armeCombat.data.ecaille_efficacite : 0;
|
||||
rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, c.actor.data.data.carac[competence.data.defaut_carac].value, bonusEcaille) + ")/100)";
|
||||
rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, Misc.data(c.actor).data.carac[competence.data.defaut_carac].value, bonusEcaille) + ")/100)";
|
||||
}
|
||||
}
|
||||
//console.log("Combatat", c);
|
||||
console.log("RR :", rollFormula);
|
||||
const roll = super._getInitiativeRoll(c, rollFormula);
|
||||
if (roll.total <= 0) roll.total = 0.00;
|
||||
console.log("Compute init for", rollFormula, roll.total);
|
||||
@ -171,10 +178,14 @@ export class RdDCombatManager extends Combat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static buildListeActionsCombat(combatant) {
|
||||
const actor = combatant.actor; // Easy access
|
||||
let items = actor.data.items;
|
||||
if (combatant.actor == undefined) {
|
||||
ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
|
||||
return [];
|
||||
}
|
||||
const actorData = Misc.data(combatant.actor);
|
||||
let items = combatant.actor.data.items;
|
||||
let actions = []
|
||||
if (actor.isCreature()) {
|
||||
if (combatant.actor.isCreature()) {
|
||||
actions = actions.concat(items.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
|
||||
.map(competence => RdDItemCompetenceCreature.toArme(competence)));
|
||||
} else {
|
||||
@ -184,9 +195,11 @@ export class RdDCombatManager extends Combat {
|
||||
.concat(RdDItemArme.mainsNues());
|
||||
|
||||
let competences = items.filter(it => it.type == 'competence');
|
||||
actions = actions.concat(RdDCombatManager.finalizeArmeList(armes, competences, actor.data.data.carac));
|
||||
actions = actions.concat(RdDCombatManager.finalizeArmeList(armes, competences, actorData.data.carac));
|
||||
|
||||
actions.push({ name: "Draconic", data: { initOnly: true, competence: "Draconic" } });
|
||||
if (actorData.data.attributs.hautrevant.value) {
|
||||
actions.push({ name: "Draconic", data: { initOnly: true, competence: "Draconic" } });
|
||||
}
|
||||
}
|
||||
|
||||
actions.push({ name: "Autre action", data: { initOnly: true, competence: "Autre action" } });
|
||||
@ -251,17 +264,20 @@ export class RdDCombatManager extends Combat {
|
||||
/* -------------------------------------------- */
|
||||
static rollInitiativeCompetence(combatantId, arme) {
|
||||
const combatant = game.combat.getCombatant(combatantId);
|
||||
const actor = combatant.actor;
|
||||
if (combatant.actor == undefined) {
|
||||
ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
|
||||
return [];
|
||||
}
|
||||
|
||||
let initInfo = "";
|
||||
let initOffset = 0;
|
||||
let caracForInit = 0;
|
||||
let compNiveau = 0;
|
||||
let competence = { name: "Aucune" };
|
||||
if (actor.getSurprise() == "totale") {
|
||||
if (combatant.actor.getSurprise() == "totale") {
|
||||
initOffset = -1; // To force 0
|
||||
initInfo = "Surprise Totale"
|
||||
} else if (actor.getSurprise() == "demi") {
|
||||
} else if (combatant.actor.getSurprise() == "demi") {
|
||||
initOffset = 0;
|
||||
initInfo = "Demi Surprise"
|
||||
} else if (arme.name == "Autre action") {
|
||||
@ -276,13 +292,13 @@ export class RdDCombatManager extends Combat {
|
||||
compNiveau = competence.data.niveau;
|
||||
initInfo = arme.name + " / " + arme.data.competence;
|
||||
|
||||
if (actor.data.type == 'creature' || actor.data.type == 'entite') {
|
||||
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
|
||||
caracForInit = competence.data.carac_value;
|
||||
if (competence.data.categorie == "lancer") {
|
||||
initOffset = 5;
|
||||
}
|
||||
} else {
|
||||
caracForInit = actor.data.data.carac[competence.data.defaut_carac].value;
|
||||
caracForInit = Misc.data(combatant.actor).data.carac[competence.data.defaut_carac].value;
|
||||
if (competence.data.categorie == "lancer") { // Offset de principe pour les armes de jet
|
||||
initOffset = 4;
|
||||
}
|
||||
@ -294,7 +310,7 @@ export class RdDCombatManager extends Combat {
|
||||
}
|
||||
}
|
||||
}
|
||||
let malus = actor.getEtatGeneral(); // Prise en compte état général
|
||||
let malus = combatant.actor.getEtatGeneral(); // Prise en compte état général
|
||||
// Cas des créatures et entités vs personnages
|
||||
let rollFormula = initOffset + "+ ( (" + RdDCombatManager.calculInitiative(compNiveau, caracForInit) + " + " + malus + ") /100)";
|
||||
// Garder la trace de l'arme/compétence utilisée pour l'iniative
|
||||
@ -348,6 +364,8 @@ export class RdDCombat {
|
||||
return RdDCombat.onMsgEncaisser(sockmsg.data);
|
||||
case "msg_defense":
|
||||
return RdDCombat.onMsgDefense(sockmsg.data);
|
||||
case "msg_combat_passearme":
|
||||
return RdDCombat.onMsgPasseArme(sockmsg.data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -381,9 +399,8 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static combatNouveauTour(combat) {
|
||||
let turn = combat.turns.find(t => t.tokenId == combat.current.tokenId);
|
||||
if (game.user.isGM) {
|
||||
// seul le GM notifie le status
|
||||
if (Misc.isElectedUser()) {
|
||||
let turn = combat.turns.find(t => t.tokenId == combat.current.tokenId);
|
||||
this.displayActorCombatStatus(combat, turn.actor);
|
||||
// TODO Playaudio for player??
|
||||
}
|
||||
@ -402,9 +419,11 @@ export class RdDCombat {
|
||||
? "Vous devez choisir <strong>une seule</strong> cible à attaquer!"
|
||||
: "Vous devez choisir une cible à attaquer!");
|
||||
}
|
||||
const defender = target?.actor;
|
||||
const defenderTokenId = target?.data._id;
|
||||
return this.create(attacker, defender, defenderTokenId, target)
|
||||
else {
|
||||
const defender = target?.actor;
|
||||
const defenderTokenId = target?.data._id;
|
||||
return this.create(attacker, defender, defenderTokenId, target)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -417,9 +436,31 @@ export class RdDCombat {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static messagePasseArme(data) {
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_combat_passearme", data: data });
|
||||
RdDCombat.onMsgPasseArme(data);
|
||||
}
|
||||
|
||||
static onMsgPasseArme(data) {
|
||||
switch (data.actionPasseArme) {
|
||||
case "store-attaque":
|
||||
game.system.rdd.combatStore.attaques[data.id] = data.rollData;
|
||||
break;
|
||||
case "store-defense":
|
||||
game.system.rdd.combatStore.defenses[data.id] = data.rollData;
|
||||
break;
|
||||
case "delete-attaque":
|
||||
delete game.system.rdd.combatStore.attaques[data.id];
|
||||
break;
|
||||
case "delete-defense":
|
||||
delete game.system.rdd.combatStore.defenses[data.id];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _storeAttaque(attackerId, attackerRoll) {
|
||||
game.system.rdd.combatStore.attaques[attackerId] = duplicate(attackerRoll);
|
||||
RdDCombat.messagePasseArme({ actionPasseArme: "store-attaque", id: attackerId, rollData: attackerRoll });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -429,12 +470,12 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _deleteAttaque(attackerId) {
|
||||
delete game.system.rdd.combatStore.attaques[attackerId];
|
||||
RdDCombat.messagePasseArme({ actionPasseArme: "delete-attaque", id: attackerId });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _storeDefense(defenderRoll) {
|
||||
game.system.rdd.combatStore.defenses[defenderRoll.passeArme] = duplicate(defenderRoll);
|
||||
static _storeDefense(passeArme, defenderRoll) {
|
||||
RdDCombat.messagePasseArme({ actionPasseArme: "store-defense", id: passeArme, rollData: defenderRoll });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -444,7 +485,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _deleteDefense(passeArme) {
|
||||
delete game.system.rdd.combatStore.defenses[passeArme];
|
||||
RdDCombat.messagePasseArme({ actionPasseArme: "delete-defense", id: passeArme });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -466,32 +507,30 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onMsgEncaisser(data) {
|
||||
let attackerRoll = RdDCombat._getAttaque(data.attackerId); // Retrieve the rolldata from the store
|
||||
|
||||
if (game.user.id === data.gmId) { // Seul le GM effectue l'encaissement sur la fiche
|
||||
if (Misc.isElectedUser()) {
|
||||
let attackerRoll = RdDCombat._getAttaque(data.attackerId); // Retrieve the rolldata from the store
|
||||
let attacker = data.attackerId ? game.actors.get(data.attackerId) : null;
|
||||
let defender = canvas.tokens.get(data.defenderTokenId).actor;
|
||||
|
||||
defender.encaisserDommages(attackerRoll, attacker);
|
||||
RdDCombat._deleteDefense(attackerRoll.passeArme);
|
||||
RdDCombat._deleteAttaque(data.attackerId);
|
||||
}
|
||||
|
||||
RdDCombat._deleteDefense(attackerRoll.passeArme);
|
||||
RdDCombat._deleteAttaque(data.attackerId);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onMsgDefense(msg) {
|
||||
let defenderToken = canvas.tokens.get(msg.defenderTokenId);
|
||||
if (defenderToken) {
|
||||
if (!game.user.isGM && !game.user.character) { // vérification / sanity check
|
||||
ui.notifications.error("Le joueur " + game.user.name + " n'est connecté à aucun personnage. Impossible de continuer.");
|
||||
return;
|
||||
}
|
||||
if ((game.user.isGM && !defenderToken.actor.hasPlayerOwner) || (defenderToken.actor.hasPlayerOwner && (game.user.character._id == defenderToken.actor.data._id))) {
|
||||
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
||||
if (!game.user.isGM && !game.user.character) { // vérification / sanity check
|
||||
ui.notifications.error("Le joueur " + game.user.name + " n'est connecté à aucun personnage. Impossible de continuer.");
|
||||
return;
|
||||
}
|
||||
if (defenderToken && Misc.isElectedUser()) {
|
||||
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
||||
if (rddCombat) {
|
||||
const defenderRoll = msg.defenderRoll;
|
||||
RdDCombat._storeAttaque(msg.attackerId, defenderRoll.attackerRoll);
|
||||
RdDCombat._storeDefense(defenderRoll);
|
||||
RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll);
|
||||
rddCombat.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
||||
rddCombat._chatMessageDefense(msg.paramChatDefense);
|
||||
}
|
||||
@ -522,9 +561,11 @@ export class RdDCombat {
|
||||
const rddCombat = RdDCombat.createForAttackerAndDefender(
|
||||
event.currentTarget.attributes['data-attackerId']?.value,
|
||||
event.currentTarget.attributes['data-defenderTokenId']?.value);
|
||||
if (rddCombat) {
|
||||
|
||||
rddCombat.onEvent(button, event);
|
||||
event.preventDefault();
|
||||
rddCombat.onEvent(button, event);
|
||||
event.preventDefault();
|
||||
}
|
||||
});
|
||||
}
|
||||
html.on("click", '#chat-jet-vie', event => {
|
||||
@ -638,6 +679,7 @@ export class RdDCombat {
|
||||
static isEchec(rollData) {
|
||||
switch (rollData.ajustements.surprise.used) {
|
||||
case 'totale': return true;
|
||||
case 'demi': return !rollData.rolled.isSign;
|
||||
}
|
||||
return rollData.rolled.isEchec;
|
||||
}
|
||||
@ -645,7 +687,7 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
static isEchecTotal(rollData) {
|
||||
if (!rollData.attackerRoll && rollData.ajustements.surprise.used) {
|
||||
return rollData.rolled.isEchec;
|
||||
return rollData.rolled.isEchec && rollData.rolled.code != 'notSign';
|
||||
}
|
||||
return rollData.rolled.isETotal;
|
||||
}
|
||||
@ -662,6 +704,7 @@ export class RdDCombat {
|
||||
static isReussite(rollData) {
|
||||
switch (rollData.ajustements.surprise.used) {
|
||||
case 'totale': return false;
|
||||
case 'demi': return rollData.rolled.isSign;
|
||||
}
|
||||
return rollData.rolled.isSuccess;
|
||||
}
|
||||
@ -674,8 +717,9 @@ export class RdDCombat {
|
||||
|
||||
let rollData = this._prepareAttaque(competence, arme);
|
||||
console.log("RdDCombat.attaque >>>", rollData);
|
||||
this.attacker.incItemUse(arme._id); // Usage
|
||||
this.attacker.verifierForceMin(arme);
|
||||
if (arme) {
|
||||
this.attacker.verifierForceMin(arme);
|
||||
}
|
||||
|
||||
const dialog = await RdDRoll.create(this.attacker, rollData,
|
||||
{
|
||||
@ -686,7 +730,9 @@ export class RdDCombat {
|
||||
label: 'Attaque: ' + (arme?.name ?? competence.name),
|
||||
callbacks: [
|
||||
this.attacker.createCallbackExperience(),
|
||||
this.attacker.createCallbackAppelAuMoral(),
|
||||
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
|
||||
{ condition: r => arme && !RdDCombat.isParticuliere(r), action: r => this.attacker.incDecItemUse(arme._id) },
|
||||
{ condition: r => (RdDCombat.isReussite(r) && !RdDCombat.isParticuliere(r)), action: r => this._onAttaqueNormale(r) },
|
||||
{ condition: RdDCombat.isParticuliere, action: r => this._onAttaqueParticuliere(r) },
|
||||
{ condition: RdDCombat.isEchec, action: r => this._onAttaqueEchec(r) },
|
||||
@ -706,7 +752,6 @@ export class RdDCombat {
|
||||
surpriseDefenseur: this.defender.getSurprise(true),
|
||||
essais: {}
|
||||
};
|
||||
rollData.diviseurSignificative = this._getDiviseurSignificative(rollData);
|
||||
|
||||
if (this.attacker.isCreature()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData);
|
||||
@ -725,10 +770,9 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
async _onAttaqueParticuliere(rollData) {
|
||||
RdDCombat._storeAttaque(this.attackerId, rollData);
|
||||
this.attacker.decItemUse( rollData.arme._id ); // Usage décrémenté sur particulière
|
||||
|
||||
// Finesse et Rapidité seulement en mêlée et si la difficulté libre est de -1 minimum
|
||||
const isMeleeDiffNegative = rollData.selectedCarac.label == "Mêlée" && rollData.diffLibre < 0;
|
||||
const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0;
|
||||
ChatMessage.create({
|
||||
alias: this.attacker.name,
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
||||
@ -751,7 +795,7 @@ export class RdDCombat {
|
||||
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
|
||||
// Save rollData for defender
|
||||
RdDCombat._storeAttaque(this.attackerId, attackerRoll);
|
||||
RdDCombat._storeDefense(defenderRoll)
|
||||
RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll);
|
||||
|
||||
attackerRoll.show = {
|
||||
cible: this.target ? this.defender.data.name : 'la cible',
|
||||
@ -802,8 +846,7 @@ export class RdDCombat {
|
||||
dmg: attackerRoll.dmg,
|
||||
};
|
||||
|
||||
const selfMessage = essaisPrecedents != undefined;
|
||||
if (!selfMessage && (!game.user.isGM || this.defender.hasPlayerOwner)) {
|
||||
if (!Misc.isElectedUser()) {
|
||||
this._socketSendMessageDefense(paramChatDefense, defenderRoll);
|
||||
}
|
||||
else {
|
||||
@ -840,7 +883,7 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
_filterArmesParade(defender, competence) {
|
||||
let items = defender.data.items;
|
||||
items = items.filter(item => RdDItemArme.isArmeUtilisable(item) || RdDItemCompetenceCreature.isCompetenceParade(item));
|
||||
items = items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it));
|
||||
for (let item of items) {
|
||||
item.data.nbUsage = defender.getItemUse(item._id); // Ajout du # d'utilisation ce round
|
||||
}
|
||||
@ -896,6 +939,10 @@ export class RdDCombat {
|
||||
async choixParticuliere(rollData, choix) {
|
||||
console.log("RdDCombat.choixParticuliere >>>", rollData, choix);
|
||||
|
||||
if (choix != "rapidite") {
|
||||
this.attacker.incDecItemUse(rollData.arme._id);
|
||||
}
|
||||
|
||||
this.removeChatMessageActionsPasseArme(rollData.passeArme);
|
||||
rollData.particuliere = choix;
|
||||
await this._onAttaqueNormale(rollData);
|
||||
@ -906,7 +953,6 @@ export class RdDCombat {
|
||||
let arme = this.defender.getArmeParade(armeParadeId);
|
||||
|
||||
console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme);
|
||||
this.defender.incItemUse(armeParadeId); // Usage
|
||||
|
||||
let rollData = this._prepareParade(attackerRoll, arme);
|
||||
|
||||
@ -919,7 +965,9 @@ export class RdDCombat {
|
||||
label: 'Parade: ' + (arme ? arme.name : rollData.competence.name),
|
||||
callbacks: [
|
||||
this.defender.createCallbackExperience(),
|
||||
this.defender.createCallbackAppelAuMoral(),
|
||||
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
|
||||
{ condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(armeParadeId) },
|
||||
{ condition: RdDCombat.isReussite, action: r => this._onParadeNormale(r) },
|
||||
{ condition: RdDCombat.isParticuliere, action: r => this._onParadeParticuliere(r) },
|
||||
{ condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) },
|
||||
@ -933,7 +981,7 @@ export class RdDCombat {
|
||||
const compName = armeParade.data.competence;
|
||||
const armeAttaque = attackerRoll.arme;
|
||||
|
||||
let rollData = {
|
||||
let defenderRoll = {
|
||||
passeArme: attackerRoll.passeArme,
|
||||
diffLibre: attackerRoll.diffLibre,
|
||||
attackerRoll: attackerRoll,
|
||||
@ -945,31 +993,12 @@ export class RdDCombat {
|
||||
carac: this.defender.data.data.carac,
|
||||
show: {}
|
||||
};
|
||||
rollData.diviseurSignificative = this._getDiviseurSignificative(rollData);
|
||||
|
||||
if (this.defender.isCreature()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData);
|
||||
RdDItemCompetenceCreature.setRollDataCreature(defenderRoll);
|
||||
}
|
||||
|
||||
return rollData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_getDiviseurSignificative(defenderRoll) {
|
||||
let facteurSign = 1;
|
||||
if (defenderRoll.surprise == 'demi') {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (defenderRoll.needParadeSignificative) {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (RdDBonus.isDefenseAttaqueFinesse(defenderRoll)) {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (!ReglesOptionelles.isUsing('tripleSignificative')) {
|
||||
facteurSign = Math.min(facteurSign, 4);
|
||||
}
|
||||
return facteurSign;
|
||||
return defenderRoll;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -1002,7 +1031,7 @@ export class RdDCombat {
|
||||
|
||||
this.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
||||
this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true });
|
||||
RdDCombat._storeDefense(defenderRoll);
|
||||
RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -1014,7 +1043,6 @@ export class RdDCombat {
|
||||
}
|
||||
console.log("RdDCombat.esquive >>>", attackerRoll, esquive);
|
||||
let rollData = this._prepareEsquive(attackerRoll, esquive);
|
||||
this.defender.incItemUse(esquive._id); // Usage
|
||||
|
||||
const dialog = await RdDRoll.create(this.defender, rollData,
|
||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html' }, {
|
||||
@ -1022,6 +1050,8 @@ export class RdDCombat {
|
||||
label: 'Esquiver',
|
||||
callbacks: [
|
||||
this.defender.createCallbackExperience(),
|
||||
this.defender.createCallbackAppelAuMoral(),
|
||||
{ condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(esquive._id) },
|
||||
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
|
||||
{ condition: RdDCombat.isReussite, action: r => this._onEsquiveNormale(r) },
|
||||
{ condition: RdDCombat.isParticuliere, action: r => this._onEsquiveParticuliere(r) },
|
||||
@ -1043,7 +1073,6 @@ export class RdDCombat {
|
||||
carac: this.defender.data.data.carac,
|
||||
show: {}
|
||||
};
|
||||
rollData.diviseurSignificative = this._getDiviseurSignificative(rollData);
|
||||
|
||||
if (this.defender.isCreature()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData);
|
||||
@ -1074,7 +1103,7 @@ export class RdDCombat {
|
||||
|
||||
this.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
||||
this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true })
|
||||
RdDCombat._storeDefense(defenderRoll);
|
||||
RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -1176,7 +1205,7 @@ export class RdDCombat {
|
||||
_computeImpactRecul(attaque) {
|
||||
const taille = this.defender.getTaille();
|
||||
const force = this.attacker.getForce();
|
||||
const dommages = attaque.arme.data.dommagesReels;
|
||||
const dommages = attaque.arme.data.dommagesReels ?? attaque.arme.data.dommages;
|
||||
return taille - (force + dommages);
|
||||
}
|
||||
|
||||
@ -1194,7 +1223,7 @@ export class RdDCombat {
|
||||
this._onEchecTotal(defenderRoll);
|
||||
}
|
||||
|
||||
if (game.user.isGM) { // Current user is the GM -> direct access
|
||||
if (Misc.isElectedUser()) {
|
||||
attackerRoll.attackerId = this.attackerId;
|
||||
attackerRoll.defenderTokenId = defenderTokenId;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
/* -------------------------------------------- */
|
||||
|
||||
import { DeDraconique } from "./de-draconique.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { RdDNameGen } from "./rdd-namegen.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
@ -10,9 +10,9 @@ import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||
import { TMRType, 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)?/;
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDCommands {
|
||||
@ -23,6 +23,8 @@ export class RdDCommands {
|
||||
rddCommands.registerCommand({ path: ["/aide"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
|
||||
rddCommands.registerCommand({ path: ["/help"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
|
||||
rddCommands.registerCommand({ path: ["/table", "queues"], func: (content, msg, params) => RdDRollTables.getQueue(true), descr: "Tire une Queue de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe(true), descr: "Tire une Idée fixe" });
|
||||
rddCommands.registerCommand({ path: ["/table", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant(true), descr: "Tire un Désir Lancinant" });
|
||||
rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre(true), descr: "Tire une Ombre de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR(true), descr: "Tire une Tête de Dragon pour Hauts Revants" });
|
||||
rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete(true), descr: "Tire une Tête de Dragon" });
|
||||
@ -32,7 +34,7 @@ export class RdDCommands {
|
||||
rddCommands.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
|
||||
|
||||
rddCommands.registerCommand({
|
||||
path: ["/tmra"], func: (content, msg, params) => rddCommands.getTMRAleatoire(msg, params),
|
||||
path: ["/tmra"], func: (content, msg, params) => rddCommands.getTMRAleatoire(msg, params),
|
||||
descr: `Tire une case aléatoire des Terres médianes
|
||||
<br><strong>/tmra forêt</strong> détermine une 'forêt' aléatoire
|
||||
<br><strong>/tmra</strong> détermine une case aléatoire dans toutes les TMR` });
|
||||
@ -61,9 +63,11 @@ export class RdDCommands {
|
||||
descr: `Effectue un jet de dés dans la table de résolution. Exemples:
|
||||
<br><strong>/rdd</strong> ouvre la table de résolution
|
||||
<br><strong>/rdd 10 3</strong> effectue un jet 10 à +3
|
||||
<br><strong>/rdd 10 +2</strong> effectue un jet 10 à +2
|
||||
<br><strong>/rdd 15 -2</strong> effectue un jet 15 à -2
|
||||
<br><strong>/rdd 15 0 s</strong> effectue un jet 15 à 0, avec significative requise`
|
||||
<br><strong>/rdd 15 0 s</strong> effectue un jet 15 à 0, avec significative requise
|
||||
<br><strong>/rdd Vue Vigilance -2</strong> effectue un jet de Vue/Vigilance à -2 pour les tokens sélectionnés
|
||||
<br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés
|
||||
`
|
||||
});
|
||||
rddCommands.registerCommand({ path: ["/ddr"], func: (content, msg, params) => rddCommands.rollDeDraconique(msg), descr: "Lance un Dé Draconique" });
|
||||
|
||||
@ -161,11 +165,25 @@ export class RdDCommands {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
help(msg, table = undefined) {
|
||||
async help(msg) {
|
||||
this.help(msg, undefined);
|
||||
}
|
||||
async help(msg, table) {
|
||||
let list = []
|
||||
this._buildSubTableHelp(list, table || this.commandsTable);
|
||||
const messageAide = list.reduce((a, b) => a + '</li><li class="list-item">' + b);
|
||||
RdDCommands._chatAnswer(msg, `Commandes disponibles<ul class="alterne-list"><li class="list-item">${messageAide}</li></ul>`);
|
||||
|
||||
let html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/settings/dialog-aide-commands.html", { commands: list });
|
||||
let d = new Dialog(
|
||||
{
|
||||
title: "Commandes disponibles dans le tchat",
|
||||
content: html,
|
||||
buttons: {},
|
||||
},
|
||||
{
|
||||
width: 600, height: 500,
|
||||
});
|
||||
|
||||
d.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -214,6 +232,27 @@ export class RdDCommands {
|
||||
await this.rollRdDNumeric(msg, carac, diff, significative);
|
||||
return;
|
||||
}
|
||||
|
||||
let actors = canvas.tokens.controlled.map(it => it.actor).filter(it => it);
|
||||
if (actors && actors.length > 0) {
|
||||
let length = params.length;
|
||||
let diff = Number(params[length - 1]);
|
||||
if (Number.isInteger(Number(diff))) {
|
||||
length--;
|
||||
}
|
||||
else {
|
||||
diff = 0;
|
||||
}
|
||||
const caracName = params[0];
|
||||
const compName = length > 1 ? params.slice(1, length).reduce((a, b) => `${a} ${b}`) : undefined;
|
||||
for (let actor of actors) {
|
||||
await actor.rollCaracCompetence(caracName, compName, diff);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ui.notifications.warn("Sélectionnez au moins un personnage pour lancer les dés")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -232,7 +271,7 @@ export class RdDCommands {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollDeDraconique(msg) {
|
||||
let ddr = new DeDraconique().evaluate();
|
||||
let ddr = new Roll("1dr + 7").evaluate();
|
||||
ddr.showDice = true;
|
||||
await RdDDice.showDiceSoNice(ddr);
|
||||
RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr.total}`);
|
||||
@ -241,7 +280,7 @@ export class RdDCommands {
|
||||
getTMRAleatoire(msg, params) {
|
||||
if (params.length < 2) {
|
||||
let type = params[0];
|
||||
const tmr = TMRUtility.getTMRAleatoire(it => it.type == type);
|
||||
const tmr = TMRUtility.getTMRAleatoire(type ? (it => it.type == type) : (it => true));
|
||||
RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`);
|
||||
}
|
||||
else {
|
||||
@ -266,7 +305,7 @@ export class RdDCommands {
|
||||
getCoutXpCarac(msg, params) {
|
||||
if (params && params.length == 1) {
|
||||
let to = Number(params[0]);
|
||||
RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDUtility.getCaracXp(to)}`);
|
||||
RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to)}`);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
|
@ -1,10 +1,140 @@
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { SYSTEM_RDD } from "./constants.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
function img(src) {
|
||||
return `<img src="${src}" class="dice-img" />`
|
||||
}
|
||||
|
||||
function iconHeure(heure) {
|
||||
if (heure < 10) {
|
||||
heure = '0' + heure;
|
||||
}
|
||||
return `systems/foundryvtt-reve-de-dragon/icons/heures/hd${heure}.webp`
|
||||
}
|
||||
const imagesHeures = [1, 2, 3, 4, 5, 6, 7, 9, 9, 10, 11, 12].map(it => iconHeure(it));
|
||||
|
||||
const imgSigneDragon = img(imagesHeures[4]);
|
||||
|
||||
/** De7 pour les jets de rencontre */
|
||||
export class De7 extends Die {
|
||||
/** @override */
|
||||
static DENOMINATION = "7";
|
||||
|
||||
static diceSoNiceData(system) {
|
||||
return {
|
||||
type: "d7",
|
||||
font: "HeuresDraconiques",
|
||||
fontScale : 0.7,
|
||||
labels: ['1', '2', '3', '4', '5', '6', 'd', '0'],
|
||||
system: system
|
||||
}
|
||||
}
|
||||
|
||||
constructor(termData) {
|
||||
termData.faces = 8;
|
||||
super(termData);
|
||||
}
|
||||
|
||||
evaluate() {
|
||||
super.evaluate();
|
||||
this.explode("x=8");
|
||||
return this;
|
||||
}
|
||||
|
||||
get total() {
|
||||
return this.values.filter(it => it != 8).reduce(Misc.sum(), 0);
|
||||
}
|
||||
|
||||
static getResultLabel(result) {
|
||||
switch (result) {
|
||||
case 7: return imgSigneDragon;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/** DeDraconique pour le D8 sans limite avec 8=>0 */
|
||||
export class DeDraconique extends Die {
|
||||
static DENOMINATION = "r";
|
||||
|
||||
static diceSoNiceData(system) {
|
||||
return {
|
||||
type: "dr",
|
||||
font: "HeuresDraconiques",
|
||||
fontScale : 0.7,
|
||||
labels: ['1', '2', '3', '4', '5', '6', 'd', '0'],
|
||||
system: system
|
||||
}
|
||||
}
|
||||
|
||||
constructor(termData) {
|
||||
termData.faces = 8;
|
||||
super(termData);
|
||||
}
|
||||
|
||||
evaluate() {
|
||||
super.evaluate();
|
||||
this.explode("x=7");
|
||||
return this;
|
||||
}
|
||||
|
||||
get total() {
|
||||
return this.values.filter(it => it != 8).reduce(Misc.sum(), 0);
|
||||
}
|
||||
|
||||
static getResultLabel(result) {
|
||||
switch (result) {
|
||||
case 7: return imgSigneDragon;
|
||||
case 8: return 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/** De 12 avec les heures */
|
||||
export class DeHeure extends Die {
|
||||
|
||||
/** @override */
|
||||
static DENOMINATION = "h";
|
||||
|
||||
static diceSoNiceData(system) {
|
||||
return {
|
||||
type: "dh",
|
||||
font: "HeuresDraconiques",
|
||||
labels: ['v', 'i', 'f', 'o', 'd', 'e', 'l', 's', 'p', 'a', 'r', 'c'],
|
||||
system: system
|
||||
}
|
||||
}
|
||||
|
||||
constructor(termData) {
|
||||
termData.faces = 12;
|
||||
super(termData);
|
||||
}
|
||||
|
||||
static getResultLabel(result) {
|
||||
return img(imagesHeures[result-1]);
|
||||
}
|
||||
}
|
||||
|
||||
export class RdDDice {
|
||||
static init() {
|
||||
CONFIG.Dice.terms[De7.DENOMINATION] = De7;
|
||||
CONFIG.Dice.terms[DeDraconique.DENOMINATION] = DeDraconique;
|
||||
CONFIG.Dice.terms[DeHeure.DENOMINATION] = DeHeure;
|
||||
}
|
||||
|
||||
static diceSoNiceReady(dice3d) {
|
||||
for (const system of Object.keys(dice3d.DiceFactory.systems)) {
|
||||
dice3d.addDicePreset(De7.diceSoNiceData(system));
|
||||
dice3d.addDicePreset(DeDraconique.diceSoNiceData(system));
|
||||
dice3d.addDicePreset(DeHeure.diceSoNiceData(system));
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async show(roll, rollMode = undefined) {
|
||||
if (roll.showDice || game.settings.get("foundryvtt-reve-de-dragon", "dice-so-nice") == true) {
|
||||
if (roll.showDice || game.settings.get(SYSTEM_RDD, "dice-so-nice") == true) {
|
||||
await this.showDiceSoNice(roll, rollMode);
|
||||
}
|
||||
return roll;
|
||||
|
@ -22,13 +22,13 @@ import { RdDTokenHud } from "./rdd-token-hud.js";
|
||||
import { RdDCommands } from "./rdd-commands.js";
|
||||
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { StatusEffects } from "./status-effects.js";
|
||||
import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js";
|
||||
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||
import { RdDHotbar } from "./rdd-hotbar-drop.js"
|
||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
@ -46,7 +46,8 @@ Hooks.once("init", async function () {
|
||||
game.system.rdd = {
|
||||
TMRUtility,
|
||||
RdDUtility,
|
||||
RdDHotbar
|
||||
RdDHotbar,
|
||||
RdDResolutionTable
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -153,6 +154,7 @@ Hooks.once("init", async function () {
|
||||
CONFIG.Combat.entityClass = RdDCombatManager;
|
||||
|
||||
// préparation des différents modules
|
||||
RdDDice.init();
|
||||
RdDCommands.init();
|
||||
RdDCombat.init();
|
||||
RdDCombatManager.init(),
|
||||
@ -211,7 +213,12 @@ Hooks.once("ready", function () {
|
||||
});
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
/* Dice-so-nice ready */
|
||||
/* -------------------------------------------- */
|
||||
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d));
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT chat message */
|
||||
/* -------------------------------------------- */
|
||||
Hooks.on("chatMessage", (html, content, msg) => {
|
||||
if (content[0] == '/') {
|
||||
|
@ -51,10 +51,8 @@ const reussites = [
|
||||
{ code: "error", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: true, ptTache: 0, ptQualite: 0, quality: "Jet de dés invalide", condition: (target, roll) => (roll <= 0 || roll > 100) }
|
||||
];
|
||||
|
||||
const reussiteInsuffisante = { code: "notSign", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Réussite insuffisante", condition: (target, roll) => false }
|
||||
/* -------------------------------------------- */
|
||||
const reussiteSignificative = reussites.find(r => r.code == "sign");
|
||||
const reussiteNormale = reussites.find(r => r.code == "norm");
|
||||
const echecNormal = reussites.find(r => r.code == "echec");
|
||||
const caracMaximumResolution = 60;
|
||||
/* -------------------------------------------- */
|
||||
export class RdDResolutionTable {
|
||||
@ -115,7 +113,7 @@ export class RdDResolutionTable {
|
||||
this._updateChancesFactor(chances, diviseur);
|
||||
chances.showDice = showDice;
|
||||
|
||||
let rolled = await this.rollChances(chances);
|
||||
let rolled = await this.rollChances(chances, diviseur);
|
||||
rolled.caracValue = caracValue;
|
||||
rolled.finalLevel = finalLevel;
|
||||
rolled.bonus = bonus;
|
||||
@ -150,12 +148,12 @@ export class RdDResolutionTable {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async rollChances(chances) {
|
||||
static async rollChances(chances, diviseur) {
|
||||
let myRoll = new Roll("1d100").roll();
|
||||
myRoll.showDice = chances.showDice;
|
||||
await RdDDice.show(myRoll);
|
||||
chances.roll = myRoll.total;
|
||||
mergeObject(chances, this.computeReussite(chances, chances.roll), { overwrite: true });
|
||||
mergeObject(chances, this.computeReussite(chances, chances.roll, diviseur), { overwrite: true });
|
||||
return chances;
|
||||
}
|
||||
|
||||
@ -167,7 +165,8 @@ export class RdDResolutionTable {
|
||||
if (difficulte < -10) {
|
||||
return duplicate(levelDown.find(levelData => levelData.level == difficulte));
|
||||
}
|
||||
return duplicate(RdDResolutionTable.resolutionTable[caracValue][difficulte + 10]);
|
||||
const chances = RdDResolutionTable.resolutionTable[caracValue][difficulte + 10];
|
||||
return chances ? duplicate(chances) : RdDResolutionTable._computeCell(difficulte, RdDResolutionTable.computeChances(caracValue, difficulte));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -216,22 +215,36 @@ export class RdDResolutionTable {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeReussite(chances, roll) {
|
||||
return reussites.find(x => x.condition(chances, roll));
|
||||
static computeReussite(chances, roll, diviseur) {
|
||||
const reussite = reussites.find(x => x.condition(chances, roll));
|
||||
if (diviseur > 1 && reussite.code == 'norm') {
|
||||
return reussiteInsuffisante;
|
||||
}
|
||||
return reussite;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _computeRow(caracValue) {
|
||||
let dataRow = [
|
||||
this._computeCell(-10, Math.max(Math.floor(caracValue / 4), 1)),
|
||||
this._computeCell(-9, Math.max(Math.floor(caracValue / 2), 1))
|
||||
]
|
||||
for (var diff = -8; diff <= 22; diff++) {
|
||||
dataRow[diff + 10] = this._computeCell(diff, Math.max(Math.floor(caracValue * (diff + 10) / 2), 1));
|
||||
let dataRow = [];
|
||||
for (var diff = -10; diff <= 22; diff++) {
|
||||
dataRow[diff + 10] = this._computeCell(diff, RdDResolutionTable._computePercentage(caracValue, diff));
|
||||
}
|
||||
return dataRow;
|
||||
}
|
||||
|
||||
static _computePercentage(caracValue, diff) {
|
||||
if (diff <-10) {
|
||||
return 1;
|
||||
}
|
||||
if (diff == -10){
|
||||
return Math.max(Math.floor(caracValue / 4), 1);
|
||||
}
|
||||
if (diff == -9) {
|
||||
return Math.max(Math.floor(caracValue / 2), 1)
|
||||
}
|
||||
return Math.max(Math.floor(caracValue * (diff + 10) / 2), 1);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _computeCell(niveau, percentage) {
|
||||
return {
|
||||
@ -269,8 +282,8 @@ export class RdDResolutionTable {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static buildHTMLResults(caracValue, levelValue) {
|
||||
if ( caracValue == undefined || isNaN(caracValue )) caracValue = 10;
|
||||
if ( levelValue == undefined || isNaN(levelValue )) levelValue = 0;
|
||||
if (caracValue == undefined || isNaN(caracValue)) caracValue = 10;
|
||||
if (levelValue == undefined || isNaN(levelValue)) levelValue = 0;
|
||||
|
||||
let cell = this.computeChances(caracValue, levelValue);
|
||||
cell.epart = cell.epart > 99 ? 'N/A' : cell.epart;
|
||||
@ -278,14 +291,14 @@ export class RdDResolutionTable {
|
||||
cell.score = Math.min(cell.score, 99);
|
||||
|
||||
return `
|
||||
<span class="table-proba-reussite competence-label">
|
||||
Particulière: <span class="rdd-roll-part">${cell.part}</span>
|
||||
- Significative: <span class="rdd-roll-sign">${cell.sign}</span>
|
||||
- Réussite: <span class="rdd-roll-norm">${cell.score}</span>
|
||||
- Echec Particulier: <span class="rdd-roll-epart">${cell.epart}</span>
|
||||
- Echec Total: <span class="rdd-roll-etotal">${cell.etotal}</span>
|
||||
</span>
|
||||
`
|
||||
<span class="table-proba-reussite competence-label">
|
||||
Particulière: <span class="rdd-roll-part">${cell.part}</span>
|
||||
- Significative: <span class="rdd-roll-sign">${cell.sign}</span>
|
||||
- Réussite: <span class="rdd-roll-norm">${cell.score}</span>
|
||||
- Echec Particulier: <span class="rdd-roll-epart">${cell.epart}</span>
|
||||
- Echec Total: <span class="rdd-roll-etotal">${cell.etotal}</span>
|
||||
</span>
|
||||
`
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -7,6 +7,7 @@ import { Misc } from "./misc.js";
|
||||
import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
|
||||
/**
|
||||
* Extend the base Dialog entity to select roll parameters
|
||||
@ -18,7 +19,7 @@ export class RdDRoll extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
static async create(actor, rollData, dialogConfig, ...actions) {
|
||||
|
||||
if (actor.isRollWindowsOpened() ) {
|
||||
if (actor.isRollWindowsOpened()) {
|
||||
ui.notifications.warn("Vous avez déja une fenêtre de Test ouverte, il faut la fermer avant d'en ouvrir une autre.")
|
||||
return;
|
||||
}
|
||||
@ -38,37 +39,58 @@ export class RdDRoll extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _setDefaultOptions(actor, rollData) {
|
||||
const actorData = Misc.data(actor);
|
||||
let defaultRollData = {
|
||||
alias: actor.name,
|
||||
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
|
||||
difficultesLibres: CONFIG.RDD.difficultesLibres,
|
||||
etat: actor.getEtatGeneral(),
|
||||
moral: actor.getMoralTotal(), /* La valeur du moral pour les jets de volonté */
|
||||
carac: actor.data.data.carac,
|
||||
carac: actorData.data.carac,
|
||||
finalLevel: 0,
|
||||
diffConditions: 0,
|
||||
diffLibre: rollData.competence?.data.default_diffLibre ?? 0,
|
||||
malusArmureValue: actor.getMalusArmure(),
|
||||
surencMalusFlag: actor.isPersonnage() ? (actor.data.data.compteurs.surenc.value < 0) : false,
|
||||
surencMalusFlag: actor.isPersonnage() ? (actorData.data.compteurs.surenc.value < 0) : false,
|
||||
surencMalusValue: actor.getSurenc(),
|
||||
useMalusSurenc: false,
|
||||
appelAuMoralPossible : false, /* Est-ce que l'appel au moral est possible ? Variable utisé pour l'affichage ou non de la ligne concernant le moral */
|
||||
appelAuMoralDemander :false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */
|
||||
jetEchouerMoralDiminuer : false, /* Pour l'affichage dans le chat */
|
||||
use: { libre: true, conditions: true, surenc: false, encTotal: false, appelAuMoral : false /* Le jet se fait ou non en utilisant l'appel au moral */},
|
||||
useMoral: false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */
|
||||
perteMoralEchec: false, /* Pour l'affichage dans le chat */
|
||||
use: { libre: true, conditions: true, surenc: false, encTotal: false },
|
||||
isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
||||
useMalusEncTotal: false,
|
||||
encTotal: actor.getEncTotal(),
|
||||
ajustementAstrologique: actor.ajustementAstrologique(),
|
||||
surprise: actor.getSurprise(false),
|
||||
canClose: true
|
||||
}
|
||||
};
|
||||
|
||||
mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });
|
||||
if (rollData.forceCarac) {
|
||||
rollData.carac = rollData.forceCarac;
|
||||
}
|
||||
rollData.diviseurSignificative = RdDRoll.getDiviseurSignificative(rollData);
|
||||
|
||||
RollDataAjustements.calcul(rollData, actor);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getDiviseurSignificative(rollData) {
|
||||
let facteurSign = 1;
|
||||
if (rollData.surprise == 'demi') {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (rollData.needParadeSignificative) {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (RdDBonus.isDefenseAttaqueFinesse(rollData)) {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (!ReglesOptionelles.isUsing('tripleSignificative')) {
|
||||
facteurSign = Math.min(facteurSign, 4);
|
||||
}
|
||||
return facteurSign;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _ensureCorrectActions(actions) {
|
||||
@ -120,11 +142,10 @@ export class RdDRoll extends Dialog {
|
||||
await RdDResolutionTable.rollData(this.rollData);
|
||||
console.log("RdDRoll -=>", this.rollData, this.rollData.rolled);
|
||||
this.actor.setRollWindowsOpened(false);
|
||||
|
||||
if (action.callbacks)
|
||||
for (let callback of action.callbacks) {
|
||||
if (callback.condition == undefined || callback.condition(this.rollData)) {
|
||||
callback.action(this.rollData);
|
||||
await callback.action(this.rollData);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -206,27 +227,22 @@ export class RdDRoll extends Dialog {
|
||||
this.rollData.useMalusEncTotal = event.currentTarget.checked;
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('#iconeSmile').change((event) => {
|
||||
console.log("iconeSmile");
|
||||
console.log(html.find('.iconeSmile'));
|
||||
html.find('.imgAppelAuMoral').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */
|
||||
this.rollData.useMoral = !this.rollData.useMoral;
|
||||
if (this.rollData.useMoral) {
|
||||
if (this.rollData.moral > 0) {
|
||||
html.find('.imgAppelAuMoral')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg";
|
||||
html.find('.tooltipAppelAuMoralText')[0].innerHTML = "Appel au moral";
|
||||
} else {
|
||||
html.find('.imgAppelAuMoral')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-malheureux.svg";
|
||||
html.find('.tooltipAppelAuMoralText')[0].innerHTML = "Appel à l'énergie du désespoir";
|
||||
}
|
||||
} else {
|
||||
html.find('.imgAppelAuMoral')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-neutre.svg";
|
||||
html.find('.tooltipAppelAuMoralText')[0].innerHTML = "Sans appel au moral";
|
||||
}
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('#iconeSmile').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */
|
||||
this.rollData.appelAuMoralDemander = ! this.rollData.appelAuMoralDemander;
|
||||
if ( this.rollData.appelAuMoralDemander ) {
|
||||
if ( this.rollData.moral > 0 ) {
|
||||
html.find('#iconeSmile')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg";
|
||||
html.find('#tooltipAppelAuMoralText')[0].innerHTML = "Appel au moral";
|
||||
} else {
|
||||
html.find('#iconeSmile')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-malheureux.svg";
|
||||
html.find('#tooltipAppelAuMoralText')[0].innerHTML = "Appel à l'énergie du désespoir";
|
||||
}
|
||||
} else {
|
||||
html.find('#iconeSmile')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-neutre.svg";
|
||||
html.find('#tooltipAppelAuMoralText')[0].innerHTML = "Sans appel au moral";
|
||||
}
|
||||
this.updateRollResult();
|
||||
});
|
||||
// Section Méditation
|
||||
html.find('.conditionMeditation').change((event) => {
|
||||
let condition = event.currentTarget.attributes['id'].value;
|
||||
@ -242,6 +258,7 @@ export class RdDRoll extends Dialog {
|
||||
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat());
|
||||
rollData.caracValue = parseInt(rollData.selectedCarac.value);
|
||||
rollData.coupsNonMortels = (rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite) == 'non-mortel';
|
||||
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);
|
||||
let dmgText = Misc.toSignedString(rollData.dmg.total);
|
||||
|
||||
if (rollData.coupsNonMortels) {
|
||||
@ -253,20 +270,11 @@ export class RdDRoll extends Dialog {
|
||||
HtmlUtility._showControlWhen($("#div-sort-ptreve"), RdDItemSort.isCoutVariable(rollData.selectedSort))
|
||||
}
|
||||
|
||||
if ( ! RdDCarac.isActionPhysique(rollData.selectedCarac || ! actor.isPersonnage() ) ) {
|
||||
rollData.appelAuMoralPossible = false;
|
||||
rollData.use.appelAuMoral = false;
|
||||
} else {
|
||||
rollData.appelAuMoralPossible = true;
|
||||
rollData.use.appelAuMoral = rollData.appelAuMoralDemander;
|
||||
|
||||
}
|
||||
|
||||
RollDataAjustements.calcul(rollData, this.actor);
|
||||
rollData.finalLevel = this._computeFinalLevel(rollData);
|
||||
|
||||
HtmlUtility._showControlWhen($(".diffMoral"), rollData.ajustements.moralTotal.used);
|
||||
HtmlUtility._showControlWhen($("#divAppelAuMoral"), rollData.appelAuMoralPossible );
|
||||
HtmlUtility._showControlWhen($(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
||||
HtmlUtility._showControlWhen($("#etat-general"), !RdDCarac.isIgnoreEtatGeneral(rollData.selectedCarac, rollData.competence));
|
||||
HtmlUtility._showControlWhen($("#ajust-astrologique"), RdDResolutionTable.isAjustementAstrologique(rollData));
|
||||
|
||||
|
@ -48,14 +48,22 @@ export class RdDRollTables {
|
||||
static async getQueue(toChat = false) {
|
||||
let queue = await RdDRollTables.drawItemFromRollTable("Queues de dragon", toChat);
|
||||
if (queue.name.toLowerCase().includes('lancinant') ) {
|
||||
queue = await RdDRollTables.drawItemFromRollTable("Désirs lancinants", toChat);
|
||||
return await RdDRollTables.getDesirLancinant(toChat);
|
||||
}
|
||||
if (queue.name.toLowerCase().includes('fixe') ) {
|
||||
queue = await RdDRollTables.drawItemFromRollTable("Idées fixes", toChat);
|
||||
return await RdDRollTables.getIdeeFixe(toChat);
|
||||
}
|
||||
return queue;
|
||||
}
|
||||
|
||||
static async getDesirLancinant(toChat = false) {
|
||||
return await RdDRollTables.drawItemFromRollTable("Désirs lancinants", toChat);
|
||||
}
|
||||
|
||||
static async getIdeeFixe(toChat = false) {
|
||||
return await RdDRollTables.drawItemFromRollTable("Idées fixes", toChat);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async getTeteHR(toChat = false) {
|
||||
return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour haut-rêvants", toChat);
|
||||
|
@ -11,6 +11,7 @@ import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||
import { PixiTMR } from "./tmr/pixi-tmr.js";
|
||||
import { Draconique } from "./tmr/draconique.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDTMRDialog extends Dialog {
|
||||
@ -72,11 +73,11 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
|
||||
loadSortsReserve() {
|
||||
this.sortsReserves = duplicate(this.actor.data.data.reve.reserve.list);
|
||||
this.sortsReserves = Misc.data(this.actor).data.reve.reserve.list;
|
||||
}
|
||||
|
||||
loadRencontres() {
|
||||
this.rencontresExistantes = duplicate(this.actor.getTMRRencontres()).list;
|
||||
this.rencontresExistantes = this.actor.getTMRRencontres();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -108,6 +109,11 @@ export class RdDTMRDialog extends Dialog {
|
||||
this._createTokens();
|
||||
}
|
||||
|
||||
removeToken(tmr, casetmr) {
|
||||
this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id);
|
||||
this.updateTokens()
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_getTokensCasesTmr() {
|
||||
return this.casesSpeciales.map(c => this._tokenCaseSpeciale(c)).filter(token => token);
|
||||
@ -131,7 +137,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortEnReserve.sort, () => sortEnReserve.coord);
|
||||
}
|
||||
_tokenDemiReve() {
|
||||
return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor, () => this.actor.data.data.reve.tmrpos.coord);
|
||||
return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor, () => Misc.data(this.actor).data.reve.tmrpos.coord);
|
||||
}
|
||||
|
||||
_updateDemiReve() {
|
||||
@ -142,7 +148,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
async activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
document.getElementById("tmrrow1").insertCell(1).append(this.pixiApp.view);
|
||||
document.getElementById("tmrrow1").insertCell(0).append(this.pixiApp.view);
|
||||
|
||||
if (this.viewOnly) {
|
||||
html.find('#lancer-sort').remove();
|
||||
@ -150,7 +156,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
else {
|
||||
// Roll Sort
|
||||
html.find('#lancer-sort').click((event) => {
|
||||
this.actor.rollUnSort(this.actor.data.data.reve.tmrpos.coord);
|
||||
this.actor.rollUnSort(Misc.data(this.actor).data.reve.tmrpos.coord);
|
||||
});
|
||||
}
|
||||
if (this.viewOnly) {
|
||||
@ -165,44 +171,43 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
// Le reste...
|
||||
this.updateValuesDisplay();
|
||||
let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord);
|
||||
let tmr = TMRUtility.getTMR(Misc.data(this.actor).data.reve.tmrpos.coord);
|
||||
await this.manageRencontre(tmr, () => {
|
||||
this.postRencontre(tmr);
|
||||
this.actor.displayTMRQueueSouffleInformation();
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateValuesDisplay() {
|
||||
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
||||
ptsreve.innerHTML = this.actor.data.data.reve.reve.value;
|
||||
const actorData = Misc.data(this.actor);
|
||||
ptsreve.innerHTML = actorData.data.reve.reve.value;
|
||||
|
||||
let tmrpos = document.getElementById("tmr-pos");
|
||||
let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord);
|
||||
tmrpos.innerHTML = this.actor.data.data.reve.tmrpos.coord + " (" + tmr.label + ")";
|
||||
let tmr = TMRUtility.getTMR(actorData.data.reve.tmrpos.coord);
|
||||
tmrpos.innerHTML = actorData.data.reve.tmrpos.coord + " (" + tmr.label + ")";
|
||||
|
||||
let etat = document.getElementById("tmr-etatgeneral-value");
|
||||
etat.innerHTML = this.actor.getEtatGeneral();
|
||||
|
||||
let refoulement = document.getElementById("tmr-refoulement-value");
|
||||
refoulement.innerHTML = this.actor.data.data.reve.refoulement.value;
|
||||
refoulement.innerHTML = actorData.data.reve.refoulement.value;
|
||||
|
||||
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
||||
//console.log("Refresh : ", this.actor.data.data.sante.fatigue.value);
|
||||
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(this.actor.data.data.sante.fatigue.value, this.actor.data.data.sante.endurance.max).html() + "</table>";
|
||||
//console.log("Refresh : ", actorData.data.sante.fatigue.value);
|
||||
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(actorData.data.sante.fatigue.value, actorData.data.sante.endurance.max).html() + "</table>";
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
close() {
|
||||
this.actor.santeIncDec("fatigue", this.cumulFatigue).then(super.close()); // moving 1 cell costs 1 fatigue
|
||||
this.actor.tmrApp = undefined; // Cleanup reference
|
||||
this.actor.setStatusDemiReve(false);
|
||||
if (!this.viewOnly) {
|
||||
this.actor.setStatusDemiReve(false);
|
||||
this._tellToGM(this.actor.name + " a quitté les terres médianes");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async derober() {
|
||||
await this.actor.addTMRRencontre(this.currentRencontre);
|
||||
@ -286,6 +291,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async quitterLesTMRInconscient() {
|
||||
if (this.currentRencontre?.isPersistant) {
|
||||
await this.refouler();
|
||||
@ -306,7 +312,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
rencontre: this.currentRencontre,
|
||||
nbRounds: 1,
|
||||
canClose: false,
|
||||
tmr: TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord)
|
||||
tmr: TMRUtility.getTMR(Misc.data(this.actor).data.reve.tmrpos.coord)
|
||||
}
|
||||
|
||||
await this._tentativeMaitrise(rencontreData);
|
||||
@ -354,6 +360,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_rollPresentCite(rencontreData) {
|
||||
let rolled = RdDResolutionTable.computeChances(rencontreData.reve, 0);
|
||||
mergeObject(rolled, { caracValue: rencontreData.reve, finalLevel: 0, roll: rolled.score });
|
||||
@ -385,6 +392,11 @@ export class RdDTMRDialog extends Dialog {
|
||||
ChatMessage.create({ content: message, user: game.user._id, whisper: ChatMessage.getWhisperRecipients("GM") });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_tellToUserAndGM(message) {
|
||||
ChatMessage.create({ content: message, user: game.user._id, whisper: [game.user._id].concat(ChatMessage.getWhisperRecipients("GM")) });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async manageRencontre(tmr, postRencontre) {
|
||||
if (this.viewOnly) {
|
||||
@ -409,6 +421,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_presentCite(tmr, postRencontre) {
|
||||
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
|
||||
if (presentCite) {
|
||||
@ -418,6 +431,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return presentCite;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _utiliserPresentCite(presentCite, typeRencontre, tmr, postRencontre) {
|
||||
this.currentRencontre = TMRRencontres.getRencontre(typeRencontre);
|
||||
await TMRRencontres.evaluerForceRencontre(this.currentRencontre);
|
||||
@ -498,9 +512,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
|
||||
async _resultatMaitriseCaseHumide(rollData) {
|
||||
if (rollData.rolled.isETotal) {
|
||||
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
|
||||
}
|
||||
await this.souffleSiEchecTotal(rollData);
|
||||
this.toclose = rollData.rolled.isEchec;
|
||||
if (rollData.rolled.isSuccess && rollData.double) {
|
||||
rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements };
|
||||
@ -518,6 +530,12 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
}
|
||||
|
||||
async souffleSiEchecTotal(rollData) {
|
||||
if (rollData.rolled.isETotal) {
|
||||
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isCaseHumide(tmr) {
|
||||
if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) {
|
||||
@ -558,16 +576,29 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this._conquerir(tmr, {
|
||||
difficulte: -9,
|
||||
action: 'Conquérir la cité',
|
||||
onConqueteReussie: r => EffetsDraconiques.fermetureCites.onConquete(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
|
||||
onConqueteEchec: r => this.close(),
|
||||
onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
|
||||
onConqueteEchec: r => {
|
||||
this.souffleSiEchecTotal(rollData);
|
||||
this.close()
|
||||
},
|
||||
canClose: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
removeToken(tmr, casetmr) {
|
||||
this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id);
|
||||
this.updateTokens()
|
||||
/* -------------------------------------------- */
|
||||
async purifierPeriple(tmr) {
|
||||
if (EffetsDraconiques.periple.find(this.casesSpeciales, tmr.coord)) {
|
||||
await this._conquerir(tmr, {
|
||||
difficulte: EffetsDraconiques.periple.getDifficulte(tmr),
|
||||
action: 'Purifier ' + TMRUtility.getTMRDescr(tmr.coord),
|
||||
onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
|
||||
onConqueteEchec: r => {
|
||||
this.souffleSiEchecTotal(rollData);
|
||||
this.close()
|
||||
},
|
||||
canClose: false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -576,8 +607,8 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this._conquerir(tmr, {
|
||||
difficulte: -7,
|
||||
action: 'Conquérir',
|
||||
onConqueteReussie: r => EffetsDraconiques.conquete.onConquete(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
|
||||
onConqueteEchec: r => { },
|
||||
onConqueteReussie: r => EffetsDraconiques.conquete.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
|
||||
onConqueteEchec: r => this.close(),
|
||||
canClose: false
|
||||
});
|
||||
}
|
||||
@ -639,23 +670,25 @@ export class RdDTMRDialog extends Dialog {
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
async validerPelerinage(tmr) {
|
||||
await EffetsDraconiques.pelerinage.onFinPelerinage(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
|
||||
async validerVisite(tmr) {
|
||||
await EffetsDraconiques.pelerinage.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
|
||||
await EffetsDraconiques.urgenceDraconique.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async declencheSortEnReserve(coord) {
|
||||
|
||||
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord);
|
||||
if (sortReserveList.length > 0) {
|
||||
if (EffetsDraconiques.isSortImpossible(this.actor)) {
|
||||
let sortsEnCoord = TMRUtility.getSortsReserve(this.sortsReserves, coord);
|
||||
if (sortsEnCoord.length > 0) {
|
||||
if (EffetsDraconiques.isSortReserveImpossible(this.actor)) {
|
||||
ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!");
|
||||
return;
|
||||
}
|
||||
if (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord)) {
|
||||
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) &&
|
||||
(EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord))) {
|
||||
let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête <strong>Reserve en Sécurité</strong> ou <strong>Réserve Exensible</strong>, vous pouvez contrôler le déclenchement. Cliquez si vous souhaitez le déclencher : <ul>";
|
||||
for (let sortReserve of sortReserveList) {
|
||||
for (let sortReserve of sortsEnCoord) {
|
||||
msg += "<li><a class='chat-card-button' id='sort-reserve' data-actor-id='" + this.actor._id + "' data-tmr-coord='" + coord + "' data-sort-id='" + sortReserve.sort._id + "'>" + sortReserve.sort.name + "</a></li>";
|
||||
}
|
||||
msg += "</ol>";
|
||||
@ -663,17 +696,16 @@ export class RdDTMRDialog extends Dialog {
|
||||
content: msg,
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||
});
|
||||
} else {
|
||||
await this.processSortReserve(sortReserveList[0]);
|
||||
return;
|
||||
}
|
||||
await this.processSortReserve(sortsEnCoord[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
lancerSortEnReserve(coord, sortId) {
|
||||
let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coord);
|
||||
let sortReserve = sortReserveList.find(sortReserve => sortReserve.sort._id == sortId);
|
||||
//console.log("SORT RESA", sortReserveList, coordTMR, sortId, sortReserve);
|
||||
let sortEnCoord = TMRUtility.getSortsReserve(this.sortsReserves, coord);
|
||||
let sortReserve = sortEnCoord.find(sortReserve => sortReserve.sort._id == sortId);
|
||||
if (sortReserve) {
|
||||
this.processSortReserve(sortReserve);
|
||||
} else {
|
||||
@ -689,7 +721,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this.actor.deleteSortReserve(sortReserve);
|
||||
//this.updateSortReserve();
|
||||
console.log("declencheSortEnReserve", sortReserve)
|
||||
this._tellToGM(`Vous avez déclenché le sort en réserve <strong> ${sortReserve.sort.name}</strong>
|
||||
this._tellToUserAndGM(`Vous avez déclenché le sort en réserve <strong> ${sortReserve.sort.name}</strong>
|
||||
avec ${sortReserve.sort.data.ptreve_reel} points de Rêve
|
||||
en ${sortReserve.coord} (${TMRUtility.getTMRLabel(sortReserve.coord)})
|
||||
`);
|
||||
@ -753,7 +785,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
|
||||
async _onClickTMRPos(eventPos) {
|
||||
let currentPos = TMRUtility.convertToCellPos(this.actor.data.data.reve.tmrpos.coord);
|
||||
let currentPos = TMRUtility.convertToCellPos(Misc.data(this.actor).data.reve.tmrpos.coord);
|
||||
|
||||
console.log("deplacerDemiReve >>>>", currentPos, eventPos);
|
||||
|
||||
@ -819,7 +851,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", {
|
||||
msg: "msg_tmr_move", data: {
|
||||
actorId: this.actor.data._id,
|
||||
tmrPos: this.actor.data.data.reve.tmrpos
|
||||
tmrPos: Misc.data(this.actor).data.reve.tmrpos
|
||||
}
|
||||
});
|
||||
|
||||
@ -835,8 +867,9 @@ export class RdDTMRDialog extends Dialog {
|
||||
if (!(this.viewOnly || this.currentRencontre)) {
|
||||
await this.manageCaseHumide(tmr);
|
||||
await this.conquerirCiteFermee(tmr);
|
||||
await this.purifierPeriple(tmr);
|
||||
await this.conquerirTMR(tmr);
|
||||
await this.validerPelerinage(tmr);
|
||||
await this.validerVisite(tmr);
|
||||
await this.declencheSortEnReserve(tmr.coord);
|
||||
await this.actor.checkSoufflePeage(tmr);
|
||||
}
|
||||
|
@ -1,43 +1,10 @@
|
||||
/* Common useful functions shared between objects */
|
||||
|
||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { RdDCombat, RdDCombatManager } from "./rdd-combat.js";
|
||||
import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||
import { RdDItemArme } from "./item-arme.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDCombat } from "./rdd-combat.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const categorieCompetences = {
|
||||
"generale": { level: "-4", label: "Générales" },
|
||||
"particuliere": { level: "-8", label: "Particulières" },
|
||||
"specialisee": { level: "-11", label: "Spécialisées" },
|
||||
"connaissance": { level: "-11", label: "Connaissances" },
|
||||
"draconic": { level: "-11", label: "Draconics" },
|
||||
"melee": { level: "-6", label: "Mêlée" },
|
||||
"tir": { level: "-8", label: "Tir" },
|
||||
"lancer": { level: "-8", label: "Lancer" }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const limitesArchetypes = [
|
||||
{ "niveau": 0, "nombreMax": 100, "nombre": 0 },
|
||||
{ "niveau": 1, "nombreMax": 10, "nombre": 0 },
|
||||
{ "niveau": 2, "nombreMax": 9, "nombre": 0 },
|
||||
{ "niveau": 3, "nombreMax": 8, "nombre": 0 },
|
||||
{ "niveau": 4, "nombreMax": 7, "nombre": 0 },
|
||||
{ "niveau": 5, "nombreMax": 6, "nombre": 0 },
|
||||
{ "niveau": 6, "nombreMax": 5, "nombre": 0 },
|
||||
{ "niveau": 7, "nombreMax": 4, "nombre": 0 },
|
||||
{ "niveau": 8, "nombreMax": 3, "nombre": 0 },
|
||||
{ "niveau": 9, "nombreMax": 2, "nombre": 0 },
|
||||
{ "niveau": 10, "nombreMax": 1, "nombre": 0 },
|
||||
{ "niveau": 11, "nombreMax": 1, "nombre": 0 }
|
||||
];
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// This table starts at 0 -> niveau -10
|
||||
const carac_array = ["taille", "apparence", "constitution", "force", "agilite", "dexterite", "vue", "ouie", "odoratgout", "volonte", "intellect", "empathie", "reve", "chance", "melee", "tir", "lancer", "derobee"];
|
||||
@ -45,42 +12,6 @@ const difficultesLibres = [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10];
|
||||
const ajustementsConditions = [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10];
|
||||
const ajustementsEncaissement = [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10, +11, +12, +13, +14, +15, +16, +17, +18, +19, +20, +21, +22, +23, +24, +25];
|
||||
|
||||
const tableCaracDerivee = {
|
||||
// xp: coût pour passer du niveau inférieur à ce niveau
|
||||
1: { xp: 3, poids: "moins de 1kg", plusdom: -5, sconst: 0.5, sust: 0.1 },
|
||||
2: { xp: 3, poids: "1-5", plusdom: -4, sconst: 0.5, sust: 0.3 },
|
||||
3: { xp: 4, poids: "6-10", plusdom: -3, sconst: 1, sust: 0.5, beaute: 'hideux' },
|
||||
4: { xp: 4, poids: "11-20", plusdom: -3, sconst: 1, sust: 1, beaute: 'repoussant' },
|
||||
5: { xp: 5, poids: "21-30", plusdom: -2, sconst: 1, sust: 1, beaute: 'franchement très laid' },
|
||||
6: { xp: 5, poids: "31-40", plusdom: -1, sconst: 2, sust: 2, beaute: 'laid' },
|
||||
7: { xp: 6, poids: "41-50", plusdom: -1, sconst: 2, sust: 2, beaute: 'très désavantagé' },
|
||||
8: { xp: 6, poids: "51-60", plusdom: 0, sconst: 2, sust: 2, beaute: 'désavantagé' },
|
||||
9: { xp: 7, poids: "61-65", plusdom: 0, sconst: 3, sust: 2, beaute: 'pas terrible' },
|
||||
10: { xp: 7, poids: "66-70", plusdom: 0, sconst: 3, sust: 3, beaute: 'commun' },
|
||||
11: { xp: 8, poids: "71-75", plusdom: 0, sconst: 3, sust: 3, beaute: 'pas mal' },
|
||||
12: { xp: 8, poids: "76-80", plusdom: +1, sconst: 4, sust: 3, beaute: 'avantagé' },
|
||||
13: { xp: 9, poids: "81-90", plusdom: +1, sconst: 4, sust: 3, beaute: 'mignon' },
|
||||
14: { xp: 9, poids: "91-100", plusdom: +2, sconst: 4, sust: 4, beaute: 'beau' },
|
||||
15: { xp: 10, poids: "101-110", plusdom: +2, sconst: 5, sust: 4, beaute: 'très beau' },
|
||||
16: { xp: 20, poids: "111-120", plusdom: +3, sconst: 5, sust: 4, beaute: 'éblouissant' },
|
||||
17: { xp: 30, poids: "121-131", plusdom: +3, sconst: 5, sust: 5 },
|
||||
18: { xp: 40, poids: "131-141", plusdom: +4, sconst: 6, sust: 5 },
|
||||
19: { xp: 50, poids: "141-150", plusdom: +4, sconst: 6, sust: 5 },
|
||||
20: { xp: 60, poids: "151-160", plusdom: +4, sconst: 6, sust: 6 },
|
||||
21: { xp: 70, poids: "161-180", plusdom: +5, sconst: 7, sust: 6 },
|
||||
22: { xp: 80, poids: "181-200", plusdom: +5, sconst: 7, sust: 7 },
|
||||
23: { xp: 90, poids: "201-300", plusdom: +6, sconst: 7, sust: 8 },
|
||||
24: { xp: 100, poids: "301-400", plusdom: +6, sconst: 8, sust: 9 },
|
||||
25: { xp: 110, poids: "401-500", plusdom: +7, sconst: 8, sust: 10 },
|
||||
26: { xp: 120, poids: "501-600", plusdom: +7, sconst: 8, sust: 11 },
|
||||
27: { xp: 130, poids: "601-700", plusdom: +8, sconst: 9, sust: 12 },
|
||||
28: { xp: 140, poids: "701-800", plusdom: +8, sconst: 9, sust: 13 },
|
||||
29: { xp: 150, poids: "801-900", plusdom: +9, sconst: 9, sust: 14 },
|
||||
30: { xp: 160, poids: "901-1000", plusdom: +9, sconst: 10, sust: 15 },
|
||||
31: { xp: 170, poids: "1001-1500", plusdom: +10, sconst: 10, sust: 16 },
|
||||
32: { xp: 180, poids: "1501-2000", plusdom: +11, sconst: 10, sust: 17 }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
function _buildAllSegmentsFatigue(max) {
|
||||
const cycle = [5, 2, 4, 1, 3, 0];
|
||||
@ -170,6 +101,8 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-competence-partial.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-liste-blessures-partial.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html',
|
||||
//Items
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html',
|
||||
@ -260,10 +193,6 @@ export class RdDUtility {
|
||||
return loadTemplates(templatePaths);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getLimitesArchetypes() {
|
||||
return duplicate(limitesArchetypes);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static checkNull(items) {
|
||||
@ -296,32 +225,40 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static filterItemsPerTypeForSheet(data) {
|
||||
data.data.materiel = this.checkNull(data.itemsByType['objet']);
|
||||
data.data.conteneurs = this.checkNull(data.itemsByType['conteneur']);
|
||||
data.data.armes = this.checkNull(data.itemsByType['arme']);
|
||||
data.data.armures = this.checkNull(data.itemsByType['armure']);
|
||||
data.data.livres = this.checkNull(data.itemsByType['livre']);
|
||||
data.data.potions = this.checkNull(data.itemsByType['potion']);
|
||||
data.data.ingredients = this.checkNull(data.itemsByType['ingredient']);
|
||||
data.data.munitions = this.checkNull(data.itemsByType['munition']);
|
||||
data.data.herbes = this.checkNull(data.itemsByType['herbe']);
|
||||
data.data.sorts = this.checkNull(data.itemsByType['sort']);
|
||||
data.data.queues = this.checkNull(data.itemsByType['queue']);
|
||||
data.data.souffles = this.checkNull(data.itemsByType['souffle']);
|
||||
data.data.ombres = this.checkNull(data.itemsByType['ombre']);
|
||||
data.data.tetes = this.checkNull(data.itemsByType['tete']);
|
||||
data.data.taches = this.checkNull(data.itemsByType['tache']);
|
||||
data.data.monnaie = this.checkNull(data.itemsByType['monnaie']);
|
||||
data.data.meditations = this.checkNull(data.itemsByType['meditation']);
|
||||
data.data.chants = this.checkNull(data.itemsByType['chant']);
|
||||
data.data.danses = this.checkNull(data.itemsByType['danse']);
|
||||
data.data.musiques = this.checkNull(data.itemsByType['musique']);
|
||||
data.data.oeuvres = this.checkNull(data.itemsByType['oeuvre']);
|
||||
data.data.jeux = this.checkNull(data.itemsByType['jeu']);
|
||||
data.data.recettescuisine = this.checkNull(data.itemsByType['recettecuisine']);
|
||||
data.data.recettesAlchimiques = this.checkNull(data.itemsByType['recettealchimique']);
|
||||
data.data.objets = data.data.conteneurs.concat(data.data.materiel).concat(data.data.armes).concat(data.data.armures).concat(data.data.munitions).concat(data.data.livres).concat(data.data.potions).concat(data.data.herbes).concat(data.data.ingredients);
|
||||
static filterItemsPerTypeForSheet(formData) {
|
||||
formData.data.materiel = this.checkNull(formData.itemsByType['objet']);
|
||||
formData.data.conteneurs = this.checkNull(formData.itemsByType['conteneur']);
|
||||
formData.data.armes = this.checkNull(formData.itemsByType['arme']);
|
||||
formData.data.armures = this.checkNull(formData.itemsByType['armure']);
|
||||
formData.data.livres = this.checkNull(formData.itemsByType['livre']);
|
||||
formData.data.potions = this.checkNull(formData.itemsByType['potion']);
|
||||
formData.data.ingredients = this.checkNull(formData.itemsByType['ingredient']);
|
||||
formData.data.munitions = this.checkNull(formData.itemsByType['munition']);
|
||||
formData.data.herbes = this.checkNull(formData.itemsByType['herbe']);
|
||||
formData.data.sorts = this.checkNull(formData.itemsByType['sort']);
|
||||
formData.data.queues = this.checkNull(formData.itemsByType['queue']);
|
||||
formData.data.souffles = this.checkNull(formData.itemsByType['souffle']);
|
||||
formData.data.ombres = this.checkNull(formData.itemsByType['ombre']);
|
||||
formData.data.tetes = this.checkNull(formData.itemsByType['tete']);
|
||||
formData.data.taches = this.checkNull(formData.itemsByType['tache']);
|
||||
formData.data.monnaie = this.checkNull(formData.itemsByType['monnaie']);
|
||||
formData.data.meditations = this.checkNull(formData.itemsByType['meditation']);
|
||||
formData.data.chants = this.checkNull(formData.itemsByType['chant']);
|
||||
formData.data.danses = this.checkNull(formData.itemsByType['danse']);
|
||||
formData.data.musiques = this.checkNull(formData.itemsByType['musique']);
|
||||
formData.data.oeuvres = this.checkNull(formData.itemsByType['oeuvre']);
|
||||
formData.data.jeux = this.checkNull(formData.itemsByType['jeu']);
|
||||
formData.data.recettescuisine = this.checkNull(formData.itemsByType['recettecuisine']);
|
||||
formData.data.recettesAlchimiques = this.checkNull(formData.itemsByType['recettealchimique']);
|
||||
formData.data.objets = formData.data.conteneurs.concat(formData.data.materiel)
|
||||
.concat(formData.data.armes)
|
||||
.concat(formData.data.armures)
|
||||
.concat(formData.data.munitions)
|
||||
.concat(formData.data.livres)
|
||||
.concat(formData.data.potions)
|
||||
.concat(formData.data.herbes)
|
||||
.concat(formData.data.ingredients);
|
||||
formData.data.competences = (formData.itemsByType.competence??[]).concat(formData.itemsByType.competencecreature??[]);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -403,15 +340,6 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCategorieCompetences() {
|
||||
return categorieCompetences;
|
||||
}
|
||||
static getLevelCategory(category) {
|
||||
return categorieCompetences[category].level;
|
||||
}
|
||||
static getLabelCategory(category) {
|
||||
return categorieCompetences[category].label;
|
||||
}
|
||||
static getCaracArray() {
|
||||
return carac_array;
|
||||
}
|
||||
@ -429,53 +357,6 @@ export class RdDUtility {
|
||||
return definitionsBlessures;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCaracNextXp(value) {
|
||||
const nextValue = Number(value) + 1;
|
||||
// xp est le coût pour atteindre cette valeur, on regarde donc le coût de la valeur+1
|
||||
return RdDUtility.getCaracXp(nextValue);
|
||||
}
|
||||
|
||||
static getCaracXp(targetValue) {
|
||||
return tableCaracDerivee[targetValue]?.xp ?? 200;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeCarac(data) {
|
||||
data.carac.force.value = Math.min(data.carac.force.value, parseInt(data.carac.taille.value) + 4);
|
||||
|
||||
data.carac.derobee.value = Math.floor(parseInt(((21 - data.carac.taille.value)) + parseInt(data.carac.agilite.value)) / 2);
|
||||
let bonusDomKey = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2);
|
||||
bonusDomKey = Math.min(Math.max(bonusDomKey, 0), 32); // Clamp de securite
|
||||
|
||||
let tailleData = tableCaracDerivee[bonusDomKey];
|
||||
data.attributs.plusdom.value = tailleData.plusdom;
|
||||
|
||||
data.attributs.sconst.value = RdDUtility.calculSConst(data.carac.constitution.value);
|
||||
data.attributs.sust.value = tableCaracDerivee[Number(data.carac.taille.value)].sust;
|
||||
|
||||
data.attributs.encombrement.value = (parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2;
|
||||
data.carac.melee.value = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.agilite.value)) / 2);
|
||||
data.carac.tir.value = Math.floor((parseInt(data.carac.vue.value) + parseInt(data.carac.dexterite.value)) / 2);
|
||||
data.carac.lancer.value = Math.floor((parseInt(data.carac.tir.value) + parseInt(data.carac.force.value)) / 2);
|
||||
|
||||
data.sante.vie.max = Math.ceil((parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value)) / 2);
|
||||
|
||||
data.sante.vie.value = Math.min(data.sante.vie.value, data.sante.vie.max)
|
||||
data.sante.endurance.max = Math.max(parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value), parseInt(data.sante.vie.max) + parseInt(data.carac.volonte.value));
|
||||
data.sante.endurance.value = Math.min(data.sante.endurance.value, data.sante.endurance.max);
|
||||
data.sante.fatigue.max = data.sante.endurance.max * 2;
|
||||
data.sante.fatigue.value = Math.min(data.sante.fatigue.value, data.sante.fatigue.max);
|
||||
|
||||
//Compteurs
|
||||
data.reve.reve.max = data.carac.reve.value;
|
||||
data.compteurs.chance.max = data.carac.chance.value;
|
||||
}
|
||||
|
||||
static calculSConst(constitution) {
|
||||
return Number(tableCaracDerivee[Number(constitution)].sconst);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getSegmentsFatigue(maxEnd) {
|
||||
maxEnd = Math.max(maxEnd, 1);
|
||||
@ -606,8 +487,10 @@ export class RdDUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async loadCompendium(compendium, filter = item => true) {
|
||||
if (!compendium){
|
||||
return [];
|
||||
}
|
||||
let compendiumItems = await RdDUtility.loadCompendiumNames(compendium);
|
||||
|
||||
const pack = game.packs.get(compendium);
|
||||
let list = [];
|
||||
for (let compendiumItem of compendiumItems) {
|
||||
@ -672,7 +555,10 @@ export class RdDUtility {
|
||||
// Gestion du bouton payer
|
||||
html.on("click", '#payer-button', event => {
|
||||
let sumdenier = event.currentTarget.attributes['data-somme-denier'].value;
|
||||
let quantite = event.currentTarget.attributes['data-quantite'].value;
|
||||
let quantite = 1;
|
||||
if ( event.currentTarget.attributes['data-quantite'] ) {
|
||||
quantite = event.currentTarget.attributes['data-quantite'].value;
|
||||
}
|
||||
let jsondata = event.currentTarget.attributes['data-jsondata']
|
||||
let objData
|
||||
if (jsondata) {
|
||||
@ -814,15 +700,19 @@ export class RdDUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static afficherHeuresChanceMalchance(heureNaissance) {
|
||||
if (heureNaissance) {
|
||||
let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance);
|
||||
ChatMessage.create({
|
||||
content: `A l'heure ${game.system.rdd.calendrier.getCurrentHeure()}, le modificateur de Chance/Malchance pour l'heure de naissance ${heureNaissance} est de : ${ajustement}.`,
|
||||
whisper: ChatMessage.getWhisperRecipients("MJ")
|
||||
});
|
||||
}
|
||||
else {
|
||||
ui.notifications.warn("Pas d'heure de naissance selectionnée")
|
||||
if ( game.user.isGM) {
|
||||
if (heureNaissance) {
|
||||
let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance);
|
||||
ChatMessage.create({
|
||||
content: `A l'heure ${game.system.rdd.calendrier.getCurrentHeure()}, le modificateur de Chance/Malchance pour l'heure de naissance ${heureNaissance} est de : ${ajustement}.`,
|
||||
whisper: ChatMessage.getWhisperRecipients("GM")
|
||||
});
|
||||
}
|
||||
else {
|
||||
ui.notifications.warn("Pas d'heure de naissance selectionnée")
|
||||
}
|
||||
} else {
|
||||
ui.notifications.warn("Vous n'avez pas accès à cette commande")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,14 +50,14 @@ export class ReglesOptionelles extends FormApplication {
|
||||
}
|
||||
|
||||
getData() {
|
||||
let data = super.getData();
|
||||
data.regles = listeReglesOptionelles.map(it => {
|
||||
let formData = super.getData();
|
||||
formData.regles = listeReglesOptionelles.map(it => {
|
||||
let r = duplicate(it);
|
||||
r.id = ReglesOptionelles._getIdRegle(r.name);
|
||||
r.active = ReglesOptionelles.isUsing(r.name);
|
||||
return r;
|
||||
})
|
||||
return data;
|
||||
return formData;
|
||||
}
|
||||
|
||||
static isUsing(name) {
|
||||
|
@ -18,9 +18,9 @@ import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
*/
|
||||
export const referenceAjustements = {
|
||||
competence: {
|
||||
isUsed: (rollData, actor) => rollData.competence,
|
||||
getLabel: (rollData, actor) => rollData.competence?.name,
|
||||
getValue: (rollData, actor) => rollData.competence?.data?.niveau,
|
||||
isUsed: (rollData, actor) => Misc.data(rollData.competence),
|
||||
getLabel: (rollData, actor) => Misc.data(rollData.competence)?.name,
|
||||
getValue: (rollData, actor) => Misc.data(rollData.competence)?.data?.niveau,
|
||||
},
|
||||
meditation: {
|
||||
isUsed: (rollData, actor) => rollData.meditation,
|
||||
@ -32,7 +32,7 @@ export const referenceAjustements = {
|
||||
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ? 'Imposée' : 'Libre',
|
||||
getValue: (rollData, actor) => rollData.selectedSort
|
||||
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
|
||||
: rollData.diffLibre ?? rollData.competence?.data.default_diffLibre ?? 0
|
||||
: rollData.diffLibre ?? Misc.data(rollData.competence)?.data.default_diffLibre ?? 0
|
||||
},
|
||||
diffConditions: {
|
||||
isUsed: (rollData, actor) => rollData.diffConditions != undefined,
|
||||
@ -73,8 +73,8 @@ export const referenceAjustements = {
|
||||
getValue: (rollData, actor) => actor.getSurenc()
|
||||
},
|
||||
moral: {
|
||||
isVisible: (rollData, actor) => RdDCarac.isActionPhysique(rollData.selectedCarac),
|
||||
isUsed: (rollData, actor) => rollData.use?.appelAuMoral,
|
||||
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac) && rollData.useMoral,
|
||||
isUsed: (rollData, actor) => rollData.useMoral,
|
||||
getLabel: (rollData, actor) => 'Appel au moral',
|
||||
getValue: (rollData, actor) => 1
|
||||
},
|
||||
@ -94,10 +94,10 @@ export const referenceAjustements = {
|
||||
getDescr: (rollData, actor) => rollData.diviseurSignificative > 1 ? `Facteur significative <span class="rdd-diviseur">×${Misc.getFractionHtml(rollData.diviseurSignificative)}</span>` : ''
|
||||
},
|
||||
isEcaille: {
|
||||
isVisible: (rollData, actor) => rollData.arme?.data.magique && Number(rollData.arme?.data.ecaille_efficacite) > 0,
|
||||
isUsed: (rollData, actor) => rollData.arme?.data.magique && Number(rollData.arme?.data.ecaille_efficacite) > 0,
|
||||
isVisible: (rollData, actor) => Misc.data(rollData.arme)?.data.magique && Number(Misc.data(rollData.arme)?.data.ecaille_efficacite) > 0,
|
||||
isUsed: (rollData, actor) => Misc.data(rollData.arme)?.data.magique && Number(Misc.data(rollData.arme)?.data.ecaille_efficacite) > 0,
|
||||
getLabel: (rollData, actor) => "Ecaille d'Efficacité: ",
|
||||
getValue: (rollData, actor) => (rollData.arme?.data.magique && Number(rollData.arme.data.ecaille_efficacite) > 0) ? rollData.arme.data.ecaille_efficacite : 0,
|
||||
getValue: (rollData, actor) => Math.max(Number(Misc.data(rollData.arme)?.data.ecaille_efficacite), 0),
|
||||
},
|
||||
finesse: {
|
||||
isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData),
|
||||
|
@ -103,9 +103,9 @@ class StatusEffectsSettings extends FormApplication {
|
||||
}
|
||||
|
||||
getData() {
|
||||
let data = super.getData();
|
||||
data.effects = CONFIG.RDD.allEffects;
|
||||
return data;
|
||||
let formData = super.getData();
|
||||
formData.effects = CONFIG.RDD.allEffects;
|
||||
return formData;
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
|
@ -1,4 +1,3 @@
|
||||
import { DeDraconique } from "./de-draconique.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
@ -269,7 +268,7 @@ const rencontresStandard = [
|
||||
{ code: "reflet", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6", isPersistant: true },
|
||||
{ code: "tbblanc", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6", isPersistant: true },
|
||||
{ code: "tbnoir", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8", isPersistant: true },
|
||||
{ code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1ddr + 7", refoulement: 2, quitterTMR: true }
|
||||
{ code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1dr + 7", refoulement: 2, quitterTMR: true }
|
||||
];
|
||||
|
||||
const rencontresPresentCite = [
|
||||
@ -381,13 +380,7 @@ export class TMRRencontres {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async evaluerForceRencontre(rencontre) {
|
||||
if (TMRRencontres.isReveDeDragon(rencontre)) {
|
||||
const ddr = await DeDraconique.ddr("selfroll")
|
||||
rencontre.force = 7 + ddr.total;
|
||||
}
|
||||
else {
|
||||
rencontre.force = new Roll(rencontre.force).evaluate().total;
|
||||
}
|
||||
rencontre.force = new Roll(rencontre.force).evaluate().total;
|
||||
return rencontre.force;
|
||||
}
|
||||
|
||||
|
@ -210,8 +210,8 @@ const TMRMapping = {
|
||||
|
||||
export const TMRType = {
|
||||
cite: { name: "cité", genre: "f" },
|
||||
sanctuaire: { name: "sanctuaire" },
|
||||
plaines: { name: "plaines", genre: "p" },
|
||||
sanctuaire: { name: "sanctuaire", genre: 'm' },
|
||||
plaines: { name: "plaines", genre: "fp" },
|
||||
pont: { name: "pont", genre: "m" },
|
||||
collines: { name: "collines", genre: "p" },
|
||||
foret: { name: "forêt", genre: "f" },
|
||||
@ -332,7 +332,12 @@ export class TMRUtility {
|
||||
}
|
||||
|
||||
static getTMRLabel(coord) {
|
||||
return TMRMapping[coord]?.label ?? (coord+": case inconnue");
|
||||
return TMRMapping[coord]?.label ?? (coord + ": case inconnue");
|
||||
}
|
||||
|
||||
static getTMRDescr(coord) {
|
||||
const tmr = TMRMapping[coord];
|
||||
return Grammar.articleDetermine(tmr.genre) + ' ' + tmr.label;
|
||||
}
|
||||
|
||||
static isCaseHumide(tmr) {
|
||||
@ -384,7 +389,7 @@ export class TMRUtility {
|
||||
currentPos.x = currentPos.x + direction.x;
|
||||
currentPos.y = currentPos.y + direction.y;
|
||||
if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Sortie de carte ! Ré-insertion aléatoire
|
||||
coord = TMRUtility.getTMR(TMRUtility.convertToTMRCoord(currentPos));
|
||||
coord = TMRUtility.getTMR(TMRUtility.convertToTMRCoord(currentPos));
|
||||
} else {
|
||||
coord = await actor.reinsertionAleatoire('Sortie de carte');
|
||||
}
|
||||
@ -427,7 +432,7 @@ export class TMRUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getSortReserveList(reserveList, coord) {
|
||||
static getSortsReserve(reserveList, coord) {
|
||||
// TODO : Gérer les têtes spéciales réserve!
|
||||
let tmrDescr = this.getTMR(coord);
|
||||
//console.log("Sort réserve : ", tmrDescr);
|
||||
@ -435,7 +440,7 @@ export class TMRUtility {
|
||||
return reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve');
|
||||
}
|
||||
// Reserve sur un case "normale"
|
||||
return reserveList.filter(it => it.coord == coord);
|
||||
return reserveList.filter(it => it.coord == coord);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -450,9 +455,8 @@ export class TMRUtility {
|
||||
for (let dy = -portee; dy <= portee; dy++) { // Loop thru lines
|
||||
const currentPos = { x: centerPos.x + dx, y: centerPos.y + dy };
|
||||
if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Coordinate is valie
|
||||
let posPicNow = this.computeRealPictureCoordinates(currentPos, tmrConstants);
|
||||
let dist = Math.sqrt(Math.pow(posPicNow.x - posPic.x, 2) + Math.pow(posPicNow.y - posPic.y, 2)) / tmrConstants.cellw;
|
||||
if (dist < portee + 0.5) {
|
||||
let dist = this.distancePosTMR(centerPos, currentPos);
|
||||
if (dist <= portee) {
|
||||
caseList.push(this.convertToTMRCoord(currentPos)); // Inside the area
|
||||
}
|
||||
}
|
||||
@ -460,5 +464,21 @@ export class TMRUtility {
|
||||
}
|
||||
return caseList;
|
||||
}
|
||||
|
||||
static distanceTMR(coord1, coord2) {
|
||||
let pos1 = this.convertToCellPos(coord1);
|
||||
let pos2 = this.convertToCellPos(coord2);
|
||||
return this.distancePosTMR(pos1, pos2);
|
||||
}
|
||||
|
||||
static distancePosTMR(pos1, pos2) {
|
||||
const dx = pos2.x - pos1.x;
|
||||
const dy = pos2.y - pos1.y;
|
||||
const abs_dx = Math.abs(dx);
|
||||
const abs_dy = Math.abs(dy);
|
||||
const distance = Math.sign(dx) == Math.sign(dy) ? Math.max(abs_dx, abs_dy) : (abs_dx + abs_dy);
|
||||
return distance;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -35,11 +35,8 @@ export class Conquete extends Draconique {
|
||||
await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue._id);
|
||||
}
|
||||
|
||||
async onConquete(actor, tmr, onRemoveToken) {
|
||||
let existants = actor.data.items.filter(it => this.isCase(it, tmr.coord));
|
||||
for (let casetmr of existants) {
|
||||
await actor.deleteOwnedItem(casetmr.data.sourceid);
|
||||
onRemoveToken(tmr, casetmr);
|
||||
}
|
||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||
await actor.deleteOwnedItem(casetmr.data.sourceid);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,10 +24,6 @@ export class Desorientation extends Draconique {
|
||||
return Object.keys(TMRType).filter(it => !dejaDesorientes.includes(it));
|
||||
}
|
||||
|
||||
async onActorDeleteOwned(actor, souffle) {
|
||||
await this._supprimerCasesTmr(actor, souffle);
|
||||
}
|
||||
|
||||
code() { return 'desorientation' }
|
||||
tooltip(linkData) { return `Désorientation, cette case n'existe plus !` }
|
||||
img() { return 'icons/svg/explosion.svg' }
|
||||
@ -51,11 +47,5 @@ export class Desorientation extends Draconique {
|
||||
}
|
||||
}
|
||||
|
||||
async _supprimerCasesTmr(actor, souffle) {
|
||||
let caseTmrs = actor.data.items.filter(it => it.data.sourceId == souffle._id);
|
||||
for (let casetmr of caseTmrs) {
|
||||
await actor.deleteOwnedItem(casetmr._id);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,8 +7,7 @@ const registeredEffects = [
|
||||
/**
|
||||
* Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR
|
||||
*/
|
||||
export class Draconique
|
||||
{
|
||||
export class Draconique {
|
||||
static isCaseTMR(element) { return element.type == 'casetmr'; }
|
||||
static isQueueDragon(element) { return element.type == 'queue' || element.type == 'ombre'; }
|
||||
static isSouffleDragon(element) { return element.type == 'souffle'; }
|
||||
@ -28,6 +27,7 @@ export class Draconique
|
||||
static all() {
|
||||
return Object.values(registeredEffects);
|
||||
}
|
||||
|
||||
static get(code) {
|
||||
return registeredEffects[code];
|
||||
}
|
||||
@ -56,10 +56,11 @@ export class Draconique
|
||||
}
|
||||
|
||||
async onActorDeleteOwned(actor, item) {
|
||||
let caseTmrs = actor.data.items.filter(it => this.isCase(it) && it.data.sourceid == item._id);
|
||||
for (let casetmr of caseTmrs) {
|
||||
await actor.deleteOwnedItem(casetmr._id);
|
||||
}
|
||||
this.deleteCasesTmr(actor, item);
|
||||
return false;
|
||||
}
|
||||
|
||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
@ -102,7 +103,7 @@ export class Draconique
|
||||
if (this.img()) {
|
||||
return pixiTMR.sprite(this.code());
|
||||
}
|
||||
else{
|
||||
else {
|
||||
return pixiTMR.circle()
|
||||
}
|
||||
}
|
||||
@ -120,11 +121,25 @@ export class Draconique
|
||||
return list.find(c => this.isCase(c, coord));
|
||||
}
|
||||
|
||||
async createCaseTmr(actor, label, tmr, sourceId=undefined) {
|
||||
async createCaseTmr(actor, label, tmr, sourceId = undefined) {
|
||||
await actor.createOwnedItem({
|
||||
name: label, type: 'casetmr', img: this.img(), _id: randomID(16),
|
||||
data: { coord: tmr.coord, specific: this.code(), sourceid:sourceId }
|
||||
data: { coord: tmr.coord, specific: this.code(), sourceid: sourceId }
|
||||
});
|
||||
}
|
||||
|
||||
async deleteCasesTmr(actor, draconique) {
|
||||
let caseTmrs = actor.data.items.filter(it => this.isCase(it) && it.data.sourceid == draconique._id);
|
||||
for (let casetmr of caseTmrs) {
|
||||
await actor.deleteOwnedItem(casetmr._id);
|
||||
}
|
||||
}
|
||||
|
||||
async onVisiteSupprimer(actor, tmr, onRemoveToken) {
|
||||
let existants = actor.data.items.filter(it => this.isCase(it, tmr.coord));
|
||||
for (let casetmr of existants) {
|
||||
await actor.deleteOwnedItem(casetmr._id);
|
||||
onRemoveToken(tmr, casetmr);
|
||||
}
|
||||
}
|
||||
}
|
@ -14,6 +14,9 @@ import { PresentCites } from "./present-cites.js";
|
||||
import { Desorientation } from "./desorientation.js";
|
||||
import { Conquete } from "./conquete.js";
|
||||
import { Pelerinage } from "./pelerinage.js";
|
||||
import { Periple } from "./periple.js";
|
||||
import { UrgenceDraconique } from "./urgence-draconique.js";
|
||||
import { Misc } from "../misc.js";
|
||||
|
||||
|
||||
export class EffetsDraconiques {
|
||||
@ -32,6 +35,8 @@ export class EffetsDraconiques {
|
||||
static desorientation = new Desorientation();
|
||||
static conquete = new Conquete();
|
||||
static pelerinage = new Pelerinage();
|
||||
static periple = new Periple();
|
||||
static urgenceDraconique = new UrgenceDraconique();
|
||||
|
||||
static init() {
|
||||
Draconique.register(EffetsDraconiques.carteTmr);
|
||||
@ -49,6 +54,8 @@ export class EffetsDraconiques {
|
||||
Draconique.register(EffetsDraconiques.desorientation);
|
||||
Draconique.register(EffetsDraconiques.conquete);
|
||||
Draconique.register(EffetsDraconiques.pelerinage);
|
||||
Draconique.register(EffetsDraconiques.periple);
|
||||
Draconique.register(EffetsDraconiques.urgenceDraconique);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -86,87 +93,100 @@ export class EffetsDraconiques {
|
||||
return EffetsDraconiques.presentCites.isCase(caseTMR, coord);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isMauvaiseRencontre(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('mauvaise rencontre'));
|
||||
static isMauvaiseRencontre(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('mauvaise rencontre'));
|
||||
}
|
||||
|
||||
static isMonteeLaborieuse(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('montée laborieuse'));
|
||||
static isMonteeLaborieuse(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('montée laborieuse'));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isFermetureCite(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.fermetureCites.match(it));
|
||||
static isFermetureCite(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => EffetsDraconiques.fermetureCites.match(it));
|
||||
}
|
||||
|
||||
static isPontImpraticable(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.pontImpraticable.match(it));
|
||||
static isPontImpraticable(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => EffetsDraconiques.pontImpraticable.match(it));
|
||||
}
|
||||
|
||||
static isDoubleResistanceFleuve(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase().includes('résistance du fleuve'));
|
||||
static isDoubleResistanceFleuve(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase().includes('résistance du fleuve'));
|
||||
}
|
||||
|
||||
static isPeage(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase().includes('péage'));
|
||||
static isPeage(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase().includes('péage'));
|
||||
}
|
||||
|
||||
static isPeriple(element) {
|
||||
// TODO
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && ir.name.toLowerCase() == 'périple');
|
||||
static isPeriple(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => EffetsDraconiques.periple.match(it));
|
||||
}
|
||||
|
||||
static isDesorientation(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.desorientation.match(it)); // TODO
|
||||
static isDesorientation(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => EffetsDraconiques.desorientation.match(it)); // TODO
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isSortImpossible(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.conquete.match(it) || EffetsDraconiques.pelerinage.match(it));
|
||||
static isSortImpossible(item) {
|
||||
return EffetsDraconiques.isMatching(item, it =>
|
||||
EffetsDraconiques.conquete.match(it) ||
|
||||
EffetsDraconiques.periple.match(it) ||
|
||||
EffetsDraconiques.urgenceDraconique.match(it) ||
|
||||
EffetsDraconiques.pelerinage.match(it)
|
||||
);
|
||||
}
|
||||
|
||||
static isConquete(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.conquete.match(it));
|
||||
static isSortReserveImpossible(item) {
|
||||
return EffetsDraconiques.isMatching(item, it =>
|
||||
EffetsDraconiques.conquete.match(it) ||
|
||||
EffetsDraconiques.periple.match(it) ||
|
||||
EffetsDraconiques.pelerinage.match(it)
|
||||
);
|
||||
}
|
||||
|
||||
static isPelerinage(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.pelerinage.match(it));
|
||||
static isConquete(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => EffetsDraconiques.conquete.match(it));
|
||||
}
|
||||
|
||||
static countInertieDraconique(element) {
|
||||
return EffetsDraconiques.count(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase().includes('inertie draconique'));
|
||||
static isPelerinage(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => EffetsDraconiques.pelerinage.match(it));
|
||||
}
|
||||
|
||||
static isUrgenceDraconique(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'urgence draconique');
|
||||
static countInertieDraconique(item) {
|
||||
return EffetsDraconiques.count(item, it => Draconique.isQueueDragon(it) && it.name.toLowerCase().includes('inertie draconique'));
|
||||
}
|
||||
|
||||
static isUrgenceDraconique(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => EffetsDraconiques.urgenceDraconique.match(it));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isDonDoubleReve(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name == 'Don de double-rêve');
|
||||
static isDonDoubleReve(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => Draconique.isTeteDragon(it) && it.name == 'Don de double-rêve');
|
||||
}
|
||||
|
||||
static isConnaissanceFleuve(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes('connaissance du fleuve'));
|
||||
static isConnaissanceFleuve(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes('connaissance du fleuve'));
|
||||
}
|
||||
|
||||
static isReserveEnSecurite(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes(' en sécurité'));
|
||||
static isReserveEnSecurite(item) {
|
||||
return EffetsDraconiques.isMatching(item, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes(' en sécurité'));
|
||||
}
|
||||
|
||||
static isDeplacementAccelere(element) {
|
||||
return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes(' déplacement accéléré'));
|
||||
static isDeplacementAccelere(item) {
|
||||
item = Misc.data(item);
|
||||
return EffetsDraconiques.isMatching(item, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes(' déplacement accéléré'));
|
||||
}
|
||||
|
||||
static isMatching(element, matcher) {
|
||||
return EffetsDraconiques.toItems(element).find(matcher);
|
||||
static isMatching(item, matcher) {
|
||||
return EffetsDraconiques.toItems(item).find(matcher);
|
||||
}
|
||||
static count(element, matcher) {
|
||||
return EffetsDraconiques.toItems(element).filter(matcher).length;
|
||||
static count(item, matcher) {
|
||||
return EffetsDraconiques.toItems(item).filter(matcher).length;
|
||||
}
|
||||
|
||||
static toItems(element) {
|
||||
return (element?.entity === 'Actor') ? element.data.items : (element?.entity === 'Item') ? [element] : [];
|
||||
static toItems(item) {
|
||||
return (item?.entity === 'Actor') ? item.data.items : (item?.entity === 'Item') ? [Misc.data(item)] : [];
|
||||
}
|
||||
|
||||
}
|
@ -35,11 +35,4 @@ export class FermetureCites extends Draconique {
|
||||
await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr, souffle._id);
|
||||
}
|
||||
}
|
||||
|
||||
async onConquete(actor, tmr, onRemoveToken) {
|
||||
const citeFermee = actor.data.items.find(it => this.isCase(it, tmr.coord));
|
||||
await actor.deleteOwnedItem(citeFermee._id);
|
||||
onRemoveToken(tmr, citeFermee);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,12 +31,8 @@ export class Pelerinage extends Draconique {
|
||||
});
|
||||
}
|
||||
|
||||
async onFinPelerinage(actor, tmr, onRemoveToken) {
|
||||
const pelerinages = actor.data.items.filter(it => this.isCase(it, tmr.coord));
|
||||
for (let p of pelerinages){
|
||||
await actor.deleteOwnedItem(p.data.sourceid);
|
||||
onRemoveToken(tmr, p);
|
||||
}
|
||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||
await actor.deleteOwnedItem(casetmr.data.sourceid);
|
||||
}
|
||||
|
||||
}
|
||||
|
44
module/tmr/periple.js
Normal file
@ -0,0 +1,44 @@
|
||||
import { Grammar } from "../grammar.js";
|
||||
import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class Periple extends Draconique {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return 'souffle' }
|
||||
match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('periple'); }
|
||||
manualMessage() { return false }
|
||||
|
||||
async onActorCreateOwned(actor, souffle) {
|
||||
let terrain = new Roll("1d2").evaluate().total == 1 ? 'sanctuaire' : 'necropole';
|
||||
let tmrs = TMRUtility.getListTMR(terrain);
|
||||
for (let tmr of tmrs) {
|
||||
await this.createCaseTmr(actor, 'Périple: ' + tmr.label, tmr, souffle._id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
code() { return 'periple' }
|
||||
tooltip(linkData) { return `Votre Périple passe par ${this.tmrLabel(linkData)}` }
|
||||
img() { return 'icons/svg/acid.svg' }
|
||||
|
||||
createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(), {
|
||||
zIndex: tmrTokenZIndex.conquete,
|
||||
alpha: 1,
|
||||
color: tmrColors.souffle,
|
||||
taille: tmrConstants.twoThird,
|
||||
decallage: tmrConstants.right
|
||||
});
|
||||
}
|
||||
getDifficulte(tmr) {
|
||||
switch (tmr.type) {
|
||||
case 'sanctuaire': return -3;
|
||||
case 'necropole': return -5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ export class Rencontre extends Draconique {
|
||||
async onActorCreateOwned(actor, item) { }
|
||||
|
||||
code() { return 'rencontre' }
|
||||
tooltip(linkData) { return `${linkData.name} de force ${linkData.force}` }
|
||||
tooltip(linkData) { return `${linkData.rencontre.name} de force ${linkData.rencontre.force}` }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg' }
|
||||
|
||||
createSprite(pixiTMR) {
|
||||
|
55
module/tmr/urgence-draconique.js
Normal file
@ -0,0 +1,55 @@
|
||||
import { ChatUtility } from "../chat-utility.js";
|
||||
import { Grammar } from "../grammar.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDRollTables } from "../rdd-rolltables.js";
|
||||
import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
export class UrgenceDraconique extends Draconique {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
type() { return 'queue' }
|
||||
match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, queue) {
|
||||
let coordSortsReserve = (actor.data.data.reve.reserve?.list.map(it => it.coord)) ?? [];
|
||||
if (coordSortsReserve.length == 0) {
|
||||
// La queue se transforme en idée fixe
|
||||
let ideeFixe = await RdDRollTables.getIdeeFixe();
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||
content: `En l'absence de sorts en réserve, l'urgence draconique de ${actor.name} se transforme en ${queue.name}`
|
||||
});
|
||||
await actor.createOwnedItem(ideeFixe);
|
||||
await actor.deleteOwnedItem(queue._id);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
let demiReve = actor.getDemiReve();
|
||||
coordSortsReserve.sort((a, b) => TMRUtility.distanceTMR(a, demiReve) - TMRUtility.distanceTMR(b, demiReve));
|
||||
let tmr = TMRUtility.getTMR(coordSortsReserve[0]);
|
||||
await this.createCaseTmr(actor, 'Urgence draconique: ' + tmr.label, tmr, queue._id);
|
||||
}
|
||||
}
|
||||
|
||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||
await actor.deleteOwnedItem(casetmr.data.sourceid);
|
||||
}
|
||||
|
||||
code() { return 'urgence' }
|
||||
tooltip(linkData) { return `Urgence draconique!` }
|
||||
img() { return 'icons/svg/hazard.svg' }
|
||||
|
||||
createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(),
|
||||
{
|
||||
zIndex: tmrTokenZIndex.conquete,
|
||||
color: tmrColors.queues,
|
||||
taille: tmrConstants.full,
|
||||
decallage: { x: 2, y: 0 }
|
||||
});
|
||||
}
|
||||
}
|
@ -34,7 +34,6 @@
|
||||
{"_id":"CMtQM06J3BZsHHxH","name":"Sandales","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/sandales.webp","effects":[]}
|
||||
{"_id":"CQSxJv1mgmIeMCbM","name":"Grappin","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.5,"equipe":false,"resistance":0,"qualite":0,"cout":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/grappin.webp","effects":[]}
|
||||
{"_id":"D5Z3FaUv91B8eCOP","name":"Obyssum vert","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"ingredient","data":{"description":"<p>Poudre verdâtre apparaissant sur les tiges de certains roseaux.</p>\n<p>VUE/Alchimie à -2</p>","niveau":0,"encombrement":0.001,"base":0,"quantite":1,"milieu":"Lieux humides","rarete":"","categorie":"Alchimie","cout":0.05},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/l_obyssum_vert.webp","effects":[]}
|
||||
{"_id":"ESU3IRLnBrFznFa3","name":"Dragons (pièces d'or)","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":10},"flags":{},"img":"icons/commodities/currency/coins-plain-stack-gold.webp","effects":[]}
|
||||
{"_id":"ElweMV283IUpqaik","name":"Sable-Poudre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"<p>Granulés. Poudre blanche.</p>","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp","effects":[]}
|
||||
{"_id":"Eospy1EFNlhgOyXc","name":"Lacet de cuir (1 m)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":0.06},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/lacet.webp","effects":[]}
|
||||
{"_id":"F0hcXfGaaYKQ0229","name":"Narcos, voie des Sortilèges","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"livre","data":{"description":"<p>Ce tome imposant, ouvertement destiné aux haut-rêvants, révèle que la voie de Narcos ne possède pas que des rituels, mais également des sortilèges. En saisir le sens demande toutefois un minimum de +4 en voie de Narcos. Il permet de comprendre le principe des sorts de transformation et d’envisager la synthèse de <em>Flèche de feu</em>,<em> Dague de force</em>, <em>Dragonne lame</em> et <em>Gourdindragon</em>. Sans son assimilation préalable, la synthèse de ces sorts est totalement inenvisageable. Sa difficulté de lecture est de -6, son assimilation requiert 28 points de tâche, périodicité 1 heure.</p>","auteur":"Segamor le Transformiste","quantite":1,"difficulte":-6,"points_de_tache":28,"encombrement":0,"xp":"","cout":0,"competence":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]}
|
||||
@ -78,7 +77,6 @@
|
||||
{"_id":"PrnJrG50u1UPdlJN","name":"Liqueur de Bagdol","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"<p>Fluide. Liquide noir et odorant.</p>","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp","effects":[]}
|
||||
{"_id":"PuuPn6WGfU8uBAyb","name":"Robe de soie","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0,"equipe":false,"resistance":0,"qualite":0,"cout":10},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/robe_soie.webp","effects":[]}
|
||||
{"name":"Bâton","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"","description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"1","penetration":0,"force":"9","resistance":8,"competence":"Masse à 2 mains","cout":0.5,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false,"initpremierround":"baton"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/baton.webp","effects":[],"_id":"Qh4Tp7lZ6wLnX4w0"}
|
||||
{"_id":"RC1co7jmHMDqlJGy","name":"Deniers (pièces d'étain)","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.005,"equipe":false,"resistance":0,"qualite":0,"cout":0.01},"flags":{},"img":"icons/commodities/currency/coins-assorted-mix-platinum.webp","effects":[]}
|
||||
{"_id":"RGdDQ3yJYMkSuA5G","name":"Provisions cuites (1 sust)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"<p>pain, fromage, viande séchée...</p>","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.02},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/provision_cuite.webp","effects":[]}
|
||||
{"_id":"RKr1ZhTvC6poiNa1","name":"Gros Clou","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.05},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/gros_clou.webp","effects":[]}
|
||||
{"_id":"RNxCQWMDy06uQ8uj","name":"Ecuelle de fer","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.15},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/ecuelle_fer.webp","effects":[]}
|
||||
@ -93,7 +91,6 @@
|
||||
{"_id":"Sm28dG9isppoQzPQ","name":"Bas de lin","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bas_lin.webp","effects":[]}
|
||||
{"_id":"SrV0r5hnGdKeSIHR","name":"Cuillère de bois","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.03,"equipe":false,"resistance":0,"qualite":0,"cout":0.03},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/cuillere_bois.webp","effects":[]}
|
||||
{"_id":"SsnGNjTekvB50uWa","name":"Chapeau de cuir souple","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.08,"equipe":false,"resistance":0,"qualite":0,"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/chapeau_cuir.webp","effects":[]}
|
||||
{"_id":"T9UiLcJonuHmGNwq","name":"Sols (pièces d'argent)","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.005,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"icons/commodities/currency/coins-assorted-mix-silver.webp","effects":[]}
|
||||
{"name":"Hache de bataille","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"haches","description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"3/4","penetration":0,"force":"12/11","resistance":8,"competence":"Hache à 1 main","cout":15,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true,"initpremierround":"hachebataille"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/hache_bataille.webp","effects":[],"_id":"TKsUXJq9w7ezcFGQ"}
|
||||
{"_id":"TY6Ft8a6WfxD6pD9","name":"Bobineau de fil","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bobineau.webp","effects":[]}
|
||||
{"_id":"UDmq6CY3NsttcHe4","name":"Peigne en corne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.04,"equipe":false,"resistance":0,"qualite":0,"cout":0.4},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/peigne.webp","effects":[]}
|
||||
@ -120,12 +117,14 @@
|
||||
{"_id":"Z0ij7qpoYeWMVocP","name":"Ceinturon de cuir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":6,"encombrement":0.1,"equipe":false,"qualite":0,"contenu":[],"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/ceinturon.webp","effects":[]}
|
||||
{"_id":"ZLda3pfrbiKucSea","name":"Cornebouffe","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"objet","data":{"description":null,"quantite":1,"encombrement":null,"equipe":false,"resistance":0,"qualite":0,"cout":2},"flags":{"core":{"sourceId":"Item.yXOePj4twuchMblc"}},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/cornebouffe.webp","effects":[]}
|
||||
{"_id":"a3Wj2WNKFrzqRGVG","name":"Chemise de soie","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0,"equipe":false,"resistance":0,"qualite":0,"cout":6},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/chemise_soie.webp","effects":[]}
|
||||
{"name":"Or (10 sols)","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"monnaie","data":{"quantite":0,"valeur_deniers":1000,"encombrement":0.01,"description":""},"flags":{"pick-up-stix":{"pick-up-stix":{"owner":"3ajJ5ZIa9bdcKUZQ"}}},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp","effects":[],"_id":"aOgha34ew68iyMnM"}
|
||||
{"_id":"b0f08L5CDeFIMluC","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":"bA0JDA7awoWhu0vO","name":"Teinture d'Erozonne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"<p>Fluide. </p>\n<p>Liquide rosâtre.</p>","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/teinture_erozonne.webp","effects":[]}
|
||||
{"_id":"beQ9d4QQwZDQl5NA","name":"Flûte à bec","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.09,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/flute_bec.webp","effects":[]}
|
||||
{"_id":"bgkEBYUEFLvAaeVf","name":"Luth, viole","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"resistance":0,"qualite":0,"cout":7},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/luth.webp","effects":[]}
|
||||
{"_id":"bxDITKRhXiyvLhMz","name":"Candique","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"ingredient","data":{"description":"<p>Poudre blanche apparaissant sous l’écorce de nombreux arbres,</p>\n<p>VUE/Alchimie à 0.</p>","niveau":0,"encombrement":0.001,"base":0,"quantite":1,"milieu":"Forêts","rarete":"","categorie":"Alchimie","cout":0.02},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/candique.webp","effects":[]}
|
||||
{"_id":"cVZbnh5cYxBx6P5b","name":"Burin, gouge, ciseau","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/gouge.webp","effects":[]}
|
||||
{"name":"Bronze (10 deniers)","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"monnaie","data":{"quantite":6,"valeur_deniers":10,"encombrement":0.01,"description":""},"flags":{"pick-up-stix":{"pick-up-stix":{"owner":"3ajJ5ZIa9bdcKUZQ"}}},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp","effects":[],"_id":"caw96HJsdScvPk7g"}
|
||||
{"_id":"ckKnviu9SHvWgya0","name":"Bougie de cire (2 heures)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.05},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bougie.webp","effects":[]}
|
||||
{"_id":"cobfvOmFpti5lJuK","name":"Chemise de lin","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/chemise_lin.webp","effects":[]}
|
||||
{"_id":"dBR6KXvfmjjIcwsc","name":"Pilon en marbre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/pilon.webp","effects":[]}
|
||||
@ -183,6 +182,7 @@
|
||||
{"name":"Sang","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"munition","data":{"description":"<p>1 mesure (20cl) de sang.</p>","quantite":1,"encombrement":0.1,"equipe":false,"qualite":0,"cout":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/liquides/liquide_sang.webp","effects":[],"_id":"slusKo2nVCtFwDkN"}
|
||||
{"_id":"snupUovwaPAe46aD","name":"Fiole en grès (20 cl)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.1,"encombrement":0.1,"equipe":false,"qualite":0,"contenu":[],"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/fiole_gres.webp","effects":[]}
|
||||
{"_id":"szOThadvQvFcS79R","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":[]}
|
||||
{"name":"Etain (1 denier)","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"monnaie","data":{"quantite":4,"valeur_deniers":1,"encombrement":0.01,"description":""},"flags":{"pick-up-stix":{"pick-up-stix":{"owner":"3ajJ5ZIa9bdcKUZQ"}}},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp","effects":[],"_id":"t1sIGhFtmxjAIfWv"}
|
||||
{"_id":"tBFt4h3jqINsOxLI","name":"Outre (2 litres)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":1,"encombrement":0.08,"equipe":false,"qualite":0,"contenu":[],"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/outre.webp","effects":[]}
|
||||
{"name":"Marteau","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"","description":"","quantite":1,"encombrement":0.3,"equipe":false,"dommages":"2","penetration":0,"force":"7","resistance":8,"competence":"Masse à 1 main","cout":1,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"initpremierround":"masse"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/marteau.webp","effects":[],"_id":"tMWzePiuMtiCQnAU"}
|
||||
{"_id":"tY3shj5FA8nwMgxX","name":"Vin","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"munition","data":{"description":"<p>1 mesure (20cl) de vin.</p>","quantite":1,"encombrement":0.1,"equipe":false,"qualite":0,"cout":0},"flags":{"core":{"sourceId":"Item.QNNWTG5yqQKmcpJ7"}},"img":"systems/foundryvtt-reve-de-dragon/icons/liquides/liquide_vin.webp","effects":[]}
|
||||
@ -203,6 +203,7 @@
|
||||
{"_id":"yILNvELKbsz2OOln","name":"Ecritoire","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/ecritoire.webp","effects":[]}
|
||||
{"_id":"yO9Vx7tqF8qbZoYw","name":"Besace de cuir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":10,"encombrement":0.2,"equipe":false,"qualite":0,"contenu":[],"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/besace.webp","effects":[]}
|
||||
{"_id":"z3xiBzZBZXlaRVzZ","name":"Le Grand Iris","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"livre","data":{"description":"<p>Cette judicieuse réflexion sur les sorts d’illusion visuelle d’Hypnos ne peut être assimilée que si l’on possède au minimum zéro en voie d’Hypnos. Il confère un bonus de synthèse de +2 et de 12 points de sorts aux trois yeux d’Hypnos : Invisibilité, Transfiguration, Métamorphose. Sa difficulté de lecture est de -3, son assimilation requiert 16 points de tâche, périodicité une heure.</p>","auteur":"Khrachtchoum le Problémeux","quantite":1,"difficulte":-3,"points_de_tache":16,"encombrement":0,"xp":"0","cout":0,"competence":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.png","effects":[]}
|
||||
{"name":"Argent (1 sol)","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"monnaie","data":{"quantite":17,"valeur_deniers":100,"encombrement":0.01,"description":""},"flags":{"pick-up-stix":{"pick-up-stix":{"owner":"3ajJ5ZIa9bdcKUZQ"}}},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp","effects":[],"_id":"z8nkjovgrEj2d8kD"}
|
||||
{"_id":"zQWlnUsd8bPySujd","name":"Aiguille à coudre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/aiguille.webp","effects":[]}
|
||||
{"_id":"zYI8mDiysWtmsSyy","name":"Carquois","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"conteneur","data":{"description":"","capacite":2,"encombrement":0.1,"equipe":false,"qualite":0,"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/carquois.webp","effects":[]}
|
||||
{"_id":"zlDa1vwmls6Uf4pt","name":"Bourse de cuir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.5,"encombrement":0.01,"equipe":false,"qualite":0,"contenu":[],"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bourse.webp","effects":[]}
|
||||
|
81
packs/signes-draconiques.txt
Normal file
@ -0,0 +1,81 @@
|
||||
des centaines de graines emport<72>es par le vent
|
||||
des chemin<69>es de f<>es
|
||||
des cristaux de neige <20>tincelants au soleil
|
||||
des feux follets dans la nuit
|
||||
des fumeroles s'<27>chappant de fissures dans le sol
|
||||
des gr<67>lons de la taille d'un oeuf de pigeon
|
||||
des lichens <20> l'assaut d'une souche
|
||||
des mirages sur l'horizon
|
||||
des nuages accroch<63>es aux flancs d'une montagne
|
||||
des nu<6E>es dans le ciel nocturne
|
||||
des plumes duveteuses accroch<63>es dans les foug<75>res
|
||||
des roches sculpt<70>es par l'<27>rosion
|
||||
des signes comme grav<61>s <20> m<>me la pierre <20>voquant la langue des Dragons
|
||||
des silhouettes impr<70>cises dans la brume
|
||||
des sons de fl<66>tes provenant du sous bois
|
||||
des traces de fossiles dans une roche
|
||||
des uages noirs qui moutonnent juste avant la pluie
|
||||
des veinures aux reflets m<>talliques dans la roche
|
||||
des voiles d'aurores bor<6F>ales tombant dans le ciel nocturne
|
||||
des <20>clairs z<>brant le ciel <20> l'horizon
|
||||
l'entrelacs des branches d'un arbre mill<6C>naire
|
||||
l'<27>coulement d'une chute l'eau
|
||||
l'<27>cume sur les vagues sal<61>es
|
||||
la brillance d'<27>toiles align<67>es
|
||||
la coloration verte des flammes
|
||||
la course hypnotique des balles d'un jongleur
|
||||
la formation de givre sur une <20>tendue d'eau
|
||||
la lueur du cr<63>puscule sur les cimes <20> l'horizon
|
||||
la lune rouge sang
|
||||
la ros<6F>e dans une toile d'araign<67>e
|
||||
la teinte rouge de la lune <20> travers les nuages
|
||||
le faisceau d'ondes caus<75> par un insecte aquatique
|
||||
le mouvement de grains de sable pouss<73>s par le vent
|
||||
le mouvement de vagues battant le rivage
|
||||
le mouvement r<>gulier des pales d'un moulin <20> vent
|
||||
le rythme de l'eau qui emporte les aubes d'un moulin
|
||||
le soleil masqu<71> par un passage de nuages
|
||||
le tableau abstrait de t<>ches sur le sol
|
||||
les cicatrices et boutons du visage d'un malade
|
||||
les colorations violac<61>es et oranges du ciel matinal
|
||||
les figures de la rouille sur un vieux casque
|
||||
les filaments d'une fleur carnivore enla<6C>ant un insecte
|
||||
les rayons du soleil couchant
|
||||
les reflets d'eau <20> travers les plantes aquatiques
|
||||
les remous cascadant d<>un torrent tels un liquide en <20>bullition dans une marmite de gigant
|
||||
les restes d'un mur antique
|
||||
les vagues du vent dans les herbes hautes
|
||||
un arbre mort fendu par la foudre
|
||||
un arc-en-ciel double
|
||||
un arc-en-ciel tr<74>s lumineux
|
||||
un cadavre d'animal inconnu
|
||||
un dragon de nuages prenant son envol
|
||||
un empilement de pierres
|
||||
un enfant sautant dans les flaques d'eau
|
||||
un fant<6E>me de poussi<73>re <20>tincellant au soleil
|
||||
un geyser projetant eau et vapeur <20> la face des Dragons
|
||||
un manche d'outil poli par l'usure
|
||||
un moustique gorg<72> de sang
|
||||
un nid d'oiseau inconnu
|
||||
un nuage d'insectes assombrissant le ciel
|
||||
un panache de fum<75>e volcaniques s'<27>levant <20> l'horizon
|
||||
un parterre de fleurs
|
||||
un prairie brumeuse
|
||||
un rideau de pluie <20>clair<69> d'un rai de lumi<6D>re diffus
|
||||
un tourbillon dans l'eau
|
||||
un tourbillon de poussi<73>re
|
||||
un vol d'oiseaux migrateurs align<67>s tra<72>ant des lettres dans le ciel
|
||||
une braise attis<69>e par le vent
|
||||
une coloration bleut<75>e de la lune
|
||||
une concr<63>tion rocheuse <20>voquant une cascade fig<69>e
|
||||
une fine couche de terre craquel<65>e par le soleil
|
||||
une forme animale <20>voqu<71>e par les courbes d'une <20>corce
|
||||
une gerbe d'<27>tincelles <20>chappant du feu
|
||||
une mante religieuse d<>vorrant son male
|
||||
une mue de l<>zard
|
||||
une nu<6E>e chaotique d'oiseaux tourbillonnant dans le vent
|
||||
une ond<6E>e illumin<69>e tombant tel un voile
|
||||
une phosphorescence dans l'eau
|
||||
une tornade dans le lointain
|
||||
une <20>toile filante
|
||||
une <20>trange disposition d'ossements sur le sol
|