forked from public/foundryvtt-reve-de-dragon
Compare commits
205 Commits
foundryvtt
...
10.0.28
Author | SHA1 | Date | |
---|---|---|---|
d795968519 | |||
37e5b3c0aa | |||
e1aecb05c3 | |||
168127d8fe | |||
21ec043e98 | |||
00b3b7f9b3 | |||
d1be242791 | |||
fa75828bc1 | |||
232f414a62 | |||
14e76ac631 | |||
43763dbe3a | |||
81ae15a6a2 | |||
6dc7272ef6 | |||
d75eef1926 | |||
18039e905b | |||
6d0e5321a2 | |||
3073670afa | |||
690dd1f0a2 | |||
0dcce5456b | |||
35f1f2437c | |||
3e17dd9b7e | |||
4f8406360f | |||
d316bba8fa | |||
9621d72f92 | |||
5382fb5df3 | |||
fd6fbba9cb | |||
3739204b42 | |||
7e2a867bdd | |||
e983715ad2 | |||
d8d5a20904 | |||
5410dd6ec0 | |||
4443548b0e | |||
3c86e1b97c | |||
5cde57e07c | |||
970c8b0244 | |||
ade977ed68 | |||
f83d51b72d | |||
34f2e33d6d | |||
0a5c5c5486 | |||
6becca6672 | |||
b2d4dc5d00 | |||
22091ef431 | |||
efdc676776 | |||
d25c6b7f1c | |||
0cc6b1de98 | |||
c41b59b703 | |||
b4ca941065 | |||
322506250b | |||
5d36ea9e0c | |||
dc0fab2957 | |||
2e158f9d39 | |||
7e1bbcada0 | |||
02ccb1f287 | |||
4afa313ffc | |||
1b8ad316b9 | |||
b35eaad757 | |||
e325ab9278 | |||
ebe19959fa | |||
5a2bc69fbb | |||
57dfdf0b65 | |||
028e8b883f | |||
4bab69b88f | |||
be0c0fbf3a | |||
cd4bf203e6 | |||
fc5674a7d8 | |||
fe80881405 | |||
3a29c25b09 | |||
e2ff813226 | |||
b67f230212 | |||
47f9e1adaa | |||
33808b8cf0 | |||
0d67d9af88 | |||
45a562f502 | |||
21fc62b302 | |||
c37c68e6db | |||
ca893088d2 | |||
e69fb222c3 | |||
c76bf912d1 | |||
4b1573ab8b | |||
e0049cc2f7 | |||
8e0949442d | |||
28427bc7c7 | |||
50980d5216 | |||
a75ee8fbc6 | |||
78c757a21a | |||
6d06c96497 | |||
5402508b26 | |||
43d097581e | |||
7785851719 | |||
8f127bc66b | |||
8c5f6b8f1b | |||
00630849cb | |||
c4392f0320 | |||
7a92ee85ef | |||
56ea9dd2e4 | |||
ee42902b5c | |||
838d4381a4 | |||
2232224951 | |||
1251d04860 | |||
63c6d5ff0f | |||
c0d37e42ca | |||
c8c13d626c | |||
e1ca7ab738 | |||
8f1ee315ef | |||
5daf15901a | |||
bddaecbc74 | |||
87fdd655d4 | |||
9cbb12e900 | |||
509b7f97dc | |||
5cd9fb3a1c | |||
336767c19e | |||
5a32cf26dc | |||
67b0555b11 | |||
59613c3bf8 | |||
e257b6fbee | |||
ea990d7c4e | |||
6271c75508 | |||
cd7cc8eeef | |||
bb3bc0ea77 | |||
f348f3dc3f | |||
dbf9f5e908 | |||
e4da124579 | |||
6e361a5531 | |||
049b23c666 | |||
3ff59d1f07 | |||
cfe8bee1c2 | |||
d4f0cce62b | |||
8c0fbf15b6 | |||
d4fddf8600 | |||
4b1862fa48 | |||
82115ed8d7 | |||
59b4f62145 | |||
3359492f13 | |||
676e6739a6 | |||
872d3fff31 | |||
5f3361ecc6 | |||
9c71827baa | |||
fc9ef06e7b | |||
9e63706de6 | |||
3958b1bdc2 | |||
6d6843223b | |||
46f5cb67f6 | |||
d51243d74f | |||
34cc671f12 | |||
16ce6a58dd | |||
c80cde6d18 | |||
89910e234d | |||
f30df47d22 | |||
c3c42bdb21 | |||
14eb655382 | |||
52e4375972 | |||
15e4bfb713 | |||
8c2d49652c | |||
ed02972a34 | |||
7d32a70e00 | |||
8aece9cad1 | |||
ffd36a045e | |||
bafc52a151 | |||
940baad04c | |||
0d288c56d4 | |||
70c26ebfe0 | |||
782c6a8fe2 | |||
b417fdfe32 | |||
09c4e691c7 | |||
3774fef20c | |||
9bc4260ae1 | |||
11274c51d6 | |||
6377964d07 | |||
8cf43d4e8a | |||
5efb7d9be0 | |||
f54804c071 | |||
59ece09357 | |||
5868bf16e0 | |||
6873cf0d41 | |||
255c0a77b4 | |||
698ff79d41 | |||
dffe191d6e | |||
1f3fd0bb46 | |||
0228d5bc56 | |||
6b48839841 | |||
451ee677d2 | |||
2c73f5aa11 | |||
035da98aaa | |||
2885ca1c8f | |||
218c88a924 | |||
e22b6c52f1 | |||
9b8f694dda | |||
75562b0af8 | |||
3a684c3c54 | |||
70354abacb | |||
bdead49d01 | |||
60b6da5cd3 | |||
66218be14a | |||
9aad57c00c | |||
395e4d4b73 | |||
25de00d2a9 | |||
0805d1df66 | |||
e2de9bb645 | |||
5d2db17c03 | |||
a3fb328b7d | |||
4538439c02 | |||
d83fd27193 | |||
580fdb996b | |||
5214b036d3 | |||
f64928858c |
@ -41,7 +41,8 @@
|
||||
"TypeOmbre": "Ombre de Thanatos",
|
||||
"TypeSouffle": "Souffle de Dragon",
|
||||
"TypeTete": "Tête de Dragon",
|
||||
"TypePossession": "Possession"
|
||||
"TypePossession": "Possession",
|
||||
"TypeSortreserve": "Sort en réserve"
|
||||
},
|
||||
"EFFECT": {
|
||||
"StatusStunned": "Sonné",
|
||||
|
@ -4,7 +4,6 @@
|
||||
* @extends {ActorSheet}
|
||||
*/
|
||||
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { RdDActorSheet } from "./actor-sheet.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
@ -24,34 +23,11 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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(),
|
||||
surEncombrementMessage: this.actor.getMessageSurEncombrement()
|
||||
}
|
||||
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||
|
||||
console.log("Creature : ", this.objetVersConteneur, formData);
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
|
@ -1,14 +1,8 @@
|
||||
/**
|
||||
* Extend the basic ActorSheet with some very simple modifications
|
||||
* @extends {ActorSheet}
|
||||
*/
|
||||
|
||||
import { RdDActorSheet } from "./actor-sheet.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDActorEntiteSheet extends ActorSheet {
|
||||
export class RdDActorEntiteSheet extends RdDActorSheet {
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
@ -22,72 +16,14 @@ export class RdDActorEntiteSheet extends ActorSheet {
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_checkNull(items) {
|
||||
if (items && items.length) {
|
||||
return items;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
const objectData = Misc.data(this.object);
|
||||
let formData = {
|
||||
title: this.title,
|
||||
id: objectData.id,
|
||||
type: objectData.type,
|
||||
img: objectData.img,
|
||||
name: objectData.name,
|
||||
// actor: this.object,
|
||||
editable: this.isEditable,
|
||||
cssClass: this.isEditable ? "editable" : "locked",
|
||||
data: foundry.utils.deepClone(Misc.templateData(this.object)),
|
||||
effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)),
|
||||
// items: items,
|
||||
limited: this.object.limited,
|
||||
options: this.options,
|
||||
owner: this.document.isOwner,
|
||||
itemsByType: Misc.classify(this.object.items.map(i => foundry.utils.deepClone(i.data))),
|
||||
};
|
||||
|
||||
formData.options.isGM = game.user.isGM;
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(event => {
|
||||
const li = $(event.currentTarget).parents(".item");
|
||||
const item = this.actor.getEmbeddedDocument('Item', li.data("itemId"));
|
||||
item.sheet.render(true);
|
||||
});
|
||||
|
||||
// Delete Inventory Item
|
||||
html.find('.item-delete').click(event => {
|
||||
const li = $(event.currentTarget).parents(".item");
|
||||
this.actor.deleteEmbeddedDocuments('Item', [li.data("itemId")]);
|
||||
li.slideUp(200, () => this.render(false));
|
||||
});
|
||||
|
||||
// Roll Carac
|
||||
html.find('.carac-label a').click(async event => {
|
||||
let caracName = event.currentTarget.attributes.name.value;
|
||||
this.actor.rollCarac( caracName.toLowerCase() );
|
||||
});
|
||||
|
||||
// On competence change
|
||||
html.find('.creature-carac').change(async event => {
|
||||
let compName = event.currentTarget.attributes.compname.value;
|
||||
@ -101,53 +37,6 @@ export class RdDActorEntiteSheet extends ActorSheet {
|
||||
let compName = event.currentTarget.attributes.compname.value;
|
||||
this.actor.updateCreatureCompetence( compName, "dommages", parseInt(event.target.value) );
|
||||
} );
|
||||
|
||||
// Roll Skill
|
||||
html.find('.competence-label a').click(async event => {
|
||||
let compName = event.currentTarget.text;
|
||||
this.actor.rollCompetence( compName );
|
||||
});
|
||||
|
||||
html.find('.endurance-plus').click(event => {
|
||||
this.actor.santeIncDec("endurance", 1);
|
||||
this.render(true);
|
||||
});
|
||||
html.find('.endurance-moins').click(event => {
|
||||
this.actor.santeIncDec("endurance", -1);
|
||||
this.render(true);
|
||||
});
|
||||
|
||||
html.find('.encaisser-direct').click(event => {
|
||||
this.actor.encaisser();
|
||||
});
|
||||
|
||||
html.find('.remise-a-neuf').click(event => {
|
||||
if (game.user.isGM) {
|
||||
this.actor.remiseANeuf();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
setPosition(options = {}) {
|
||||
const position = super.setPosition(options);
|
||||
const sheetHeader = this.element.find(".sheet-header");
|
||||
const sheetTabs = this.element.find(".sheet-tabs");
|
||||
const sheetBody = this.element.find(".sheet-body");
|
||||
const bodyHeight = position.height - sheetHeader[0].clientHeight - sheetTabs[0].clientHeight;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
// Update the Actor
|
||||
return this.object.update(formData);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import { DialogSplitItem } from "./dialog-split-item.js";
|
||||
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
import { DialogRepos } from "./dialog-repos.js";
|
||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||
import { STATUSES } from "./status-effects.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDActorSheet extends ActorSheet {
|
||||
@ -28,7 +29,6 @@ export class RdDActorSheet extends ActorSheet {
|
||||
width: 640,
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
||||
editCaracComp: false,
|
||||
showCompNiveauBase: false,
|
||||
vueDetaillee: false
|
||||
});
|
||||
@ -36,91 +36,85 @@ export class RdDActorSheet extends ActorSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
const objectData = Misc.data(this.object);
|
||||
|
||||
//this.actor.checkMonnaiePresence(this.actor.data.items); // Always check
|
||||
this.timerRecherche = undefined;
|
||||
|
||||
let formData = {
|
||||
title: this.title,
|
||||
id: objectData.id,
|
||||
type: objectData.type,
|
||||
img: objectData.img,
|
||||
name: objectData.name,
|
||||
id: this.actor.id,
|
||||
type: this.actor.type,
|
||||
img: this.actor.img,
|
||||
name: this.actor.name,
|
||||
editable: this.isEditable,
|
||||
cssClass: this.isEditable ? "editable" : "locked",
|
||||
data: foundry.utils.deepClone(Misc.templateData(this.object)),
|
||||
effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)),
|
||||
limited: this.object.limited,
|
||||
system: foundry.utils.deepClone(this.actor.system),
|
||||
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
|
||||
limited: this.actor.limited,
|
||||
options: this.options,
|
||||
owner: this.document.isOwner,
|
||||
itemsByType: Misc.classify(this.object.items.map(i => foundry.utils.deepClone(i.data))),
|
||||
};
|
||||
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||
|
||||
formData.options.isGM = game.user.isGM;
|
||||
|
||||
if (formData.type == 'creature') return formData; // Shortcut
|
||||
|
||||
formData.competenceByCategory = Misc.classify(formData.competences, it => it.data.categorie);
|
||||
|
||||
formData.calc = {
|
||||
comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.competences),
|
||||
competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.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: this.actor.computePrixTotalEquipement(),
|
||||
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
|
||||
fatigue: RdDUtility.calculFatigueHtml(formData.data.sante.fatigue.value, formData.data.sante.endurance.max),
|
||||
resumeBlessures: this.actor.computeResumeBlessure(formData.data.blessures),
|
||||
surEncombrementMessage: this.actor.getMessageSurEncombrement()
|
||||
};
|
||||
|
||||
formData.competences.forEach(item => {
|
||||
item.visible = this.options.cherchercompetence
|
||||
? RdDItemCompetence.nomContientTexte(item, this.options.cherchercompetence)
|
||||
: (!this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item));
|
||||
RdDItemCompetence.levelUp(item, formData.data.compteurs.experience.value);
|
||||
});
|
||||
|
||||
Object.values(formData.data.carac).forEach(c => {
|
||||
RdDCarac.levelUp(c);
|
||||
});
|
||||
|
||||
|
||||
// toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
|
||||
formData.combat = duplicate(formData.armes ?? []);
|
||||
RdDItemArme.computeNiveauArmes(formData.combat, formData.competences);
|
||||
RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.data.carac);
|
||||
formData.esquives = this.actor.getCompetences("Esquive").map(i => foundry.utils.deepClone(i.data));
|
||||
formData.combat = RdDCombatManager.finalizeArmeList(formData.combat, formData.competences, formData.data.carac);
|
||||
|
||||
this.armesList = formData.combat;
|
||||
|
||||
// Common data
|
||||
formData.ajustementsConditions = CONFIG.RDD.ajustementsConditions;
|
||||
formData.difficultesLibres = CONFIG.RDD.difficultesLibres;
|
||||
|
||||
formData.hautreve = {
|
||||
isDemiReve: this.actor.getEffectByLabel("Demi-rêve"),
|
||||
sortsReserve: formData.data.reve.reserve.list,
|
||||
rencontres: duplicate(formData.data.reve.rencontre.list),
|
||||
casesTmr: formData.itemsByType.casetmr,
|
||||
cacheTMR: this.actor.isTMRCache()
|
||||
owner: this.actor.isOwner,
|
||||
description: await TextEditor.enrichHTML(this.object.system.description, {async: true}),
|
||||
biographie: await TextEditor.enrichHTML(this.object.system.biographie, {async: true}),
|
||||
notes: await TextEditor.enrichHTML(this.object.system.notes, {async: true}),
|
||||
notesmj: await TextEditor.enrichHTML(this.object.system.notesmj, {async: true}),
|
||||
calc: {
|
||||
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
||||
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
||||
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
|
||||
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
|
||||
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
|
||||
surEncombrementMessage: this.actor.getMessageSurEncombrement(),
|
||||
},
|
||||
}
|
||||
formData.options.isGM = game.user.isGM;
|
||||
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||
|
||||
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`);
|
||||
if (formData.type == 'personnage') {
|
||||
formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie)
|
||||
formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences);
|
||||
formData.calc.competenceXPTotal= RdDItemCompetence.computeTotalXP(formData.competences);
|
||||
formData.calc.fatigue= RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max);
|
||||
|
||||
formData.competences.forEach(item => {
|
||||
item.system.isVisible = this.options.recherche
|
||||
? RdDItemCompetence.nomContientTexte(item, this.options.recherche.text)
|
||||
: (!this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item));
|
||||
RdDItemCompetence.levelUp(item, formData.system.compteurs.experience.value);
|
||||
});
|
||||
|
||||
Object.values(formData.system.carac).forEach(c => {
|
||||
RdDCarac.levelUp(c);
|
||||
});
|
||||
|
||||
// toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
|
||||
formData.combat = duplicate(formData.armes ?? []);
|
||||
RdDItemArme.computeNiveauArmes(formData.combat, formData.competences);
|
||||
RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.system.carac);
|
||||
formData.esquives = this.actor.getCompetences("Esquive");
|
||||
formData.combat = RdDCombatManager.listActionsArmes(formData.combat, formData.competences, formData.system.carac);
|
||||
|
||||
this.armesList = formData.combat;
|
||||
|
||||
// Common data
|
||||
formData.ajustementsConditions = CONFIG.RDD.ajustementsConditions;
|
||||
formData.difficultesLibres = CONFIG.RDD.difficultesLibres;
|
||||
|
||||
formData.hautreve = {
|
||||
isDemiReve: this.actor.getEffect(STATUSES.StatusDemiReve),
|
||||
rencontres: duplicate(formData.system.reve.rencontre.list),
|
||||
cacheTMR: this.actor.isTMRCache()
|
||||
}
|
||||
|
||||
formData.subacteurs = {
|
||||
vehicules: this.actor.listeVehicules(),
|
||||
montures: this.actor.listeMontures(),
|
||||
suivants: this.actor.listeSuivants()
|
||||
}
|
||||
if (this.actor.getBestDraconic().system.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;
|
||||
}
|
||||
@ -131,16 +125,16 @@ export class RdDActorSheet extends ActorSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _onDropActor(event, dragData) {
|
||||
console.log("_onDropActor", this.actor.id, dragData);
|
||||
this.actor.addSubActeur(dragData.id || dragData.data._id);
|
||||
const dropActor = fromUuidSync(dragData.uuid);
|
||||
this.actor.addSubActeur(dropActor);
|
||||
super._onDropActor(event, dragData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _onDropItem(event, dragData) {
|
||||
const destItemId = $(event.target)?.closest('.item').attr('data-item-id');
|
||||
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor.id, dragData, this.objetVersConteneur);
|
||||
const callSuper = await this.actor.processDropItem(dropParams);
|
||||
const destItemId = $(event.target)?.closest('.item').attr('data-item-id')
|
||||
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor.id, dragData, this.objetVersConteneur)
|
||||
const callSuper = await this.actor.processDropItem(dropParams)
|
||||
if (callSuper) {
|
||||
await super._onDropItem(event, dragData)
|
||||
}
|
||||
@ -160,7 +154,6 @@ export class RdDActorSheet extends ActorSheet {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
|
||||
HtmlUtility._showControlWhen($(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
@ -172,7 +165,6 @@ export class RdDActorSheet extends ActorSheet {
|
||||
});
|
||||
html.find('.item-edit').click(async event => {
|
||||
const item = RdDSheetUtility.getItem(event, this.actor)
|
||||
console.log("ITEM :", item)
|
||||
item.sheet.render(true)
|
||||
})
|
||||
html.find('.display-label a').click(async event => {
|
||||
@ -184,7 +176,8 @@ export class RdDActorSheet extends ActorSheet {
|
||||
});
|
||||
html.find('.item-delete').click(async event => {
|
||||
const li = RdDSheetUtility.getEventElement(event);
|
||||
RdDUtility.confirmerSuppression(this, li);
|
||||
const item = this.actor.getObjet(li.data("item-id"));
|
||||
RdDUtility.confirmerSuppressionItem(this, item, li);
|
||||
});
|
||||
html.find('.item-vendre').click(async event => {
|
||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||
@ -194,16 +187,28 @@ export class RdDActorSheet extends ActorSheet {
|
||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||
item?.postItem();
|
||||
});
|
||||
|
||||
html.find('.item-action').click(async event => {
|
||||
const item = RdDSheetUtility.getItem(event, this.actor)
|
||||
this.actor.actionItem(item);
|
||||
});
|
||||
html.find('.subacteur-delete').click(async event => {
|
||||
const li = RdDSheetUtility.getEventElement(event);
|
||||
RdDUtility.confirmerSuppressionSubacteur(this, li);
|
||||
const actorId = li.data("actor-id");
|
||||
if (actorId) {
|
||||
const subActor = game.actors.get(actorId);
|
||||
RdDUtility.confirmerSuppressionSubacteur(this, subActor, li);
|
||||
}
|
||||
});
|
||||
html.find('.experiencelog-delete').click(async event => {
|
||||
const li = $(event.currentTarget)?.parents(".experiencelog");
|
||||
const key = Number(li.data("key") ?? -1);
|
||||
await this.actor.deleteExperienceLog(key, 1);
|
||||
});
|
||||
html.find('.experiencelog-delete-previous').click(async event => {
|
||||
const li = $(event.currentTarget)?.parents(".experiencelog");
|
||||
const key = Number(li.data("key") ?? -1);
|
||||
await this.actor.deleteExperienceLog(0, key + 1);
|
||||
});
|
||||
|
||||
html.find('.encaisser-direct').click(async event => {
|
||||
this.actor.encaisser();
|
||||
})
|
||||
@ -225,7 +230,7 @@ export class RdDActorSheet extends ActorSheet {
|
||||
html.find('.creer-une-oeuvre').click(async event => {
|
||||
RdDUtility.selectTypeOeuvre(this);
|
||||
});
|
||||
html.find('#nettoyer-conteneurs').click(async event => {
|
||||
html.find('.nettoyer-conteneurs').click(async event => {
|
||||
this.actor.nettoyerConteneurs();
|
||||
});
|
||||
|
||||
@ -240,7 +245,7 @@ export class RdDActorSheet extends ActorSheet {
|
||||
});
|
||||
|
||||
// Blessure data
|
||||
html.find('.blessures-soins').change(async event => {
|
||||
html.find('.blessure-soins').change(async event => {
|
||||
const tr = $(event.currentTarget).parents(".item");
|
||||
let btype = tr.data('blessure-type');
|
||||
let index = tr.data('blessure-index');
|
||||
@ -315,10 +320,10 @@ export class RdDActorSheet extends ActorSheet {
|
||||
|
||||
// Boutons spéciaux MJs
|
||||
html.find('.forcer-tmr-aleatoire').click(async event => {
|
||||
this.actor.cacheTMRetMessage();
|
||||
this.actor.reinsertionAleatoire("Action MJ");
|
||||
});
|
||||
html.find('.afficher-tmr').click(async event => {
|
||||
this.actor.afficheTMRetMessage();
|
||||
this.actor.changeTMRVisible();
|
||||
});
|
||||
|
||||
// Points de reve actuel
|
||||
@ -333,10 +338,10 @@ export class RdDActorSheet extends ActorSheet {
|
||||
});
|
||||
// Initiative pour l'arme
|
||||
html.find('.arme-initiative a').click(async event => {
|
||||
let combatant = game.combat.data.combatants.find(c => c.actor.data._id == this.actor.data._id);
|
||||
let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id);
|
||||
if (combatant) {
|
||||
let arme = this._getEventArmeCombat(event);
|
||||
RdDCombatManager.rollInitiativeCompetence(combatant._id, arme);
|
||||
let action = this._getEventArmeCombat(event);
|
||||
RdDCombatManager.rollInitiativeAction(combatant._id, action);
|
||||
} else {
|
||||
ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat.");
|
||||
}
|
||||
@ -360,11 +365,15 @@ export class RdDActorSheet extends ActorSheet {
|
||||
await DialogRepos.create(this.actor);
|
||||
});
|
||||
html.find('.delete-active-effect').click(async event => {
|
||||
let id = $(event.currentTarget).parents(".active-effect").data('id');
|
||||
this.actor.enleverActiveEffectById(id);
|
||||
if (game.user.isGM) {
|
||||
let effect = $(event.currentTarget).parents(".active-effect").data('effect');
|
||||
this.actor.removeEffect(effect);
|
||||
}
|
||||
});
|
||||
html.find('.enlever-tous-effets').click(async event => {
|
||||
this.actor.enleverTousLesEffets();
|
||||
if (game.user.isGM) {
|
||||
await this.actor.removeEffects();
|
||||
}
|
||||
});
|
||||
html.find('.conteneur-name a').click(async event => {
|
||||
RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event));
|
||||
@ -381,16 +390,14 @@ export class RdDActorSheet extends ActorSheet {
|
||||
this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event));
|
||||
});
|
||||
|
||||
if (this.options.editCaracComp) {
|
||||
if (this.options.vueDetaillee) {
|
||||
// On carac change
|
||||
html.find('.carac-value').change(async event => {
|
||||
let caracName = event.currentTarget.name.replace(".value", "").replace("data.carac.", "");
|
||||
//console.log("Value changed :", event, caracName);
|
||||
let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", "");
|
||||
this.actor.updateCarac(caracName, parseInt(event.target.value));
|
||||
});
|
||||
html.find('.carac-xp').change(async event => {
|
||||
let caracName = event.currentTarget.name.replace(".xp", "").replace("data.carac.", "");
|
||||
//console.log("Value changed :", event, caracName);
|
||||
html.find('input.carac-xp').change(async event => {
|
||||
let caracName = event.currentTarget.name.replace(".xp", "").replace("system.carac.", "");
|
||||
this.actor.updateCaracXP(caracName, parseInt(event.target.value));
|
||||
});
|
||||
// On competence change
|
||||
@ -400,12 +407,12 @@ export class RdDActorSheet extends ActorSheet {
|
||||
this.actor.updateCompetence(compName, parseInt(event.target.value));
|
||||
});
|
||||
// On competence xp change
|
||||
html.find('.competence-xp').change(async event => {
|
||||
html.find('input.competence-xp').change(async event => {
|
||||
let compName = event.currentTarget.attributes.compname.value;
|
||||
this.actor.updateCompetenceXP(compName, parseInt(event.target.value));
|
||||
});
|
||||
// On competence xp change
|
||||
html.find('.competence-xp-sort').change(async event => {
|
||||
html.find('input.competence-xp-sort').change(async event => {
|
||||
let compName = event.currentTarget.attributes.compname.value;
|
||||
this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value));
|
||||
});
|
||||
@ -420,16 +427,31 @@ export class RdDActorSheet extends ActorSheet {
|
||||
this.options.showCompNiveauBase = !this.options.showCompNiveauBase;
|
||||
this.render(true);
|
||||
});
|
||||
html.find('.lock-unlock-sheet').click(async event => {
|
||||
this.options.editCaracComp = !this.options.editCaracComp;
|
||||
this.render(true);
|
||||
});
|
||||
html.find('.cherchercompetence').change(async event => {
|
||||
this.options.cherchercompetence = event.currentTarget.value;
|
||||
this.render(true);
|
||||
});
|
||||
|
||||
html.find('.recherche')
|
||||
.each((index, field) => {
|
||||
if (this.options.recherche) {
|
||||
field.focus();
|
||||
field.setSelectionRange(this.options.recherche.start, this.options.recherche.end);
|
||||
}
|
||||
})
|
||||
.keyup(async event => {
|
||||
const nouvelleRecherche = this._optionRecherche(event.currentTarget);
|
||||
if (this.options.recherche?.text != nouvelleRecherche?.text){
|
||||
this.options.recherche = nouvelleRecherche;
|
||||
if (this.timerRecherche) {
|
||||
clearTimeout(this.timerRecherche);
|
||||
}
|
||||
this.timerRecherche = setTimeout(() => {
|
||||
this.timerRecherche = undefined;
|
||||
this.render(true);
|
||||
}, 500);
|
||||
}
|
||||
})
|
||||
.change(async event =>
|
||||
this.options.recherche = this._optionRecherche(event.currentTarget)
|
||||
);
|
||||
html.find('.vue-detaillee').click(async event => {
|
||||
console.log("CONTROLS", this.options.vueDetaillee)
|
||||
this.options.vueDetaillee = !this.options.vueDetaillee;
|
||||
this.render(true);
|
||||
});
|
||||
@ -437,7 +459,7 @@ export class RdDActorSheet extends ActorSheet {
|
||||
// On pts de reve change
|
||||
html.find('.pointsreve-value').change(async event => {
|
||||
let reveValue = event.currentTarget.value;
|
||||
this.actor.update({ "data.reve.reve.value": reveValue });
|
||||
this.actor.update({ "system.reve.reve.value": reveValue });
|
||||
});
|
||||
|
||||
// On seuil de reve change
|
||||
@ -471,7 +493,7 @@ export class RdDActorSheet extends ActorSheet {
|
||||
html.find('.moral-heureux').click(async event => {
|
||||
this.actor.jetDeMoral('heureuse');
|
||||
});
|
||||
html.find('#ethylisme-test').click(async event => {
|
||||
html.find('.ethylisme-test').click(async event => {
|
||||
this.actor.jetEthylisme();
|
||||
});
|
||||
|
||||
@ -515,13 +537,24 @@ export class RdDActorSheet extends ActorSheet {
|
||||
});
|
||||
}
|
||||
|
||||
_optionRecherche(target) {
|
||||
if (!target.value?.length){
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
text: target.value,
|
||||
start: target.selectionStart,
|
||||
end: target.selectionEnd,
|
||||
};
|
||||
}
|
||||
|
||||
_getEventArmeCombat(event) {
|
||||
const li = $(event.currentTarget)?.parents(".item");
|
||||
let armeName = li.data("arme-name");
|
||||
let compName = li.data('competence-name');
|
||||
const arme = this.armesList.find(a => a.name == armeName && a.data.competence == compName);
|
||||
const arme = this.armesList.find(a => a.name == armeName && a.system.competence == compName);
|
||||
if (!arme) {
|
||||
return { name: armeName, data: { competence: compName } };
|
||||
return { name: armeName, system: { competence: compName } };
|
||||
}
|
||||
return arme;
|
||||
}
|
||||
@ -533,7 +566,10 @@ export class RdDActorSheet extends ActorSheet {
|
||||
const sheetHeader = this.element.find(".sheet-header");
|
||||
const sheetTabs = this.element.find(".sheet-tabs");
|
||||
const sheetBody = this.element.find(".sheet-body");
|
||||
const bodyHeight = position.height - sheetHeader[0].clientHeight - sheetTabs[0].clientHeight;
|
||||
let bodyHeight = position.height - sheetHeader[0].clientHeight;
|
||||
if (sheetTabs.length>0) {
|
||||
bodyHeight -= sheetTabs[0].clientHeight;
|
||||
}
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
}
|
||||
@ -543,7 +579,7 @@ export class RdDActorSheet extends ActorSheet {
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
// Update the Actor
|
||||
return this.object.update(formData);
|
||||
return this.actor.update(formData);
|
||||
}
|
||||
|
||||
async splitItem(item) {
|
||||
@ -552,11 +588,11 @@ export class RdDActorSheet extends ActorSheet {
|
||||
}
|
||||
|
||||
async _onSplitItem(item, split) {
|
||||
if (split >= 1 && split < Misc.data(item).data.quantite) {
|
||||
if (split >= 1 && split < item.system.quantite) {
|
||||
await item.diminuerQuantite(split);
|
||||
const itemData = duplicate(Misc.data(item));
|
||||
itemData.data.quantite = split;
|
||||
await this.actor.createEmbeddedDocuments('Item', [itemData])
|
||||
const splitItem = duplicate(item);
|
||||
splitItem.system.quantite = split;
|
||||
await this.actor.createEmbeddedDocuments('Item', [splitItem])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,15 +1,9 @@
|
||||
/**
|
||||
* Extend the basic ActorSheet with some very simple modifications
|
||||
* @extends {ActorSheet}
|
||||
*/
|
||||
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||
import { RdDActorSheet } from "./actor-sheet.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDActorVehiculeSheet extends ActorSheet {
|
||||
export class RdDActorVehiculeSheet extends RdDActorSheet {
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
@ -25,149 +19,5 @@ export class RdDActorVehiculeSheet extends ActorSheet {
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_checkNull(items) {
|
||||
if (items && items.length) {
|
||||
return items;
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
const objectData = Misc.data(this.object);
|
||||
let formData = {
|
||||
title: this.title,
|
||||
id: objectData.id,
|
||||
type: objectData.type,
|
||||
img: objectData.img,
|
||||
name: objectData.name,
|
||||
editable: this.isEditable,
|
||||
cssClass: this.isEditable ? "editable" : "locked",
|
||||
data: foundry.utils.deepClone(Misc.templateData(this.object)),
|
||||
effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)),
|
||||
limited: this.object.limited,
|
||||
options: this.options,
|
||||
owner: this.document.isOwner,
|
||||
itemsByType: Misc.classify(this.object.items.map(i => foundry.utils.deepClone(i.data))),
|
||||
};
|
||||
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||
|
||||
formData.options.isGM = game.user.isGM;
|
||||
|
||||
formData.calc = {
|
||||
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
||||
surEncombrementMessage: this.actor.getMessageSurEncombrement()
|
||||
}
|
||||
|
||||
console.log("DATA", formData);
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
async computeMalusArmure() {
|
||||
// pas de malus armure
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
async _onDropItem(event, dragData) {
|
||||
const destItemId = $(event.target)?.closest('.item').attr('data-item-id');
|
||||
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor.id, dragData, this.objetVersConteneur);
|
||||
const callSuper = await this.actor.processDropItem(dropParams);
|
||||
if (callSuper) {
|
||||
await super._onDropItem(event, dragData)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async createItem(name, type) {
|
||||
await this.actor.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async monnaieIncDec(id, value) {
|
||||
let monnaie = this.getMonnaie(id);
|
||||
if (monnaie) {
|
||||
const quantite = Math.max(0, Misc.templateData(monnaie).quantite + value);
|
||||
await this.updateEmbeddedDocuments('Item', [{ _id: monnaie.id, 'data.quantite': quantite }]);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(async event => {
|
||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||
item.sheet.render(true);
|
||||
});
|
||||
// Delete Inventory Item
|
||||
html.find('.item-delete').click(async event => {
|
||||
const li = RdDSheetUtility.getEventElement(event);
|
||||
RdDUtility.confirmerSuppression(this, li);
|
||||
});
|
||||
html.find('.item-vendre').click(async event => {
|
||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||
item?.proposerVente();
|
||||
});
|
||||
html.find('.item-montrer').click(async event => {
|
||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||
item?.postItem();
|
||||
});
|
||||
|
||||
html.find('.item-action').click(async event => {
|
||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||
this.actor.actionItem(item);
|
||||
});
|
||||
|
||||
html.find('.creer-un-objet').click(async event => {
|
||||
RdDUtility.selectObjetType(this);
|
||||
});
|
||||
html.find('#nettoyer-conteneurs').click(async event => {
|
||||
this.actor.nettoyerConteneurs();
|
||||
});
|
||||
|
||||
html.find('.monnaie-plus').click(async event => {
|
||||
this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), 1);
|
||||
});
|
||||
html.find('.monnaie-moins').click(async event => {
|
||||
this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), -1);
|
||||
});
|
||||
|
||||
// Display info about queue
|
||||
html.find('.conteneur-name a').click((event) => {
|
||||
RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event));
|
||||
this.render(true);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
setPosition(options = {}) {
|
||||
const position = super.setPosition(options);
|
||||
const sheetHeader = this.element.find(".sheet-header");
|
||||
const sheetTabs = this.element.find(".sheet-tabs");
|
||||
const sheetBody = this.element.find(".sheet-body");
|
||||
const bodyHeight = position.height - sheetHeader[0].clientHeight - sheetTabs[0].clientHeight;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
// Update the Actor
|
||||
return this.object.update(formData);
|
||||
}
|
||||
}
|
||||
|
1689
module/actor.js
1689
module/actor.js
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,6 @@
|
||||
import { Misc } from "./misc.js";
|
||||
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||
|
||||
export const MESSAGE_DATA = 'message-data';
|
||||
|
||||
/**
|
||||
* Class providing helper methods to get the list of users, and
|
||||
@ -19,61 +18,50 @@ export class ChatUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static notifyUser(userId, level = 'info', message) {
|
||||
const data = {
|
||||
const socketData = {
|
||||
userId: userId, level: level, message: message
|
||||
};
|
||||
if (game.user.id == userId) {
|
||||
ChatUtility.onNotifyUser(data);
|
||||
ChatUtility.onNotifyUser(socketData);
|
||||
}
|
||||
else {
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||
msg: "msg_user_ui_notifications", data: data
|
||||
msg: "msg_user_ui_notifications", data: socketData
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
static onNotifyUser(data) {
|
||||
if (game.user.id == data.userId) {
|
||||
switch (data.level) {
|
||||
case 'warn': ui.notifications.warn(data.message); break;
|
||||
case 'error': ui.notifications.error(data.message); break;
|
||||
default: ui.notifications.info(data.message); break;
|
||||
static onNotifyUser(socketData) {
|
||||
if (game.user.id == socketData.userId) {
|
||||
switch (socketData.level) {
|
||||
case 'warn': ui.notifications.warn(socketData.message); break;
|
||||
case 'error': ui.notifications.error(socketData.message); break;
|
||||
default: ui.notifications.info(socketData.message); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onRemoveMessages(data) {
|
||||
static onRemoveMessages(socketData) {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (data.part) {
|
||||
const toDelete = game.messages.filter(it => it.data.content.includes(data.part));
|
||||
if (socketData.part) {
|
||||
const toDelete = game.messages.filter(it => it.content.includes(socketData.part));
|
||||
toDelete.forEach(it => it.delete());
|
||||
}
|
||||
if (data.messageId) {
|
||||
game.messages.get(data.messageId)?.delete();
|
||||
if (socketData.messageId) {
|
||||
game.messages.get(socketData.messageId)?.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static onRemoveMessages(data) {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
if (data.part) {
|
||||
const toDelete = game.messages.filter(it => it.data.content.includes(data.part));
|
||||
toDelete.forEach(it => it.delete());
|
||||
}
|
||||
if (data.messageId) {
|
||||
game.messages.get(data.messageId)?.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
|
||||
static removeMessages(data) {
|
||||
static removeMessages(socketData) {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
ChatUtility.onRemoveMessages(data);
|
||||
ChatUtility.onRemoveMessages(socketData);
|
||||
}
|
||||
else {
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_delete_chat_message", data: data });
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_delete_chat_message", data: socketData });
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,7 +129,7 @@ export class ChatUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getUsers(filter) {
|
||||
return Misc.getUsers().filter(filter).map(user => user.data._id);
|
||||
return game.users.filter(filter).map(user => user.id);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -154,17 +142,17 @@ export class ChatUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static handleGMChatMessage(data) {
|
||||
console.log("blindMessageToGM", data);
|
||||
static handleGMChatMessage(socketData) {
|
||||
console.log("blindMessageToGM", socketData);
|
||||
if (game.user.isGM) { // message privé pour GM only
|
||||
data.user = game.user.id;
|
||||
ChatMessage.create(data);
|
||||
socketData.user = game.user.id;
|
||||
ChatMessage.create(socketData);
|
||||
}
|
||||
}
|
||||
|
||||
static async setMessageData(chatMessage, key, data) {
|
||||
if (data) {
|
||||
await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(data));
|
||||
static async setMessageData(chatMessage, key, flag) {
|
||||
if (flag) {
|
||||
await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(flag));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
export const SYSTEM_RDD = 'foundryvtt-reve-de-dragon';
|
||||
export const SYSTEM_SOCKET_ID = 'system.foundryvtt-reve-de-dragon';
|
||||
export const LOG_HEAD = 'RdD | ';
|
||||
|
||||
export const HIDE_DICE = 'hide';
|
||||
export const SHOW_DICE = 'show';
|
||||
|
||||
export const ENTITE_INCARNE = 'incarne';
|
||||
export const ENTITE_NONINCARNE = 'nonincarne';
|
||||
export const ENTITE_BLURETTE = 'blurette';
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
|
||||
export class DialogCreateSigneDraconique extends Dialog {
|
||||
@ -10,12 +9,13 @@ export class DialogCreateSigneDraconique extends Dialog {
|
||||
const signe = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
|
||||
let dialogData = {
|
||||
signe: signe,
|
||||
tmrs: TMRUtility.listSelectedTMR(signe.data.typesTMR ?? []),
|
||||
actors: game.actors.filter(actor => actor.isHautRevant()).map(actor => {
|
||||
let actorData = duplicate(Misc.data(actor));
|
||||
actorData.selected = actor.hasPlayerOwner;
|
||||
return actorData;
|
||||
})
|
||||
tmrs: TMRUtility.buildSelectionTypesTMR(signe.system.typesTMR),
|
||||
actors: game.actors.filter(actor => actor.isPersonnage() && actor.isHautRevant())
|
||||
.map(actor => ({
|
||||
id: actor.id,
|
||||
name: actor.name,
|
||||
selected: true
|
||||
}))
|
||||
};
|
||||
|
||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-create-signedraconique.html", dialogData);
|
||||
@ -23,12 +23,11 @@ export class DialogCreateSigneDraconique extends Dialog {
|
||||
.render(true);
|
||||
}
|
||||
|
||||
constructor(dialogData, html, callback) {
|
||||
constructor(dialogData, html) {
|
||||
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 500, height: 650, 'z-index': 99999 };
|
||||
let conf = {
|
||||
title: "Créer un signe",
|
||||
content: html,
|
||||
default: "Ajouter aux haut-rêvants",
|
||||
buttons: {
|
||||
"Ajouter aux haut-rêvants": { label: "Ajouter aux haut-rêvants", callback: it => { this._onCreerSigneActeurs(); } }
|
||||
}
|
||||
@ -38,81 +37,91 @@ export class DialogCreateSigneDraconique extends Dialog {
|
||||
}
|
||||
|
||||
async _onCreerSigneActeurs() {
|
||||
await $("[name='signe.data.ephemere']").change();
|
||||
await $("[name='signe.system.ephemere']").change();
|
||||
await $(".signe-xp-sort").change();
|
||||
this.validerSigne();
|
||||
this.dialogData.actors.filter(it => it.selected).map(it => game.actors.get(it._id))
|
||||
this.dialogData.actors.filter(it => it.selected)
|
||||
.map(it => game.actors.get(it.id))
|
||||
.forEach(actor => this._createSigneForActor(actor, this.dialogData.signe));
|
||||
}
|
||||
|
||||
async _createSigneForActor(actor, signe) {
|
||||
actor.createEmbeddedDocuments("Item", [signe]);
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(Misc.data(actor).name),
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(actor.name),
|
||||
content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html", {
|
||||
signe: signe,
|
||||
alias: Misc.data(actor).name
|
||||
alias: actor.name
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
validerSigne() {
|
||||
this.dialogData.signe.name = $("[name='signe.name']").val();
|
||||
this.dialogData.signe.data.valeur.norm = $("[name='signe.data.valeur.norm']").val();
|
||||
this.dialogData.signe.data.valeur.sign = $("[name='signe.data.valeur.sign']").val();
|
||||
this.dialogData.signe.data.valeur.part = $("[name='signe.data.valeur.part']").val();
|
||||
this.dialogData.signe.data.difficulte = $("[name='signe.data.difficulte']").val();
|
||||
this.dialogData.signe.data.ephemere = $("[name='signe.data.ephemere']").prop("checked");
|
||||
this.dialogData.signe.data.duree = $("[name='signe.data.duree']").val();
|
||||
this.dialogData.signe.data.typesTMR = $(".select-tmr").val();
|
||||
this.dialogData.signe.system.valeur.norm = $("[name='signe.system.valeur.norm']").val();
|
||||
this.dialogData.signe.system.valeur.sign = $("[name='signe.system.valeur.sign']").val();
|
||||
this.dialogData.signe.system.valeur.part = $("[name='signe.system.valeur.part']").val();
|
||||
this.dialogData.signe.system.difficulte = $("[name='signe.system.difficulte']").val();
|
||||
this.dialogData.signe.system.ephemere = $("[name='signe.system.ephemere']").prop("checked");
|
||||
this.dialogData.signe.system.duree = $("[name='signe.system.duree']").val();
|
||||
this.dialogData.signe.system.typesTMR = TMRUtility.buildListTypesTMRSelection(this.dialogData.tmrs);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
this.setEphemere(this.dialogData.signe.data.ephemere);
|
||||
this.setEphemere(this.dialogData.signe.system.ephemere);
|
||||
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
|
||||
html.find("[name='signe.data.ephemere']").change((event) => this.setEphemere(event.currentTarget.checked));
|
||||
html.find(".select-actor").change((event) => this.onSelectActor(event));
|
||||
html.find("[name='signe.system.ephemere']").change((event) => this.setEphemere(event.currentTarget.checked));
|
||||
html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event));
|
||||
html.find("input.select-actor").change((event) => this.onSelectActor(event));
|
||||
html.find("input.select-tmr").change((event) => this.onSelectTmr(event));
|
||||
}
|
||||
|
||||
async setSigneAleatoire() {
|
||||
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
|
||||
|
||||
$("[name='signe.name']").val(newSigne.name);
|
||||
$("[name='signe.data.valeur.norm']").val(newSigne.data.valeur.norm);
|
||||
$("[name='signe.data.valeur.sign']").val(newSigne.data.valeur.sign);
|
||||
$("[name='signe.data.valeur.part']").val(newSigne.data.valeur.part);
|
||||
$("[name='signe.data.difficulte']").val(newSigne.data.difficulte);
|
||||
$("[name='signe.data.duree']").val(newSigne.data.duree);
|
||||
$("[name='signe.data.ephemere']").prop("checked", newSigne.data.ephemere);
|
||||
$(".select-tmr").val(newSigne.data.typesTMR);
|
||||
this.setEphemere(newSigne.data.ephemere);
|
||||
$("[name='signe.system.valeur.norm']").val(newSigne.system.valeur.norm);
|
||||
$("[name='signe.system.valeur.sign']").val(newSigne.system.valeur.sign);
|
||||
$("[name='signe.system.valeur.part']").val(newSigne.system.valeur.part);
|
||||
$("[name='signe.system.difficulte']").val(newSigne.system.difficulte);
|
||||
$("[name='signe.system.duree']").val(newSigne.system.duree);
|
||||
$("[name='signe.system.ephemere']").prop("checked", newSigne.system.ephemere);
|
||||
this.dialogData.tmrs = TMRUtility.buildSelectionTypesTMR(newSigne.system.typesTMR);
|
||||
this.dialogData.tmrs.forEach(t => {
|
||||
$(`[data-tmr-name='${t.name}']`).prop( "checked", t.selected);
|
||||
})
|
||||
this.setEphemere(newSigne.system.ephemere);
|
||||
}
|
||||
|
||||
async setEphemere(ephemere) {
|
||||
this.dialogData.signe.data.ephemere = ephemere;
|
||||
HtmlUtility._showControlWhen($(".signe-data-duree"), ephemere);
|
||||
this.dialogData.signe.system.ephemere = ephemere;
|
||||
HtmlUtility._showControlWhen($(".signe-system-duree"), ephemere);
|
||||
}
|
||||
|
||||
async onSelectActor(event) {
|
||||
event.preventDefault();
|
||||
const options = event.currentTarget.options;
|
||||
for (var i = 0; i < options.length; i++) { // looping over the options
|
||||
const actorId = options[i].attributes["data-actor-id"].value;
|
||||
const actor = this.dialogData.actors.find(it => it._id == actorId);
|
||||
if (actor) {
|
||||
actor.selected = options[i].selected;
|
||||
}
|
||||
};
|
||||
const actorId = $(event.currentTarget)?.data("actor-id");
|
||||
const actor = this.dialogData.actors.find(it => it.id == actorId);
|
||||
if (actor) {
|
||||
actor.selected = event.currentTarget.checked;
|
||||
}
|
||||
}
|
||||
|
||||
onSelectTmr(event) {
|
||||
const tmrName = $(event.currentTarget)?.data("tmr-name");
|
||||
const onTmr = this.tmrs.find(it => it.name == tmrName);
|
||||
if (onTmr){
|
||||
onTmr.selected = event.currentTarget.checked;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
onValeurXpSort(event) {
|
||||
const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0;
|
||||
const xp = Number(event.currentTarget.value);
|
||||
const oldValeur = this.dialogData.signe.data.valeur;
|
||||
this.dialogData.signe.data.valeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
|
||||
const oldValeur = this.dialogData.signe.system.valeur;
|
||||
this.dialogData.signe.system.valeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
|
||||
}
|
||||
|
||||
}
|
@ -6,10 +6,15 @@ export class DialogFabriquerPotion extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async create(actor, item, dialogConfig) {
|
||||
const min = DialogFabriquerPotion.nombreBrinsMinimum(item);
|
||||
if (item.system.quantite < min) {
|
||||
ui.notifications.warn(`Vous avez ${item.system.quantite} brins de ${item.name}, il en faut au moins ${min} pour faire une potion!`);
|
||||
return;
|
||||
}
|
||||
let potionData = DialogFabriquerPotion.prepareData(actor, item);
|
||||
|
||||
let conf = {
|
||||
title: `Fabriquer une potion de ${potionData.data.categorie}`,
|
||||
title: `Fabriquer une potion de ${potionData.system.categorie}`,
|
||||
content: await renderTemplate(dialogConfig.html, potionData),
|
||||
default: potionData.buttonName,
|
||||
};
|
||||
@ -24,9 +29,12 @@ export class DialogFabriquerPotion extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static prepareData(actor, item) {
|
||||
let potionData = duplicate(Misc.data(item));
|
||||
potionData.nbBrinsSelect = RdDUtility.buildListOptions(1, potionData.data.quantite);
|
||||
potionData.nbBrins = Math.min(potionData.data.quantite, DialogFabriquerPotion.getNombreBrinOptimal(potionData));
|
||||
let potionData = duplicate(item)
|
||||
potionData.nbBrinsSelect = RdDUtility.buildListOptions(
|
||||
DialogFabriquerPotion.nombreBrinsMinimum(item),
|
||||
DialogFabriquerPotion.nombreBrinsOptimal(item));
|
||||
potionData.nbBrins = Math.min(potionData.system.quantite, DialogFabriquerPotion.nombreBrinsOptimal(potionData));
|
||||
potionData.herbebonus = item.system.niveau;
|
||||
potionData.buttonName = "Fabriquer";
|
||||
return potionData;
|
||||
}
|
||||
@ -45,10 +53,18 @@ export class DialogFabriquerPotion extends Dialog {
|
||||
this.potionData = potionData;
|
||||
}
|
||||
|
||||
static getNombreBrinOptimal(herbeData) {
|
||||
switch (herbeData.data.categorie ?? '') {
|
||||
case "Soin": return 12 - herbeData.data.niveau;
|
||||
case "Repos": return 7 - herbeData.data.niveau;
|
||||
static nombreBrinsMinimum(herbeData) {
|
||||
switch (herbeData.system.categorie ?? '') {
|
||||
case "Soin": return 1 + Math.max(0, 12 - 2 * herbeData.system.niveau);
|
||||
case "Repos": return 1 + Math.max(0, 7 - 2 * herbeData.system.niveau);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static nombreBrinsOptimal(herbeData) {
|
||||
switch (herbeData.system.categorie ?? '') {
|
||||
case "Soin": return 12 - herbeData.system.niveau;
|
||||
case "Repos": return 7 - herbeData.system.niveau;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@ -59,6 +75,8 @@ export class DialogFabriquerPotion extends Dialog {
|
||||
|
||||
html.find("#nbBrins").change(event => {
|
||||
this.potionData.nbBrins = Misc.toInt(event.currentTarget.value);
|
||||
const brinsManquants = Math.max(0, DialogFabriquerPotion.nombreBrinsOptimal(this.potionData) - this.potionData.nbBrins);
|
||||
this.potionData.herbebonus = Math.max(0, this.potionData.system.niveau - brinsManquants)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,69 +1,33 @@
|
||||
|
||||
import { Monnaie } from "./item-monnaie.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
export class DialogItemAchat extends Dialog {
|
||||
|
||||
static async onButtonAcheter(event) {
|
||||
const buttonAcheter = event.currentTarget;
|
||||
if (!buttonAcheter.attributes['data-jsondata']?.value) {
|
||||
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
|
||||
return;
|
||||
}
|
||||
const chatMessageIdVente = RdDUtility.findChatMessageId(buttonAcheter);
|
||||
|
||||
const vendeurId = buttonAcheter.attributes['data-vendeurId']?.value;
|
||||
static venteData(button) {
|
||||
const vendeurId = button.attributes['data-vendeurId']?.value;
|
||||
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
|
||||
const acheteur = RdDUtility.getSelectedActor();
|
||||
|
||||
const json = button.attributes['data-jsondata']?.value;
|
||||
if (!acheteur && !vendeur) {
|
||||
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
|
||||
return;
|
||||
return undefined;
|
||||
}
|
||||
if (!json) {
|
||||
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
|
||||
return undefined;
|
||||
}
|
||||
|
||||
let venteData = DialogItemAchat.prepareVenteData(buttonAcheter, vendeurId, vendeur, acheteur);
|
||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
|
||||
const dialog = new DialogItemAchat(html, vendeur, acheteur, venteData, chatMessageIdVente);
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
constructor(html, vendeur, acheteur, venteData, chatMessageIdVente) {
|
||||
const isConsommable = venteData.item.type == 'nourritureboisson';
|
||||
let options = { classes: ["dialogachat"], width: 400, height: isConsommable ? 450 : 350, 'z-index': 99999 };
|
||||
|
||||
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
|
||||
const buttons = {};
|
||||
if (isConsommable) {
|
||||
buttons["consommer"] = { label: venteData.item.data.boisson ? "Boire" : "Manger", callback: it => { this.onAchatConsommer(); } }
|
||||
}
|
||||
buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
|
||||
buttons["decliner"] = { label: "Décliner", callback: it => { } };
|
||||
let conf = {
|
||||
title: venteData.acheteur? venteData.acheteur.name + " - " + actionAchat : actionAchat,
|
||||
content: html,
|
||||
default: actionAchat,
|
||||
buttons: buttons
|
||||
};
|
||||
|
||||
super(conf, options);
|
||||
|
||||
this.vendeur = vendeur;
|
||||
this.acheteur = acheteur;
|
||||
this.chatMessageIdVente = chatMessageIdVente;
|
||||
this.venteData = venteData;
|
||||
}
|
||||
|
||||
static prepareVenteData(buttonAcheter, vendeurId, vendeur, acheteur) {
|
||||
const jsondata = buttonAcheter.attributes['data-jsondata']?.value;
|
||||
const prixLot = buttonAcheter.attributes['data-prixLot']?.value ?? 0;
|
||||
let venteData = {
|
||||
item: JSON.parse(jsondata),
|
||||
const prixLot = Monnaie.arrondiDeniers(button.attributes['data-prixLot']?.value ?? 0);
|
||||
return {
|
||||
item: json ? JSON.parse(json) : undefined,
|
||||
vendeurId: vendeurId,
|
||||
vendeur: Misc.data(vendeur),
|
||||
acheteur: Misc.data(acheteur),
|
||||
tailleLot: parseInt(buttonAcheter.attributes['data-tailleLot']?.value ?? 1),
|
||||
quantiteIllimite: buttonAcheter.attributes['data-quantiteIllimite']?.value == 'true',
|
||||
quantiteNbLots: parseInt(buttonAcheter.attributes['data-quantiteNbLots']?.value),
|
||||
vendeur: vendeur,
|
||||
acheteur: acheteur,
|
||||
tailleLot: parseInt(button.attributes['data-tailleLot']?.value ?? 1),
|
||||
quantiteIllimite: button.attributes['data-quantiteIllimite']?.value == 'true',
|
||||
quantiteNbLots: parseInt(button.attributes['data-quantiteNbLots']?.value),
|
||||
choix: {
|
||||
nombreLots: 1,
|
||||
seForcer: false,
|
||||
@ -71,23 +35,51 @@ export class DialogItemAchat extends Dialog {
|
||||
},
|
||||
prixLot: prixLot,
|
||||
prixTotal: prixLot,
|
||||
isVente: prixLot > 0
|
||||
isVente: prixLot > 0,
|
||||
chatMessageIdVente: RdDUtility.findChatMessageId(button)
|
||||
};
|
||||
return venteData;
|
||||
}
|
||||
static async onAcheter(venteData) {
|
||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
|
||||
const dialog = new DialogItemAchat(html, venteData);
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
constructor(html, venteData) {
|
||||
const isConsommable = venteData.item.type == 'nourritureboisson' && venteData.acheteur?.isPersonnage();
|
||||
let options = { classes: ["dialogachat"], width: 400, height: isConsommable ? 450 : 350, 'z-index': 99999 };
|
||||
|
||||
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
|
||||
const buttons = {};
|
||||
if (isConsommable) {
|
||||
buttons["consommer"] = { label: venteData.item.system.boisson ? "Boire" : "Manger", callback: it => { this.onAchatConsommer(); } }
|
||||
}
|
||||
buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
|
||||
buttons["decliner"] = { label: "Décliner", callback: it => { } };
|
||||
let conf = {
|
||||
title: venteData.acheteur ? venteData.acheteur.name + " - " + actionAchat : actionAchat,
|
||||
content: html,
|
||||
default: actionAchat,
|
||||
buttons: buttons
|
||||
};
|
||||
|
||||
super(conf, options);
|
||||
|
||||
this.venteData = venteData;
|
||||
}
|
||||
|
||||
async onAchat() {
|
||||
await $(".nombreLots").change();
|
||||
(this.vendeur ?? this.acheteur).achatVente({
|
||||
(this.venteData.vendeur ?? this.venteData.acheteur).achatVente({
|
||||
userId: game.user.id,
|
||||
vendeurId: this.vendeur?.id,
|
||||
acheteurId: this.acheteur?.id,
|
||||
vendeurId: this.venteData.vendeur?.id,
|
||||
acheteurId: this.venteData.acheteur?.id,
|
||||
prixTotal: this.venteData.prixTotal,
|
||||
chatMessageIdVente: this.chatMessageIdVente,
|
||||
chatMessageIdVente: this.venteData.chatMessageIdVente,
|
||||
choix: this.venteData.choix
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
async onAchatConsommer() {
|
||||
this.venteData.choix.consommer = true;
|
||||
await this.onAchat();
|
||||
@ -106,8 +98,12 @@ export class DialogItemAchat extends Dialog {
|
||||
}
|
||||
|
||||
setNombreLots(nombreLots) {
|
||||
this.venteData.choix.nombreLots = nombreLots;
|
||||
if (nombreLots > this.venteData.quantiteNbLots) {
|
||||
ui.notifications.warn(`Seulement ${this.venteData.quantiteNbLots} lots disponibles, vous ne pouvez pas en prendre ${nombreLots}`)
|
||||
}
|
||||
this.venteData.choix.nombreLots = Math.min(nombreLots, this.venteData.quantiteNbLots);
|
||||
this.venteData.prixTotal = (nombreLots * this.venteData.prixLot).toFixed(2);
|
||||
$(".nombreLots").val(this.venteData.choix.nombreLots);
|
||||
$(".prixTotal").text(this.venteData.prixTotal);
|
||||
}
|
||||
|
||||
|
@ -38,22 +38,22 @@ export class DialogConsommer extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static prepareData(actor, item) {
|
||||
const itemData = duplicate(Misc.data(item));
|
||||
item = duplicate(item);
|
||||
let consommerData = {
|
||||
item: itemData,
|
||||
cuisine: Misc.data(actor.getCompetence('cuisine')),
|
||||
item: item,
|
||||
cuisine: actor.getCompetence('cuisine'),
|
||||
choix: {
|
||||
doses: 1,
|
||||
seForcer: false,
|
||||
}
|
||||
}
|
||||
switch (itemData.type) {
|
||||
switch (item.type) {
|
||||
case 'nourritureboisson':
|
||||
consommerData.title = itemData.data.boisson ? `${itemData.name}: boire une dose` : `${itemData.name}: manger une portion`;
|
||||
consommerData.buttonName = itemData.data.boisson ? "Boire" : "Manger";
|
||||
consommerData.title = item.system.boisson ? `${item.name}: boire une dose` : `${item.name}: manger une portion`;
|
||||
consommerData.buttonName = item.system.boisson ? "Boire" : "Manger";
|
||||
break;
|
||||
case 'potion':
|
||||
consommerData.title = `${itemData.name}: boire la potion`;
|
||||
consommerData.title = `${item.name}: boire la potion`;
|
||||
consommerData.buttonName = "Boire";
|
||||
break;
|
||||
}
|
||||
@ -61,11 +61,11 @@ export class DialogConsommer extends Dialog {
|
||||
return consommerData;
|
||||
}
|
||||
|
||||
static calculDoses(consommerData) {
|
||||
const doses = consommerData.choix.doses;
|
||||
consommerData.totalSust = Misc.keepDecimals(doses * (consommerData.item.data.sust ?? 0), 2);
|
||||
consommerData.totalDesaltere = consommerData.item.data.boisson
|
||||
? Misc.keepDecimals(doses * (consommerData.item.data.desaltere ?? 0), 2)
|
||||
static calculDoses(consommer) {
|
||||
const doses = consommer.choix.doses;
|
||||
consommer.totalSust = Misc.keepDecimals(doses * (consommer.item.system.sust ?? 0), 2);
|
||||
consommer.totalDesaltere = consommer.item.system.boisson
|
||||
? Misc.keepDecimals(doses * (consommer.item.system.desaltere ?? 0), 2)
|
||||
: 0;
|
||||
}
|
||||
|
||||
|
@ -3,16 +3,15 @@ import { Misc } from "./misc.js";
|
||||
|
||||
export class DialogItemVente extends Dialog {
|
||||
|
||||
static async create(item, callback) {
|
||||
const itemData = Misc.data(item);
|
||||
const quantite = item.isConteneur() ? 1 : itemData.data.quantite;
|
||||
static async display(item, callback) {
|
||||
const quantite = item.isConteneur() ? 1 : item.system.quantite;
|
||||
const venteData = {
|
||||
item: itemData,
|
||||
item: item,
|
||||
alias: item.actor?.name ?? game.user.name,
|
||||
vendeurId: item.actor?.id,
|
||||
prixOrigine: itemData.data.cout,
|
||||
prixUnitaire: itemData.data.cout,
|
||||
prixLot: itemData.data.cout,
|
||||
prixOrigine: item.system.cout,
|
||||
prixUnitaire: item.system.cout,
|
||||
prixLot: item.system.cout,
|
||||
tailleLot: 1,
|
||||
quantiteNbLots: quantite,
|
||||
quantiteMaxLots: quantite,
|
||||
@ -21,7 +20,7 @@ export class DialogItemVente extends Dialog {
|
||||
isOwned: item.isOwned,
|
||||
};
|
||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
|
||||
return new DialogItemVente(venteData, html, callback);
|
||||
return new DialogItemVente(venteData, html, callback).render(true);
|
||||
}
|
||||
|
||||
constructor(venteData, html, callback) {
|
||||
|
@ -3,7 +3,7 @@ import { Misc } from "./misc.js";
|
||||
export class DialogRepos extends Dialog {
|
||||
|
||||
static async create(actor) {
|
||||
let actorData = Misc.data(actor)
|
||||
let actorData = actor
|
||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-repos.html", actorData);
|
||||
new DialogRepos(html, actor).render(true);
|
||||
}
|
||||
|
@ -3,10 +3,9 @@ import { Misc } from "./misc.js";
|
||||
export class DialogSplitItem extends Dialog {
|
||||
|
||||
static async create(item, callback) {
|
||||
const itemData = Misc.data(item);
|
||||
const splitData = {
|
||||
item: itemData,
|
||||
choix: { quantite: 1, max: itemData.data.quantite - 1 }
|
||||
item: item,
|
||||
choix: { quantite: 1, max: item.system.quantite - 1 }
|
||||
};
|
||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-split.html`, splitData);
|
||||
return new DialogSplitItem(item, splitData, html, callback)
|
||||
|
@ -1,18 +1,19 @@
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||
|
||||
export class DialogStress extends Dialog {
|
||||
|
||||
static async distribuerStress() {
|
||||
let dialogData = {
|
||||
const dialogData = {
|
||||
motif: "Motif",
|
||||
stress: 10,
|
||||
immediat: false,
|
||||
actors: game.actors.filter(actor => actor.hasPlayerOwner && actor.isPersonnage())
|
||||
.map(actor => {
|
||||
let actorData = duplicate(Misc.data(actor));
|
||||
actorData.selected = actor.hasPlayerOwner;
|
||||
return actorData;
|
||||
})
|
||||
.map(actor => ({
|
||||
id: actor.id,
|
||||
name: actor.name,
|
||||
selected: true
|
||||
})
|
||||
)
|
||||
};
|
||||
|
||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-stress.html", dialogData);
|
||||
@ -21,52 +22,44 @@ export class DialogStress extends Dialog {
|
||||
}
|
||||
|
||||
constructor(dialogData, html) {
|
||||
let options = { classes: ["DialogStress"], width: 400, height: 320, 'z-index': 99999 };
|
||||
let conf = {
|
||||
const options = { classes: ["DialogStress"],
|
||||
width: 400,
|
||||
height: 205+dialogData.actors.length*25,
|
||||
'z-index': 99999
|
||||
};
|
||||
const conf = {
|
||||
title: "Donner du stress",
|
||||
content: html,
|
||||
buttons: {
|
||||
"Stress": { label: "Stress !", callback: it => { this._onStress(); } }
|
||||
}
|
||||
stress: { label: "Stress !", callback: it => { this.onStress(); } }
|
||||
},
|
||||
default: "stress"
|
||||
};
|
||||
super(conf, options);
|
||||
this.dialogData = dialogData;
|
||||
}
|
||||
|
||||
async _onStress() {
|
||||
this.validerStress();
|
||||
const compteur = this.dialogData.immediat ? 'experience' : 'stress';
|
||||
const stress = this.dialogData.stress;
|
||||
const motif = this.dialogData.motif;
|
||||
async onStress() {
|
||||
const motif = $("form.rdddialogstress input[name='motif']").val();
|
||||
const stress = Number($("form.rdddialogstress input[name='stress']").val());
|
||||
const compteur = ($("form.rdddialogstress input[name='immediat']").prop("checked")) ? 'experience' : 'stress';
|
||||
|
||||
this.dialogData.actors.filter(it => it.selected)
|
||||
.map(it => game.actors.get(it._id))
|
||||
.map(it => game.actors.get(it.id))
|
||||
.forEach(actor => actor.distribuerStress(compteur, stress, motif));
|
||||
}
|
||||
|
||||
|
||||
validerStress() {
|
||||
this.dialogData.motif = $("form.rdddialogstress input[name='motif']").val();
|
||||
this.dialogData.stress = $("form.rdddialogstress input[name='stress']").val();
|
||||
this.dialogData.immediat = $("form.rdddialogstress input[name='immediat']").prop("checked");;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
html.find(".select-actor").change((event) => this.onSelectActor(event));
|
||||
html.find("input.select-actor").change((event) => this.onSelectActor(event));
|
||||
}
|
||||
|
||||
async onSelectActor(event) {
|
||||
event.preventDefault();
|
||||
const options = event.currentTarget.options;
|
||||
for (var i = 0; i < options.length; i++) { // looping over the options
|
||||
const actorId = options[i].attributes["data-actor-id"].value;
|
||||
const actor = this.dialogData.actors.find(it => it._id == actorId);
|
||||
if (actor) {
|
||||
actor.selected = options[i].selected;
|
||||
}
|
||||
};
|
||||
const actorId = $(event.currentTarget)?.data("actor-id");
|
||||
const actor = this.dialogData.actors.find(it => it.id == actorId);
|
||||
if (actor) {
|
||||
actor.selected = event.currentTarget.checked;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
70
module/dialog-validation-encaissement.js
Normal file
70
module/dialog-validation-encaissement.js
Normal file
@ -0,0 +1,70 @@
|
||||
import { HIDE_DICE, SHOW_DICE } from "./constants.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
/**
|
||||
* Extend the base Dialog entity by defining a custom window to perform roll.
|
||||
* @extends {Dialog}
|
||||
*/
|
||||
export class DialogValidationEncaissement extends Dialog {
|
||||
|
||||
static async validerEncaissement(actor, rollData, armure, show, onEncaisser) {
|
||||
let encaissement = await RdDUtility.jetEncaissement(rollData, armure, { showDice: HIDE_DICE });
|
||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', {
|
||||
actor: actor,
|
||||
rollData: rollData,
|
||||
encaissement: encaissement,
|
||||
show: show
|
||||
});
|
||||
const dialog = new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, show, onEncaisser);
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, actor, rollData, armure, encaissement, show, onEncaisser) {
|
||||
// Common conf
|
||||
let buttons = {
|
||||
"valider": { label: "Valider", callback: html => this.validerEncaissement() },
|
||||
"annuler": { label: "Annuler", callback: html => { } },
|
||||
};
|
||||
|
||||
let dialogConf = {
|
||||
title: "Validation d'encaissement",
|
||||
content: html,
|
||||
buttons: buttons,
|
||||
default: "valider"
|
||||
}
|
||||
|
||||
let dialogOptions = {
|
||||
classes: ["rdddialog"],
|
||||
width: 350,
|
||||
height: 290
|
||||
}
|
||||
|
||||
// Select proper roll dialog template and stuff
|
||||
super(dialogConf, dialogOptions);
|
||||
|
||||
this.actor = actor
|
||||
this.rollData = rollData;
|
||||
this.armure = armure;
|
||||
this.encaissement = encaissement;
|
||||
this.show = show;
|
||||
this.onEncaisser = onEncaisser;
|
||||
this.forceDiceResult = {total: encaissement.roll.result };
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
html.find('input.encaissement-roll-result').keyup(async event => {
|
||||
this.forceDiceResult.total = event.currentTarget.value;
|
||||
this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: HIDE_DICE, forceDiceResult: this.forceDiceResult});
|
||||
$('label.encaissement-total').text(this.encaissement.total);
|
||||
$('label.encaissement-blessure').text(this.encaissement.blessures)
|
||||
});
|
||||
}
|
||||
|
||||
async validerEncaissement() {
|
||||
this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: SHOW_DICE, forceDiceResult: this.forceDiceResult});
|
||||
this.onEncaisser(this.encaissement, this.show)
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
/* -------------------------------------------- */
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// Activate chat listeners defined
|
||||
// Hooks.on('renderChatLog', (log, html, data) => {
|
||||
// RdDUtility.chatListeners(html);
|
||||
// });
|
||||
|
@ -19,36 +19,34 @@ const nomCategorieParade = {
|
||||
/* -------------------------------------------- */
|
||||
export class RdDItemArme extends Item {
|
||||
|
||||
static isArme(itemData) {
|
||||
itemData = Misc.data(itemData);
|
||||
return (itemData.type == 'competencecreature' && itemData.data.iscombat) || itemData.type == 'arme';
|
||||
static isArme(item) {
|
||||
return (item.type == 'competencecreature' && item.system.iscombat) || item.type == 'arme';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getArmeData(armeData) {
|
||||
armeData = Misc.data(armeData);
|
||||
switch (armeData ? armeData.type : '') {
|
||||
case 'arme': return armeData;
|
||||
static getArme(arme) {
|
||||
switch (arme ? arme.type : '') {
|
||||
case 'arme': return arme;
|
||||
case 'competencecreature':
|
||||
return RdDItemCompetenceCreature.toArme(armeData);
|
||||
return RdDItemCompetenceCreature.toActionArme(arme);
|
||||
}
|
||||
return RdDItemArme.mainsNues();
|
||||
}
|
||||
|
||||
static computeNiveauArmes(armes, competences) {
|
||||
for (const arme of armes) {
|
||||
arme.data.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
|
||||
arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
|
||||
}
|
||||
}
|
||||
|
||||
static niveauCompetenceArme(arme, competences) {
|
||||
const compArme = competences.find(it => it.name == arme.data.competence);
|
||||
return compArme?.data.niveau ?? -8;
|
||||
const compArme = competences.find(it => it.name == arme.system.competence);
|
||||
return compArme?.system.niveau ?? -8;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getNomCategorieParade(arme) {
|
||||
const categorie = arme?.data ? RdDItemArme.getCategorieParade(arme) : arme;
|
||||
const categorie = arme?.system ? RdDItemArme.getCategorieParade(arme) : arme;
|
||||
return nomCategorieParade[categorie];
|
||||
}
|
||||
|
||||
@ -66,21 +64,20 @@ export class RdDItemArme extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCategorieParade(armeData) {
|
||||
armeData = Misc.data(armeData);
|
||||
if (armeData.data.categorie_parade) {
|
||||
return armeData.data.categorie_parade;
|
||||
if (armeData.system.categorie_parade) {
|
||||
return armeData.system.categorie_parade;
|
||||
}
|
||||
// pour compatibilité avec des personnages existants
|
||||
if (armeData.type == 'competencecreature' || armeData.data.categorie == 'creature') {
|
||||
return armeData.data.categorie_parade || (armeData.data.isparade ? 'armes-naturelles' : '');
|
||||
if (armeData.type == 'competencecreature' || armeData.system.categorie == 'creature') {
|
||||
return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '');
|
||||
}
|
||||
if (!armeData.type.match(/arme|competencecreature/)) {
|
||||
return '';
|
||||
}
|
||||
if (armeData.data.competence == undefined) {
|
||||
if (armeData.system.competence == undefined) {
|
||||
return 'competencecreature';
|
||||
}
|
||||
let compname = armeData.data.competence.toLowerCase();
|
||||
let compname = armeData.system.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';
|
||||
@ -137,22 +134,21 @@ export class RdDItemArme extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static armeUneOuDeuxMains(armeData, aUneMain) {
|
||||
armeData = Misc.data(armeData);
|
||||
if (armeData && !armeData.data.cac) {
|
||||
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 (armeData && !armeData.system.cac) {
|
||||
armeData.system.unemain = armeData.system.unemain || !armeData.system.deuxmains;
|
||||
const uneOuDeuxMains = armeData.system.unemain && armeData.system.deuxmains;
|
||||
const containsSlash = !Number.isInteger(armeData.system.dommages) && armeData.system.dommages.includes("/");
|
||||
if (containsSlash) { // Sanity check
|
||||
armeData = duplicate(armeData);
|
||||
|
||||
const tableauDegats = armeData.data.dommages.split("/");
|
||||
const tableauDegats = armeData.system.dommages.split("/");
|
||||
if (aUneMain)
|
||||
armeData.data.dommagesReels = Number(tableauDegats[0]);
|
||||
armeData.system.dommagesReels = Number(tableauDegats[0]);
|
||||
else // 2 mains
|
||||
armeData.data.dommagesReels = Number(tableauDegats[1]);
|
||||
armeData.system.dommagesReels = Number(tableauDegats[1]);
|
||||
}
|
||||
else {
|
||||
armeData.data.dommagesReels = Number(armeData.data.dommages);
|
||||
armeData.system.dommagesReels = Number(armeData.system.dommages);
|
||||
}
|
||||
|
||||
if (uneOuDeuxMains != containsSlash) {
|
||||
@ -162,23 +158,22 @@ export class RdDItemArme extends Item {
|
||||
return armeData;
|
||||
}
|
||||
|
||||
static isArmeUtilisable(itemData) {
|
||||
itemData = Misc.data(itemData);
|
||||
return itemData.type == 'arme' && itemData.data.equipe && (itemData.data.resistance > 0 || itemData.data.portee_courte > 0);
|
||||
static isArmeUtilisable(arme) {
|
||||
return arme.type == 'arme' && arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0);
|
||||
}
|
||||
|
||||
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 }));
|
||||
//armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.data.niveau, initiative: init }));
|
||||
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { system: { niveau: -6 } };
|
||||
let init = RdDCombatManager.calculInitiative(corpsACorps.system.niveau, carac['melee'].value);
|
||||
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.system.niveau, initiative: init }));
|
||||
//armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
|
||||
}
|
||||
|
||||
static corpsACorps(actorData) {
|
||||
static corpsACorps(mainsNuesActor) {
|
||||
const corpsACorps = {
|
||||
name: 'Corps à corps',
|
||||
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
|
||||
data: {
|
||||
system: {
|
||||
equipe: true,
|
||||
rapide: true,
|
||||
force: 0,
|
||||
@ -189,24 +184,24 @@ export class RdDItemArme extends Item {
|
||||
categorie_parade: 'sans-armes'
|
||||
}
|
||||
};
|
||||
mergeObject(corpsACorps.data, actorData ??{}, { overwrite: false });
|
||||
mergeObject(corpsACorps.system, mainsNuesActor ?? {}, { overwrite: false });
|
||||
return corpsACorps;
|
||||
}
|
||||
|
||||
static mainsNues(actorData) {
|
||||
const mainsNues = RdDItemArme.corpsACorps(actorData);
|
||||
mainsNues.name = 'Mains nues';
|
||||
mainsNues.data.cac = 'pugilat';
|
||||
mainsNues.data.baseInit = 4;
|
||||
static mainsNues(mainsNuesActor) {
|
||||
const mainsNues = RdDItemArme.corpsACorps(mainsNuesActor)
|
||||
mainsNues.name = 'Mains nues'
|
||||
mainsNues.system.cac = 'pugilat'
|
||||
mainsNues.system.baseInit = 4
|
||||
return mainsNues;
|
||||
}
|
||||
|
||||
static empoignade(actorData) {
|
||||
const empoignade = RdDItemArme.corpsACorps(actorData);
|
||||
empoignade.name = 'Empoignade';
|
||||
empoignade.data.cac = 'empoignade';
|
||||
empoignade.data.baseInit = 3;
|
||||
empoignade.data.mortalite = 'empoignade';
|
||||
return empoignade;
|
||||
static empoignade(mainsNuesActor) {
|
||||
const empoignade = RdDItemArme.corpsACorps(mainsNuesActor)
|
||||
empoignade.name = 'Empoignade'
|
||||
empoignade.system.cac = 'empoignade'
|
||||
empoignade.system.baseInit = 3
|
||||
empoignade.system.mortalite = 'empoignade'
|
||||
return empoignade
|
||||
}
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ const competence_xp_cumul = _buildCumulXP();
|
||||
export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static actorCompendium(actorType) {
|
||||
return compendiumCompetences[actorType];
|
||||
static actorCompendium(actorType = undefined) {
|
||||
return compendiumCompetences[actorType ?? 'personnage'];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -76,40 +76,49 @@ export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCategorie(competence) {
|
||||
return Misc.data(competence)?.data.categorie;
|
||||
return competence?.system.categorie;
|
||||
}
|
||||
static isDraconic(competence) {
|
||||
return Misc.data(competence)?.data.categorie == 'draconic';
|
||||
return competence?.system.categorie == 'draconic';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getVoieDraconic(competences, voie) {
|
||||
return RdDItemCompetence.findCompetence(competences.filter(it => RdDItemCompetence.isDraconic(it)), voie);
|
||||
return RdDItemCompetence.findFirstItem(competences, voie, {
|
||||
preFilter: it => it.isCompetence() && RdDItemCompetence.isDraconic(it),
|
||||
description: 'Draconic',
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCompetenceArme(competence) {
|
||||
switch (Misc.templateData(competence).categorie) {
|
||||
case 'melee':
|
||||
return Misc.data(competence).name != 'Esquive';
|
||||
case 'tir':
|
||||
case 'lancer':
|
||||
return true;
|
||||
if (competence.isCompetence()) {
|
||||
switch (competence.system.categorie) {
|
||||
case 'melee':
|
||||
return !Grammar.toLowerCaseNoAccent(competence.name).includes('esquive');
|
||||
case 'tir':
|
||||
case 'lancer':
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isArmeUneMain(competence) {
|
||||
return Misc.data(competence)?.name.toLowerCase().includes("1 main");
|
||||
return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("1 main");
|
||||
}
|
||||
static isArme2Main(competence) {
|
||||
return Misc.data(competence)?.name.toLowerCase().includes("2 main");
|
||||
return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("2 main");
|
||||
}
|
||||
|
||||
static isThanatos(competence) {
|
||||
return competence.isCompetencePersonnage() && Grammar.toLowerCaseNoAccent(competence.name).includes('thanatos');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isMalusEncombrementTotal(competence) {
|
||||
return Misc.data(competence)?.name.toLowerCase().match(/(natation|acrobatie)/);
|
||||
return competence?.name.toLowerCase().match(/(natation|acrobatie)/) || 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -133,11 +142,10 @@ export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeXP(competence) {
|
||||
const itemData = Misc.data(competence);
|
||||
const factor = itemData.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double !
|
||||
const xpNiveau = RdDItemCompetence.computeDeltaXP(itemData.data.base, itemData.data.niveau ?? itemData.data.base);
|
||||
const xp = itemData.data.xp ?? 0;
|
||||
const xpSort = itemData.data.xp_sort ?? 0;
|
||||
const factor = RdDItemCompetence.isThanatos(competence) ? 2 : 1; // Thanatos compte double !
|
||||
const xpNiveau = RdDItemCompetence.computeDeltaXP(competence.system.base, competence.system.niveau ?? competence.system.base);
|
||||
const xp = competence.system.xp ?? 0;
|
||||
const xpSort = competence.system.xp_sort ?? 0;
|
||||
return factor * (xpNiveau + xp) + xpSort;
|
||||
}
|
||||
|
||||
@ -146,7 +154,7 @@ export class RdDItemCompetence extends Item {
|
||||
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)))
|
||||
.map(it => RdDItemCompetence.computeDeltaXP(it?.system.base ?? -11, Math.min(it?.system.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)
|
||||
@ -162,11 +170,10 @@ export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeCompetenceXPCost(competence) {
|
||||
const compData = Misc.data(competence);
|
||||
let xp = RdDItemCompetence.getDeltaXp(compData.data.base, compData.data.niveau ?? compData.data.base);
|
||||
xp += compData.data.xp ?? 0;
|
||||
let xp = RdDItemCompetence.getDeltaXp(competence.system.base, competence.system.niveau ?? competence.system.base);
|
||||
xp += competence.system.xp ?? 0;
|
||||
if (compData.name.includes('Thanatos')) xp *= 2; /// Thanatos compte double !
|
||||
xp += compData.data.xp_sort ?? 0;
|
||||
xp += competence.system.xp_sort ?? 0;
|
||||
return xp;
|
||||
}
|
||||
|
||||
@ -175,58 +182,58 @@ export class RdDItemCompetence extends Item {
|
||||
let economie = 0;
|
||||
for (let troncList of competenceTroncs) {
|
||||
let list = troncList.map(name => RdDItemCompetence.findCompetence(competences, name))
|
||||
.sort(Misc.descending(c => Misc.templateData(c).niveau)); // tri du plus haut au plus bas
|
||||
.sort(Misc.descending(c => this.system.niveau)); // tri du plus haut au plus bas
|
||||
list.splice(0, 1); // ignorer la plus élevée
|
||||
list.map(c => Misc.templateData(c)).forEach(tplData => {
|
||||
economie += RdDItemCompetence.getDeltaXp(tplData.base, Math.min(tplData.niveau, 0));
|
||||
list.map(c => c).forEach(c => {
|
||||
economie += RdDItemCompetence.getDeltaXp(c.system.base, Math.min(c.system.niveau, 0))
|
||||
});
|
||||
}
|
||||
return economie;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static levelUp(itemData, stressTransforme) {
|
||||
itemData.data.xpNext = RdDItemCompetence.getCompetenceNextXp(itemData.data.niveau);
|
||||
const xpManquant = itemData.data.xpNext - itemData.data.xp;
|
||||
itemData.data.isLevelUp = xpManquant <= 0;
|
||||
itemData.data.isStressLevelUp = (xpManquant > 0 && stressTransforme >= xpManquant && itemData.data.niveau < itemData.data.niveau_archetype);
|
||||
itemData.data.stressXpMax = 0;
|
||||
if (xpManquant > 0 && stressTransforme > 0 && itemData.data.niveau < itemData.data.niveau_archetype) {
|
||||
itemData.data.stressXpMax = Math.min(xpManquant , stressTransforme);
|
||||
static levelUp(item, stressTransforme) {
|
||||
item.system.xpNext = RdDItemCompetence.getCompetenceNextXp(item.system.niveau);
|
||||
const xpManquant = item.system.xpNext - item.system.xp;
|
||||
item.system.isLevelUp = xpManquant <= 0;
|
||||
item.system.isStressLevelUp = (xpManquant > 0 && stressTransforme >= xpManquant && item.system.niveau < item.system.niveau_archetype);
|
||||
item.system.stressXpMax = 0;
|
||||
if (xpManquant > 0 && stressTransforme > 0 && item.system.niveau < item.system.niveau_archetype) {
|
||||
item.system.stressXpMax = Math.min(xpManquant , stressTransforme);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isVisible(itemData) {
|
||||
return Number(itemData.data.niveau) != RdDItemCompetence.getNiveauBase(itemData.data.categorie);
|
||||
static isVisible(item) {
|
||||
return Number(item.system.niveau) != RdDItemCompetence.getNiveauBase(item.system.categorie);
|
||||
}
|
||||
|
||||
static nomContientTexte(itemData, texte) {
|
||||
return Grammar.toLowerCaseNoAccent(itemData.name).includes(Grammar.toLowerCaseNoAccent(texte))
|
||||
static nomContientTexte(item, texte) {
|
||||
return Grammar.toLowerCaseNoAccent(item.name).includes(Grammar.toLowerCaseNoAccent(texte))
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isNiveauBase(itemData) {
|
||||
return Number(itemData.data.niveau) == RdDItemCompetence.getNiveauBase(itemData.data.categorie);
|
||||
static isNiveauBase(item) {
|
||||
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static findCompetence(list, idOrName, options = {}) {
|
||||
options = mergeObject(options, {
|
||||
filter: it => RdDItemCompetence.isCompetence(it),
|
||||
description: 'compétence',
|
||||
});
|
||||
return list.find(it => it.id == idOrName && RdDItemCompetence.isCompetence(it))
|
||||
?? Misc.findFirstLike(idOrName, list, options);
|
||||
if (idOrName == undefined) {
|
||||
return undefined;
|
||||
}
|
||||
options = mergeObject(options, { preFilter: it => it.isCompetence(), description: 'compétence' }, {overwrite: false});
|
||||
return RdDItemCompetence.findFirstItem(list, idOrName, options);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static findCompetences(list, name) {
|
||||
return Misc.findAllLike(name, list, { filter: it => RdDItemCompetence.isCompetence(it), description: 'compétence' });
|
||||
return Misc.findAllLike(name, list, { filter: it => it.isCompetence(), description: 'compétence' });
|
||||
}
|
||||
|
||||
static isCompetence(item) {
|
||||
return item.type == 'competence' || item.type == 'competencecreature';
|
||||
static findFirstItem(list, idOrName, options) {
|
||||
return list.find(it => it.id == idOrName && options.preFilter(it))
|
||||
?? Misc.findFirstLike(idOrName, list, options);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -257,7 +264,7 @@ export class RdDItemCompetence extends Item {
|
||||
/* -------------------------------------------- */
|
||||
static computeResumeArchetype(competences) {
|
||||
const archetype = RdDItemCompetence.getLimitesArchetypes();
|
||||
competences.map(it => Math.max(0, Misc.templateData(it).niveau_archetype))
|
||||
competences.map(it => Math.max(0, it.system.niveau_archetype))
|
||||
.forEach(niveau => {
|
||||
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
|
||||
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;
|
||||
|
@ -1,50 +1,53 @@
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDCombatManager } from "./rdd-combat.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDItemCompetenceCreature extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static setRollDataCreature(rollData) {
|
||||
rollData.competence = Misc.data(rollData.competence);
|
||||
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.data.carac_value } };
|
||||
rollData.competence.data.defaut_carac = "carac_creature"
|
||||
rollData.competence.data.categorie = "creature"
|
||||
rollData.competence = rollData.competence
|
||||
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
|
||||
rollData.competence.system.defaut_carac = "carac_creature"
|
||||
rollData.competence.system.categorie = "creature"
|
||||
rollData.selectedCarac = rollData.carac.carac_creature
|
||||
if (rollData.competence.data.iscombat) {
|
||||
rollData.arme = RdDItemCompetenceCreature.toArme(rollData.competence);
|
||||
if (rollData.competence.system.iscombat) {
|
||||
rollData.arme = RdDItemCompetenceCreature.toActionArme(rollData.competence);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static toArme(item) {
|
||||
if (RdDItemCompetenceCreature.isCompetenceAttaque(item)) {
|
||||
static toActionArme(competencecreature) {
|
||||
if (RdDItemCompetenceCreature.isCompetenceAttaque(competencecreature)) {
|
||||
// si c'est un Item compétence: cloner pour ne pas modifier lma compétence
|
||||
let arme = Misc.data( (item instanceof Item) ? item.clone(): item);
|
||||
mergeObject(arme.data,
|
||||
let arme = (competencecreature instanceof Item) ? competencecreature.clone(): competencecreature;
|
||||
mergeObject(arme.system,
|
||||
{
|
||||
competence: arme.name,
|
||||
resistance: 100,
|
||||
initiative: RdDCombatManager.calculInitiative(competencecreature.system.niveau, competencecreature.system.carac_value),
|
||||
niveau: competencecreature.system.niveau,
|
||||
equipe: true,
|
||||
dommagesReels: arme.data.dommages,
|
||||
resistance: 100,
|
||||
dommagesReels: arme.system.dommages,
|
||||
penetration: 0,
|
||||
force: 0,
|
||||
rapide: true
|
||||
rapide: true,
|
||||
cac: competencecreature.system.isnaturelle ? "naturelle" : "",
|
||||
action: 'attaque'
|
||||
});
|
||||
return arme;
|
||||
}
|
||||
console.error("RdDItemCompetenceCreature.toArme(", item, ") : impossible de transformer l'Item en arme");
|
||||
console.error("RdDItemCompetenceCreature.toActionArme(", competencecreature, ") : impossible de transformer l'Item en arme");
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCompetenceAttaque(itemData) {
|
||||
itemData = Misc.data(itemData);
|
||||
return itemData.type == 'competencecreature' && itemData.data.iscombat;
|
||||
static isCompetenceAttaque(item) {
|
||||
return item.type == 'competencecreature' && item.system.iscombat;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCompetenceParade(itemData) {
|
||||
itemData = Misc.data(itemData);
|
||||
return itemData.type == 'competencecreature' && itemData.data.isparade;
|
||||
static isCompetenceParade(item) {
|
||||
return item.type == 'competencecreature' && item.system.categorie_parade !== "";
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ export class RdDItemMeditation {
|
||||
static calculDifficulte(rollData) {
|
||||
if (rollData.meditation) {
|
||||
// Malus permanent éventuel
|
||||
let diff = -rollData.meditation.data.malus ?? 0;
|
||||
let diff = rollData.meditation.system.malus ?? 0;
|
||||
if (!rollData.conditionMeditation.isHeure) diff -= 2;
|
||||
if (!rollData.conditionMeditation.isVeture) diff -= 2;
|
||||
if (!rollData.conditionMeditation.isComportement) diff -= 2;
|
||||
|
@ -1,61 +1,93 @@
|
||||
import { Misc } from "./misc.js";
|
||||
import { LOG_HEAD } from "./constants.js";
|
||||
|
||||
const monnaiesData = [
|
||||
{
|
||||
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: "" }
|
||||
},
|
||||
{
|
||||
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: "" }
|
||||
},
|
||||
{
|
||||
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: "" }
|
||||
},
|
||||
{
|
||||
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: "" }
|
||||
}
|
||||
]
|
||||
const MONNAIE_ETAIN = {
|
||||
name: "Etain (1 denier)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
|
||||
system: { quantite: 0, valeur_deniers: 1, encombrement: 0.001, description: "" }
|
||||
};
|
||||
const MONNAIE_BRONZE = {
|
||||
name: "Bronze (10 deniers)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp",
|
||||
system: { quantite: 0, valeur_deniers: 10, encombrement: 0.002, description: "" }
|
||||
};
|
||||
const MONNAIE_ARGENT = {
|
||||
name: "Argent (1 sol)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp",
|
||||
system: { quantite: 0, valeur_deniers: 100, encombrement: 0.003, description: "" }
|
||||
};
|
||||
const MONNAIE_OR = {
|
||||
name: "Or (10 sols)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
|
||||
system: { quantite: 0, valeur_deniers: 1000, encombrement: 0.004, description: "" }
|
||||
};
|
||||
|
||||
const MONNAIES_STANDARD = [MONNAIE_ETAIN, MONNAIE_BRONZE, MONNAIE_ARGENT, MONNAIE_OR];
|
||||
|
||||
export class Monnaie {
|
||||
|
||||
static isSystemMonnaie(item) {
|
||||
let present = monnaiesData.find(monnaie => monnaie.data.valeur_deniers == Misc.data(item)?.data?.valeur_deniers);
|
||||
return present;
|
||||
static monnaiesStandard() {
|
||||
return MONNAIES_STANDARD;
|
||||
}
|
||||
|
||||
static monnaiesData() {
|
||||
return monnaiesData;
|
||||
static monnaiesManquantes(actor) {
|
||||
const disponibles = actor.itemTypes['monnaie'];
|
||||
const manquantes = MONNAIES_STANDARD.filter(standard => !disponibles.find(disponible => Monnaie.deValeur(disponible, standard.system?.valeur_deniers)));
|
||||
if (manquantes.length > 0) {
|
||||
console.error(`${LOG_HEAD} monnaiesManquantes pour ${actor.name}`, manquantes, ' avec monnaies', disponibles, MONNAIES_STANDARD);
|
||||
}
|
||||
return manquantes;
|
||||
}
|
||||
|
||||
static filtrerMonnaies(items) {
|
||||
return items.filter(it => Misc.data(it).type == 'monnaie');
|
||||
}
|
||||
|
||||
static monnaiesManquantes(items) {
|
||||
const valeurs = Monnaie.filtrerMonnaies(items)
|
||||
.map(it => Misc.templateData(it).valeur_deniers);
|
||||
const manquantes = monnaiesData.filter(monnaie => !valeurs.find(v => v != Misc.templateData(monnaie).valeur_deniers));
|
||||
//const manquantes = monnaiesData.filter(monnaie => !valeurs.find(v => v != Misc.templateData(monnaie).valeur_deniers) );
|
||||
//console.log("Valeurs : ", valeurs, manquantes);
|
||||
return []; //manquantes;
|
||||
}
|
||||
|
||||
static deValeur(monnaie, v) {
|
||||
return v != monnaie.data.valeur_deniers;
|
||||
static deValeur(monnaie, valeur) {
|
||||
return valeur == monnaie.system.valeur_deniers
|
||||
}
|
||||
|
||||
static arrondiDeniers(sols) {
|
||||
return sols.toFixed(2);
|
||||
return Number(sols).toFixed(2);
|
||||
}
|
||||
|
||||
static triValeurDenier() {
|
||||
return Misc.ascending(item => Misc.data(item).data.valeur_deniers);
|
||||
return Misc.ascending(item => item.system.valeur_deniers)
|
||||
}
|
||||
|
||||
static async creerMonnaiesStandard(actor) {
|
||||
await actor.createEmbeddedDocuments('Item', MONNAIES_STANDARD, { renderSheet: false });
|
||||
}
|
||||
|
||||
static async creerMonnaiesDeniers(actor, fortune) {
|
||||
await actor.createEmbeddedDocuments('Item', [Monnaie.creerDeniers(fortune)], { renderSheet: false });
|
||||
}
|
||||
|
||||
static creerDeniers(fortune) {
|
||||
const deniers = duplicate(MONNAIE_ETAIN);
|
||||
deniers.system.quantite = fortune;
|
||||
return deniers;
|
||||
}
|
||||
|
||||
static async optimiser(actor, fortune) {
|
||||
let reste = fortune;
|
||||
let monnaies = actor.itemTypes['monnaie'];
|
||||
let updates = [];
|
||||
let parValeur = Misc.classifyFirst(monnaies, it => it.system.valeur_deniers);
|
||||
for (let valeur of [1000, 100, 10, 1]) {
|
||||
const itemPiece = parValeur[valeur];
|
||||
const piecesDeCetteValeur = Math.floor(reste / valeur);
|
||||
if (itemPiece) {
|
||||
if (piecesDeCetteValeur != itemPiece.system.quantite) {
|
||||
updates.push({ _id: parValeur[valeur].id, 'system.quantite': piecesDeCetteValeur });
|
||||
}
|
||||
reste -= piecesDeCetteValeur*valeur;
|
||||
}
|
||||
}
|
||||
console.log('Monnaie.optimiser', actor.name, 'total', fortune, 'parValeur', parValeur, 'updates', updates, 'reste', reste);
|
||||
if (updates.length > 0) {
|
||||
await actor.updateEmbeddedDocuments('Item', updates);
|
||||
}
|
||||
if (reste>0){
|
||||
// créer le reste en deniers fortune en deniers
|
||||
await Monnaie.creerMonnaiesDeniers(actor, reste);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ export class RdDItemSheet extends ItemSheet {
|
||||
let buttons = super._getHeaderButtons();
|
||||
// Add "Post to chat" button
|
||||
// We previously restricted this to GM and editable items only. If you ever find this comment because it broke something: eh, sorry!
|
||||
if ("cout" in Misc.templateData(this.object) && this.object.isVideOuNonConteneur()) {
|
||||
if ("cout" in this.item.system && this.item.isVideOuNonConteneur()) {
|
||||
buttons.unshift({
|
||||
class: "vendre",
|
||||
icon: "fas fa-comments-dollar",
|
||||
@ -60,55 +60,69 @@ export class RdDItemSheet extends ItemSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
const objectData = Misc.data(this.object)
|
||||
let formData = {
|
||||
id: this.object.id,
|
||||
title: objectData.name,
|
||||
type: objectData.type,
|
||||
img: objectData.img,
|
||||
name: objectData.name,
|
||||
data: objectData.data,
|
||||
id: this.item.id,
|
||||
title: this.item.name,
|
||||
type: this.item.type,
|
||||
img: this.item.img,
|
||||
name: this.item.name,
|
||||
system: this.item.system,
|
||||
// TODO: v10 remove
|
||||
data: this.item.system,
|
||||
isGM: game.user.isGM,
|
||||
actorId: this.actor?.id,
|
||||
owner: this.document.isOwner,
|
||||
owner: this.item.isOwner,
|
||||
editable: this.isEditable,
|
||||
cssClass: this.isEditable ? "editable" : "locked",
|
||||
isSoins: false
|
||||
isSoins: false,
|
||||
description: await TextEditor.enrichHTML(this.object.system.description, {async: true}),
|
||||
descriptionmj: await TextEditor.enrichHTML(this.object.system.descriptionmj, {async: true})
|
||||
|
||||
}
|
||||
if (this.actor) {
|
||||
formData.isOwned = true;
|
||||
if (objectData.type == 'conteneur') {
|
||||
if (this.item.type == 'conteneur') {
|
||||
this.prepareConteneurData(formData);
|
||||
}
|
||||
}
|
||||
|
||||
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences()
|
||||
if (formData.type == 'tache' || formData.type == 'livre' || formData.type == 'meditation' || formData.type == 'oeuvre') {
|
||||
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
|
||||
formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
|
||||
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve)
|
||||
formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences')
|
||||
formData.competences = await RdDUtility.loadItems(it => it.isCompetencePersonnage(), RdDItemCompetence.actorCompendium(this.actor?.type))
|
||||
}
|
||||
if (formData.type == 'arme') {
|
||||
formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it));
|
||||
console.log(formData.competences)
|
||||
if (this.item.type == 'arme') {
|
||||
formData.competences = await RdDUtility.loadItems(it => RdDItemCompetence.isCompetenceArme(it), RdDItemCompetence.actorCompendium(this.actor?.type))
|
||||
}
|
||||
if (formData.type == 'recettealchimique') {
|
||||
RdDAlchimie.processManipulation(objectData, this.actor && this.actor.id);
|
||||
if (this.item.type == 'recettecuisine') {
|
||||
formData.ingredients = await TextEditor.enrichHTML(this.object.system.ingredients, {async: true})
|
||||
}
|
||||
if (formData.type == 'gemme') {
|
||||
if (this.item.type == 'recettealchimique') {
|
||||
RdDAlchimie.processManipulation(this.item, this.actor && this.actor.id);
|
||||
formData.manipulation_update = await TextEditor.enrichHTML(this.object.system.manipulation_update, {async: true})
|
||||
formData.utilisation = await TextEditor.enrichHTML(this.object.system.utilisation, {async: true})
|
||||
formData.enchantement = await TextEditor.enrichHTML(this.object.system.enchantement, {async: true})
|
||||
formData.sureffet = await TextEditor.enrichHTML(this.object.system.sureffet, {async: true})
|
||||
}
|
||||
if (this.item.type == 'gemme') {
|
||||
formData.gemmeTypeList = RdDGemme.getGemmeTypeOptionList();
|
||||
RdDGemme.calculDataDerivees(formData.data);
|
||||
RdDGemme.calculDataDerivees(this.item);
|
||||
}
|
||||
if (formData.type == 'potion') {
|
||||
if (this.item.type == 'potion') {
|
||||
if (this.dateUpdated) {
|
||||
formData.data.prdate = this.dateUpdated;
|
||||
formData.system.prdate = this.dateUpdated;
|
||||
this.dateUpdated = undefined;
|
||||
}
|
||||
RdDHerbes.updatePotionData(formData);
|
||||
await RdDHerbes.updatePotionData(formData);
|
||||
}
|
||||
if (formData.isOwned && formData.type == 'herbe' && (formData.data.categorie == 'Soin' || formData.data.categorie == 'Repos')) {
|
||||
if (formData.isOwned && this.item.type == 'herbe' && (formData.system.categorie == 'Soin' || formData.system.categorie == 'Repos')) {
|
||||
formData.isIngredientPotionBase = true;
|
||||
}
|
||||
if (this.item.type == 'sortreserve') {
|
||||
const sortId = this.item.system.sortid;
|
||||
formData.sort = formData.isOwned ? this.item.actor.items.get(sortId) : game.items.get(sortId);
|
||||
}
|
||||
formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
|
||||
|
||||
return formData;
|
||||
@ -116,11 +130,10 @@ export class RdDItemSheet extends ItemSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
prepareConteneurData(formData) {
|
||||
formData.itemsByType = Misc.classify(this.actor.items.map(i => foundry.utils.deepClone(i.data)));
|
||||
RdDUtility.filterEquipementParType(formData);
|
||||
RdDUtility.filterEquipementParType(formData, this.actor.itemTypes);
|
||||
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||
formData.subItems = formData.conteneurs.find(it => it._id == this.object.id)?.subItems;
|
||||
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
|
||||
|
||||
}
|
||||
|
||||
@ -129,15 +142,15 @@ export class RdDItemSheet extends ItemSheet {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
if (this.object.type == 'conteneur') {
|
||||
if (this.item.type == 'conteneur') {
|
||||
this.form.ondragstart = (event) => this._onDragStart(event);
|
||||
this.form.ondrop = (event) => this._onDrop(event);
|
||||
}
|
||||
|
||||
let itemSheetDialog = this;
|
||||
|
||||
HtmlUtility._showControlWhen($(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.object.isOwned);
|
||||
HtmlUtility._showControlWhen($(".item-magique"), this.object.isMagique());
|
||||
HtmlUtility._showControlWhen($(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.item.isOwned);
|
||||
HtmlUtility._showControlWhen($(".item-magique"), this.item.isMagique());
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
@ -146,8 +159,8 @@ export class RdDItemSheet extends ItemSheet {
|
||||
html.find(".categorie").change(event => this._onSelectCategorie(event));
|
||||
|
||||
html.find('.sheet-competence-xp').change((event) => {
|
||||
if (this.object.data.type == 'competence') {
|
||||
RdDUtility.checkThanatosXP(this.object.data.name);
|
||||
if (this.item.isCompetencePersonnage()) {
|
||||
RdDUtility.checkThanatosXP(this.item.name);
|
||||
}
|
||||
});
|
||||
|
||||
@ -182,7 +195,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 trouver un acteur pour réaliser cette tache Alchimique.");
|
||||
}
|
||||
});
|
||||
|
||||
@ -196,7 +209,8 @@ export class RdDItemSheet extends ItemSheet {
|
||||
});
|
||||
html.find('.item-delete').click(async event => {
|
||||
const li = RdDSheetUtility.getEventElement(event);
|
||||
RdDUtility.confirmerSuppression(this, li);
|
||||
const item = this.actor.getObjet(li.data("item-id"));
|
||||
RdDUtility.confirmerSuppressionItem(this, item, li);
|
||||
});
|
||||
html.find('.item-vendre').click(async event => {
|
||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||
@ -220,16 +234,16 @@ export class RdDItemSheet extends ItemSheet {
|
||||
async _onSelectCategorie(event) {
|
||||
event.preventDefault();
|
||||
|
||||
if (this.object.isCompetence()) {
|
||||
if (this.item.isCompetence()) {
|
||||
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
|
||||
Misc.templateData(this.object).base = level;
|
||||
this.item.system.base = level;
|
||||
$("#base").val(level);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
get template() {
|
||||
let type = this.object.data.type;
|
||||
let type = this.item.type
|
||||
return `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`;
|
||||
}
|
||||
|
||||
@ -240,7 +254,7 @@ export class RdDItemSheet extends ItemSheet {
|
||||
// Données de bonus de cases ?
|
||||
formData = RdDItemSort.buildBonusCaseStringFromFormData(formData);
|
||||
|
||||
return this.object.update(formData);
|
||||
return this.item.update(formData);
|
||||
}
|
||||
|
||||
async _onDragStart(event) {
|
||||
@ -253,28 +267,28 @@ export class RdDItemSheet extends ItemSheet {
|
||||
const dragData = {
|
||||
actorId: this.actor.id,
|
||||
type: "Item",
|
||||
data: item.data
|
||||
data: item.system
|
||||
};
|
||||
|
||||
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
|
||||
}
|
||||
|
||||
async _onDrop(event) {
|
||||
// Try to extract the data
|
||||
let data;
|
||||
// Try to extract the dragData
|
||||
let dragData;
|
||||
try {
|
||||
data = JSON.parse(event.dataTransfer.getData('text/plain'));
|
||||
dragData = JSON.parse(event.dataTransfer.getData('text/plain'));
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const allowed = Hooks.call("dropActorSheetData", this.actor, this, data);
|
||||
const allowed = Hooks.call("dropActorSheetData", this.actor, this, dragData);
|
||||
if (allowed === false) return;
|
||||
|
||||
// Handle different data types
|
||||
switch (data.type) {
|
||||
// Handle different dragData types
|
||||
switch (dragData.type) {
|
||||
case "Item":
|
||||
return this._onDropItem(event, data);
|
||||
return this._onDropItem(event, dragData);
|
||||
}
|
||||
return super._onDrop(event);
|
||||
}
|
||||
@ -282,7 +296,7 @@ export class RdDItemSheet extends ItemSheet {
|
||||
/* -------------------------------------------- */
|
||||
async _onDropItem(event, dragData) {
|
||||
if (this.actor) {
|
||||
const dropParams = RdDSheetUtility.prepareItemDropParameters(this.object.id, this.actor.id, dragData, this.objetVersConteneur);
|
||||
const dropParams = RdDSheetUtility.prepareItemDropParameters(this.item.id, this.actor.id, dragData, this.objetVersConteneur);
|
||||
await this.actor.processDropItem(dropParams);
|
||||
await this.render(true);
|
||||
}
|
||||
|
@ -32,25 +32,25 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet {
|
||||
const position = super.setPosition(options);
|
||||
const sheetHeader = this.element.find(".sheet-header");
|
||||
const sheetBody = this.element.find(".sheet-body");
|
||||
const bodyHeight = position.height - sheetHeader[0].clientHeight;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
const formData = duplicate(Misc.data(this.object));
|
||||
const formData = duplicate(this.item);
|
||||
this.tmrs = TMRUtility.buildSelectionTypesTMR(this.item.system.typesTMR);
|
||||
mergeObject(formData, {
|
||||
tmrs: this.tmrs,
|
||||
title: formData.name,
|
||||
isGM: game.user.isGM,
|
||||
owner: this.document.isOwner,
|
||||
owner: this.actor?.isOwner,
|
||||
isOwned: this.actor ? true : false,
|
||||
actorId: this.actor?.id,
|
||||
editable: this.isEditable,
|
||||
cssClass: this.isEditable ? "editable" : "locked",
|
||||
});
|
||||
formData.tmrs = TMRUtility.listSelectedTMR(formData.data.typesTMR ?? []);
|
||||
return formData;
|
||||
}
|
||||
|
||||
@ -62,27 +62,31 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet {
|
||||
if (!this.options.editable) return;
|
||||
|
||||
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
|
||||
html.find(".select-tmr").change((event) => this.onSelectTmr(event));
|
||||
html.find("input.select-tmr").change((event) => this.onSelectTmr(event));
|
||||
html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event.currentTarget.attributes['data-typereussite']?.value, Number(event.currentTarget.value)));
|
||||
}
|
||||
|
||||
async setSigneAleatoire() {
|
||||
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique();
|
||||
this.object.update(newSigne);
|
||||
this.item.update(newSigne);
|
||||
}
|
||||
|
||||
async onSelectTmr(event) {
|
||||
event.preventDefault();
|
||||
const selectedTMR = $(".select-tmr").val();
|
||||
this.object.update({ 'data.typesTMR': selectedTMR });
|
||||
const tmrName = $(event.currentTarget)?.data("tmr-name");
|
||||
const onTmr = this.tmrs.find(it => it.name == tmrName);
|
||||
if (onTmr){
|
||||
onTmr.selected = event.currentTarget.checked;
|
||||
}
|
||||
|
||||
this.item.update({ 'system.typesTMR': TMRUtility.buildListTypesTMRSelection(this.tmrs) });
|
||||
}
|
||||
|
||||
async onValeurXpSort(event) {
|
||||
const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0;
|
||||
const xp = Number(event.currentTarget.value);
|
||||
const oldValeur = Misc.templateData(this.object).valeur;
|
||||
const oldValeur = this.item.system.valeur;
|
||||
const newValeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
|
||||
await this.object.update({ 'data.valeur': newValeur });
|
||||
await this.item.update({ 'system.valeur': newValeur });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -13,25 +13,23 @@ const tableSignesIndicatifs = [
|
||||
|
||||
]
|
||||
|
||||
const DIFFICULTE_LECTURE_SIGNE_MANQUE = +11;
|
||||
|
||||
export class RdDItemSigneDraconique {
|
||||
|
||||
static prepareSigneDraconiqueMeditation(meditation, rolled) {
|
||||
if (rolled.isSuccess != undefined) {
|
||||
meditation = Misc.data(meditation);
|
||||
return {
|
||||
name: "de la " + meditation.name,
|
||||
type: "signedraconique",
|
||||
img: meditation.img,
|
||||
data: {
|
||||
typesTMR: [TMRUtility.typeTmrName(meditation.data.tmr)],
|
||||
difficulte: RdDItemSigneDraconique.getDiffSigneMeditation(rolled.code),
|
||||
ephemere: true,
|
||||
duree: "1 round",
|
||||
valeur: { "norm": 3, "sign": 5, "part": 10 }
|
||||
}
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
return {
|
||||
name: "de la " + meditation.name,
|
||||
type: "signedraconique",
|
||||
img: meditation.img,
|
||||
system: {
|
||||
typesTMR: [TMRUtility.typeTmrName(meditation.system.tmr)],
|
||||
difficulte: rolled.isSuccess ? RdDItemSigneDraconique.getDiffSigneMeditation(rolled.code) : DIFFICULTE_LECTURE_SIGNE_MANQUE,
|
||||
ephemere: true,
|
||||
duree: "1 round",
|
||||
valeur: rolled.isSuccess ? { "norm": 3, "sign": 5, "part": 10 } : { "norm": 0, "sign": 0, "part": 0 }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static getDiffSigneMeditation(code) {
|
||||
@ -44,7 +42,7 @@ export class RdDItemSigneDraconique {
|
||||
}
|
||||
|
||||
static getXpSortSigneDraconique(code, signe) {
|
||||
return Misc.data(signe).data.valeur[code] ?? 0;
|
||||
return Misc.toInt(signe.system.valeur[code] ?? 0);
|
||||
}
|
||||
|
||||
static calculValeursXpSort(qualite, valeur, avant) {
|
||||
@ -76,7 +74,7 @@ export class RdDItemSigneDraconique {
|
||||
name: await RdDItemSigneDraconique.randomSigneDescription(),
|
||||
type: "signedraconique",
|
||||
img: defaultItemImg.signedraconique,
|
||||
data: {
|
||||
system: {
|
||||
typesTMR: await RdDItemSigneDraconique.randomTmrs(modele.nbCases),
|
||||
ephemere: options?.ephemere == undefined ? RdDDice.rollTotal("1d2") == 2 : options.ephemere,
|
||||
duree: "1 round",
|
||||
|
@ -7,25 +7,25 @@ export class RdDItemSort extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isDifficulteVariable(sort) {
|
||||
return sort && (sort.data.difficulte.toLowerCase() == "variable");
|
||||
return sort && (sort.system.difficulte.toLowerCase() == "variable");
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCoutVariable(sort) {
|
||||
return sort && (sort.data.ptreve.toLowerCase() == "variable" || sort.data.ptreve.indexOf("+") >= 0);
|
||||
return sort && (sort.system.ptreve.toLowerCase() == "variable" || sort.system.ptreve.indexOf("+") >= 0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static setCoutReveReel(sort){
|
||||
if (sort) {
|
||||
sort.data.ptreve_reel = this.isCoutVariable(sort) ? 1 : sort.data.ptreve;
|
||||
sort.system.ptreve_reel = this.isCoutVariable(sort) ? 1 : sort.system.ptreve;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getDifficulte(sort, variable) {
|
||||
if (sort && !RdDItemSort.isDifficulteVariable(sort)) {
|
||||
return Misc.toInt(sort.data.difficulte);
|
||||
return Misc.toInt(sort.system.difficulte);
|
||||
}
|
||||
return variable;
|
||||
}
|
||||
@ -54,40 +54,40 @@ export class RdDItemSort extends Item {
|
||||
static getBonusCaseList( item, newCase = false ) {
|
||||
// Gestion spéciale case bonus
|
||||
if ( item.type == 'sort') {
|
||||
return this.buildBonusCaseList(item.data.bonuscase, newCase );
|
||||
return this.buildBonusCaseList(item.system.bonuscase, newCase );
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** Met à jour les données de formulaire
|
||||
* si static des bonus de cases sont présents
|
||||
* */
|
||||
static buildBonusCaseStringFromFormData( formData ) {
|
||||
if ( formData.bonusValue ) {
|
||||
let list = [];
|
||||
let caseCheck = {};
|
||||
for(let i=0; i<formData.bonusValue.length; i++) {
|
||||
let coord = formData.caseValue[i] || 'A1';
|
||||
coord = coord.toUpperCase();
|
||||
if ( TMRUtility.verifyTMRCoord( coord ) ) { // Sanity check
|
||||
let bonus = formData.bonusValue[i] || 0;
|
||||
if ( bonus > 0 && caseCheck[coord] == undefined ) {
|
||||
caseCheck[coord] = bonus;
|
||||
list.push( coord+":"+bonus );
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
/** Met à jour les données de formulaire
|
||||
* si static des bonus de cases sont présents
|
||||
* */
|
||||
static buildBonusCaseStringFromFormData( formData ) {
|
||||
if ( formData.bonusValue ) {
|
||||
let list = [];
|
||||
let caseCheck = {};
|
||||
for(let i=0; i<formData.bonusValue.length; i++) {
|
||||
let coord = formData.caseValue[i] || 'A1';
|
||||
coord = coord.toUpperCase();
|
||||
if ( TMRUtility.verifyTMRCoord( coord ) ) { // Sanity check
|
||||
let bonus = formData.bonusValue[i] || 0;
|
||||
if ( bonus > 0 && caseCheck[coord] == undefined ) {
|
||||
caseCheck[coord] = bonus;
|
||||
list.push( coord+":"+bonus );
|
||||
}
|
||||
}
|
||||
formData.bonusValue = undefined;
|
||||
formData.caseValue = undefined;
|
||||
formData['data.bonuscase'] = list.toString(); // Reset
|
||||
}
|
||||
return formData;
|
||||
formData.bonusValue = undefined;
|
||||
formData.caseValue = undefined;
|
||||
formData.system.bonuscase = list.toString(); // Reset
|
||||
}
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static incrementBonusCase( actor, sort, coord ) {
|
||||
let bonusCaseList = this.buildBonusCaseList(sort.data.bonuscase, false);
|
||||
let bonusCaseList = this.buildBonusCaseList(sort.system.bonuscase, false);
|
||||
//console.log("ITEMSORT", sort, bonusCaseList);
|
||||
|
||||
let found = false;
|
||||
@ -106,12 +106,12 @@ export class RdDItemSort extends Item {
|
||||
// Sauvegarde/update
|
||||
let bonuscase = StringList.toString();
|
||||
//console.log("Bonus cae :", bonuscase);
|
||||
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'data.bonuscase': bonuscase }] );
|
||||
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }] );
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCaseBonus( sort, coord) {
|
||||
let bonusCaseList = this.buildBonusCaseList(sort.data.bonuscase, false);
|
||||
let bonusCaseList = this.buildBonusCaseList(sort.system.bonuscase, false);
|
||||
for( let bc of bonusCaseList) {
|
||||
if (bc.case == coord) { // Case existante
|
||||
return Number(bc.bonus);
|
||||
|
321
module/item.js
321
module/item.js
@ -1,15 +1,35 @@
|
||||
import { DialogItemVente } from "./dialog-item-vente.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDHerbes } from "./rdd-herbes.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
const typesObjetsEquipement = ["objet", "arme", "armure", "gemme", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "nourritureboisson", "monnaie"]
|
||||
const typesObjetsEquipement = [
|
||||
"arme",
|
||||
"armure",
|
||||
"conteneur",
|
||||
"gemme",
|
||||
"herbe",
|
||||
"ingredient",
|
||||
"livre",
|
||||
"monnaie",
|
||||
"munition",
|
||||
"nourritureboisson",
|
||||
"objet",
|
||||
"potion",
|
||||
]
|
||||
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
|
||||
const encBrin = 0.00005;// un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
|
||||
const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve"]
|
||||
const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"]
|
||||
const typesObjetsEffet = ["possession", "poison", "maladie"]
|
||||
const typesObjetsCompetence = ["competence", "competencecreature"]
|
||||
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
|
||||
const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc
|
||||
densité 3.5 (~2.3 à 4, parfois plus) -- https://www.juwelo.fr/guide-des-pierres/faits-et-chiffres/
|
||||
*/
|
||||
|
||||
export const defaultItemImg = {
|
||||
competence: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
|
||||
compcreature: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
|
||||
competencecreature: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
|
||||
arme: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp",
|
||||
armure: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp",
|
||||
conteneur: "systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp",
|
||||
@ -35,20 +55,21 @@ export const defaultItemImg = {
|
||||
nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
|
||||
signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
|
||||
gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp",
|
||||
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp"
|
||||
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
||||
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDItem extends Item {
|
||||
|
||||
constructor(data, context) {
|
||||
if (!data.img) {
|
||||
data.img = defaultItemImg[data.type];
|
||||
constructor(itemData, context) {
|
||||
if (!itemData.img) {
|
||||
itemData.img = defaultItemImg[itemData.type];
|
||||
}
|
||||
super(data, context);
|
||||
super(itemData, context);
|
||||
}
|
||||
|
||||
static getTypeObjetsEquipement() {
|
||||
static getTypesObjetsEquipement() {
|
||||
return typesObjetsEquipement
|
||||
}
|
||||
|
||||
@ -56,120 +77,141 @@ export class RdDItem extends Item {
|
||||
return typesObjetsOeuvres
|
||||
}
|
||||
|
||||
isCompetencePersonnage() {
|
||||
return this.type == 'competence'
|
||||
}
|
||||
isCompetence() {
|
||||
return Misc.data(this).type == 'competence';
|
||||
return typesObjetsCompetence.includes(this.type)
|
||||
}
|
||||
isEquipement() {
|
||||
return typesObjetsEquipement.includes(this.type)
|
||||
}
|
||||
isOeuvre() {
|
||||
return typesObjetsOeuvres.includes(this.type)
|
||||
}
|
||||
isDraconique() {
|
||||
return typesObjetsDraconiques.includes(this.type)
|
||||
}
|
||||
isEffet() {
|
||||
return typesObjetsEffet.includes(this.type)
|
||||
}
|
||||
isConnaissance() {
|
||||
return typesObjetsConnaissance.includes(this.type)
|
||||
}
|
||||
isConteneur() {
|
||||
return this.type == 'conteneur';
|
||||
}
|
||||
|
||||
isConteneur() {
|
||||
return Misc.data(this).type == 'conteneur';
|
||||
getItemGroup() {
|
||||
if (this.isEquipement()) return "equipement";
|
||||
if (this.isOeuvre()) return "oeuvre";
|
||||
if (this.isDraconique()) return "draconique";
|
||||
if (this.isConnaissance()) return "connaissance";
|
||||
if (this.isEffet()) return "effet";
|
||||
if (this.isCompetence()) return "competence";
|
||||
return "autres";
|
||||
}
|
||||
|
||||
isConteneurNonVide() {
|
||||
return this.isConteneur() && (Misc.templateData(this).contenu?.length ?? 0) > 0;
|
||||
return this.isConteneur() && (this.system.contenu?.length ?? 0) > 0;
|
||||
}
|
||||
|
||||
isConteneurVide() {
|
||||
return this.isConteneur() && (Misc.templateData(this).contenu?.length ?? 0) == 0;
|
||||
return this.isConteneur() && (this.system.contenu?.length ?? 0) == 0;
|
||||
}
|
||||
|
||||
isVideOuNonConteneur() {
|
||||
return !this.isConteneur() || (Misc.templateData(this).contenu?.length ?? 0) == 0;
|
||||
return !this.isConteneur() || (this.system.contenu?.length ?? 0) == 0;
|
||||
}
|
||||
|
||||
isAlcool() {
|
||||
const itemData = Misc.data(this);
|
||||
return itemData.type == 'nourritureboisson' && itemData.data.boisson && itemData.data.alcoolise;
|
||||
return this.type == 'nourritureboisson' && this.system.boisson && this.system.alcoolise;
|
||||
}
|
||||
isHerbeAPotion() {
|
||||
const itemData = Misc.data(this);
|
||||
return itemData.type == 'herbe' && (itemData.data.categorie == 'Soin' || itemData.data.categorie == 'Repos');
|
||||
return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos');
|
||||
}
|
||||
isPotion() {
|
||||
return Misc.data(this).type == 'potion';
|
||||
return this.type == 'potion';
|
||||
}
|
||||
|
||||
isEquipement() {
|
||||
return RdDItem.getTypeObjetsEquipement().includes(Misc.data(this).type);
|
||||
}
|
||||
|
||||
isCristalAlchimique() {
|
||||
const itemData = Misc.data(this);
|
||||
return itemData.type == 'objet' && Grammar.toLowerCaseNoAccent(itemData.name) == 'cristal alchimique' && itemData.data.quantite > 0;
|
||||
return this.type == 'objet' && Grammar.toLowerCaseNoAccent(this.name) == 'cristal alchimique' && this.system.quantite > 0;
|
||||
}
|
||||
|
||||
isMagique() {
|
||||
return Misc.templateData(this).magique;
|
||||
return this.system.magique
|
||||
}
|
||||
|
||||
getQuantite() {
|
||||
return Math.round(this.isConteneur() ? 1 : (this.system.quantite ?? 0))
|
||||
}
|
||||
|
||||
getEncTotal() {
|
||||
const itemData = Misc.data(this);
|
||||
return Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
|
||||
}
|
||||
return this.getEnc() * this.getQuantite();
|
||||
}
|
||||
|
||||
getEnc() {
|
||||
const itemData = Misc.data(this);
|
||||
switch (itemData.type) {
|
||||
switch (this.type) {
|
||||
case 'herbe':
|
||||
return encBrin;
|
||||
case 'gemme':
|
||||
return encPepin * this.system.taille;
|
||||
}
|
||||
return itemData.data.encombrement ?? 0;
|
||||
return Math.max(this.system.encombrement ?? 0, 0);
|
||||
}
|
||||
|
||||
prixTotalDeniers() {
|
||||
return this.getQuantite() * this.valeurDeniers()
|
||||
}
|
||||
|
||||
valeurDeniers() {
|
||||
return Math.max(Math.round(this.system.cout ? (this.system.cout * 100) : (this.system.valeur_deniers ?? 0)), 0)
|
||||
}
|
||||
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData();
|
||||
if (this.isEquipement()) {
|
||||
this._calculsEquipement();
|
||||
|
||||
this.system.encTotal = this.getEncTotal();
|
||||
if (this.isPotion()) {
|
||||
this.prepareDataPotion()
|
||||
}
|
||||
const itemData = Misc.data(this);
|
||||
itemData.data.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
|
||||
this.system.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
|
||||
}
|
||||
}
|
||||
|
||||
prepareDataPotion() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const categorie = Grammar.toLowerCaseNoAccent(tplData.categorie);
|
||||
tplData.magique = categorie.includes('enchante');
|
||||
if (tplData.magique) {
|
||||
const categorie = Grammar.toLowerCaseNoAccent(this.system.categorie);
|
||||
this.system.magique = categorie.includes('enchante');
|
||||
if (this.system.magique) {
|
||||
if (categorie.includes('soin') || categorie.includes('repos')) {
|
||||
tplData.puissance = tplData.herbebonus * tplData.pr;
|
||||
// TODO: utiliser calculPointsRepos / calculPointsGuerison
|
||||
this.system.puissance = RdDHerbes.calculPuissancePotion(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_calculsEquipement() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const quantite = this.isConteneur() ? 1 : (tplData.quantite ?? 0);
|
||||
const enc = this.getEnc();
|
||||
if (enc != undefined) {
|
||||
tplData.encTotal = Math.max(enc, 0) * quantite;
|
||||
}
|
||||
if (tplData.cout != undefined) {
|
||||
tplData.prixTotal = Math.max(tplData.cout, 0) * quantite;
|
||||
}
|
||||
}
|
||||
|
||||
getActionPrincipale(options = { warnIfNot: true }) {
|
||||
const itemData = Misc.data(this);
|
||||
if (!this.isConteneur() && (itemData.data.quantite ?? 0) <= 0) {
|
||||
if (options.warnIfNot) {
|
||||
ui.notifications.warn(`Vous n'avez plus de ${itemData.name}.`);
|
||||
const warn = options.warnIfNot;
|
||||
switch (this.type) {
|
||||
case 'nourritureboisson': return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
|
||||
case 'potion': return this._actionOrWarnQuantiteZero('Boire', warn);
|
||||
case 'livre': return this._actionOrWarnQuantiteZero('Lire', warn);
|
||||
case 'conteneur': return 'Ouvrir';
|
||||
case 'herbe': return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
|
||||
case 'queue': case 'ombre': return this.system.refoulement>0 ? 'Refouler' : undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
_actionOrWarnQuantiteZero(actionName, warn){
|
||||
if ((this.system.quantite ?? 0) <= 0) {
|
||||
if (warn) {
|
||||
ui.notifications.warn(`Vous n'avez plus de ${this.name}.`);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
switch (itemData.type) {
|
||||
case 'nourritureboisson': return itemData.data.boisson ? 'Boire' : 'Manger';
|
||||
case 'potion': return 'Boire';
|
||||
case 'livre': return 'Lire';
|
||||
case 'conteneur': return 'Ouvrir';
|
||||
else {
|
||||
return actionName;
|
||||
}
|
||||
if (this.isHerbeAPotion()) { return 'Décoction'; }
|
||||
if (options.warnIfNot) {
|
||||
ui.notifications.warn(`Impossible d'utiliser un ${itemData.name}, aucune action associée définie.`);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
async diminuerQuantite(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
|
||||
@ -178,86 +220,85 @@ export class RdDItem extends Item {
|
||||
}
|
||||
|
||||
async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
|
||||
const itemData = Misc.data(this);
|
||||
const quantite = Number(itemData.data.quantite ?? -1);
|
||||
const quantite = Number(this.system.quantite ?? -1);
|
||||
if (quantite >= 0) {
|
||||
const reste = Math.max(quantite + Number(nombre), 0);
|
||||
|
||||
if (reste == 0) {
|
||||
if (options.supprimerSiZero) {
|
||||
ui.notifications.notify(`${itemData.name} supprimé de votre équipement`);
|
||||
ui.notifications.notify(`${this.name} supprimé de votre équipement`);
|
||||
await this.delete();
|
||||
}
|
||||
else {
|
||||
ui.notifications.notify(`Il ne vous reste plus de ${itemData.name}, vous pouvez le supprimer de votre équipement, ou trouver un moyen de vous en procurer.`);
|
||||
await this.update({ "data.quantite": 0 });
|
||||
ui.notifications.notify(`Il ne vous reste plus de ${this.name}, vous pouvez le supprimer de votre équipement, ou trouver un moyen de vous en procurer.`);
|
||||
await this.update({ "system.quantite": 0 });
|
||||
}
|
||||
}
|
||||
else {
|
||||
await this.update({ "data.quantite": reste });
|
||||
await this.update({ "system.quantite": reste });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// détermine si deux équipements sont similaires: de même type, et avec les même champs hormis la quantité
|
||||
isEquipementSimilaire(other) {
|
||||
const itemData = Misc.data(this);
|
||||
const otherData = Misc.data(other);
|
||||
const tplData = Misc.templateData(this);
|
||||
const otherTplData = Misc.templateData(other);
|
||||
if (!this.isEquipement()) return false;
|
||||
if (itemData.type != otherData.type) return false;
|
||||
if (itemData.name != otherData.name) return false;
|
||||
if (tplData.quantite == undefined) return false;
|
||||
messageEquipementDifferent(other) {
|
||||
if (!other || !this.isEquipement()) return undefined;
|
||||
|
||||
const differences = Object.entries(tplData).filter(([key, value]) => !['quantite', 'encTotal', 'prixTotal', 'cout'].includes(key))
|
||||
.filter(([key, value]) => value != otherTplData[key]);
|
||||
if (differences.length > 0) {
|
||||
let message = `Impossible de regrouper les ${itemData.type} ${itemData.name}: `;
|
||||
for (const [key, value] of differences) {
|
||||
message += `<br>${key}: ${value} vs ${otherTplData[key]}`;
|
||||
}
|
||||
ui.notifications.info(message)
|
||||
return false;
|
||||
let message = undefined;
|
||||
if (this.system.quantite == undefined) {
|
||||
message = `Impossible de regrouper des ${this.type}, ils ne sont pas empilables`;
|
||||
}
|
||||
else if (this.type != other.type) {
|
||||
message = `Impossible de regrouper des ${this.type} avec des ${other.type}`;
|
||||
}
|
||||
return true;
|
||||
else if (this.name != other.name) {
|
||||
message = `Impossible de regrouper ${this.name} avec ${other.name}`;
|
||||
}
|
||||
else {
|
||||
const differences = Object.entries(this.system)
|
||||
.filter(([key, value]) => !['quantite', 'cout'].includes(key) && value != other.system[key]);
|
||||
if (differences.length > 0) {
|
||||
message = `Impossible de regrouper les ${this.type} ${this.name}: `;
|
||||
for (const [key, value] of differences) {
|
||||
message += `<br>${key}: ${value} vs ${other.system[key]}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
async proposerVente() {
|
||||
console.log(this);
|
||||
if (this.isConteneurNonVide()) {
|
||||
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le donner ou le vendre`);
|
||||
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`);
|
||||
return;
|
||||
}
|
||||
const dialog = await DialogItemVente.create(this, (vente) => this._onProposerVente(vente))
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
async _onProposerVente(venteData) {
|
||||
venteData["properties"] = this.getProprietes();
|
||||
if (venteData.isOwned) {
|
||||
if (venteData.quantiteNbLots * venteData.tailleLot > venteData.quantiteMax) {
|
||||
ui.notifications.warn(`Vous avez ${venteData.quantiteMax} ${venteData.item.name}, ce n'est pas suffisant pour vendre ${venteData.quantiteNbLots} de ${venteData.tailleLot}`)
|
||||
return;
|
||||
await DialogItemVente.display(this, async (vente) => {
|
||||
vente["properties"] = this.getProprietes();
|
||||
if (vente.isOwned) {
|
||||
if (vente.quantiteNbLots * vente.tailleLot > vente.quantiteMax) {
|
||||
ui.notifications.warn(`Vous avez ${vente.quantiteMax} ${vente.item.name}, ce n'est pas suffisant pour vendre ${vente.quantiteNbLots} de ${vente.tailleLot}`)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
venteData.jsondata = JSON.stringify(venteData.item);
|
||||
|
||||
console.log(venteData);
|
||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', venteData);
|
||||
ChatMessage.create(RdDUtility.chatDataSetup(html));
|
||||
vente.jsondata = JSON.stringify(vente.item);
|
||||
|
||||
console.log(vente);
|
||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
|
||||
ChatMessage.create(RdDUtility.chatDataSetup(html));
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getProprietes() {
|
||||
return this[`_${Misc.data(this).type}ChatData`]();
|
||||
return this[`_${this.type}ChatData`]();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async postItem(modeOverride) {
|
||||
console.log(this);
|
||||
let chatData = duplicate(Misc.data(this));
|
||||
let chatData = duplicate(this);
|
||||
const properties = this.getProprietes();
|
||||
chatData["properties"] = properties
|
||||
if (this.actor) {
|
||||
@ -282,7 +323,7 @@ export class RdDItem extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_objetChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [].concat(
|
||||
RdDItem.propertyIfDefined('Résistance', tplData.resistance, tplData.resistance),
|
||||
RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
|
||||
@ -293,7 +334,7 @@ export class RdDItem extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_nourritureboissonChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [].concat(
|
||||
RdDItem.propertyIfDefined('Sustentation', tplData.sust, tplData.sust > 0),
|
||||
RdDItem.propertyIfDefined('Désaltère', tplData.desaltere, tplData.boisson),
|
||||
@ -306,7 +347,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_armeChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Compétence</b>: ${tplData.competence}`,
|
||||
`<b>Dommages</b>: ${tplData.dommages}`,
|
||||
@ -318,7 +359,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_conteneurChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Capacité</b>: ${tplData.capacite} Enc.`,
|
||||
`<b>Encombrement</b>: ${tplData.encombrement}`
|
||||
@ -327,7 +368,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_munitionChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Encombrement</b>: ${tplData.encombrement}`
|
||||
]
|
||||
@ -335,7 +376,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_armureChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Protection</b>: ${tplData.protection}`,
|
||||
`<b>Détérioration</b>: ${tplData.deterioration}`,
|
||||
@ -346,7 +387,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_competenceChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Catégorie</b>: ${tplData.categorie}`,
|
||||
`<b>Niveau</b>: ${tplData.niveau}`,
|
||||
@ -357,7 +398,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_competencecreatureChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Catégorie</b>: ${tplData.categorie}`,
|
||||
`<b>Niveau</b>: ${tplData.niveau}`,
|
||||
@ -368,7 +409,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_sortChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Draconic</b>: ${tplData.draconic}`,
|
||||
`<b>Difficulté</b>: ${tplData.difficulte}`,
|
||||
@ -379,7 +420,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_herbeChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Milieu</b>: ${tplData.milieu}`,
|
||||
`<b>Rareté</b>: ${tplData.rarete}`,
|
||||
@ -389,7 +430,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_ingredientChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Milieu</b>: ${tplData.milieu}`,
|
||||
`<b>Rareté</b>: ${tplData.rarete}`,
|
||||
@ -399,7 +440,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_tacheChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Caractéristique</b>: ${tplData.carac}`,
|
||||
`<b>Compétence</b>: ${tplData.competence}`,
|
||||
@ -415,7 +456,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_livreChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Compétence</b>: ${tplData.competence}`,
|
||||
`<b>Auteur</b>: ${tplData.auteur}`,
|
||||
@ -427,7 +468,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_potionChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Rareté</b>: ${tplData.rarete}`,
|
||||
`<b>Catégorie</b>: ${tplData.categorie}`,
|
||||
@ -437,7 +478,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_queueChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Refoulement</b>: ${tplData.refoulement}`
|
||||
]
|
||||
@ -445,7 +486,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_ombreChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Refoulement</b>: ${tplData.refoulement}`
|
||||
]
|
||||
@ -453,19 +494,19 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_souffleChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [];
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_teteChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [];
|
||||
return properties;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_tarotChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Concept</b>: ${tplData.concept}`,
|
||||
`<b>Aspect</b>: ${tplData.aspect}`,
|
||||
@ -474,7 +515,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_nombreastralChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Valeur</b>: ${tplData.value}`,
|
||||
`<b>Jour</b>: ${tplData.jourlabel}`,
|
||||
@ -483,7 +524,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_monnaieChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Valeur en Deniers</b>: ${tplData.valeur_deniers}`,
|
||||
`<b>Encombrement</b>: ${tplData.encombrement}`
|
||||
@ -492,7 +533,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_meditationChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Thème</b>: ${tplData.theme}`,
|
||||
`<b>Compétence</b>: ${tplData.competence}`,
|
||||
@ -507,7 +548,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_casetmrChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Coordonnée</b>: ${tplData.coord}`,
|
||||
`<b>Spécificité</b>: ${tplData.specific}`
|
||||
@ -516,7 +557,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_maladieChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties
|
||||
if (tplData.identifie) {
|
||||
properties = [
|
||||
@ -541,7 +582,7 @@ export class RdDItem extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_gemmeChatData() {
|
||||
const tplData = Misc.templateData(this);
|
||||
const tplData = this.system
|
||||
let properties = [
|
||||
`<b>Pureté</b>: ${tplData.purete}`,
|
||||
`<b>Taille</b>: ${tplData.taille}`,
|
||||
|
160
module/migrations.js
Normal file
160
module/migrations.js
Normal file
@ -0,0 +1,160 @@
|
||||
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
|
||||
class Migration {
|
||||
get code() { return "sample"; }
|
||||
get version() { return "0.0.0"; }
|
||||
async migrate() { }
|
||||
|
||||
async applyItemsUpdates(computeUpdates) {
|
||||
await game.actors.forEach(async (actor) => {
|
||||
const actorItemUpdates = computeUpdates(actor.items);
|
||||
if (actorItemUpdates.length > 0) {
|
||||
console.log(
|
||||
this.code,
|
||||
`Applying updates on actor ${actor.name} items`,
|
||||
actorItemUpdates
|
||||
);
|
||||
await actor.updateEmbeddedDocuments("Item", actorItemUpdates);
|
||||
}
|
||||
});
|
||||
|
||||
const itemUpdates = computeUpdates(game.items);
|
||||
if (itemUpdates.length > 0) {
|
||||
console.log(this.code, "Applying updates on items", itemUpdates);
|
||||
await Item.updateDocuments(itemUpdates);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class _10_0_16_MigrationSortsReserve extends Migration {
|
||||
get code() { return "creation-item-sort-reserve"; }
|
||||
get version() { return "10.0.16"; }
|
||||
|
||||
async migrate() {
|
||||
await game.actors
|
||||
.filter((actor) => actor.type == "personnage")
|
||||
.filter((actor) => actor.system.reve?.reserve?.list?.length ?? 0 > 0)
|
||||
.forEach(async (actor) => {
|
||||
const sortsReserve = actor.system.reve.reserve.list.map(this.conversionSortReserve);
|
||||
console.log(`${LOG_HEAD} Migration des sorts en réserve de ${actor.name}`, sortsReserve);
|
||||
await actor.createEmbeddedDocuments("Item", sortsReserve, {
|
||||
renderSheet: false,
|
||||
});
|
||||
await actor.update({ 'system.reve.reserve.list': [] })
|
||||
});
|
||||
}
|
||||
|
||||
conversionSortReserve(it) {
|
||||
return {
|
||||
type: 'sortreserve',
|
||||
name: it.sort.name,
|
||||
img: it.sort.img,
|
||||
system: {
|
||||
// ATTENTION, utilisation de data / _id possibles, encore présents pour les anciens sorts en réserve
|
||||
sortid: it.sort._id,
|
||||
draconic: it.sort.draconic,
|
||||
ptreve: (it.sort.system ?? it.sort.data).ptreve_reel,
|
||||
coord: it.coord,
|
||||
heurecible: 'Vaisseau',
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
class _10_0_17_MigrationCompetenceCreature extends Migration {
|
||||
get code() { return "competences-creature-parade"; }
|
||||
get version() { return "10.0.17"; }
|
||||
|
||||
async migrate() {
|
||||
await this.applyItemsUpdates(items => items
|
||||
.filter(it => it.type == "competencecreature" && it.system.isparade && it.system.categorie_parade == "")
|
||||
.map(it => { return { _id: it.id, "system.categorie_parade": "armes-naturelles" } }));
|
||||
|
||||
await this.applyItemsUpdates(items => items
|
||||
.filter(it => it.type == "competencecreature" && it.system.iscombat)
|
||||
.map(it => { return { _id: it.id, "system.categorie": (Grammar.includesLowerCaseNoAccent(it.name, "lancee") ? "lancer" : "melee") } })
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class _10_0_21_VehiculeStructureResistanceMax extends Migration {
|
||||
get code() { return "vehicule-structure-resistance-max"; }
|
||||
get version() { return "10.0.21"; }
|
||||
|
||||
async migrate() {
|
||||
await game.actors
|
||||
.filter((actor) => actor.type == "vehicule")
|
||||
.forEach(async (actor) => {
|
||||
await actor.update({
|
||||
'system.etat.resistance.value': actor.system.resistance,
|
||||
'system.etat.resistance.max': actor.system.resistance,
|
||||
'system.etat.structure.value': actor.system.structure,
|
||||
'system.etat.structure.max': actor.system.structure
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class Migrations {
|
||||
static getMigrations() {
|
||||
return [
|
||||
new _10_0_16_MigrationSortsReserve(),
|
||||
new _10_0_17_MigrationCompetenceCreature(),
|
||||
new _10_0_21_VehiculeStructureResistanceMax(),
|
||||
];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
game.settings.register(SYSTEM_RDD, "systemMigrationVersion", {
|
||||
name: "System Migration Version",
|
||||
scope: "world",
|
||||
config: false,
|
||||
type: String,
|
||||
default: "0.0.0",
|
||||
});
|
||||
}
|
||||
|
||||
migrate() {
|
||||
const currentVersion = game.settings.get(
|
||||
SYSTEM_RDD,
|
||||
"systemMigrationVersion"
|
||||
);
|
||||
if (isNewerVersion(game.system.version, currentVersion)) {
|
||||
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
|
||||
if (migrations.length > 0) {
|
||||
migrations.sort((a, b) =>
|
||||
isNewerVersion(a.version, b.version)
|
||||
? 1
|
||||
: isNewerVersion(b.version, a.version)
|
||||
? -1
|
||||
: 0
|
||||
);
|
||||
migrations.forEach(async (m) => {
|
||||
ui.notifications.info(
|
||||
`Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}`
|
||||
);
|
||||
await m.migrate();
|
||||
});
|
||||
ui.notifications.info(
|
||||
`Migrations done, version will change to ${game.system.version}`
|
||||
);
|
||||
} else {
|
||||
console.log(
|
||||
LOG_HEAD +
|
||||
`No migration needeed, version will change to ${game.system.version}`
|
||||
);
|
||||
}
|
||||
|
||||
game.settings.set(
|
||||
SYSTEM_RDD,
|
||||
"systemMigrationVersion",
|
||||
game.system.version
|
||||
);
|
||||
} else {
|
||||
console.log(LOG_HEAD + `No system version changed`);
|
||||
}
|
||||
}
|
||||
}
|
@ -69,9 +69,9 @@ export class Misc {
|
||||
}
|
||||
|
||||
static classify(items, classifier = it => it.type) {
|
||||
let itemsBy = {};
|
||||
Misc.classifyInto(itemsBy, items, classifier);
|
||||
return itemsBy;
|
||||
let itemsBy = {}
|
||||
Misc.classifyInto(itemsBy, items, classifier)
|
||||
return itemsBy
|
||||
}
|
||||
|
||||
static classifyFirst(items, classifier) {
|
||||
@ -87,13 +87,13 @@ export class Misc {
|
||||
|
||||
static classifyInto(itemsBy, items, classifier = it => it.type) {
|
||||
for (const item of items) {
|
||||
const classification = classifier(item);
|
||||
const classification = classifier(item)
|
||||
let list = itemsBy[classification];
|
||||
if (!list) {
|
||||
list = [];
|
||||
itemsBy[classification] = list;
|
||||
list = []
|
||||
itemsBy[classification] = list
|
||||
}
|
||||
list.push(item);
|
||||
list.push(item)
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,28 +105,6 @@ export class Misc {
|
||||
return params.reduce((a, b) => a + separator + b);
|
||||
}
|
||||
|
||||
|
||||
static data(it) {
|
||||
if (it instanceof Actor || it instanceof Item || it instanceof Combatant) {
|
||||
return it.data;
|
||||
}
|
||||
return it;
|
||||
}
|
||||
|
||||
static templateData(it) {
|
||||
return Misc.data(it)?.data ?? {}
|
||||
}
|
||||
|
||||
static getEntityTypeLabel(entity) {
|
||||
const documentName = entity?.documentName;
|
||||
const type = entity?.data.type;
|
||||
if (documentName === 'Actor' || documentName === 'Item') {
|
||||
const label = CONFIG[documentName]?.typeLabels?.[type] ?? type;
|
||||
return game.i18n.has(label) ? game.i18n.localize(label) : t;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
static connectedGMOrUser(ownerId = undefined) {
|
||||
if (ownerId && game.user.id == ownerId) {
|
||||
return ownerId;
|
||||
@ -134,16 +112,12 @@ export class Misc {
|
||||
return Misc.firstConnectedGM()?.id ?? game.user.id;
|
||||
}
|
||||
|
||||
static getUsers() {
|
||||
return game.version ? game.users : game.users.entities;
|
||||
}
|
||||
|
||||
static getActiveUser(id) {
|
||||
return Misc.getUsers().find(u => u.id == id && u.active);
|
||||
return game.users.find(u => u.id == id && u.active);
|
||||
}
|
||||
|
||||
static firstConnectedGM() {
|
||||
return Misc.getUsers().filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
|
||||
return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
|
||||
|
||||
}
|
||||
|
||||
@ -164,7 +138,7 @@ export class Misc {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static findPlayer(name) {
|
||||
return Misc.findFirstLike(name, Misc.getUsers(), { description: 'joueur' });
|
||||
return Misc.findFirstLike(name, game.users, { description: 'joueur' });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -192,7 +166,7 @@ export class Misc {
|
||||
if (!single) {
|
||||
single = subset[0];
|
||||
const choices = Misc.join(subset.map(it => options.mapper(it)), '<br>');
|
||||
options.info(`Plusieurs choix de ${options.description}s possibles:<br>${choices}<br>Le premier sera choisi: ${mapToValue(single)}`);
|
||||
options.onMessage(`Plusieurs choix de ${options.description}s possibles:<br>${choices}<br>Le premier sera choisi: ${options.mapper(single)}`);
|
||||
}
|
||||
return single;
|
||||
}
|
||||
@ -211,7 +185,7 @@ export class Misc {
|
||||
}
|
||||
value = Grammar.toLowerCaseNoAccent(value);
|
||||
const subset = elements.filter(options.preFilter)
|
||||
.filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it)).includes(value));
|
||||
.filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value));
|
||||
if (subset.length == 0) {
|
||||
options.onMessage(`Pas de ${options.description} correspondant à ${value}`);
|
||||
}
|
||||
|
@ -7,9 +7,9 @@ const matchOperationTerms = new RegExp(/@(\w*){([\w\-]+)}/i);
|
||||
export class RdDAlchimie {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static processManipulation(recetteData, actorId = undefined) {
|
||||
static processManipulation(recette, actorId = undefined) {
|
||||
//console.log("CALLED", recette, recette.isOwned, actorId );
|
||||
let manip = recetteData.data.manipulation;
|
||||
let manip = recette.system.manipulation;
|
||||
let matchArray = manip.match(matchOperations);
|
||||
if (matchArray) {
|
||||
for (let matchStr of matchArray) {
|
||||
@ -17,12 +17,12 @@ export class RdDAlchimie {
|
||||
//console.log("RESULT ", result);
|
||||
if (result[1] && result[2]) {
|
||||
let commande = Misc.upperFirst(result[1]);
|
||||
let replacement = this[`_alchimie${commande}`](recetteData, result[2], actorId);
|
||||
let replacement = this[`_alchimie${commande}`](recette, result[2], actorId);
|
||||
manip = manip.replace(result[0], replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
recetteData.data.manipulation_update = manip;
|
||||
recette.system.manipulation_update = manip;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -12,23 +12,23 @@ export class RdDAstrologieJoueur extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
static async create(actor, dialogConfig) {
|
||||
|
||||
let data = {
|
||||
let dialogData = {
|
||||
nombres: this.organizeNombres(actor),
|
||||
dates: game.system.rdd.calendrier.getJoursSuivants(10),
|
||||
etat: actor.getEtatGeneral(),
|
||||
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
|
||||
astrologie: RdDItemCompetence.findCompetence(actor.data.items, 'Astrologie')
|
||||
astrologie: RdDItemCompetence.findCompetence(actor.items, 'Astrologie')
|
||||
}
|
||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', data);
|
||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', dialogData);
|
||||
let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 };
|
||||
if (dialogConfig.options) {
|
||||
mergeObject(options, dialogConfig.options, { overwrite: true });
|
||||
}
|
||||
return new RdDAstrologieJoueur(html, actor, data);
|
||||
return new RdDAstrologieJoueur(html, actor, dialogData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, actor, data) {
|
||||
constructor(html, actor, dialogData) {
|
||||
|
||||
let myButtons = {
|
||||
saveButton: { label: "Fermer", callback: html => this.quitDialog() }
|
||||
@ -41,7 +41,7 @@ export class RdDAstrologieJoueur extends Dialog {
|
||||
super(dialogConf, dialogOptions);
|
||||
|
||||
this.actor = actor;
|
||||
this.dataNombreAstral = duplicate(data);
|
||||
this.dataNombreAstral = duplicate(dialogData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -49,12 +49,12 @@ export class RdDAstrologieJoueur extends Dialog {
|
||||
let itemNombres = actor.listItemsData('nombreastral');
|
||||
let itemFiltered = {};
|
||||
for (let item of itemNombres) {
|
||||
if (itemFiltered[item.data.jourindex]) {
|
||||
itemFiltered[item.data.jourindex].listValues.push(item.data.value);
|
||||
if (itemFiltered[item.system.jourindex]) {
|
||||
itemFiltered[item.system.jourindex].listValues.push(item.system.value);
|
||||
} else {
|
||||
itemFiltered[item.data.jourindex] = {
|
||||
listValues: [item.data.value],
|
||||
jourlabel: item.data.jourlabel
|
||||
itemFiltered[item.system.jourindex] = {
|
||||
listValues: [item.system.value],
|
||||
jourlabel: item.system.jourlabel
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -63,9 +63,9 @@ export class RdDAstrologieJoueur extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
requestJetAstrologie() {
|
||||
let data = {
|
||||
id: this.actor.data._id,
|
||||
carac_vue: Misc.data(this.actor).data.carac['vue'].value,
|
||||
let socketData = {
|
||||
id: this.actor.id,
|
||||
carac_vue: this.actor.system.carac['vue'].value,
|
||||
etat: this.dataNombreAstral.etat,
|
||||
astrologie: this.dataNombreAstral.astrologie,
|
||||
conditions: $("#diffConditions").val(),
|
||||
@ -73,11 +73,11 @@ export class RdDAstrologieJoueur extends Dialog {
|
||||
userId: game.user.id
|
||||
}
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
game.system.rdd.calendrier.requestNombreAstral(data);
|
||||
game.system.rdd.calendrier.requestNombreAstral(socketData);
|
||||
} else {
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||
msg: "msg_request_nombre_astral",
|
||||
data: data
|
||||
data: socketData
|
||||
});
|
||||
}
|
||||
this.close();
|
||||
|
@ -20,7 +20,7 @@ export class RdDBonus {
|
||||
|
||||
static isAjustementAstrologique(rollData) {
|
||||
return RdDCarac.isChance(rollData.selectedCarac) ||
|
||||
rollData.selectedSort?.data.isrituel;
|
||||
rollData.selectedSort?.system.isrituel;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isDefenseAttaqueFinesse(rollData) {
|
||||
@ -68,23 +68,23 @@ export class RdDBonus {
|
||||
}
|
||||
return isCauchemar ? "cauchemar"
|
||||
: rollData.dmg?.mortalite
|
||||
?? rollData.arme?.data.mortalite
|
||||
?? rollData.arme?.system.mortalite
|
||||
?? "mortel";
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _dmgArme(rollData) {
|
||||
if ( rollData.arme) {
|
||||
let dmgBase = rollData.arme.data.dommagesReels ?? Number(rollData.arme.data.dommages ?? 0);
|
||||
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0);
|
||||
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
|
||||
return dmgBase + Math.min(dmgBase, rollData.arme.data.magique ? rollData.arme.data.ecaille_efficacite : 0);
|
||||
return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _peneration(rollData) {
|
||||
return parseInt(rollData.arme?.data.penetration ?? 0);
|
||||
return parseInt(rollData.arme?.system.penetration ?? 0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -223,9 +223,9 @@ export class RdDCalendrier extends Application {
|
||||
checkMaladie( periode) {
|
||||
for (let actor of game.actors) {
|
||||
if (actor.type == 'personnage') {
|
||||
let maladies = actor.filterItems( item => (item.type == 'maladie' || (item.type == 'poison' && item.data.active) ) && item.data.periodicite.toLowerCase().includes(periode) );
|
||||
let maladies = actor.items.filter( item => (item.type == 'maladie' || (item.type == 'poison' && item.system.active) ) && item.system.periodicite.toLowerCase().includes(periode) );
|
||||
for (let maladie of maladies) {
|
||||
if ( maladie.data.identifie) {
|
||||
if ( maladie.system.identifie) {
|
||||
ChatMessage.create({ content: `${actor.name} souffre de ${maladie.name} (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
|
||||
} else {
|
||||
ChatMessage.create({ content: `${actor.name} souffre d'un mal inconnu (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
|
||||
@ -320,7 +320,7 @@ export class RdDCalendrier extends Application {
|
||||
if (Misc.isUniqueConnectedGM()) { // Only once
|
||||
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 niveau = Number(request.astrologie.system.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
|
||||
let rollData = {
|
||||
caracValue: request.carac_vue,
|
||||
finalLevel: niveau,
|
||||
@ -444,9 +444,9 @@ export class RdDCalendrier extends Application {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateDisplay() {
|
||||
let data = this.fillCalendrierData();
|
||||
// Rebuild data
|
||||
let dateHTML = `Jour ${data.jourMois} de ${data.nomMois} (${data.nomSaison})`
|
||||
let calendrier = this.fillCalendrierData();
|
||||
// Rebuild text du calendrier
|
||||
let dateHTML = `Jour ${calendrier.jourMois} de ${calendrier.nomMois} (${calendrier.nomSaison})`
|
||||
if (game.user.isGM) {
|
||||
dateHTML = dateHTML + " - NA: " + (this.getCurrentNombreAstral() ?? "indéterminé");
|
||||
}
|
||||
@ -454,13 +454,13 @@ export class RdDCalendrier extends Application {
|
||||
handle.innerHTML = dateHTML;
|
||||
}
|
||||
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
|
||||
heure.innerHTML = data.nomHeure;
|
||||
heure.innerHTML = calendrier.nomHeure;
|
||||
}
|
||||
for (const minute of document.getElementsByClassName("calendar-time-disp")) {
|
||||
minute.innerHTML = `${data.minutesRelative} minutes`;
|
||||
minute.innerHTML = `${calendrier.minutesRelative} minutes`;
|
||||
}
|
||||
for (const heureImg of document.getElementsByClassName("calendar-heure-img")) {
|
||||
heureImg.src = data.iconHeure;
|
||||
heureImg.src = calendrier.iconHeure;
|
||||
}
|
||||
}
|
||||
|
||||
@ -534,9 +534,7 @@ export class RdDCalendrier extends Application {
|
||||
async activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
|
||||
|
||||
await this.updateDisplay();
|
||||
this.updateDisplay();
|
||||
|
||||
html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
|
||||
|
||||
|
@ -62,7 +62,7 @@ export class RdDCarac {
|
||||
|
||||
|
||||
static computeTotal(carac, beaute = undefined) {
|
||||
const total = Object.values(carac).filter(c => !c.derivee)
|
||||
const total = Object.values(carac ?? {}).filter(c => !c.derivee)
|
||||
.map(it => parseInt(it.value))
|
||||
.reduce(Misc.sum(), 0);
|
||||
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0);
|
||||
@ -101,35 +101,35 @@ export class RdDCarac {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeCarac(data) {
|
||||
data.carac.force.value = Math.min(data.carac.force.value, parseInt(data.carac.taille.value) + 4);
|
||||
static computeCarac(system) {
|
||||
system.carac.force.value = Math.min(system.carac.force.value, parseInt(system.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);
|
||||
system.carac.derobee.value = Math.floor(parseInt(((21 - system.carac.taille.value)) + parseInt(system.carac.agilite.value)) / 2);
|
||||
let bonusDomKey = Math.floor((parseInt(system.carac.force.value) + parseInt(system.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;
|
||||
system.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;
|
||||
system.attributs.sconst.value = RdDCarac.calculSConst(system.carac.constitution.value);
|
||||
system.attributs.sust.value = tableCaracDerivee[Number(system.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);
|
||||
system.attributs.encombrement.value = (parseInt(system.carac.force.value) + parseInt(system.carac.taille.value)) / 2;
|
||||
system.carac.melee.value = Math.floor((parseInt(system.carac.force.value) + parseInt(system.carac.agilite.value)) / 2);
|
||||
system.carac.tir.value = Math.floor((parseInt(system.carac.vue.value) + parseInt(system.carac.dexterite.value)) / 2);
|
||||
system.carac.lancer.value = Math.floor((parseInt(system.carac.tir.value) + parseInt(system.carac.force.value)) / 2);
|
||||
|
||||
data.sante.vie.max = Math.ceil((parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value)) / 2);
|
||||
system.sante.vie.max = Math.ceil((parseInt(system.carac.taille.value) + parseInt(system.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);
|
||||
system.sante.vie.value = Math.min(system.sante.vie.value, system.sante.vie.max)
|
||||
system.sante.endurance.max = Math.max(parseInt(system.carac.taille.value) + parseInt(system.carac.constitution.value), parseInt(system.sante.vie.max) + parseInt(system.carac.volonte.value));
|
||||
system.sante.endurance.value = Math.min(system.sante.endurance.value, system.sante.endurance.max);
|
||||
system.sante.fatigue.max = system.sante.endurance.max * 2;
|
||||
system.sante.fatigue.value = Math.min(system.sante.fatigue.value, system.sante.fatigue.max);
|
||||
|
||||
//Compteurs
|
||||
data.reve.reve.max = data.carac.reve.value;
|
||||
data.compteurs.chance.max = data.carac.chance.value;
|
||||
system.reve.reve.max = system.carac.reve.value;
|
||||
system.compteurs.chance.max = system.carac.chance.value;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { RdDItemArme } from "./item-arme.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||
@ -9,6 +10,7 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDRoll } from "./rdd-roll.js";
|
||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
import { STATUSES } from "./status-effects.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const premierRoundInit = [
|
||||
@ -26,7 +28,7 @@ const premierRoundInit = [
|
||||
{ pattern: 'epeegnome', init: 5.35 },
|
||||
{ pattern: 'masse', init: 5.30 },
|
||||
{ pattern: 'gourdin', init: 5.25 },
|
||||
{ pattern: 'fléau', init: 5.20 },
|
||||
{ pattern: 'fleau', init: 5.20 },
|
||||
{ pattern: 'dague', init: 5.15 },
|
||||
{ pattern: 'autre', init: 5.10 },
|
||||
];
|
||||
@ -65,7 +67,7 @@ export class RdDCombatManager extends Combat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async finDeRound(options = { terminer: false }) {
|
||||
for (let combatant of this.data.combatants) {
|
||||
for (let combatant of this.combatants) {
|
||||
if (combatant.actor) {
|
||||
await combatant.actor.finDeRound(options);
|
||||
}
|
||||
@ -77,35 +79,30 @@ export class RdDCombatManager extends Combat {
|
||||
|
||||
/************************************************************************************/
|
||||
async rollInitiative(ids, formula = undefined, messageOptions = {}) {
|
||||
console.log(`${game.data.system.data.title} | Combat.rollInitiative()`, ids, formula, messageOptions);
|
||||
// Structure input data
|
||||
console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions);
|
||||
|
||||
ids = typeof ids === "string" ? [ids] : ids;
|
||||
const currentId = this.combatant._id;
|
||||
// calculate initiative
|
||||
for (let cId = 0; cId < ids.length; cId++) {
|
||||
const combatant = this.combatants.get(ids[cId]);
|
||||
//if (!c) return results;
|
||||
|
||||
let rollFormula = formula; // Init per default
|
||||
if (!rollFormula) {
|
||||
let armeCombat, competence;
|
||||
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
|
||||
for (const competenceItemData of combatant.actor.data.items) {
|
||||
if (competenceItemData.data.data.iscombat) {
|
||||
competence = duplicate(competenceItemData);
|
||||
}
|
||||
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0);
|
||||
if (!formula) {
|
||||
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
|
||||
const competence = combatant.actor.items.find(it => it.system.iscombat)
|
||||
if (competence) {
|
||||
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, 0);
|
||||
}
|
||||
rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, competence.data.carac_value) + ")/100)";
|
||||
} else {
|
||||
for (const itemData of combatant.actor.data.items) {
|
||||
if (itemData.type == "arme" && itemData.data.equipe) {
|
||||
armeCombat = duplicate(itemData);
|
||||
}
|
||||
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
|
||||
const compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.system.competence;
|
||||
const competence = RdDItemCompetence.findCompetence(combatant.actor.items, compName);
|
||||
if (competence) {
|
||||
const carac = combatant.actor.system.carac[competence.system.defaut_carac].value;
|
||||
const niveau = competence.system.niveau;
|
||||
const bonusEcaille = (armeCombat?.system.magique) ? armeCombat.system.ecaille_efficacite : 0;
|
||||
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, bonusEcaille);
|
||||
}
|
||||
let compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.data.competence;
|
||||
competence = RdDItemCompetence.findCompetence(combatant.actor.data.items, compName);
|
||||
let bonusEcaille = (armeCombat && armeCombat.data.magique) ? armeCombat.data.ecaille_efficacite : 0;
|
||||
rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, Misc.data(combatant.actor).data.carac[competence.data.defaut_carac].value, bonusEcaille) + ")/100)";
|
||||
}
|
||||
}
|
||||
//console.log("Combatat", c);
|
||||
@ -142,6 +139,10 @@ export class RdDCombatManager extends Combat {
|
||||
return this;
|
||||
};
|
||||
|
||||
static formuleInitiative(rang, carac, niveau, bonusMalus) {
|
||||
return `${rang} +( (${RdDCombatManager.calculInitiative(niveau, carac, bonusMalus)} )/100)`;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static calculInitiative(niveau, caracValue, bonusEcaille = 0) {
|
||||
let base = niveau + Math.floor(caracValue / 2);
|
||||
@ -150,78 +151,98 @@ export class RdDCombatManager extends Combat {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** Retourne une liste triée d'armes avec le split arme1 main / arme 2 main */
|
||||
static finalizeArmeList(armes, competences, carac) {
|
||||
/** Retourne une liste triée d'actions d'armes avec le split arme1 main / arme 2 main */
|
||||
static listActionsArmes(armes, competences, carac) {
|
||||
// Gestion des armes 1/2 mains
|
||||
let armesEquipe = [];
|
||||
let actionsArme = [];
|
||||
for (const arme of armes) {
|
||||
let armeData = duplicate(Misc.data(arme));
|
||||
if (armeData.data.equipe) {
|
||||
let compData = competences.map(c => Misc.data(c)).find(c => c.name == armeData.data.competence);
|
||||
let action = duplicate(arme)
|
||||
if (action.system.equipe) {
|
||||
let compData = competences.find(c => c.name == action.system.competence)
|
||||
|
||||
armesEquipe.push(armeData);
|
||||
armeData.data.dommagesReels = Number(armeData.data.dommages);
|
||||
armeData.data.niveau = compData.data.niveau;
|
||||
armeData.data.initiative = RdDCombatManager.calculInitiative(compData.data.niveau, carac[compData.data.defaut_carac].value);
|
||||
actionsArme.push(action);
|
||||
action.action = 'attaque';
|
||||
action.system.dommagesReels = Number(action.system.dommages);
|
||||
action.system.niveau = compData.system.niveau;
|
||||
action.system.initiative = RdDCombatManager.calculInitiative(compData.system.niveau, carac[compData.system.defaut_carac].value);
|
||||
// Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence
|
||||
if (armeData.data.unemain && !armeData.data.deuxmains) {
|
||||
armeData.data.mainInfo = "(1m)";
|
||||
} else if (!armeData.data.unemain && armeData.data.deuxmains) {
|
||||
armeData.data.mainInfo = "(2m)";
|
||||
} else if (armeData.data.unemain && armeData.data.deuxmains) {
|
||||
armeData.data.mainInfo = "(1m)";
|
||||
if (action.system.unemain && !action.system.deuxmains) {
|
||||
action.system.mainInfo = "(1m)";
|
||||
} else if (!action.system.unemain && action.system.deuxmains) {
|
||||
action.system.mainInfo = "(2m)";
|
||||
} else if (action.system.unemain && action.system.deuxmains) {
|
||||
action.system.mainInfo = "(1m)";
|
||||
|
||||
const comp2m = armeData.data.competence.replace(" 1 main", " 2 mains"); // Replace !
|
||||
const comp = Misc.data(competences.find(c => c.name == comp2m));
|
||||
const comp2m = action.system.competence.replace(" 1 main", " 2 mains"); // Replace !
|
||||
const comp = competences.find(c => c.name == comp2m)
|
||||
|
||||
const arme2main = duplicate(armeData);
|
||||
arme2main.data.mainInfo = "(2m)";
|
||||
arme2main.data.niveau = comp.data.niveau;
|
||||
arme2main.data.competence = comp2m;
|
||||
arme2main.data.initiative = RdDCombatManager.calculInitiative(arme2main.data.niveau, carac[comp.data.defaut_carac].value);
|
||||
armesEquipe.push(arme2main);
|
||||
const containsSlash = armeData.data.dommages.includes("/");
|
||||
const arme2main = duplicate(action);
|
||||
arme2main.system.mainInfo = "(2m)";
|
||||
arme2main.system.niveau = comp.system.niveau;
|
||||
arme2main.system.competence = comp2m;
|
||||
arme2main.system.initiative = RdDCombatManager.calculInitiative(arme2main.system.niveau, carac[comp.system.defaut_carac].value);
|
||||
actionsArme.push(arme2main);
|
||||
const containsSlash = action.system.dommages.includes("/");
|
||||
if (containsSlash) {
|
||||
const tableauDegats = armeData.data.dommages.split("/");
|
||||
armeData.data.dommagesReels = Number(tableauDegats[0]);
|
||||
arme2main.data.dommagesReels = Number(tableauDegats[1]);
|
||||
const tableauDegats = action.system.dommages.split("/");
|
||||
action.system.dommagesReels = Number(tableauDegats[0]);
|
||||
arme2main.system.dommagesReels = Number(tableauDegats[1]);
|
||||
}
|
||||
else{
|
||||
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + armeData.name + " ne sont pas corrects (ie sous la forme X/Y)");
|
||||
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + action.name + " ne sont pas corrects (ie sous la forme X/Y)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return armesEquipe.sort(Misc.ascending(armeData => armeData.name + (armeData.data.mainInfo ?? '')));
|
||||
return actionsArme.sort(Misc.ascending(armeData => armeData.name + (armeData.system.mainInfo ?? '')));
|
||||
}
|
||||
|
||||
static listActionsCreature(competences) {
|
||||
return competences.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
|
||||
.map(it => RdDItemCompetenceCreature.toActionArme(it));
|
||||
}
|
||||
|
||||
static listActionsPossessions(actor) {
|
||||
return RdDCombatManager._indexActions(actor.getPossessions().map(p =>
|
||||
{
|
||||
return {
|
||||
name: p.name,
|
||||
action: 'conjurer',
|
||||
system: {
|
||||
competence: p.name,
|
||||
possessionid: p.system.possessionid,
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static buildListeActionsCombat(combatant) {
|
||||
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 [];
|
||||
static listActionsCombat(combatant) {
|
||||
const actor = combatant.actor;
|
||||
let actions = RdDCombatManager.listActionsPossessions(actor);
|
||||
if (actions.length>0) {
|
||||
return actions;
|
||||
}
|
||||
const actorData = Misc.data(combatant.actor);
|
||||
let items = combatant.actor.data.items;
|
||||
let actions = []
|
||||
if (combatant.actor.isCreature()) {
|
||||
actions = actions.concat(items.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
|
||||
.map(competence => RdDItemCompetenceCreature.toArme(competence)));
|
||||
if (actor.isCreature()) {
|
||||
actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']));
|
||||
} else {
|
||||
// Recupération des items 'arme'
|
||||
let armes = items.filter(it => RdDItemArme.isArmeUtilisable(it))
|
||||
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
|
||||
//.concat(RdDItemArme.empoignade())
|
||||
.concat(RdDItemArme.mainsNues());
|
||||
|
||||
let competences = items.filter(it => it.type == 'competence');
|
||||
actions = actions.concat(RdDCombatManager.finalizeArmeList(armes, competences, actorData.data.carac));
|
||||
const competences = actor.itemTypes['competence'];
|
||||
actions = actions.concat(RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac));
|
||||
|
||||
if (actorData.data.attributs.hautrevant.value) {
|
||||
actions.push({ name: "Draconic", data: { initOnly: true, competence: "Draconic" } });
|
||||
if (actor.system.attributs.hautrevant.value) {
|
||||
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
|
||||
}
|
||||
}
|
||||
|
||||
actions.push({ name: "Autre action", data: { initOnly: true, competence: "Autre action" } });
|
||||
return RdDCombatManager._indexActions(actions);
|
||||
}
|
||||
|
||||
static _indexActions(actions) {
|
||||
for (let index = 0; index < actions.length; index++) {
|
||||
actions[index].index = index;
|
||||
}
|
||||
@ -232,18 +253,18 @@ export class RdDCombatManager extends Combat {
|
||||
static processPremierRoundInit() {
|
||||
// Check if we have the whole init !
|
||||
if (Misc.isUniqueConnectedGM() && game.combat.current.round == 1) {
|
||||
let initMissing = game.combat.data.combatants.find(it => !it.initiative);
|
||||
let initMissing = game.combat.combatants.find(it => !it.initiative);
|
||||
if (!initMissing) { // Premier round !
|
||||
for (let combatant of game.combat.data.combatants) {
|
||||
let arme = combatant.initiativeData?.arme;
|
||||
for (let combatant of game.combat.combatants) {
|
||||
let action = combatant.initiativeData?.arme;
|
||||
//console.log("Parsed !!!", combatant, initDone, game.combat.current, arme);
|
||||
if (arme && arme.type == "arme") {
|
||||
if (action && action.type == "arme") {
|
||||
for (let initData of premierRoundInit) {
|
||||
if (arme.data.initpremierround.toLowerCase().includes(initData.pattern)) {
|
||||
if (Grammar.toLowerCaseNoAccentNoSpace(action.system.initpremierround).includes(initData.pattern)) {
|
||||
let msg = `<h4>L'initiative de ${combatant.actor.name} a été modifiée !</h4>
|
||||
<hr>
|
||||
<div>
|
||||
Etant donné son ${arme.name}, son initative pour ce premier round est désormais de ${initData.init}.
|
||||
Etant donné son ${action.name}, son initative pour ce premier round est désormais de ${initData.init}.
|
||||
</div>`
|
||||
ChatMessage.create({ content: msg });
|
||||
game.combat.setInitiative(combatant._id, initData.init);
|
||||
@ -281,7 +302,7 @@ export class RdDCombatManager extends Combat {
|
||||
].concat(options);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static rollInitiativeCompetence(combatantId, arme) {
|
||||
static rollInitiativeAction(combatantId, action) {
|
||||
const combatant = game.combat.combatants.get(combatantId);
|
||||
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!`)
|
||||
@ -299,37 +320,38 @@ export class RdDCombatManager extends Combat {
|
||||
} else if (combatant.actor.getSurprise() == "demi") {
|
||||
initOffset = 0;
|
||||
initInfo = "Demi Surprise"
|
||||
} else if (arme.name == "Autre action") {
|
||||
} else if (action.action == 'conjurer') {
|
||||
initOffset = 10;
|
||||
caracForInit = combatant.actor.getReveActuel();
|
||||
initInfo = "Possession"
|
||||
} else if (action.action == 'autre') {
|
||||
initOffset = 2;
|
||||
initInfo = "Autre Action"
|
||||
} else if (arme.name == "Draconic") {
|
||||
} else if (action.action == 'haut-reve') {
|
||||
initOffset = 9;
|
||||
initInfo = "Draconic"
|
||||
} else {
|
||||
compData = Misc.data(RdDItemCompetence.findCompetence(combatant.actor.data.items, arme.data.competence));
|
||||
compNiveau = compData.data.niveau;
|
||||
initInfo = arme.name + " / " + arme.data.competence;
|
||||
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
|
||||
caracForInit = compData.data.carac_value;
|
||||
if (compData.data.categorie == "lancer") {
|
||||
initOffset = 7;
|
||||
}
|
||||
else {
|
||||
initOffset = 5;
|
||||
}
|
||||
compData = RdDItemCompetence.findCompetence(combatant.actor.items, action.system.competence);
|
||||
compNiveau = compData.system.niveau;
|
||||
initInfo = action.name + " / " + action.system.competence;
|
||||
|
||||
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
|
||||
caracForInit = compData.system.carac_value;
|
||||
} else {
|
||||
caracForInit = Misc.data(combatant.actor).data.carac[compData.data.defaut_carac].value;
|
||||
initOffset = RdDCombatManager._baseInitOffset(compData.data.categorie, arme);
|
||||
caracForInit = combatant.actor.system.carac[compData.system.defaut_carac].value;
|
||||
}
|
||||
initOffset = RdDCombatManager._baseInitOffset(compData.system.categorie, action);
|
||||
}
|
||||
|
||||
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)";
|
||||
let rollFormula = RdDCombatManager.formuleInitiative(initOffset, caracForInit, compNiveau, malus);
|
||||
// Garder la trace de l'arme/compétence utilisée pour l'iniative
|
||||
combatant.initiativeData = { arme: arme } // pour reclasser l'init au round 0
|
||||
combatant.initiativeData = { arme: action } // pour reclasser l'init au round 0
|
||||
game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _baseInitOffset(categorie, arme) {
|
||||
if (categorie == "tir") { // Offset de principe pour les armes de jet
|
||||
return 8;
|
||||
@ -337,10 +359,12 @@ export class RdDCombatManager extends Combat {
|
||||
if (categorie == "lancer") { // Offset de principe pour les armes de jet
|
||||
return 7;
|
||||
}
|
||||
// Offset de principe pour les armes de jet
|
||||
switch (arme.data.cac) {
|
||||
case "empoignade": return 3;
|
||||
case "pugilat": return 4;
|
||||
switch (arme.system.cac) {
|
||||
case "empoignade":
|
||||
return 3;
|
||||
case "pugilat":
|
||||
case "naturelle":
|
||||
return 4;
|
||||
}
|
||||
return 5;
|
||||
}
|
||||
@ -349,16 +373,21 @@ export class RdDCombatManager extends Combat {
|
||||
static displayInitiativeMenu(html, combatantId) {
|
||||
console.log("Combatant ; ", combatantId);
|
||||
const combatant = game.combat.combatants.get(combatantId);
|
||||
let armesList = RdDCombatManager.buildListeActionsCombat(combatant);
|
||||
if (! (combatant?.actor) ) {
|
||||
ui.notifications.warn(`Le combatant ${combatant.name ?? combatantId} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
|
||||
return;
|
||||
}
|
||||
|
||||
let actions = RdDCombatManager.listActionsCombat(combatant);
|
||||
|
||||
// Build the relevant submenu
|
||||
if (armesList) {
|
||||
if (actions) {
|
||||
let menuItems = [];
|
||||
for (let arme of armesList) {
|
||||
for (let action of actions) {
|
||||
menuItems.push({
|
||||
name: arme.data.competence,
|
||||
name: action.system.competence,
|
||||
icon: "<i class='fas fa-dice-d6'></i>",
|
||||
callback: target => { RdDCombatManager.rollInitiativeCompetence(combatantId, arme) }
|
||||
callback: target => { RdDCombatManager.rollInitiativeAction(combatantId, action) }
|
||||
});
|
||||
}
|
||||
new ContextMenu(html, ".directory-list", menuItems).render();
|
||||
@ -387,7 +416,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onUpdateCombat(combat, change, options, userId) {
|
||||
if (combat.data.round != 0 && combat.turns && combat.data.active) {
|
||||
if (combat.round != 0 && combat.turns && combat.active) {
|
||||
RdDCombat.combatNouveauTour(combat);
|
||||
}
|
||||
}
|
||||
@ -420,7 +449,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static createUsingTarget(attacker) {
|
||||
const target = RdDCombat.getTarget();
|
||||
const target = RdDCombat.getTarget()
|
||||
if (target == undefined) {
|
||||
ui.notifications.warn((game.user.targets?.size ?? 0) > 1
|
||||
? "Vous devez choisir <strong>une seule</strong> cible à attaquer!"
|
||||
@ -428,8 +457,8 @@ export class RdDCombat {
|
||||
}
|
||||
else {
|
||||
const defender = target?.actor;
|
||||
const defenderTokenId = target?.data._id;
|
||||
if ( defender.type == 'entite' && defender.data.data.definition.typeentite == 'nonincarne') {
|
||||
const defenderTokenId = target?.id;
|
||||
if ( defender.type == 'entite' && defender.system.definition.typeentite == ENTITE_NONINCARNE) {
|
||||
ui.notifications.warn("Vous ne pouvez pas cibler une entité non incarnée !!!!");
|
||||
} else {
|
||||
return this.create(attacker, defender, defenderTokenId, target)
|
||||
@ -465,15 +494,15 @@ export class RdDCombat {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onMsgEncaisser(data) {
|
||||
let defender = canvas.tokens.get(data.defenderTokenId).actor;
|
||||
static onMsgEncaisser(msg) {
|
||||
let defender = canvas.tokens.get(msg.defenderTokenId).actor;
|
||||
if (Misc.isOwnerPlayerOrUniqueConnectedGM()) {
|
||||
let attackerRoll = data.attackerRoll;
|
||||
let attacker = data.attackerId ? game.actors.get(data.attackerId) : null;
|
||||
let attackerRoll = msg.attackerRoll;
|
||||
let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : null;
|
||||
|
||||
defender.encaisserDommages(attackerRoll, attacker);
|
||||
RdDCombat._deleteDefense(attackerRoll.passeArme);
|
||||
RdDCombat._deleteAttaque(data.attackerId);
|
||||
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
||||
rddCombat?.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
|
||||
}
|
||||
}
|
||||
|
||||
@ -482,11 +511,8 @@ export class RdDCombat {
|
||||
let defenderToken = canvas.tokens.get(msg.defenderTokenId);
|
||||
if (defenderToken && Misc.isUniqueConnectedGM()) {
|
||||
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
||||
if (rddCombat) {
|
||||
const defenderRoll = msg.defenderRoll;
|
||||
rddCombat.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
||||
rddCombat._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll);
|
||||
}
|
||||
rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme);
|
||||
rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll);
|
||||
}
|
||||
}
|
||||
|
||||
@ -530,12 +556,12 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(attacker, defender, defenderTokenId, target) {
|
||||
this.attacker = attacker;
|
||||
this.defender = defender;
|
||||
this.target = target;
|
||||
this.attackerId = this.attacker.data._id;
|
||||
this.defenderId = this.defender.data._id;
|
||||
this.defenderTokenId = defenderTokenId;
|
||||
this.attacker = attacker
|
||||
this.defender = defender
|
||||
this.target = target
|
||||
this.attackerId = this.attacker.id
|
||||
this.defenderId = this.defender.id
|
||||
this.defenderTokenId = defenderTokenId
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -661,12 +687,86 @@ export class RdDCombat {
|
||||
return rollData.rolled.isSuccess;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async proposerAjustementTirLancer( rollData ) {
|
||||
if (['tir', 'lancer'].includes(rollData.competence.system.categorie)) {
|
||||
if (this.defender.isEntite([ENTITE_BLURETTE])){
|
||||
ChatMessage.create( {
|
||||
content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`,
|
||||
whisper: ChatMessage.getWhisperRecipients("GM")})
|
||||
}
|
||||
else {
|
||||
const defenderToken = canvas.tokens.get(this.defenderTokenId);
|
||||
const dist = this.distance(_token, defenderToken)
|
||||
const isVisible = this.isVisible(_token, defenderToken)
|
||||
const portee = this._ajustementPortee(dist, rollData.arme)
|
||||
const taille = this._ajustementTaille(this.defender)
|
||||
const activite = this._ajustementMouvement(this.defender)
|
||||
const total = [portee, taille, activite].map(it=>it.diff).filter(d => !Number.isNaN(d)).reduce(Misc.sum(), 0)
|
||||
ChatMessage.create({
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.html', {
|
||||
rollData: rollData,
|
||||
attacker: _token,
|
||||
isVisible: isVisible,
|
||||
defender: defenderToken,
|
||||
distance: dist,
|
||||
portee: portee,
|
||||
taille: taille,
|
||||
activite: activite,
|
||||
total: total
|
||||
}),
|
||||
whisper: ChatMessage.getWhisperRecipients("GM")
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isVisible(token, defenderToken) {
|
||||
return canvas.effects.visibility.testVisibility(defenderToken.center, { object: token })
|
||||
}
|
||||
|
||||
distance(token, defenderToken) {
|
||||
return Number(canvas.grid.measureDistances([{ ray: new Ray(token.center, defenderToken.center) }], { gridSpaces: false })).toFixed(1);
|
||||
}
|
||||
|
||||
_ajustementPortee(dist, arme) {
|
||||
if (dist <= arme.system.portee_courte) return {msg:"courte", diff:0};
|
||||
if (dist <= arme.system.portee_moyenne) return {msg: "moyenne" , diff: -3};
|
||||
if (dist <= arme.system.portee_extreme) return {msg: "extrême", diff:-5};
|
||||
return {msg: "inatteignable", diff: -10};
|
||||
}
|
||||
|
||||
_ajustementTaille(actor) {
|
||||
if (actor.isVehicule()) return {msg: "véhicule", diff: 0}
|
||||
const taille = actor.getCaracByName('TAILLE')?.value ?? 1;
|
||||
if (taille <= 1) return {msg: "souris", diff: -8};
|
||||
if (taille <= 3) return {msg: "chat", diff: -4};
|
||||
if (taille <= 5) return {msg: "chien", diff: -2};
|
||||
if (taille <= 15) return {msg: "humanoïde", diff: 0};
|
||||
if (taille <= 20) return {msg: "ogre", diff: 2};
|
||||
return {msg: "gigantesque", diff: 4};
|
||||
}
|
||||
_ajustementMouvement(defender) {
|
||||
if (defender.getSurprise(true)) return {msg: "immobile (surprise)", diff: 0};
|
||||
if (game.combat?.combatants.find(it => it.actorId == defender.id)) return {msg: "en mouvement (combat)", diff: -4};
|
||||
return {msg: "à déterminer (0 immobile, -3 actif, -4 en mouvement, -5 en zig-zag)", diff: -3};
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async attaque(competence, arme) {
|
||||
// const nonIncarnee = this.defender.isEntite([ENTITE_NONINCARNE])
|
||||
// const blurette = this.defender.isEntite([ENTITE_BLURETTE])
|
||||
// if (nonIncarnee || blurette) {
|
||||
// ChatMessage.create( {
|
||||
// content: `<strong>La cible est ${nonIncarnee ? 'non incarnée' : 'une blurette'}.
|
||||
// Il est impossible de l'atteindre.`,
|
||||
// whisper: ChatMessage.getWhisperRecipients("GM")})
|
||||
// }
|
||||
|
||||
if (!await this.accorderEntite('avant-attaque')) {
|
||||
return;
|
||||
}
|
||||
if (arme.data.cac == 'empoignade' && this.attacker.isCombatTouche()) {
|
||||
if (arme.system.cac == 'empoignade' && this.attacker.isCombatTouche()) {
|
||||
ChatMessage.create({
|
||||
alias: this.attacker.name,
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
||||
@ -683,6 +783,7 @@ export class RdDCombat {
|
||||
if (arme) {
|
||||
this.attacker.verifierForceMin(arme);
|
||||
}
|
||||
await this.proposerAjustementTirLancer(rollData)
|
||||
|
||||
const dialog = await RdDRoll.create(this.attacker, rollData,
|
||||
{
|
||||
@ -709,7 +810,7 @@ export class RdDCombat {
|
||||
_prepareAttaque(competence, arme) {
|
||||
let rollData = {
|
||||
passeArme: randomID(16),
|
||||
mortalite: arme?.data.mortalite,
|
||||
mortalite: arme?.system.mortalite,
|
||||
coupsNonMortels: false,
|
||||
competence: competence,
|
||||
surprise: this.attacker.getSurprise(true),
|
||||
@ -726,8 +827,8 @@ export class RdDCombat {
|
||||
}
|
||||
else {
|
||||
// sans armes: à mains nues
|
||||
const niveau = competence.data.niveau;
|
||||
const init = RdDCombatManager.calculInitiative(niveau, Misc.templateData(this.attacker).carac['melee'].value);
|
||||
const niveau = competence.system.niveau;
|
||||
const init = RdDCombatManager.calculInitiative(niveau, this.attacker.system.carac['melee'].value);
|
||||
rollData.arme = RdDItemArme.mainsNues({ niveau: niveau, initiative: init });
|
||||
}
|
||||
return rollData;
|
||||
@ -740,9 +841,9 @@ export class RdDCombat {
|
||||
// force toujours, sauf empoignade
|
||||
// finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum
|
||||
// rapidité seulement en mêlée, si l'arme le permet, et si la difficulté libre est de -1 minimum
|
||||
const isForce = !rollData.arme.data.empoignade;
|
||||
const isFinesse = rollData.arme.data.empoignade || isMeleeDiffNegative;
|
||||
const isRapide = !rollData.arme.data.empoignade && isMeleeDiffNegative && rollData.arme.data.rapide;
|
||||
const isForce = !rollData.arme.system.empoignade;
|
||||
const isFinesse = rollData.arme.system.empoignade || isMeleeDiffNegative;
|
||||
const isRapide = !rollData.arme.system.empoignade && isMeleeDiffNegative && rollData.arme.system.rapide;
|
||||
// si un seul choix possible, le prendre
|
||||
if (isForce && !isFinesse && !isRapide) {
|
||||
return await this.choixParticuliere(rollData, "force");
|
||||
@ -774,10 +875,10 @@ export class RdDCombat {
|
||||
async _onAttaqueNormale(attackerRoll) {
|
||||
console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll);
|
||||
|
||||
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntiteCauchemar());
|
||||
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntite());
|
||||
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
|
||||
attackerRoll.show = {
|
||||
cible: this.target ? this.defender.data.name : 'la cible',
|
||||
cible: this.target ? this.defender.name : 'la cible',
|
||||
isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge')
|
||||
}
|
||||
await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html');
|
||||
@ -798,7 +899,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _sendMessageDefense(attackerRoll, defenderRoll, essaisPrecedents = undefined) {
|
||||
console.log("RdDCombat._sendMessageDefense", attackerRoll, defenderRoll, essaisPrecedents, " / ", this.attacker, this.target, this.attackerId, attackerRoll.competence.data.categorie);
|
||||
console.log("RdDCombat._sendMessageDefense", attackerRoll, defenderRoll, essaisPrecedents, " / ", this.attacker, this.target, this.attackerId, attackerRoll.competence.system.categorie);
|
||||
|
||||
this.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
|
||||
if (essaisPrecedents) {
|
||||
@ -806,16 +907,16 @@ export class RdDCombat {
|
||||
}
|
||||
|
||||
// # utilisation esquive
|
||||
const corpsACorps = Misc.data(this.defender.getCompetence("Corps à corps", { onMessage: it => console.info(it, this.defender) }));
|
||||
const esquives = duplicate(this.defender.getCompetences("esquive", { onMessage: it => console.info(it, this.defender) }).map(c => Misc.data(c)));
|
||||
esquives.forEach(e => e.usages = e?.id ? this.defender.getItemUse(e.id) : 0);
|
||||
const corpsACorps = this.defender.getCompetence("Corps à corps", { onMessage: it => console.info(it, this.defender) });
|
||||
const esquives = duplicate(this.defender.getCompetences("esquive", { onMessage: it => console.info(it, this.defender) }))
|
||||
esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0);
|
||||
|
||||
const paramChatDefense = {
|
||||
passeArme: attackerRoll.passeArme,
|
||||
essais: attackerRoll.essais,
|
||||
isPossession: this.isPossession(attackerRoll),
|
||||
defender: Misc.data(this.defender),
|
||||
attacker: Misc.data(this.attacker),
|
||||
defender: this.defender,
|
||||
attacker: this.attacker,
|
||||
attackerId: this.attackerId,
|
||||
esquives: esquives,
|
||||
defenderTokenId: this.defenderTokenId,
|
||||
@ -823,7 +924,7 @@ export class RdDCombat {
|
||||
armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme),
|
||||
diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0,
|
||||
attaqueParticuliere: attackerRoll.particuliere,
|
||||
attaqueCategorie: attackerRoll.competence.data.categorie,
|
||||
attaqueCategorie: attackerRoll.competence.system.categorie,
|
||||
attaqueArme: attackerRoll.arme,
|
||||
surprise: this.defender.getSurprise(true),
|
||||
dmg: attackerRoll.dmg,
|
||||
@ -855,8 +956,8 @@ export class RdDCombat {
|
||||
// envoyer le message au destinataire
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||
msg: "msg_defense", data: {
|
||||
attackerId: this.attacker?.data._id,
|
||||
defenderId: this.defender?.data._id,
|
||||
attackerId: this.attacker?.id,
|
||||
defenderId: this.defender?.id,
|
||||
defenderTokenId: this.defenderTokenId,
|
||||
defenderRoll: defenderRoll,
|
||||
paramChatDefense: paramChatDefense,
|
||||
@ -867,13 +968,11 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_filterArmesParade(defender, competence) {
|
||||
let items = defender.data.items;
|
||||
items = items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it))
|
||||
.map(Misc.data);
|
||||
let items = defender.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
|
||||
item.system.nbUsage = defender.getItemUse(item.id); // Ajout du # d'utilisation ce round
|
||||
}
|
||||
switch (competence.data.categorie) {
|
||||
switch (competence.system.categorie) {
|
||||
case 'tir':
|
||||
case 'lancer':
|
||||
return items.filter(item => RdDItemArme.getCategorieParade(item) == 'boucliers')
|
||||
@ -892,7 +991,7 @@ export class RdDCombat {
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', {
|
||||
attackerId: this.attackerId,
|
||||
attacker: Misc.data(this.attacker),
|
||||
attacker: this.attacker,
|
||||
defenderTokenId: this.defenderTokenId,
|
||||
essais: attackerRoll.essais
|
||||
})
|
||||
@ -905,7 +1004,7 @@ export class RdDCombat {
|
||||
console.log("RdDCombat._onEchecTotal >>>", rollData);
|
||||
|
||||
const arme = rollData.arme;
|
||||
const avecArme = !['', 'sans-armes', 'armes-naturelles'].includes(arme?.data.categorie_parade ?? '');
|
||||
const avecArme = !['', 'sans-armes', 'armes-naturelles'].includes(arme?.system.categorie_parade ?? '');
|
||||
const action = (rollData.attackerRoll ? (arme ? "la parade" : "l'esquive") : "l'attaque");
|
||||
ChatUtility.createChatWithRollMode(this.defender.name, {
|
||||
content: `<strong>Maladresse à ${action}!</strong> ` + await RdDRollTables.getMaladresse({ arme: avecArme })
|
||||
@ -924,7 +1023,7 @@ export class RdDCombat {
|
||||
console.log("RdDCombat.choixParticuliere >>>", rollData, choix);
|
||||
|
||||
if (choix != "rapidite") {
|
||||
this.attacker.incDecItemUse(rollData.arme._id);
|
||||
this.attacker.incDecItemUse(rollData.arme.id);
|
||||
}
|
||||
|
||||
this.removeChatMessageActionsPasseArme(rollData.passeArme);
|
||||
@ -936,10 +1035,10 @@ export class RdDCombat {
|
||||
async parade(attackerRoll, armeParadeId) {
|
||||
const arme = this.defender.getArmeParade(armeParadeId);
|
||||
console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme);
|
||||
const competence = Misc.templateData(arme)?.competence;
|
||||
const competence = arme?.system?.competence;
|
||||
if (competence == undefined)
|
||||
{
|
||||
console.error("Pas de compétence de parade associée à ", arme) ;
|
||||
console.error("Pas de compétence de parade associée à ", arme?.name, armeParadeId) ;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -971,12 +1070,12 @@ export class RdDCombat {
|
||||
passeArme: attackerRoll.passeArme,
|
||||
diffLibre: attackerRoll.diffLibre,
|
||||
attackerRoll: attackerRoll,
|
||||
competence: Misc.data(this.defender.getCompetence(competenceParade)),
|
||||
competence: this.defender.getCompetence(competenceParade),
|
||||
arme: armeParade,
|
||||
surprise: this.defender.getSurprise(true),
|
||||
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
||||
needResist: RdDItemArme.needArmeResist(attackerRoll.arme, armeParade),
|
||||
carac: Misc.templateData(this.defender).carac,
|
||||
carac: this.defender.system.carac,
|
||||
show: {}
|
||||
};
|
||||
|
||||
@ -1005,8 +1104,7 @@ export class RdDCombat {
|
||||
await this.computeRecul(defenderRoll);
|
||||
await this.computeDeteriorationArme(defenderRoll);
|
||||
await RdDResolutionTable.displayRollData(defenderRoll, this.defender, 'chat-resultat-parade.html');
|
||||
|
||||
RdDCombat._deleteDefense(defenderRoll.passeArme);
|
||||
this.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -1021,7 +1119,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async esquive(attackerRoll, compId, compName) {
|
||||
const esquive = Misc.data(this.defender.getCompetence(compId) ?? this.defender.getCompetence(compName));
|
||||
const esquive = this.defender.getCompetence(compId) ?? this.defender.getCompetence(compName)
|
||||
if (esquive == undefined) {
|
||||
ui.notifications.error(this.defender.name + " n'a pas de compétence " + compName);
|
||||
return;
|
||||
@ -1055,7 +1153,7 @@ export class RdDCombat {
|
||||
competence: competence,
|
||||
surprise: this.defender.getSurprise(true),
|
||||
surpriseDefenseur: this.defender.getSurprise(true),
|
||||
carac: Misc.templateData(this.defender).carac,
|
||||
carac: this.defender.system.carac,
|
||||
show: {}
|
||||
};
|
||||
|
||||
@ -1077,7 +1175,7 @@ export class RdDCombat {
|
||||
async _onEsquiveNormale(defenderRoll) {
|
||||
console.log("RdDCombat._onEsquiveNormal >>>", defenderRoll);
|
||||
await RdDResolutionTable.displayRollData(defenderRoll, this.defender, 'chat-resultat-esquive.html');
|
||||
RdDCombat._deleteDefense(defenderRoll.passeArme);
|
||||
this.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -1105,11 +1203,11 @@ export class RdDCombat {
|
||||
|
||||
const dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor;
|
||||
let arme = defenderRoll.arme;
|
||||
let resistance = Misc.toInt(arme.data.resistance);
|
||||
if (arme.data.magique) {
|
||||
let resistance = Misc.toInt(arme.system.resistance);
|
||||
if (arme.system.magique) {
|
||||
defenderRoll.show.deteriorationArme = 'resiste'; // Par défaut
|
||||
if (arme.data.resistance_magique == undefined) arme.data.resistance_magique = 0; // Quick fix
|
||||
if (dmg > arme.data.resistance_magique) { // Jet uniquement si dommages supérieur à résistance magique (cf. 274)
|
||||
if (arme.system.resistance_magique == undefined) arme.system.resistance_magique = 0; // Quick fix
|
||||
if (dmg > arme.system.resistance_magique) { // Jet uniquement si dommages supérieur à résistance magique (cf. 274)
|
||||
// Jet de résistance de l'arme de parade (p.132)
|
||||
let resistRoll = await RdDResolutionTable.rollData({
|
||||
caracValue: resistance,
|
||||
@ -1117,11 +1215,11 @@ export class RdDCombat {
|
||||
showDice: HIDE_DICE
|
||||
});
|
||||
if (!resistRoll.rolled.isSuccess) {
|
||||
let perteResistance = (dmg - arme.data.resistance_magique)
|
||||
let perteResistance = (dmg - arme.system.resistance_magique)
|
||||
resistance -= perteResistance;
|
||||
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
|
||||
defenderRoll.show.perteResistance = perteResistance;
|
||||
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'data.resistance': resistance }]);
|
||||
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'system.resistance': resistance }]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1137,14 +1235,14 @@ export class RdDCombat {
|
||||
resistance -= dmg;
|
||||
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
|
||||
defenderRoll.show.perteResistance = dmg;
|
||||
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'data.resistance': resistance }]);
|
||||
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'system.resistance': resistance }]);
|
||||
}
|
||||
}
|
||||
// Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
|
||||
if (ReglesOptionelles.isUsing('defenseurDesarme') && resistance > 0 && RdDItemArme.getCategorieParade(defenderRoll.arme) != 'boucliers') {
|
||||
let desarme = await RdDResolutionTable.rollData({
|
||||
caracValue: this.defender.getForce(),
|
||||
finalLevel: Misc.toInt(defenderRoll.competence.data.niveau) - dmg,
|
||||
finalLevel: Misc.toInt(defenderRoll.competence.system.niveau) - dmg,
|
||||
showDice: HIDE_DICE
|
||||
});
|
||||
defenderRoll.show.desarme = desarme.rolled.isEchec;
|
||||
@ -1163,7 +1261,7 @@ export class RdDCombat {
|
||||
defenderRoll.show.recul = 'encaisse';
|
||||
} else if (rollRecul.rolled.isETotal || this._isReculCauseChute(impact)) {
|
||||
defenderRoll.show.recul = 'chute';
|
||||
await this.defender.setStatusEffect("EFFECT.StatusProne", true);
|
||||
await this.defender.setEffect(STATUSES.StatusProne, true);
|
||||
}
|
||||
else {
|
||||
defenderRoll.show.recul = 'recul';
|
||||
@ -1187,7 +1285,7 @@ export class RdDCombat {
|
||||
_computeImpactRecul(attaque) {
|
||||
const taille = this.defender.getTaille();
|
||||
const force = this.attacker.getForce();
|
||||
const dommages = attaque.arme.data.dommagesReels ?? attaque.arme.data.dommages;
|
||||
const dommages = attaque.arme.system.dommagesReels ?? attaque.arme.system.dommages;
|
||||
return taille - (force + dommages);
|
||||
}
|
||||
|
||||
@ -1205,7 +1303,7 @@ export class RdDCombat {
|
||||
attackerRoll.defenderTokenId = defenderTokenId;
|
||||
|
||||
await this.computeRecul(defenderRoll);
|
||||
this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll);
|
||||
this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll?.show);
|
||||
}
|
||||
else { // envoi à un GM: les joueurs n'ont pas le droit de modifier les personnages qu'ils ne possèdent pas
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||
@ -1217,7 +1315,6 @@ export class RdDCombat {
|
||||
}
|
||||
});
|
||||
}
|
||||
RdDCombat._deleteDefense(attackerRoll.passeArme);
|
||||
this.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
|
||||
}
|
||||
|
||||
@ -1226,12 +1323,12 @@ export class RdDCombat {
|
||||
async accorderEntite(when = 'avant-encaissement') {
|
||||
if (when != game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar")
|
||||
|| this.defender == undefined
|
||||
|| !this.defender.isEntiteCauchemar()
|
||||
|| this.defender.isEntiteCauchemarAccordee(this.attacker)) {
|
||||
|| !this.defender.isEntite([ENTITE_INCARNE])
|
||||
|| this.defender.isEntiteAccordee(this.attacker)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(Misc.templateData(this.defender).carac.niveau.value));
|
||||
let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(this.defender.system.carac.niveau.value));
|
||||
|
||||
let message = {
|
||||
content: "Jet de points actuels de rêve à " + rolled.finalLevel + RdDResolutionTable.explain(rolled) + "<br>",
|
||||
@ -1252,25 +1349,25 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async displayActorCombatStatus(combat, actor) {
|
||||
let data = {
|
||||
let formData = {
|
||||
combatId: combat._id,
|
||||
alias: actor.name,
|
||||
etatGeneral: actor.getEtatGeneral(),
|
||||
isSonne: actor.getSonne(),
|
||||
blessuresStatus: actor.computeResumeBlessure(),
|
||||
SConst: actor.getSConst(),
|
||||
actorId: actor.data._id,
|
||||
actorId: actor.id,
|
||||
isGrave: false,
|
||||
isCritique: false
|
||||
}
|
||||
if (actor.countBlessuresNonSoigneeByName("critiques") > 0) { // Pour éviter le cumul grave + critique
|
||||
data.isCritique = true;
|
||||
formData.isCritique = true;
|
||||
} else if (actor.countBlessuresNonSoigneeByName("graves") > 0) {
|
||||
data.isGrave = true;
|
||||
formData.isGrave = true;
|
||||
}
|
||||
|
||||
ChatUtility.createChatWithRollMode(actor.name, {
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, data)
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, formData)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { RdDMeteo } from "./rdd-meteo.js";
|
||||
import { RdDNameGen } from "./rdd-namegen.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
||||
@ -34,6 +35,7 @@ export class RdDCommands {
|
||||
rddCommands.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle(true), descr: " Tire un Souffle de Dragon" });
|
||||
rddCommands.registerCommand({ path: ["/table", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence(true), descr: "Tire une compétence au hasard" });
|
||||
rddCommands.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot(true), descr: "Tire une carte du Tarot Draconique" });
|
||||
rddCommands.registerCommand({ path: ["/meteo"], func: (content, msg, params) => rddCommands.getMeteo(msg, params), descr: "Propose une météo marine" });
|
||||
rddCommands.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
|
||||
|
||||
rddCommands.registerCommand({
|
||||
@ -274,9 +276,11 @@ export class RdDCommands {
|
||||
diff = 0;
|
||||
}
|
||||
const caracName = params[0];
|
||||
const compName = length > 1 ? Misc.join(params.slice(1, length), ' ') : undefined;
|
||||
for (let actor of actors) {
|
||||
await actor.rollCaracCompetence(caracName, compName, diff);
|
||||
let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : undefined;
|
||||
if (competence) {
|
||||
for (let actor of actors) {
|
||||
await actor.rollCaracCompetence(caracName, competence.name, diff);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -354,10 +358,9 @@ export class RdDCommands {
|
||||
|
||||
async supprimerSignesDraconiquesEphemeres() {
|
||||
game.actors.forEach(actor => {
|
||||
const ephemeres = actor.filterItems(item => Misc.data(item).type = 'signedraconique' && Misc.data(item).data.ephemere)
|
||||
.map(item => item.id);
|
||||
const ephemeres = actor.items.filter(item => item.type = 'signedraconique' && item.system.ephemere);
|
||||
if (ephemeres.length > 0) {
|
||||
actor.deleteEmbeddedDocuments("Item", ephemeres);
|
||||
actor.deleteEmbeddedDocuments("Item", ephemeres.map(item => item.id));
|
||||
}
|
||||
});
|
||||
return true;
|
||||
@ -398,5 +401,8 @@ export class RdDCommands {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
async getMeteo(msg, params) {
|
||||
return await RdDMeteo.getMeteo();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { SYSTEM_RDD } from "./constants.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
export class RddCompendiumOrganiser {
|
||||
static init() {
|
||||
Hooks.on('renderCompendium', async (pack, html, data) => RddCompendiumOrganiser.onRenderCompendium(pack, html, data))
|
||||
Hooks.on('renderCompendium', async (pack, html, compendiumData) => RddCompendiumOrganiser.onRenderCompendium(pack, html, compendiumData))
|
||||
}
|
||||
|
||||
static async onRenderCompendium(compendium, html, data) {
|
||||
console.log('onRenderCompendium', compendium, html, data);
|
||||
static async onRenderCompendium(compendium, html, compendiumData) {
|
||||
console.log('onRenderCompendium', compendium, html, compendiumData);
|
||||
const pack = compendium.collection
|
||||
if (pack.metadata.system === SYSTEM_RDD) {
|
||||
html.find('.directory-item').each((i, element) => {
|
||||
@ -17,7 +16,7 @@ export class RddCompendiumOrganiser {
|
||||
}
|
||||
|
||||
static async setEntityTypeName(pack, element) {
|
||||
const label = Misc.getEntityTypeLabel(await pack.getDocument(element.dataset.documentId));
|
||||
const label = RddCompendiumOrganiser.getEntityTypeLabel(await pack.getDocument(element.dataset.documentId));
|
||||
RddCompendiumOrganiser.insertEntityType(element, label);
|
||||
}
|
||||
|
||||
@ -27,4 +26,16 @@ export class RddCompendiumOrganiser {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static getEntityTypeLabel(entity) {
|
||||
const documentName = entity?.documentName
|
||||
const type = entity?.type
|
||||
if (documentName === 'Actor' || documentName === 'Item') {
|
||||
const label = CONFIG[documentName]?.typeLabels?.[type] ?? type;
|
||||
return game.i18n.has(label) ? game.i18n.localize(label) : t;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
}
|
56
module/rdd-confirm.js
Normal file
56
module/rdd-confirm.js
Normal file
@ -0,0 +1,56 @@
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
|
||||
export class RdDConfirm {
|
||||
/* -------------------------------------------- */
|
||||
static confirmer(options, autresActions) {
|
||||
options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionelles.isUsing(options.settingConfirmer));
|
||||
if (options.bypass) {
|
||||
options.onAction();
|
||||
}
|
||||
else {
|
||||
let buttons = {
|
||||
"action": RdDConfirm._createButtonAction(options),
|
||||
"cancel": RdDConfirm._createButtonCancel()
|
||||
};
|
||||
if (options.settingConfirmer) {
|
||||
buttons = mergeObject(RdDConfirm._createButtonActionSave(options), buttons);
|
||||
}
|
||||
if (autresActions) {
|
||||
buttons = mergeObject(autresActions, buttons);
|
||||
}
|
||||
const dialogDetails = {
|
||||
title: options.title,
|
||||
content: options.content,
|
||||
default: "cancel",
|
||||
buttons: buttons
|
||||
};
|
||||
new Dialog(dialogDetails, { width: 150 * Object.keys(buttons).length }).render(true);
|
||||
}
|
||||
}
|
||||
|
||||
static _createButtonCancel() {
|
||||
return { icon: '<i class="fas fa-times"></i>', label: "Annuler" };
|
||||
}
|
||||
|
||||
static _createButtonAction(options) {
|
||||
return {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: options.buttonLabel,
|
||||
callback: () => options.onAction()
|
||||
};
|
||||
}
|
||||
|
||||
static _createButtonActionSave(options) {
|
||||
return {
|
||||
"actionSave": {
|
||||
icon: '<i class="fas fa-user-check"></i>',
|
||||
label: "Toujours "+ options.buttonLabel.toLowerCase(),
|
||||
callback: () => {
|
||||
ReglesOptionelles.set(options.settingConfirmer, false);
|
||||
options.onAction();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -132,18 +132,15 @@ export class RdDDice {
|
||||
}
|
||||
}
|
||||
|
||||
static async roll(formula, options = { showDice: SHOW_DICE, rollMode: undefined }) {
|
||||
const roll = new Roll(formula);
|
||||
await roll.evaluate({ async: true });
|
||||
if (options.showDice != HIDE_DICE) {
|
||||
await this.showDiceSoNice(roll, options.rollMode ?? game.settings.get("core", "rollMode"));
|
||||
}
|
||||
return roll;
|
||||
static async rollTotal(formula, options = { showDice: HIDE_DICE }) {
|
||||
return (await RdDDice.roll(formula, options)).total;
|
||||
}
|
||||
|
||||
static async rollTotal(formula, options = { showDice: HIDE_DICE}) {
|
||||
const roll = await RdDDice.roll(formula, options);
|
||||
return roll.total;
|
||||
static async roll(formula, options = { showDice: SHOW_DICE, rollMode: undefined }) {
|
||||
const roll = new Roll(RdDDice._formulaOrFake(formula, options));
|
||||
await roll.evaluate({ async: true });
|
||||
await this.showDiceSoNice(roll, options);
|
||||
return roll;
|
||||
}
|
||||
|
||||
static async rollOneOf(array) {
|
||||
@ -160,27 +157,106 @@ export class RdDDice {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async showDiceSoNice(roll, rollMode) {
|
||||
if (game.modules.get("dice-so-nice")?.active) {
|
||||
if (game.dice3d) {
|
||||
let whisper = null;
|
||||
let blind = false;
|
||||
rollMode = rollMode ?? game.settings.get("core", "rollMode");
|
||||
switch (rollMode) {
|
||||
case "blindroll": //GM only
|
||||
blind = true;
|
||||
case "gmroll": //GM + rolling player
|
||||
whisper = ChatUtility.getUsers(user => user.isGM);
|
||||
break;
|
||||
case "roll": //everybody
|
||||
whisper = ChatUtility.getUsers(user => user.active);
|
||||
break;
|
||||
case "selfroll":
|
||||
whisper = [game.user.id];
|
||||
break;
|
||||
}
|
||||
await game.dice3d.showForRoll(roll, game.user, true, whisper, blind);
|
||||
static async showDiceSoNice(roll, options) {
|
||||
if (options.showDice == HIDE_DICE || !game.modules.get("dice-so-nice")?.active || !game.dice3d) {
|
||||
return;
|
||||
}
|
||||
|
||||
let { whisper, blind } = RdDDice._getWhisperBlind(options);
|
||||
if (options.forceDiceResult?.total) {
|
||||
let terms = await RdDDice._getForcedTerms(options);
|
||||
if (terms) {
|
||||
await game.dice3d.show({ throws: [{ dice: terms }] })
|
||||
return;
|
||||
}
|
||||
}
|
||||
await game.dice3d.showForRoll(roll, game.user, true, whisper, blind);
|
||||
}
|
||||
|
||||
static _formulaOrFake(formula, options) {
|
||||
if (options?.forceDiceResult?.total) {
|
||||
options.forceDiceResult.formula = formula;
|
||||
return options.forceDiceResult.total.toString()
|
||||
}
|
||||
return formula;
|
||||
}
|
||||
|
||||
static async _getForcedTerms(options) {
|
||||
const total = options.forceDiceResult.total;
|
||||
switch (options.forceDiceResult.formula) {
|
||||
case '1d100':
|
||||
return terms1d100(total);
|
||||
case "2d10":
|
||||
return await terms2d10(total);
|
||||
}
|
||||
return undefined;
|
||||
|
||||
function terms1d100(total) {
|
||||
const unites = total % 10;
|
||||
const dizaines = Math.floor(total / 10);
|
||||
return [{
|
||||
resultLabel: dizaines * 10,
|
||||
d100Result: total,
|
||||
result: dizaines,
|
||||
type: "d100",
|
||||
vectors: [],
|
||||
options: {}
|
||||
},
|
||||
{
|
||||
resultLabel: unites,
|
||||
d100Result: total,
|
||||
result: unites,
|
||||
type: "d10",
|
||||
vectors: [],
|
||||
options: {}
|
||||
}];
|
||||
}
|
||||
|
||||
async function terms2d10(total) {
|
||||
if (total>20 || total<2) { return undefined }
|
||||
let first = await RdDDice.d10();
|
||||
let second = Math.min(total-first, 10);
|
||||
first = Math.max(first, total-second);
|
||||
return [{
|
||||
resultLabel:first,
|
||||
result: first,
|
||||
type: "d10",
|
||||
vectors: [],
|
||||
options: {}
|
||||
},
|
||||
{
|
||||
resultLabel: second,
|
||||
result: second,
|
||||
type: "d10",
|
||||
vectors: [],
|
||||
options: {}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
static async d10() {
|
||||
let roll = new Roll('1d10');
|
||||
await roll.evaluate({ async: true });
|
||||
return roll.total;
|
||||
}
|
||||
|
||||
static _getWhisperBlind(options) {
|
||||
let whisper = null;
|
||||
let blind = false;
|
||||
let rollMode = options.rollMode ?? game.settings.get("core", "rollMode");
|
||||
switch (rollMode) {
|
||||
case "blindroll": //GM only
|
||||
blind = true;
|
||||
case "gmroll": //GM + rolling player
|
||||
whisper = ChatUtility.getUsers(user => user.isGM);
|
||||
break;
|
||||
case "roll": //everybody
|
||||
whisper = ChatUtility.getUsers(user => user.active);
|
||||
break;
|
||||
case "selfroll":
|
||||
whisper = [game.user.id];
|
||||
break;
|
||||
}
|
||||
return { whisper, blind };
|
||||
}
|
||||
}
|
@ -18,18 +18,19 @@ const tableGemmes = {
|
||||
export class RdDGemme extends Item {
|
||||
|
||||
static getGemmeTypeOptionList() {
|
||||
// TODO: look how to map object key-value pairs
|
||||
let options = ""
|
||||
for (let gemmeKey in tableGemmes) {
|
||||
let gemmeData = tableGemmes[gemmeKey];
|
||||
options += `<option value="${gemmeKey}">${gemmeData.label}</option>`
|
||||
options += `<option value="${gemmeKey}">${tableGemmes[gemmeKey].label}</option>`
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
static calculDataDerivees(data) {
|
||||
data.cout = (data.taille * data.purete) + data.qualite;
|
||||
data.inertie = 7 - data.purete;
|
||||
data.enchantabilite = data.taille - data.inertie;
|
||||
|
||||
static calculDataDerivees(gemme) {
|
||||
gemme.system.cout = (gemme.system.taille * gemme.system.purete) + gemme.system.qualite;
|
||||
gemme.system.inertie = 7 - gemme.system.purete;
|
||||
gemme.system.enchantabilite = gemme.system.taille - gemme.system.inertie;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,76 +1,75 @@
|
||||
/* -------------------------------------------- */
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDHerbes extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isHerbeSoin( botaniqueItem ) {
|
||||
return Misc.templateData(botaniqueItem).categorie == 'Soin';
|
||||
static async initializeHerbes() {
|
||||
this.herbesSoins = await RdDHerbes.listCategorieHerbes('Soin');
|
||||
this.herbesRepos = await RdDHerbes.listCategorieHerbes('Repos');
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isHerbeRepos( botaniqueItem ) {
|
||||
return Misc.templateData(botaniqueItem).categorie == 'Repos';
|
||||
|
||||
static async listCategorieHerbes(categorie) {
|
||||
return await RdDUtility.loadItems(
|
||||
it => it.type == 'herbe' && it.system.categorie.toLowerCase() == categorie.toLowerCase(),
|
||||
'foundryvtt-reve-de-dragon.botanique');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async initializeHerbes( ) {
|
||||
this.herbesSoins = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.botanique', item => this.isHerbeSoin(item));
|
||||
this.herbesRepos = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.botanique', item => this.isHerbeRepos(item));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static buildHerbesList(listHerbes, max) {
|
||||
static buildHerbesList(listeHerbes, max) {
|
||||
let list = {}
|
||||
for ( let herbe of listHerbes) {
|
||||
let herbeData = Misc.templateData(herbe);
|
||||
let brins = max - herbeData.niveau;
|
||||
list[herbe.data.name] = `${herbe.data.name} (Bonus: ${herbeData.niveau}, Brins: ${brins})`;
|
||||
for (let herbe of listeHerbes) {
|
||||
let brins = max - herbe.system.niveau;
|
||||
list[herbe.name] = `${herbe.name} (Bonus: ${herbe.system.niveau}, Brins: ${brins})`;
|
||||
}
|
||||
list['Autre'] = 'Autre (Bonus: variable, Brins: variable)'
|
||||
return list;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static updatePotionData( formData ) {
|
||||
formData.herbesSoins = this.buildHerbesList(this.herbesSoins, 12);
|
||||
formData.herbesRepos = this.buildHerbesList(this.herbesRepos, 7);
|
||||
static async updatePotionData(formData) {
|
||||
formData.isSoins = formData.system.categorie.includes('Soin');
|
||||
formData.isRepos = formData.system.categorie.includes('Repos');
|
||||
if (formData.isSoins) {
|
||||
RdDHerbes.calculBonusHerbe(formData, this.herbesSoins, 12);
|
||||
}
|
||||
if (formData.isRepos) {
|
||||
RdDHerbes.calculBonusHerbe(formData, this.herbesRepos, 7);
|
||||
}
|
||||
formData.herbesSoins = RdDHerbes.buildHerbesList(this.herbesSoins, 12);
|
||||
formData.herbesRepos = RdDHerbes.buildHerbesList(this.herbesRepos, 7);
|
||||
formData.jourMoisOptions = RdDCalendrier.buildJoursMois();
|
||||
formData.dateActuelle = game.system.rdd.calendrier.getDateFromIndex();
|
||||
formData.splitDate = game.system.rdd.calendrier.getNumericDateFromIndex(formData.data.prdate);
|
||||
|
||||
if (formData.data.categorie.includes('Soin') ) {
|
||||
formData.isHerbe = true;
|
||||
this.computeHerbeBonus(formData, this.herbesSoins, 12);
|
||||
} else if (formData.data.categorie.includes('Repos')) {
|
||||
formData.isRepos = true;
|
||||
this.computeHerbeBonus(formData, this.herbesRepos, 7);
|
||||
}
|
||||
formData.splitDate = game.system.rdd.calendrier.getNumericDateFromIndex(formData.system.prdate);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static calculePointsRepos( data ) {
|
||||
return data.herbebonus * data.pr;
|
||||
static calculPuissancePotion(potion) {
|
||||
return potion.system.herbebonus * potion.system.pr;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static calculePointsGuerison( data ){
|
||||
return data.herbebonus * data.pr;
|
||||
static calculPointsRepos(potion) {
|
||||
return potion.system.herbebonus * potion.system.pr;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeHerbeBonus( formData, herbesList, max) {
|
||||
if ( Number(formData.data.herbebrins) ) {
|
||||
let herbe = herbesList.find(item => item.name.toLowerCase() == formData.data.herbe.toLowerCase() );
|
||||
if( herbe ) {
|
||||
let herbeData = Misc.templateData(herbe);
|
||||
let brinsBase = max - herbeData.niveau;
|
||||
//console.log(herbeData, brinsBase, formData.data.herbebrins);
|
||||
formData.data.herbebonus = Math.max(herbeData.niveau - Math.max(brinsBase - formData.data.herbebrins, 0), 0);
|
||||
static calculPointsGuerison(potion) {
|
||||
return potion.system.herbebonus * potion.system.pr;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static calculBonusHerbe(formData, herbesList, max) {
|
||||
if (Number(formData.system.herbebrins)) {
|
||||
let herbe = herbesList.find(item => item.name.toLowerCase() == formData.system.herbe.toLowerCase());
|
||||
if (herbe) {
|
||||
const brinsRequis = max - herbe.system.niveau;
|
||||
const brinsManquants = Math.max(brinsRequis - formData.system.herbebrins, 0);
|
||||
formData.system.herbebonus = Math.max(herbe.system.niveau - brinsManquants, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -2,64 +2,46 @@ import { Misc } from "./misc.js";
|
||||
|
||||
export class RdDHotbar {
|
||||
|
||||
static async addToHotbar(item, slot) {
|
||||
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}");`;
|
||||
let macro = game.macros.contents.find(m => (m.name === item.name) && (m.command === command));
|
||||
if (!macro) {
|
||||
macro = await Macro.create({
|
||||
name: item.name,
|
||||
type: "script",
|
||||
img: item.img,
|
||||
command: command
|
||||
}, { displaySheet: false })
|
||||
}
|
||||
await game.user.assignHotbarMacro(macro, slot);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a macro when dropping an entity on the hotbar
|
||||
* Item - open roll dialog for item
|
||||
* Actor - open actor sheet
|
||||
* Journal - open journal sheet
|
||||
*/
|
||||
static initDropbar( ) {
|
||||
static initDropbar() {
|
||||
|
||||
Hooks.on("hotbarDrop", async (bar, documentData, slot) => {
|
||||
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill
|
||||
if (documentData.type == "Item") {
|
||||
if (documentData.data.type != "arme" && documentData.data.type != "competence" )
|
||||
return
|
||||
let item = documentData.data
|
||||
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}");`;
|
||||
let macro = game.macros.contents.find(m => (m.name === item.name) && (m.command === command));
|
||||
if (!macro) {
|
||||
macro = await Macro.create({
|
||||
name: item.name,
|
||||
type: "script",
|
||||
img: item.img,
|
||||
command: command
|
||||
}, { displaySheet: false })
|
||||
Hooks.on("hotbarDrop", (bar, documentData, slot) => {
|
||||
|
||||
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill
|
||||
if (documentData.type == "Item") {
|
||||
let item = fromUuidSync(documentData.uuid)
|
||||
if (item == undefined) {
|
||||
item = this.actor.items.get(documentData.uuid)
|
||||
}
|
||||
console.log("DROP", documentData, item)
|
||||
if (!item || (item.type != "arme" && item.type != "competence")) {
|
||||
return true
|
||||
}
|
||||
this.addToHotbar(item, slot)
|
||||
return false
|
||||
}
|
||||
game.user.assignHotbarMacro(macro, slot);
|
||||
}
|
||||
// Create a macro to open the actor sheet of the actor dropped on the hotbar
|
||||
else if (documentData.type == "Actor") {
|
||||
let actor = game.actors.get(documentData.id);
|
||||
let command = `game.actors.get("${documentData.id}").sheet.render(true)`
|
||||
let macro = game.macros.contents.find(m => (m.name === actor.name) && (m.command === command));
|
||||
if (!macro) {
|
||||
macro = await Macro.create({
|
||||
name: actor.data.name,
|
||||
type: "script",
|
||||
img: actor.data.img,
|
||||
command: command
|
||||
}, { displaySheet: false })
|
||||
game.user.assignHotbarMacro(macro, slot);
|
||||
}
|
||||
}
|
||||
// Create a macro to open the journal sheet of the journal dropped on the hotbar
|
||||
else if (documentData.type == "JournalEntry") {
|
||||
let journal = game.journal.get(documentData.id);
|
||||
let command = `game.journal.get("${documentData.id}").sheet.render(true)`
|
||||
let macro = game.macros.contents.find(m => (m.name === journal.name) && (m.command === command));
|
||||
if (!macro) {
|
||||
macro = await Macro.create({
|
||||
name: journal.data.name,
|
||||
type: "script",
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp",
|
||||
command: command
|
||||
}, { displaySheet: false })
|
||||
game.user.assignHotbarMacro(macro, slot);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
/** Roll macro */
|
||||
@ -69,15 +51,17 @@ export class RdDHotbar {
|
||||
if (speaker.token) actor = game.actors.tokens[speaker.token];
|
||||
if (!actor) actor = game.actors.get(speaker.actor);
|
||||
|
||||
let item = Misc.data(actor?.items.find(it => it.name === itemName && it.type == itemType));
|
||||
if (!item) return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`);
|
||||
let item = actor?.items.find(it => it.name === itemName && it.type == itemType) ?? undefined;
|
||||
if (!item) {
|
||||
return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`);
|
||||
}
|
||||
|
||||
// Trigger the item roll
|
||||
switch (item.type) {
|
||||
case "arme":
|
||||
return actor.rollArme(item);
|
||||
case "competence":
|
||||
return actor.rollCompetence( itemName );
|
||||
return actor.rollCompetence(itemName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,7 @@ import { RdDDice } from "./rdd-dice.js";
|
||||
import { RdDPossession } from "./rdd-possession.js";
|
||||
import { RdDSigneDraconiqueItemSheet } from "./item-signedraconique-sheet.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { Migrations } from './migrations.js';
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
@ -149,11 +150,14 @@ Hooks.once("init", async function () {
|
||||
/* -------------------------------------------- */
|
||||
game.socket.on(SYSTEM_SOCKET_ID, sockmsg => {
|
||||
console.log(">>>>> MSG RECV", sockmsg);
|
||||
|
||||
RdDUtility.onSocketMessage(sockmsg);
|
||||
RdDCombat.onSocketMessage(sockmsg);
|
||||
ChatUtility.onSocketMessage(sockmsg);
|
||||
RdDActor.onSocketMessage(sockmsg);
|
||||
try {
|
||||
RdDUtility.onSocketMessage(sockmsg);
|
||||
RdDCombat.onSocketMessage(sockmsg);
|
||||
ChatUtility.onSocketMessage(sockmsg);
|
||||
RdDActor.onSocketMessage(sockmsg);
|
||||
} catch(e) {
|
||||
console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg,' => ', e)
|
||||
}
|
||||
});
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -183,7 +187,7 @@ Hooks.once("init", async function () {
|
||||
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
|
||||
types: ["arme", "armure", "objet", "arme", "armure", "conteneur", "competence", "sort", "herbe", "ingredient", "livre", "potion", "munition", "rencontresTMR", "queue", "ombre", "souffle",
|
||||
"tete", "competencecreature", "tarot", "monnaie", "nombreastral", "tache", "meditation", "casetmr", "recettealchimique", "gemme",
|
||||
"musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre", "nourritureboisson", "possession"], makeDefault: true
|
||||
"musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre", "nourritureboisson", "possession", "sortreserve"], makeDefault: true
|
||||
});
|
||||
CONFIG.Combat.documentClass = RdDCombatManager;
|
||||
|
||||
@ -221,19 +225,20 @@ function messageDeBienvenue() {
|
||||
// Register world usage statistics
|
||||
function registerUsageCount( registerKey ) {
|
||||
if ( game.user.isGM ) {
|
||||
game.settings.register(registerKey, "world-key", {
|
||||
game.settings.register("world", "world-key", {
|
||||
name: "Unique world key",
|
||||
scope: "world",
|
||||
config: false,
|
||||
default: "NONE",
|
||||
type: String
|
||||
});
|
||||
|
||||
let worldKey = game.settings.get(registerKey, "world-key")
|
||||
let worldKey = game.settings.get("world", "world-key")
|
||||
if ( worldKey == undefined || worldKey == "" ) {
|
||||
worldKey = randomID(32)
|
||||
game.settings.set(registerKey, "world-key", worldKey )
|
||||
game.settings.set("world", "world-key", worldKey )
|
||||
}
|
||||
let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.data.version}"`
|
||||
let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.version}"`
|
||||
$.ajax(regURL)
|
||||
/* -------------------------------------------- */
|
||||
}
|
||||
@ -244,6 +249,9 @@ function registerUsageCount( registerKey ) {
|
||||
/* -------------------------------------------- */
|
||||
Hooks.once("ready", async function () {
|
||||
await migrationPngWebp_1_5_34()
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
new Migrations().migrate();
|
||||
}
|
||||
|
||||
StatusEffects.onReady();
|
||||
RdDHerbes.initializeHerbes();
|
||||
@ -291,8 +299,8 @@ async function migrationPngWebp_1_5_34() {
|
||||
await Item.updateDocuments(itemsUpdates);
|
||||
await Actor.updateDocuments(actorsUpdates);
|
||||
game.actors.forEach(actor => {
|
||||
if (actor.data.token?.img && actor.data.token.img.match(regexOldPngJpg)) {
|
||||
actor.update({ "token.img": convertImgToWebp(actor.data.token.img) });
|
||||
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
|
||||
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
|
||||
}
|
||||
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
|
||||
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
|
||||
|
134
module/rdd-meteo.js
Normal file
134
module/rdd-meteo.js
Normal file
@ -0,0 +1,134 @@
|
||||
|
||||
const vents = [
|
||||
{ min: 0, max: 0, valeur: 'Calme' },
|
||||
{ min: 1, max: 1, valeur: 'Légère brise' },
|
||||
{ min: 2, max: 2, valeur: 'Jolie brise' },
|
||||
{ min: 3, max: 3, valeur: 'Bonne brise' },
|
||||
{ min: 4, max: 4, valeur: 'Vent frais' },
|
||||
{ min: 5, max: 5, valeur: 'Coup de vent' },
|
||||
{ min: 6, max: 6, valeur: 'Fort coup de vent' },
|
||||
{ min: 7, max: 9, valeur: 'Tempête' },
|
||||
{ min: 10, max: 13, valeur: 'Violente tempête' },
|
||||
{ min: 14, valeur: 'Ouragan' },
|
||||
]
|
||||
const mers = [
|
||||
{ min: 0, max: 0, valeur: 'Calme' },
|
||||
{ min: 1, max: 1, valeur: 'Belle' },
|
||||
{ min: 2, max: 2, valeur: 'Peu agitée' },
|
||||
{ min: 3, max: 3, valeur: 'Agitée' },
|
||||
{ min: 4, max: 4, valeur: 'Forte' },
|
||||
{ min: 5, max: 6, valeur: 'Très forte' },
|
||||
{ min: 7, max: 9, valeur: 'Grosse' },
|
||||
{ min: 10, max: 13, valeur: 'Très grosse' },
|
||||
{ min: 14, valeur: 'Énorme' },
|
||||
]
|
||||
|
||||
const nuages = [
|
||||
{ min: 0, max: 3, valeur: 'dégagé' },
|
||||
{ min: 4, max: 6, valeur: 'passages nuageux' },
|
||||
{ min: 7, max: 9, valeur: 'nuageux', },
|
||||
{ min: 10, max: 10, valeur: 'brouillard' },
|
||||
{ min: 11, max: 12, valeur: 'bruine' },
|
||||
{ min: 13, valeur: 'très nuageux' },
|
||||
]
|
||||
|
||||
const pluies = [
|
||||
{ min: 0, max: 4, valeur: 'aucune' },
|
||||
{ min: 5, max: 5, valeur: 'bruine, crachin, éparse' },
|
||||
{ min: 6, max: 7, valeur: 'averses' },
|
||||
{ min: 8, max: 10, valeur: 'pluvieux', },
|
||||
{ min: 11, max: 13, valeur: 'forte pluie' },
|
||||
{ min: 14, valeur: 'déluge' },
|
||||
]
|
||||
|
||||
const temperatures = [
|
||||
{ max: -14, valeur: 'glaciale' },
|
||||
{ min: -13, max: -10, valeur: 'Très froide' },
|
||||
{ min: -9, max: -7, valeur: 'froide' },
|
||||
{ min: -6, max: -4, valeur: 'fraîche' },
|
||||
{ min: -3, max: 3, valeur: 'de saison' },
|
||||
{ min: 4, max: 6, valeur: 'élevée' },
|
||||
{ min: 7, max: 9, valeur: 'chaude' },
|
||||
{ min: 10, max: 13, valeur: 'torride' },
|
||||
{ min: 14, valeur: 'caniculaire' },
|
||||
]
|
||||
|
||||
export class RdDMeteo {
|
||||
static async getForce() {
|
||||
const roll = new Roll(`1dr`);
|
||||
await roll.evaluate({ async: true });
|
||||
return roll.total;
|
||||
}
|
||||
|
||||
static async getPluie(nuage) {
|
||||
return nuage <= 3 ? 0 : await RdDMeteo.getForce();
|
||||
}
|
||||
|
||||
static async getTemperature() {
|
||||
const degre = await RdDMeteo.getForce();
|
||||
const rollChaudFroid = new Roll('1d2');
|
||||
await rollChaudFroid.evaluate({ async: true });
|
||||
const chaudFroid = rollChaudFroid.total == 1;
|
||||
return chaudFroid.total ? degre : -degre;
|
||||
}
|
||||
|
||||
static async getDirection(direction) {
|
||||
const roll = new Roll(`1d16`);
|
||||
await roll.evaluate({ async: true });
|
||||
switch (roll.total % 16) {
|
||||
case 0: return 'Nord';
|
||||
case 1: return 'Nord Nord Est';
|
||||
case 2: return 'Nord Est';
|
||||
case 3: return 'Est Nord Est';
|
||||
case 4: return 'Est';
|
||||
case 5: return 'Est Sud Est';
|
||||
case 6: return 'Sud Est';
|
||||
case 7: return 'Sud Sud Est';
|
||||
case 8: return 'Sud';
|
||||
case 9: return 'Sud Sud Ouest';
|
||||
case 10: return 'Sud Ouest';
|
||||
case 11: return 'Ouest Sud Ouest';
|
||||
case 12: return 'Ouest';
|
||||
case 13: return 'Ouest Nord Ouest';
|
||||
case 14: return 'Nord Ouest';
|
||||
case 15: return 'Nord Nord Ouest';
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static async getMeteo() {
|
||||
const vent = await RdDMeteo.getForce();
|
||||
const mer = await RdDMeteo.getForce();
|
||||
const nuage = await RdDMeteo.getForce();
|
||||
const pluie = await RdDMeteo.getPluie(nuage);
|
||||
const temperature = await RdDMeteo.getTemperature();
|
||||
const meteo = {
|
||||
vent: { force: vent, direction: await RdDMeteo.getDirection(), },
|
||||
mer: { force: mer, direction: await RdDMeteo.getDirection(), },
|
||||
temperature: { force: temperature },
|
||||
nuage: { force: nuage, },
|
||||
pluie: { force: pluie },
|
||||
}
|
||||
meteo.vent.description = RdDMeteo.vent(meteo.vent.force);
|
||||
meteo.mer.description = RdDMeteo.mer(meteo.mer.force),
|
||||
meteo.temperature.description = RdDMeteo.temperature(meteo.temperature.force);
|
||||
meteo.nuage.description = RdDMeteo.nuage(meteo.nuage.force);
|
||||
meteo.pluie.description = RdDMeteo.pluie(meteo.pluie.force);
|
||||
|
||||
ChatMessage.create({
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-meteo.html', meteo),
|
||||
whisper: ChatMessage.getWhisperRecipients('GM')
|
||||
});
|
||||
}
|
||||
|
||||
static description(liste, force, valeur = it => it.valeur) {
|
||||
let select = liste.find(it => (it.min == undefined || it.min <= force) && (it.max == undefined || force <= it.max));
|
||||
return valeur(select ?? liste[0]);
|
||||
}
|
||||
|
||||
static vent(force) { return this.description(vents, force); }
|
||||
static mer(force) { return this.description(mers, force); }
|
||||
static nuage(force) { return this.description(nuages, force); }
|
||||
static pluie(force) { return this.description(pluies, force); }
|
||||
static temperature(force) { return this.description(temperatures, force); }
|
||||
}
|
@ -1,19 +1,29 @@
|
||||
import { RdDActor } from "./actor.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
|
||||
const words = [ 'pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', 'onse', 'iane', 'ane', 'zach', 'arri', 'ba', 'bo', 'bi',
|
||||
'alta', 'par', 'pir', 'zor', 'zir', 'de', 'pol', 'tran', 'no', 'la', 'al' , 'pul', 'one', 'ner', 'nur', 'mac', 'mery',
|
||||
'cat', 'do', 'di', 'der', 'er', 'el', 'far', 'fer', 'go', 'guer', 'hot', 'jor', 'jar', 'ji', 'kri', 'ket', 'lor', 'hur',
|
||||
'lar', 'lir', 'lu', 'pot', 'pro', 'pra', 'pit', 'qua', 'qui', 're', 'ral', 'sal', 'sen', 'ted', 'to', 'ta', 'lars', 'ver',
|
||||
'vin', 'ov', 'wal', 'ry', 'ly', '' ];
|
||||
const words = ['pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', 'onse', 'iane', 'ane', 'zach', 'arri', 'ba', 'bo', 'bi',
|
||||
'alta', 'par', 'pir', 'zor', 'zir', 'de', 'pol', 'tran', 'no', 'la', 'al', 'pul', 'one', 'ner', 'nur', 'mac', 'mery',
|
||||
'cat', 'do', 'di', 'der', 'er', 'el', 'far', 'fer', 'go', 'guer', 'hot', 'jor', 'jar', 'ji', 'kri', 'ket', 'lor', 'hur',
|
||||
'lar', 'lir', 'lu', 'pot', 'pro', 'pra', 'pit', 'qua', 'qui', 're', 'ral', 'sal', 'sen', 'ted', 'to', 'ta', 'lars', 'ver',
|
||||
'vin', 'ov', 'wal', 'ry', 'ly', ''];
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDNameGen {
|
||||
|
||||
static async getName( msg, params ) {
|
||||
let name = Misc.upperFirst( await RdDDice.rollOneOf(words) + await RdDDice.rollOneOf(words) )
|
||||
//console.log(name);
|
||||
ChatMessage.create( { content: `Nom : ${name}`, whisper: ChatMessage.getWhisperRecipients("GM") } );
|
||||
static async getName(msg, params) {
|
||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-command-nom.html`, {
|
||||
nom: Misc.upperFirst(await RdDDice.rollOneOf(words) + await RdDDice.rollOneOf(words))
|
||||
});
|
||||
ChatMessage.create({ content: html, whisper: ChatMessage.getWhisperRecipients("GM") });
|
||||
}
|
||||
|
||||
static async onCreerActeur(event) {
|
||||
const button = event.currentTarget;
|
||||
await RdDActor.create({
|
||||
name: button.attributes['data-nom'].value,
|
||||
type: button.attributes['data-type'].value
|
||||
},
|
||||
{renderSheet: true});
|
||||
}
|
||||
}
|
@ -14,100 +14,86 @@ Donc la compétence Possession ne peut être démarrée que par le MJ.
|
||||
export class RdDPossession {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static init() {
|
||||
static init() {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static searchPossessionFromEntite( attacker, defender) {
|
||||
let poss = attacker.data.items.find( poss => poss.type == 'possession' && poss.data.data.possedeid == defender.data._id);
|
||||
static searchPossessionFromEntite(attacker, defender) {
|
||||
let poss = attacker.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
|
||||
if (!poss) {
|
||||
poss = defender.data.items.find( poss => poss.type == 'possession' && poss.data.data.possedeid == defender.data._id);
|
||||
poss = defender.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
|
||||
}
|
||||
return poss && duplicate(poss) || undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static updateEtatPossession( possession ) {
|
||||
static updateEtatPossession(possession) {
|
||||
possession.ptsConjuration = 0
|
||||
possession.ptsPossession = 0
|
||||
console.log("Possession", possession)
|
||||
if ( possession.data.compteur > 0) {
|
||||
possession.ptsPossession = possession.data.compteur
|
||||
}
|
||||
if ( possession.data.compteur < 0) {
|
||||
possession.ptsConjuration = Math.abs(possession.data.compteur)
|
||||
}
|
||||
if (possession.system.compteur > 0) {
|
||||
possession.ptsPossession = possession.system.compteur
|
||||
}
|
||||
if (possession.system.compteur < 0) {
|
||||
possession.ptsConjuration = Math.abs(possession.system.compteur)
|
||||
}
|
||||
possession.isPosseder = false
|
||||
possession.isConjurer = false
|
||||
if (possession.ptsPossession >= 2 ) {
|
||||
if (possession.ptsPossession >= 2) {
|
||||
possession.isPosseder = true
|
||||
}
|
||||
if (possession.ptsConjuration >= 2 ) {
|
||||
if (possession.ptsConjuration >= 2) {
|
||||
possession.isConjurer = true
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async resultConjuration( rollData) {
|
||||
let actor = game.actors.get(rollData.possession.data.possedeid)
|
||||
if ( !rollData.rolled.isSuccess ) {
|
||||
if( rollData.isECNIDefender) {
|
||||
rollData.possession.data.compteur--
|
||||
static async resultConjuration(rollData) {
|
||||
let actor = game.actors.get(rollData.possession.system.possedeid)
|
||||
if (!rollData.rolled.isSuccess) {
|
||||
if (rollData.isECNIDefender) {
|
||||
rollData.possession.system.compteur--
|
||||
} else {
|
||||
rollData.possession.data.compteur++
|
||||
rollData.possession.system.compteur++
|
||||
}
|
||||
let update = { _id: rollData.possession._id, "data.compteur": rollData.possession.data.compteur }
|
||||
let update = { _id: rollData.possession._id, "system.compteur": rollData.possession.system.compteur }
|
||||
await actor.updateEmbeddedDocuments('Item', [update])
|
||||
}
|
||||
|
||||
|
||||
this.updateEtatPossession(rollData.possession)
|
||||
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-possession.html')
|
||||
if ( rollData.possession.isPosseder || rollData.possession.isConjurer) {
|
||||
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
|
||||
actor.deleteEmbeddedDocuments("Item", [rollData.possession._id])
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onDefensePossession( attackerId, defenderId, possessionId) {
|
||||
static async onDefensePossession(attackerId, defenderId, possessionId) {
|
||||
let attacker = game.actors.get(attackerId)
|
||||
let defender = game.actors.get(defenderId)
|
||||
|
||||
let possession = attacker.items.find( item => item.type =='possession' && item.data.data.possessionid == possessionId)
|
||||
if ( !possession ) {
|
||||
possession = defender.items.find( item => item.type =='possession' && item.data.data.possessionid == possessionId)
|
||||
if ( !possession) {
|
||||
ui.notifications.warn("Une erreur s'est produite : Aucune possession trouvée !!")
|
||||
return
|
||||
}
|
||||
let possession = attacker.getPossession(possessionId) ?? defender.getPossession(possessionId) ;
|
||||
if (!possession) {
|
||||
ui.notifications.warn("Une erreur s'est produite : Aucune possession trouvée !!")
|
||||
return
|
||||
}
|
||||
possession = duplicate(possession)
|
||||
|
||||
// Update for draconic roll
|
||||
let rollData = {
|
||||
possession: possession
|
||||
mode: "conjuration",
|
||||
isECNIDefender: defender.type == "entite",
|
||||
possession: duplicate(possession),
|
||||
attacker: attacker,
|
||||
defender: defender,
|
||||
competence: defender.getDraconicOuPossession(),
|
||||
selectedCarac: defender.system.carac.reve,
|
||||
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } }
|
||||
}
|
||||
rollData.actor = defender
|
||||
if ( defender.type == "personnage") {
|
||||
rollData.competence = duplicate(defender.getDraconicOrZero())
|
||||
rollData.competence.data.defaut_carac = 'reve-actuel'
|
||||
rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } }
|
||||
rollData.selectedCarac = defender.data.data.carac.reve
|
||||
rollData.isECNIDefender = false
|
||||
} else {
|
||||
rollData.competence = duplicate(defender.getCompetence("Possession"))
|
||||
rollData.competence.data.defaut_carac = "reve"
|
||||
rollData.forceCarac = { 'reve': { label: "Rêve", value: defender.data.data.carac.reve.value } }
|
||||
rollData.selectedCarac = defender.data.data.carac.reve
|
||||
rollData.isECNIDefender = true
|
||||
//RdDItemCompetenceCreature.setRollDataCreature( rollData )
|
||||
}
|
||||
rollData.mode = "conjuration"
|
||||
rollData.possesseur = attacker.name
|
||||
rollData.competence.system.defaut_carac = 'reve-actuel'
|
||||
|
||||
|
||||
const dialog = await RdDRoll.create(defender, rollData,
|
||||
{
|
||||
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html',
|
||||
options: { height: 400 }
|
||||
options: { height: 450 }
|
||||
},
|
||||
{
|
||||
name: 'conjurer',
|
||||
@ -121,54 +107,38 @@ export class RdDPossession {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async _onRollPossession( rollData, isSuccess ) {
|
||||
let possession = rollData.possession
|
||||
possession.isSuccess = isSuccess
|
||||
this.updateEtatPossession( possession)
|
||||
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-possession.html');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async managePossession(attacker, competence, possession=undefined) {
|
||||
|
||||
static async onAttaquePossession(attacker, competence, possession = undefined) {
|
||||
const target = RdDCombat.getTarget()
|
||||
if (target == undefined) {
|
||||
ui.notifications.warn((game.user.targets?.size ?? 0) > 1
|
||||
? "Vous devez choisir <strong>une seule</strong> cible à posséder!"
|
||||
: "Vous devez choisir une cible à posséder!");
|
||||
return;
|
||||
}
|
||||
|
||||
const defender = target.actor
|
||||
if ( !possession) {
|
||||
possession = this.searchPossessionFromEntite( attacker, defender)
|
||||
if ( !possession) {
|
||||
possession = await this.createPossession(attacker, defender)
|
||||
}
|
||||
}
|
||||
possession = duplicate(possession)
|
||||
|
||||
const defender = target.actor;
|
||||
possession = duplicate(possession ?? this.searchPossessionFromEntite(attacker, defender) ??(await this.createPossession(attacker, defender)));
|
||||
|
||||
this.updateEtatPossession(possession)
|
||||
let rollData = {
|
||||
mode: "possession",
|
||||
isECNIDefender: defender.type == "entite",
|
||||
competence: competence,
|
||||
possession: possession,
|
||||
possede: defender.name,
|
||||
possesseur: attacker.name,
|
||||
attackerId: attacker.data._id,
|
||||
defenderId: defender.data._id,
|
||||
mode: "possession"
|
||||
attacker: attacker,
|
||||
defender: defender
|
||||
};
|
||||
if ( attacker.isCreature()) {
|
||||
if (attacker.isCreature()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||
}
|
||||
|
||||
const dialog = await RdDRoll.create( attacker, rollData,
|
||||
const dialog = await RdDRoll.create(attacker, rollData,
|
||||
{
|
||||
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
|
||||
options: { height: 540 }
|
||||
}, {
|
||||
name: 'jet-possession',
|
||||
label: 'Possession: ',
|
||||
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
|
||||
callbacks: [
|
||||
{ condition: r => (r.rolled.isSuccess), action: async r => await this._onRollPossession(r, true) },
|
||||
{ condition: r => (r.rolled.isEchec), action: async r => await this._onRollPossession(r, false) },
|
||||
@ -178,11 +148,18 @@ export class RdDPossession {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createPossession( attacker, defender ) {
|
||||
static async _onRollPossession(rollData, isSuccess) {
|
||||
rollData.possession.isSuccess = isSuccess;
|
||||
this.updateEtatPossession(rollData.possession);
|
||||
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-possession.html');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createPossession(attacker, defender) {
|
||||
let possessionData = {
|
||||
name: "Possession en cours de " + attacker.name, type: 'possession',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
||||
data: { description: "", typepossession: attacker.name, possede: false, possessionid: randomID(16), possesseurid: attacker.data._id, possedeid: defender.data._id, date: 0, compteur: 0 }
|
||||
system: { description: "", typepossession: attacker.name, possede: false, possessionid: randomID(16), possesseurid: attacker.id, possedeid: defender.id, date: 0, compteur: 0 }
|
||||
}
|
||||
// Creates only the possession on the personnage side
|
||||
let poss = await defender.createEmbeddedDocuments('Item', [possessionData])
|
||||
|
@ -142,10 +142,8 @@ export class RdDResolutionTable {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async rollChances(chances, diviseur, forceDiceResult = -1) {
|
||||
if (forceDiceResult <= 0 || forceDiceResult > 100) {
|
||||
forceDiceResult = -1;
|
||||
}
|
||||
chances.roll = await RdDDice.rollTotal((forceDiceResult == -1) ? "1d100" : `${forceDiceResult}`, chances);
|
||||
chances.forceDiceResult = forceDiceResult <= 0 || forceDiceResult > 100 ? undefined : {total: forceDiceResult};
|
||||
chances.roll = await RdDDice.rollTotal( "1d100", chances);
|
||||
mergeObject(chances, this.computeReussite(chances, chances.roll, diviseur), { overwrite: true });
|
||||
return chances;
|
||||
}
|
||||
@ -166,7 +164,7 @@ export class RdDResolutionTable {
|
||||
if (rollData.selectedCarac?.label.toLowerCase().includes('chance')) {
|
||||
return true;
|
||||
}
|
||||
if (rollData.selectedSort?.data.isrituel) {
|
||||
if (rollData.selectedSort?.system.isrituel) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { ENTITE_BLURETTE, ENTITE_INCARNE} from "./constants.js";
|
||||
|
||||
/**
|
||||
* Extend the base Dialog entity by defining a custom window to perform roll.
|
||||
* @extends {Dialog}
|
||||
@ -7,15 +9,19 @@ export class RdDEncaisser extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, actor) {
|
||||
// Common conf
|
||||
const buttonsCreatures = {
|
||||
"mortel": { label: "Mortel", callback: html => this.performEncaisser("mortel") },
|
||||
"non-mortel": { label: "Non-mortel", callback: html => this.performEncaisser("non-mortel") },
|
||||
"sonne": { label: "Sonné", callback: html => this.actor.setSonne() },
|
||||
};
|
||||
const buttonsEntitesCauchemar = {
|
||||
"cauchemar": { label: "cauchemar", callback: html => this.performEncaisser("cauchemar") }
|
||||
};
|
||||
const buttons = actor.isEntiteCauchemar() ? buttonsEntitesCauchemar : buttonsCreatures;
|
||||
let buttons = {};
|
||||
if (!actor.isEntite()){
|
||||
buttons = {
|
||||
"mortel": { label: "Mortel", callback: html => this.performEncaisser("mortel") },
|
||||
"non-mortel": { label: "Non-mortel", callback: html => this.performEncaisser("non-mortel") },
|
||||
"sonne": { label: "Sonné", callback: html => this.actor.setSonne() },
|
||||
};
|
||||
}
|
||||
else if (actor.isEntite([ENTITE_BLURETTE, ENTITE_INCARNE])){
|
||||
buttons = {
|
||||
"cauchemar": { label: "cauchemar", callback: html => this.performEncaisser("cauchemar") }
|
||||
}
|
||||
}
|
||||
|
||||
let dialogConf = {
|
||||
title: "Jet d'Encaissement",
|
||||
@ -24,11 +30,10 @@ export class RdDEncaisser extends Dialog {
|
||||
default: "mortel"
|
||||
}
|
||||
|
||||
|
||||
let dialogOptions = {
|
||||
classes: ["rdddialog"],
|
||||
width: 320,
|
||||
height: 240
|
||||
height: 260
|
||||
}
|
||||
|
||||
// Select proper roll dialog template and stuff
|
||||
@ -46,6 +51,7 @@ export class RdDEncaisser extends Dialog {
|
||||
this.actor.encaisserDommages({
|
||||
dmg: {
|
||||
total: Number(this.modifier),
|
||||
ajustement: Number(this.modifier),
|
||||
encaisserSpecial: this.encaisserSpecial,
|
||||
loc: { result: 0, label: "" },
|
||||
mortalite: mortalite
|
||||
|
@ -38,25 +38,25 @@ export class RdDRoll extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _setDefaultOptions(actor, rollData) {
|
||||
const actorData = Misc.data(actor);
|
||||
const actorData = actor.system
|
||||
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: actorData.data.carac,
|
||||
carac: actorData.carac,
|
||||
finalLevel: 0,
|
||||
diffConditions: 0,
|
||||
diffLibre: rollData.competence?.data.default_diffLibre ?? 0,
|
||||
diffLibre: rollData.competence?.system.default_diffLibre ?? 0,
|
||||
malusArmureValue: actor.getMalusArmure(),
|
||||
surencMalusFlag: actor.isPersonnage() ? (actorData.data.compteurs.surenc.value < 0) : false,
|
||||
surencMalusFlag: actor.isPersonnage() ? (actorData.compteurs.surenc.value < 0) : false,
|
||||
surencMalusValue: actor.computeMalusSurEncombrement(),
|
||||
useMalusSurenc: false,
|
||||
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),
|
||||
isMalusEncombrementTotal: rollData.competence ? RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) : 0,
|
||||
useMalusEncTotal: false,
|
||||
encTotal: actor.getEncTotal(),
|
||||
ajustementAstrologique: actor.ajustementAstrologique(),
|
||||
@ -67,7 +67,7 @@ export class RdDRoll extends Dialog {
|
||||
}
|
||||
// Mini patch :Ajout du rêve actuel
|
||||
if ( actorData.type == "personnage") {
|
||||
defaultRollData.carac["reve-actuel"] = actorData.data.reve.reve
|
||||
defaultRollData.carac["reve-actuel"] = actorData.reve.reve
|
||||
}
|
||||
|
||||
mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });
|
||||
@ -144,6 +144,7 @@ export class RdDRoll extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async onAction(action, html) {
|
||||
this.rollData.forceDiceResult = Number.parseInt($('#force-dice-result').val()) ?? -1;
|
||||
await RdDResolutionTable.rollData(this.rollData);
|
||||
console.log("RdDRoll -=>", this.rollData, this.rollData.rolled);
|
||||
this.actor.setRollWindowsOpened(false);
|
||||
@ -165,17 +166,17 @@ export class RdDRoll extends Dialog {
|
||||
|
||||
function onLoad() {
|
||||
let rollData = dialog.rollData;
|
||||
console.log(rollData);
|
||||
// Update html, according to data
|
||||
console.log('Ouverture RdDRoll', rollData);
|
||||
// Update html, according to rollData
|
||||
if (rollData.competence) {
|
||||
const defaut_carac = Misc.templateData(rollData.competence).defaut_carac;
|
||||
const defaut_carac = rollData.competence.system.defaut_carac
|
||||
// Set the default carac from the competence item
|
||||
rollData.selectedCarac = rollData.carac[defaut_carac];
|
||||
$("#carac").val(defaut_carac);
|
||||
}
|
||||
if (rollData.selectedSort) {
|
||||
dialog.setSelectedSort(rollData.selectedSort);
|
||||
$(".draconic").val(rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
|
||||
$(".draconic").val(rollData.selectedSort.system.listIndex); // Uniquement a la selection du sort, pour permettre de changer
|
||||
}
|
||||
RdDItemSort.setCoutReveReel(rollData.selectedSort);
|
||||
$("#diffLibre").val(Misc.toInt(rollData.diffLibre));
|
||||
@ -221,7 +222,7 @@ export class RdDRoll extends Dialog {
|
||||
});
|
||||
html.find('#ptreve-variable').change((event) => {
|
||||
let ptreve = Misc.toInt(event.currentTarget.value);
|
||||
this.rollData.selectedSort.data.ptreve_reel = ptreve;
|
||||
this.rollData.selectedSort.system.ptreve_reel = ptreve;
|
||||
console.log("RdDRollSelectDialog - Cout reve", ptreve);
|
||||
this.updateRollResult();
|
||||
});
|
||||
@ -271,21 +272,21 @@ export class RdDRoll extends Dialog {
|
||||
|
||||
async setSelectedSort(sort) {
|
||||
this.rollData.selectedSort = sort; // Update the selectedCarac
|
||||
this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.data.draconic);
|
||||
this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.system.draconic);
|
||||
this.rollData.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord);
|
||||
this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7);
|
||||
RdDItemSort.setCoutReveReel(sort);
|
||||
const htmlSortDescription = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html", { sort: sort });
|
||||
$(".sort-ou-rituel").text(sort.data.isrituel ? "rituel" : "sort");
|
||||
$(".sort-ou-rituel").text(sort.system.isrituel ? "rituel" : "sort");
|
||||
$(".bonus-case").text(`${this.rollData.bonus}%`);
|
||||
$(".details-sort").remove();
|
||||
$(".description-sort").append(htmlSortDescription);
|
||||
$(".roll-draconic").val(sort.data.listIndex);
|
||||
$(".div-sort-difficulte-fixe").text(Misc.toSignedString(sort.data.difficulte));
|
||||
$(".div-sort-ptreve-fixe").text(sort.data.ptreve);
|
||||
$(".roll-draconic").val(sort.system.listIndex);
|
||||
$(".div-sort-difficulte-fixe").text(Misc.toSignedString(sort.system.difficulte));
|
||||
$(".div-sort-ptreve-fixe").text(sort.system.ptreve);
|
||||
const diffVariable = RdDItemSort.isDifficulteVariable(sort);
|
||||
const coutVariable = RdDItemSort.isCoutVariable(sort);
|
||||
HtmlUtility._showControlWhen($(".div-sort-non-rituel"), !sort.data.isrituel);
|
||||
HtmlUtility._showControlWhen($(".div-sort-non-rituel"), !sort.system.isrituel);
|
||||
HtmlUtility._showControlWhen($(".div-sort-difficulte-var"), diffVariable);
|
||||
HtmlUtility._showControlWhen($(".div-sort-difficulte-fixe"), !diffVariable);
|
||||
HtmlUtility._showControlWhen($(".div-sort-ptreve-var"), coutVariable);
|
||||
@ -294,7 +295,7 @@ export class RdDRoll extends Dialog {
|
||||
|
||||
async setSelectedSigneDraconique(signe){
|
||||
this.rollData.signe = signe;
|
||||
this.rollData.diffLibre = Misc.data(signe).data.difficulte,
|
||||
this.rollData.diffLibre = signe.system.difficulte,
|
||||
$(".signe-difficulte").text(Misc.toSignedString(this.rollData.diffLibre));
|
||||
}
|
||||
|
||||
@ -348,10 +349,10 @@ export class RdDRoll extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
_computeDiffCompetence(rollData) {
|
||||
if (rollData.competence) {
|
||||
return Misc.toInt(rollData.competence.data.niveau);
|
||||
return Misc.toInt(rollData.competence.system.niveau);
|
||||
}
|
||||
if (rollData.draconicList) {
|
||||
return Misc.toInt(rollData.competence.data.niveau);
|
||||
return Misc.toInt(rollData.competence.system.niveau);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -388,7 +389,7 @@ export class RdDRoll extends Dialog {
|
||||
return compName + " - " + rollData.selectedSort.name;
|
||||
}
|
||||
// If a weapon is there, add it in the title
|
||||
const niveau = Misc.toSignedString(rollData.competence.data.niveau);
|
||||
const niveau = Misc.toSignedString(rollData.competence.system.niveau)
|
||||
if (compName == carac) {
|
||||
// cas des créatures
|
||||
return carac + " Niveau " + niveau
|
||||
|
@ -2,29 +2,36 @@ export class RdDRollTables {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async genericGetTableResult(tableName, toChat) {
|
||||
let table = game.tables.find(table => table.name.toLowerCase() == tableName.toLowerCase())
|
||||
if ( !table) {
|
||||
const pack = game.packs.get("foundryvtt-reve-de-dragon.tables-diverses");
|
||||
const index = await pack.getIndex();
|
||||
const entry = index.find(e => e.name === tableName);
|
||||
table = await pack.getDocument(entry._id);
|
||||
}
|
||||
let table = RdDRollTables.getWorldTable(tableName) ?? (await RdDRollTables.getSystemTable(tableName));
|
||||
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll"});
|
||||
console.log("RdDRollTables", tableName, toChat, ":", draw);
|
||||
//console.log("RdDRollTables", tableName, toChat, ":", draw);
|
||||
return draw.results.length > 0 ? draw.results[0] : undefined;
|
||||
|
||||
}
|
||||
|
||||
static getWorldTable(tableName) {
|
||||
return game.tables.find(table => table.name.toLowerCase() == tableName.toLowerCase());
|
||||
}
|
||||
|
||||
static async getSystemTable(tableName) {
|
||||
const pack = game.packs.get("foundryvtt-reve-de-dragon.tables-diverses");
|
||||
const index = await pack.getIndex();
|
||||
const entry = index.find(e => e.name === tableName);
|
||||
return await pack.getDocument(entry._id);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async drawItemFromRollTable(tableName, toChat = false) {
|
||||
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
||||
const pack = game.packs.get(drawResult.data.collection);
|
||||
return await pack.getDocument(drawResult.data.resultId);
|
||||
const pack = game.packs.get(drawResult.documentCollection)
|
||||
let doc = await pack.getDocument(drawResult.documentId)
|
||||
return doc
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async drawTextFromRollTable(tableName, toChat) {
|
||||
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
||||
return drawResult.data.text;
|
||||
return drawResult.text;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { DialogSplitItem } from "./dialog-split-item.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
export class RdDSheetUtility {
|
||||
|
||||
@ -21,14 +20,14 @@ export class RdDSheetUtility {
|
||||
}
|
||||
|
||||
static prepareItemDropParameters(destItemId, actorId, dragData, objetVersConteneur) {
|
||||
const itemId = dragData.id || dragData.data._id;
|
||||
const item = fromUuidSync(dragData.uuid)
|
||||
return {
|
||||
destId: destItemId,
|
||||
targetActorId: actorId,
|
||||
itemId: itemId,
|
||||
sourceActorId: dragData.actorId,
|
||||
srcId: objetVersConteneur[itemId],
|
||||
onEnleverConteneur: () => { delete objetVersConteneur[itemId]; },
|
||||
itemId: item.id,
|
||||
sourceActorId: item.actor?.id,
|
||||
srcId: objetVersConteneur[item.id],
|
||||
onEnleverConteneur: () => { delete objetVersConteneur[item.id]; },
|
||||
onAjouterDansConteneur: (itemId, conteneurId) => { objetVersConteneur[itemId] = conteneurId; }
|
||||
}
|
||||
}
|
||||
@ -42,12 +41,12 @@ export class RdDSheetUtility {
|
||||
}
|
||||
|
||||
static async _onSplitItem(item, split, actor) {
|
||||
if (split >= 1 && split < Misc.data(item).data.quantite) {
|
||||
if (split >= 1 && split < item.system.quantite) {
|
||||
await item.diminuerQuantite(split);
|
||||
const itemData = duplicate(Misc.data(item));
|
||||
const splitItem = duplicate(item);
|
||||
// todo: ajouter dans le même conteneur?
|
||||
itemData.data.quantite = split;
|
||||
await actor.createEmbeddedDocuments('Item', [itemData])
|
||||
splitItem.system.quantite = split;
|
||||
await actor.createEmbeddedDocuments('Item', [splitItem])
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,3 @@
|
||||
import { SYSTEM_SOCKET_ID } from "./constants.js";
|
||||
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
@ -16,6 +15,7 @@ import { Misc } from "./misc.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { STATUSES } from "./status-effects.js";
|
||||
/* -------------------------------------------- */
|
||||
|
||||
export class RdDTMRDialog extends Dialog {
|
||||
@ -55,7 +55,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.fatigueParCase = this.viewOnly || !ReglesOptionelles.isUsing("appliquer-fatigue") ? 0 : this.actor.getTMRFatigue();
|
||||
this.cumulFatigue = 0;
|
||||
this.loadRencontres();
|
||||
this.loadSortsReserve();
|
||||
this.loadCasesSpeciales();
|
||||
this.allTokens = [];
|
||||
this.rencontreState = 'aucune';
|
||||
@ -78,12 +77,19 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
loadCasesSpeciales() {
|
||||
this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item));
|
||||
this.casesSpeciales = this.actor.items.filter(item => Draconique.isCaseTMR(item));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
loadSortsReserve() {
|
||||
this.sortsReserves = Misc.data(this.actor).data.reve.reserve.list;
|
||||
get sortsReserve() {
|
||||
return this.actor.itemTypes['sortreserve'];
|
||||
}
|
||||
|
||||
getSortsReserve(coord) {
|
||||
return this.actor.itemTypes['sortreserve'].filter(// Reserve sur une case fleuve ou normale
|
||||
TMRUtility.getTMR(coord).type == 'fleuve'
|
||||
? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve'
|
||||
: it => it.system.coord == coord
|
||||
);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -95,12 +101,15 @@ export class RdDTMRDialog extends Dialog {
|
||||
createPixiSprites() {
|
||||
EffetsDraconiques.carteTmr.createSprite(this.pixiTMR);
|
||||
this.updateTokens();
|
||||
this.demiReve = this._tokenDemiReve();
|
||||
this._updateDemiReve();
|
||||
this.forceDemiRevePositionView();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_createTokens() {
|
||||
if (!this.isDemiReveCache()) {
|
||||
this.demiReve = this._tokenDemiReve();
|
||||
this._trackToken(this.demiReve);
|
||||
}
|
||||
let tokens = this._getTokensCasesTmr()
|
||||
.concat(this._getTokensRencontres())
|
||||
.concat(this._getTokensSortsReserve());
|
||||
@ -114,7 +123,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
updateTokens() {
|
||||
this._removeTokens(t => true);
|
||||
this.loadRencontres();
|
||||
this.loadSortsReserve();
|
||||
this.loadCasesSpeciales();
|
||||
this._createTokens();
|
||||
}
|
||||
@ -133,7 +141,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return this.rencontresExistantes.map(it => this._tokenRencontre(it));
|
||||
}
|
||||
_getTokensSortsReserve() {
|
||||
return this.sortsReserves.map(it => this._tokenSortEnReserve(it));
|
||||
return this.actor.itemTypes['sortreserve'].map(it => this._tokenSortEnReserve(it));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -141,26 +149,25 @@ export class RdDTMRDialog extends Dialog {
|
||||
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord);
|
||||
}
|
||||
_tokenCaseSpeciale(casetmr) {
|
||||
const caseData = Misc.data(casetmr);
|
||||
const draconique = Draconique.get(caseData.data.specific);
|
||||
return draconique?.token(this.pixiTMR, caseData, () => caseData.data.coord);
|
||||
const caseData = casetmr;
|
||||
const draconique = Draconique.get(caseData.system.specific);
|
||||
return draconique?.token(this.pixiTMR, caseData, () => caseData.system.coord);
|
||||
}
|
||||
_tokenSortEnReserve(sortEnReserve) {
|
||||
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortEnReserve.sort, () => sortEnReserve.coord);
|
||||
_tokenSortEnReserve(sortReserve) {
|
||||
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortReserve, () => sortReserve.system.coord);
|
||||
}
|
||||
|
||||
_tokenDemiReve() {
|
||||
const actorData = Misc.data(this.actor);
|
||||
return EffetsDraconiques.demiReve.token(this.pixiTMR, actorData, () => actorData.data.reve.tmrpos.coord);
|
||||
return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor, () => this.actor.system.reve.tmrpos.coord);
|
||||
}
|
||||
|
||||
_updateDemiReve() {
|
||||
forceDemiRevePositionView() {
|
||||
this.notifierResonanceSigneDraconique(this._getActorCoord());
|
||||
this._setTokenPosition(this.demiReve);
|
||||
this._trackToken(this.demiReve);
|
||||
}
|
||||
|
||||
_getActorCoord() {
|
||||
return Misc.data(this.actor).data.reve.tmrpos.coord;
|
||||
return this.actor.system.reve.tmrpos.coord;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -207,24 +214,12 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.actor.rollLireSigneDraconique(this._getActorCoord());
|
||||
});
|
||||
|
||||
html.find('#dir-top').click((event) => {
|
||||
this.moveFromKey("top");
|
||||
});
|
||||
html.find('#dir-top-left').click((event) => {
|
||||
this.moveFromKey("top-left");
|
||||
});
|
||||
html.find('#dir-top-right').click((event) => {
|
||||
this.moveFromKey("top-right");
|
||||
});
|
||||
html.find('#dir-bottom-left').click((event) => {
|
||||
this.moveFromKey("bottom-left");
|
||||
});
|
||||
html.find('#dir-bottom-right').click((event) => {
|
||||
this.moveFromKey("bottom-right");
|
||||
});
|
||||
html.find('#dir-bottom').click((event) => {
|
||||
this.moveFromKey("bottom");
|
||||
});
|
||||
html.find('#dir-top').click((event) => this.moveFromKey("top"));
|
||||
html.find('#dir-top-left').click((event) => this.moveFromKey("top-left"));
|
||||
html.find('#dir-top-right').click((event) => this.moveFromKey("top-right"));
|
||||
html.find('#dir-bottom-left').click((event) => this.moveFromKey("bottom-left"));
|
||||
html.find('#dir-bottom-right').click((event) => this.moveFromKey("bottom-right"));
|
||||
html.find('#dir-bottom').click((event) => this.moveFromKey("bottom"));
|
||||
|
||||
// Gestion du cout de montée en points de rêve
|
||||
let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse();
|
||||
@ -236,51 +231,52 @@ export class RdDTMRDialog extends Dialog {
|
||||
// Le reste...
|
||||
this.updateValuesDisplay();
|
||||
let tmr = TMRUtility.getTMR(this._getActorCoord());
|
||||
await this.manageRencontre(tmr, () => {
|
||||
this.postRencontre(tmr);
|
||||
});
|
||||
await this.manageRencontre(tmr);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async updateValuesDisplay() {
|
||||
if (!this.rendered) {
|
||||
return;
|
||||
}
|
||||
const coord = this._getActorCoord();
|
||||
const actorData = Misc.data(this.actor);
|
||||
|
||||
HtmlUtility._showControlWhen($(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
|
||||
|
||||
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
||||
ptsreve.innerHTML = actorData.data.reve.reve.value;
|
||||
ptsreve.innerHTML = this.actor.system.reve.reve.value;
|
||||
|
||||
let tmrpos = document.getElementById("tmr-pos");
|
||||
if (this.isDemiReveCache()) {
|
||||
tmrpos.innerHTML = '?? (' + TMRUtility.getTMRType(coord) + ')';
|
||||
tmrpos.innerHTML = `?? ( ${ TMRUtility.getTMRType(coord)})`;
|
||||
} else {
|
||||
tmrpos.innerHTML = coord + " (" + TMRUtility.getTMRLabel(coord) + ")";
|
||||
tmrpos.innerHTML = `${coord} ( ${TMRUtility.getTMRLabel(coord)})`;
|
||||
}
|
||||
|
||||
let etat = document.getElementById("tmr-etatgeneral-value");
|
||||
etat.innerHTML = this.actor.getEtatGeneral();
|
||||
|
||||
let refoulement = document.getElementById("tmr-refoulement-value");
|
||||
refoulement.innerHTML = actorData.data.reve.refoulement.value;
|
||||
refoulement.innerHTML = this.actor.system.reve.refoulement.value;
|
||||
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
let fatigueItem = document.getElementById("tmr-fatigue-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>";
|
||||
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(this.actor.system.sante.fatigue.value, this.actor.system.sante.endurance.max).html() + "</table>";
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
close() {
|
||||
if ( this.actor.tmrApp ) {
|
||||
async close() {
|
||||
this.descenteTMR = true;
|
||||
if (this.actor.tmrApp) {
|
||||
this.actor.tmrApp = undefined; // Cleanup reference
|
||||
if ( !this.viewOnly ) {
|
||||
this.actor.setStatusEffect("EFFECT.StatusDemiReve", false);
|
||||
if (!this.viewOnly) {
|
||||
await this.actor.setEffect(STATUSES.StatusDemiReve, false)
|
||||
this._tellToGM(this.actor.name + " a quitté les terres médianes");
|
||||
}
|
||||
this.actor.santeIncDec("fatigue", this.cumulFatigue).then(super.close()); // moving 1 cell costs 1 fatigue
|
||||
await this.actor.santeIncDec("fatigue", this.cumulFatigue)
|
||||
}
|
||||
await super.close(); // moving 1 cell costs 1 fatigue
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -316,11 +312,11 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.currentRencontre.graphics = []; // Keep track of rectangles to delete it
|
||||
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location
|
||||
for (let coordTMR of listCoordTMR) {
|
||||
let rect = this._getCaseRectangleCoord(coordTMR);
|
||||
var rectDraw = new PIXI.Graphics();
|
||||
rectDraw.beginFill(0xFFFF00, 0.3);
|
||||
const rect = this._getCaseRectangleCoord(coordTMR);
|
||||
const rectDraw = new PIXI.Graphics();
|
||||
rectDraw.beginFill(0xffff00, 0.3);
|
||||
// set the line style to have a width of 5 and set the color to red
|
||||
rectDraw.lineStyle(5, 0xFF0000);
|
||||
rectDraw.lineStyle(5, 0xff0000);
|
||||
// draw a rectangle
|
||||
rectDraw.drawRect(rect.x, rect.y, rect.w, rect.h);
|
||||
this.pixiApp.stage.addChild(rectDraw);
|
||||
@ -337,14 +333,12 @@ export class RdDTMRDialog extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
async choisirCasePortee(coord, portee) {
|
||||
// Récupère la liste des cases à portées
|
||||
let locList = TMRUtility.getTMRPortee(coord, portee);
|
||||
this.colorierZoneRencontre(locList);
|
||||
this.colorierZoneRencontre(TMRUtility.getTMRPortee(coord, portee));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async choisirCaseType(type) {
|
||||
const locList = TMRUtility.filterTMR(it => it.type == type).map(it => it.coord);
|
||||
this.colorierZoneRencontre(locList);
|
||||
this.colorierZoneRencontre(TMRUtility.filterTMR(it => it.type == type).map(it => it.coord));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -479,12 +473,13 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async manageRencontre(tmr, postRencontre) {
|
||||
async manageRencontre(tmr) {
|
||||
if (this.viewOnly) {
|
||||
return;
|
||||
}
|
||||
this.descenteTMR = false;
|
||||
this.currentRencontre = undefined;
|
||||
if (this._presentCite(tmr, postRencontre)) {
|
||||
if (this._presentCite(tmr)) {
|
||||
return;
|
||||
}
|
||||
let rencontre = await this._jetDeRencontre(tmr);
|
||||
@ -494,27 +489,27 @@ export class RdDTMRDialog extends Dialog {
|
||||
console.log("manageRencontre", rencontre);
|
||||
this.currentRencontre = duplicate(rencontre);
|
||||
|
||||
let dialog = new RdDTMRRencontreDialog("", this, this.currentRencontre, postRencontre);
|
||||
let dialog = new RdDTMRRencontreDialog(this, this.currentRencontre, () => this.postRencontre(tmr));
|
||||
dialog.render(true);
|
||||
}
|
||||
else {
|
||||
postRencontre();
|
||||
this.postRencontre(tmr);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_presentCite(tmr, postRencontre) {
|
||||
_presentCite(tmr) {
|
||||
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
|
||||
if (presentCite) {
|
||||
this.minimize();
|
||||
const caseData = Misc.data(presentCite);
|
||||
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (type => this._utiliserPresentCite(presentCite, type, tmr, postRencontre)));
|
||||
const caseData = presentCite;
|
||||
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (type => this._utiliserPresentCite(presentCite, type, tmr)));
|
||||
}
|
||||
return presentCite;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _utiliserPresentCite(presentCite, typeRencontre, tmr, postRencontre) {
|
||||
async _utiliserPresentCite(presentCite, typeRencontre, tmr) {
|
||||
this.currentRencontre = TMRRencontres.getRencontre(typeRencontre);
|
||||
await TMRRencontres.evaluerForceRencontre(this.currentRencontre);
|
||||
await EffetsDraconiques.presentCites.ouvrirLePresent(this.actor, presentCite);
|
||||
@ -533,7 +528,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this._tentativeMaitrise(rencontreData);
|
||||
|
||||
this.maximize();
|
||||
postRencontre();
|
||||
this.postRencontre(tmr);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -569,6 +564,9 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async manageTmrInnaccessible(tmr) {
|
||||
if (!tmr) {
|
||||
return await this.actor.reinsertionAleatoire('Sortie de carte');
|
||||
}
|
||||
const caseTmrInnaccessible = this.casesSpeciales.find(c => EffetsDraconiques.isInnaccessible(c, tmr.coord));
|
||||
if (caseTmrInnaccessible) {
|
||||
return await this.actor.reinsertionAleatoire(caseTmrInnaccessible.name);
|
||||
@ -589,7 +587,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
|
||||
}
|
||||
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined,
|
||||
rollData.competence.data.defaut_carac = 'reve-actuel';
|
||||
rollData.competence.system.defaut_carac = 'reve-actuel';
|
||||
await this._rollMaitriseCaseHumide(rollData);
|
||||
}
|
||||
}
|
||||
@ -601,7 +599,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
async _resultatMaitriseCaseHumide(rollData) {
|
||||
await this.souffleSiEchecTotal(rollData);
|
||||
this.toclose = rollData.rolled.isEchec;
|
||||
if (rollData.rolled.isSuccess && rollData.double) {
|
||||
rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements };
|
||||
rollData.double = undefined;
|
||||
@ -614,7 +611,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
|
||||
});
|
||||
if (rollData.rolled.isEchec) {
|
||||
this.close();
|
||||
await this.close();
|
||||
}
|
||||
}
|
||||
|
||||
@ -628,16 +625,16 @@ export class RdDTMRDialog extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
isCaseHumide(tmr) {
|
||||
if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) {
|
||||
return undefined;
|
||||
return false;
|
||||
}
|
||||
if (this.isCaseMaitrisee(tmr.coord)) {
|
||||
ChatMessage.create({
|
||||
content: tmr.label + ": cette case humide est déja maitrisée grâce à votre Tête <strong>Quête des Eaux</strong>",
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||
});
|
||||
return undefined;
|
||||
return false;
|
||||
}
|
||||
return -7;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -714,7 +711,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
|
||||
maitrise: { verbe: 'conquérir', action: options.action }
|
||||
};
|
||||
rollData.competence.data.defaut_carac = 'reve-actuel';
|
||||
rollData.competence.system.defaut_carac = 'reve-actuel';
|
||||
|
||||
await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options));
|
||||
}
|
||||
@ -724,8 +721,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
if (rollData.rolled.isETotal) {
|
||||
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
|
||||
}
|
||||
this.toclose = rollData.rolled.isEchec;
|
||||
|
||||
rollData.poesie = await Poetique.getExtrait();
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||
@ -743,6 +738,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
async _maitriserTMR(rollData, callbackMaitrise) {
|
||||
this.minimize(); // Hide
|
||||
rollData.isTMRCache = rollData.actor.isTMRCache();
|
||||
const dialog = await RdDRoll.create(this.actor, rollData,
|
||||
{
|
||||
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
|
||||
@ -769,9 +765,8 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async declencheSortEnReserve(coord) {
|
||||
|
||||
let sortsEnCoord = TMRUtility.getSortsReserve(this.sortsReserves, coord);
|
||||
if (sortsEnCoord.length > 0) {
|
||||
let sorts = this.getSortsReserve(coord);
|
||||
if (sorts.length > 0) {
|
||||
if (EffetsDraconiques.isSortReserveImpossible(this.actor)) {
|
||||
ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!");
|
||||
return;
|
||||
@ -779,8 +774,8 @@ export class RdDTMRDialog extends Dialog {
|
||||
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 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>";
|
||||
for (let sort of sorts) {
|
||||
msg += `<li><a class="chat-card-button declencher-sort-reserve" data-actor-id="${this.actor.id}" data-tmr-coord="${coord}" data-sort-id='${sort.id}">${sort.name}</a></li>`;
|
||||
}
|
||||
msg += "</ol>";
|
||||
ChatMessage.create({
|
||||
@ -789,33 +784,35 @@ export class RdDTMRDialog extends Dialog {
|
||||
});
|
||||
return;
|
||||
}
|
||||
await this.processSortReserve(sortsEnCoord[0]);
|
||||
await this.processSortReserve(sorts[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
lancerSortEnReserve(coord, sortId) {
|
||||
let sortEnCoord = TMRUtility.getSortsReserve(this.sortsReserves, coord);
|
||||
let sortReserve = sortEnCoord.find(sortReserve => sortReserve.sort._id == sortId);
|
||||
if (sortReserve) {
|
||||
this.processSortReserve(sortReserve);
|
||||
let sorts = this.getSortsReserve(coord);
|
||||
let sort = sorts.find(it => it.id == sortId);
|
||||
if (sort) {
|
||||
this.processSortReserve(sort);
|
||||
} else {
|
||||
ChatMessage.create({
|
||||
content: "Une erreur est survenue : impossible de récupérer le sort en réserve demandé.",
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||
content:
|
||||
"Une erreur est survenue : impossible de récupérer le sort en réserve demandé.",
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async processSortReserve(sortReserve) {
|
||||
await this.actor.deleteSortReserve(sortReserve);
|
||||
//this.updateSortReserve();
|
||||
console.log("declencheSortEnReserve", sortReserve)
|
||||
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)})
|
||||
`);
|
||||
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
|
||||
console.log("declencheSortEnReserve", sortReserve);
|
||||
this._tellToUserAndGM(`Vous avez déclenché
|
||||
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"}
|
||||
en réserve <strong>${sortReserve.name}</strong>
|
||||
avec ${sortReserve.system.ptreve} points de Rêve
|
||||
en ${sortReserve.system.coord} (${TMRUtility.getTMRLabel(sortReserve.system.coord)}).
|
||||
L'heure ciblée est ${sortReserve.system.heurecible}`);
|
||||
this.close();
|
||||
}
|
||||
|
||||
@ -867,56 +864,70 @@ export class RdDTMRDialog extends Dialog {
|
||||
if (this.viewOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
let clickOddq = RdDTMRDialog._computeEventOddq(event.data.originalEvent);
|
||||
await this._onClickTMRPos(clickOddq); // Vérifier l'état des compteurs reve/fatigue/vie
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _onClickTMRPos(clickOddq) {
|
||||
if (this.isDemiReveCache()) {
|
||||
ui.notifications.error(`Vous ne connaissez plus votre position dans les TMR.
|
||||
Vous devez utiliser les boutons de direction pour vous déplacer.
|
||||
Une fois que vous aurez retrouvé votre demi-rêve, demandez au gardien de vérifier et rendre les TMR visibles.
|
||||
`);
|
||||
return;
|
||||
}
|
||||
|
||||
let currentOddq = TMRUtility.coordTMRToOddq(this._getActorCoord());
|
||||
|
||||
console.log("deplacerDemiReve >>>>", currentOddq, clickOddq);
|
||||
|
||||
let targetCoord = TMRUtility.oddqToCoordTMR(clickOddq);
|
||||
let currentCoord = TMRUtility.oddqToCoordTMR(currentOddq);
|
||||
|
||||
// Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter)
|
||||
let deplacementType = this._calculDeplacement(targetCoord, currentCoord, currentOddq, clickOddq);
|
||||
|
||||
// Si le deplacement est valide
|
||||
if (deplacementType == 'normal' || deplacementType == 'saut') {
|
||||
await this._deplacerDemiReve(targetCoord, deplacementType);
|
||||
} else if (deplacementType == 'messager') { // Dans ce cas, ouverture du lancement de sort sur la case visée
|
||||
await this._messagerDemiReve(targetCoord);
|
||||
} else {
|
||||
ui.notifications.error("Vous ne pouvez pas vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
|
||||
console.log("STATUS :", this.rencontreState, this.currentRencontre);
|
||||
if (this.isDemiReveCache()) {
|
||||
if (this.isTerreAttache(targetCoord)
|
||||
|| this.isConnaissanceFleuve(currentCoord, targetCoord)
|
||||
|| deplacementType == 'changeur')
|
||||
{
|
||||
// déplacement possible
|
||||
await this.actor.setTMRVisible(true);
|
||||
this.demiReve = this._tokenDemiReve();
|
||||
this._trackToken(this.demiReve);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui.notifications.error(`Vous ne connaissez plus votre position dans les TMR.
|
||||
Vous devez utiliser les boutons de direction pour vous déplacer.
|
||||
Une fois que vous aurez retrouvé votre demi-rêve, demandez au gardien de vérifier et rendre les TMR visibles.
|
||||
`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (deplacementType){
|
||||
case 'normal':
|
||||
await this._deplacerDemiReve(targetCoord, deplacementType);
|
||||
break;
|
||||
case 'messager':
|
||||
await this._messagerDemiReve(targetCoord);
|
||||
break;
|
||||
case 'changeur':
|
||||
case 'passeur':
|
||||
await this._deplacerDemiReve(targetCoord, deplacementType);
|
||||
break;
|
||||
default:
|
||||
ui.notifications.error("Vous ne pouvez pas vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
|
||||
console.log("STATUS :", this.rencontreState, this.currentRencontre);
|
||||
}
|
||||
|
||||
this.checkQuitterTMR();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_calculDeplacement(targetCoord, currentCoord, fromOddq, toOddq) {
|
||||
|
||||
const isInArea = this.rencontreState == 'aucune'
|
||||
? (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || TMRUtility.distanceOddq(fromOddq, toOddq) <= 1)
|
||||
: this.currentRencontre?.locList.find(coord => coord == targetCoord) ?? false
|
||||
: this.currentRencontre?.locList?.find(coord => coord == targetCoord) ?? false
|
||||
if (isInArea) {
|
||||
switch (this.rencontreState) {
|
||||
case 'aucune': return 'normal';
|
||||
case 'messager': return 'messager';
|
||||
case 'passeur': case 'changeur': return 'saut';
|
||||
case 'passeur': case 'changeur': case 'messager': return this.rencontreState;
|
||||
}
|
||||
}
|
||||
return 'erreur'
|
||||
return 'erreur';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -932,9 +943,8 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
externalRefresh(tmrData) {
|
||||
externalRefresh() {
|
||||
this.createPixiSprites();
|
||||
this.forceDemiRevePositionView();
|
||||
this.updateValuesDisplay();
|
||||
this.updateTokens();
|
||||
console.log("TMR REFRESHED !!!");
|
||||
@ -946,26 +956,20 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.nettoyerRencontre();
|
||||
}
|
||||
let tmr = TMRUtility.getTMR(targetCoord);
|
||||
//console.log("deplacerDemiReve", tmr, this);
|
||||
// Gestion cases spéciales type Trou noir, etc
|
||||
tmr = await this.manageTmrInnaccessible(tmr);
|
||||
|
||||
await this.actor.updateCoordTMR(tmr.coord);
|
||||
|
||||
this._updateDemiReve();
|
||||
this.forceDemiRevePositionView();
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
}
|
||||
this.updateValuesDisplay();
|
||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||
msg: "msg_tmr_move", data: {
|
||||
actorId: this.actor.data._id,
|
||||
tmrPos: Misc.data(this.actor).data.reve.tmrpos
|
||||
}
|
||||
});
|
||||
this.actor.notifyRefreshTMR();
|
||||
|
||||
if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/...
|
||||
await this.manageRencontre(tmr, () => this.postRencontre(tmr));
|
||||
await this.manageRencontre(tmr);
|
||||
}
|
||||
else {
|
||||
await this.postRencontre(tmr);
|
||||
@ -984,25 +988,21 @@ export class RdDTMRDialog extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
async postRencontre(tmr) {
|
||||
if (!(this.viewOnly || this.currentRencontre)) {
|
||||
await this.manageCaseHumide(tmr);
|
||||
await this.conquerirCiteFermee(tmr);
|
||||
await this.purifierPeriple(tmr);
|
||||
await this.conquerirTMR(tmr);
|
||||
await this.validerVisite(tmr);
|
||||
await this.declencheSortEnReserve(tmr.coord);
|
||||
await this.actor.checkSoufflePeage(tmr);
|
||||
// TODO: vérifier que la méthode s'arrête en cas de non-maîtrise
|
||||
if (!this.descenteTMR) await this.manageCaseHumide(tmr);
|
||||
if (!this.descenteTMR) await this.conquerirCiteFermee(tmr);
|
||||
if (!this.descenteTMR) await this.purifierPeriple(tmr);
|
||||
if (!this.descenteTMR) await this.conquerirTMR(tmr);
|
||||
if (!this.descenteTMR) await this.validerVisite(tmr);
|
||||
if (!this.descenteTMR) await this.declencheSortEnReserve(tmr.coord);
|
||||
if (!this.descenteTMR) await this.actor.checkSoufflePeage(tmr);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async forceDemiRevePositionView() {
|
||||
this._updateDemiReve();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async forceDemiRevePosition(coord) {
|
||||
async positionnerDemiReve(coord) {
|
||||
await this.actor.updateCoordTMR(coord);
|
||||
this._updateDemiReve();
|
||||
this.forceDemiRevePositionView();
|
||||
let tmr = TMRUtility.getTMR(coord);
|
||||
await this.postRencontre(tmr);
|
||||
return tmr;
|
||||
@ -1014,7 +1014,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
let x = origEvent.clientX - canvasRect.left;
|
||||
let y = origEvent.clientY - canvasRect.top;
|
||||
let col = Math.floor(x / tmrConstants.cellw); // [From 0 -> 12]
|
||||
y -= (col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||
y -= col % 2 == 0 ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||
let row = Math.floor(y / tmrConstants.cellh); // [From 0 -> 14]
|
||||
return { col: col, row: row };
|
||||
}
|
||||
@ -1025,14 +1025,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
return this.pixiTMR.getCaseRectangle(TMRUtility.coordTMRToOddq(coord));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_setTokenPosition(token) {
|
||||
if (this.isDemiReveCache() && this.demiReve === token ) {
|
||||
return;
|
||||
}
|
||||
this.pixiTMR.setPosition(token.sprite, TMRUtility.coordTMRToOddq(token.coordTMR()));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_removeTokens(filter) {
|
||||
const tokensToRemove = this.allTokens.filter(filter);
|
||||
@ -1043,7 +1035,10 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_trackToken(token) {
|
||||
if (this.demiReve === token && this.isDemiReveCache()) {
|
||||
return;
|
||||
}
|
||||
this.pixiTMR.setPosition(token.sprite, TMRUtility.coordTMRToOddq(token.coordTMR()));
|
||||
this.allTokens.push(token);
|
||||
this._setTokenPosition(token);
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
export class RdDTMRRencontreDialog extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, tmrApp, rencontre, postRencontre) {
|
||||
constructor(tmrApp, rencontre, postRencontre) {
|
||||
const dialogConf = {
|
||||
title: "Rencontre en TMR!",
|
||||
content: "Vous rencontrez un " + rencontre.name + " de force " + rencontre.force + "<br>",
|
||||
|
@ -8,7 +8,7 @@ export class RdDTokenHud {
|
||||
|
||||
static init() {
|
||||
// Integration du TokenHUD
|
||||
Hooks.on('renderTokenHUD', (app, html, data) => { RdDTokenHud.addTokenHudExtensions(app, html, data._id) });
|
||||
Hooks.on('renderTokenHUD', (app, html, token) => { RdDTokenHud.addTokenHudExtensions(app, html, token._id) });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -22,41 +22,64 @@ export class RdDTokenHud {
|
||||
|
||||
let token = canvas.tokens.get(tokenId);
|
||||
let actor = token.actor;
|
||||
let combatant = game.combat.combatants.find(c => Misc.data(c).tokenId == tokenId);
|
||||
let combatant = game.combat.combatants.find(c => c.tokenId == tokenId);
|
||||
if (! (combatant?.actor) ) {
|
||||
ui.notifications.warn(`Le combatant ${token.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
|
||||
return;
|
||||
}
|
||||
app.hasExtension = true;
|
||||
|
||||
let armesList = RdDCombatManager.buildListeActionsCombat(combatant);
|
||||
let actionsCombat = RdDCombatManager.listActionsCombat(combatant);
|
||||
const hudData = {
|
||||
combatant: combatant, armes: armesList,
|
||||
commandes: [{ name: 'Initiative +1', command: 'inc', value: 0.01 }, { name: 'Initiative -1', command: 'dec', value: -0.01 }]
|
||||
combatant: combatant,
|
||||
actions: actionsCombat,
|
||||
commandes: [
|
||||
{ name: "Autre action", command: 'autre' },
|
||||
{ name: 'Initiative +1', command: 'inc', value: 0.01 },
|
||||
{ name: 'Initiative -1', command: 'dec', value: -0.01 }]
|
||||
};
|
||||
|
||||
const controlIconCombat = html.find('.control-icon[data-action=combat]');
|
||||
// initiative
|
||||
await RdDTokenHud._configureSubMenu(controlIconCombat, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', hudData,
|
||||
await RdDTokenHud._configureSubMenu(controlIconCombat,
|
||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
|
||||
hudData,
|
||||
(event) => {
|
||||
let initCommand = event.currentTarget.attributes['data-command'].value;
|
||||
let combatantId = event.currentTarget.attributes['data-combatant-id'].value;
|
||||
if (!initCommand) {
|
||||
let armeIndex = event.currentTarget.attributes['data-arme-id'].value;
|
||||
let arme = armesList[armeIndex];
|
||||
RdDCombatManager.rollInitiativeCompetence(combatantId, arme);
|
||||
} else if (initCommand == 'inc') {
|
||||
RdDCombatManager.incDecInit(combatantId, 0.01);
|
||||
} else if (initCommand == 'dec') {
|
||||
RdDCombatManager.incDecInit(combatantId, -0.01);
|
||||
}
|
||||
let initCommand = event.currentTarget.attributes['data-command']?.value;
|
||||
let combatantId = event.currentTarget.attributes['data-combatant-id']?.value;
|
||||
if (initCommand) {
|
||||
RdDTokenHud._initiativeCommand(initCommand, combatantId);
|
||||
} else {
|
||||
let index = event.currentTarget.attributes['data-action-index'].value;
|
||||
let action = actionsCombat[index];
|
||||
RdDCombatManager.rollInitiativeAction(combatantId, action);
|
||||
}
|
||||
});
|
||||
|
||||
const controlIconTarget = html.find('.control-icon[data-action=target]');
|
||||
// combat
|
||||
await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData,
|
||||
(event) => {
|
||||
let armeIndex = event.currentTarget.attributes['data-arme-id'].value;
|
||||
actor.rollArme(armesList[armeIndex]);
|
||||
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
|
||||
const action = actionsCombat[actionIndex];
|
||||
if (action.action == 'conjurer') {
|
||||
actor.conjurerPossession(actor.getPossession(action.system.possessionid));
|
||||
}
|
||||
else {
|
||||
actor.rollArme(action);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static _initiativeCommand(initCommand, combatantId) {
|
||||
switch (initCommand) {
|
||||
case 'inc': return RdDCombatManager.incDecInit(combatantId, 0.01);
|
||||
case 'dec': return RdDCombatManager.incDecInit(combatantId, -0.01);
|
||||
case 'autre': return RdDCombatManager.rollInitiativeAction(combatantId,
|
||||
{ name: "Autre action", action: 'autre', system: { initOnly: true, competence: "Autre action" } });
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async addTokenHudExtensions(app, html, tokenId) {
|
||||
const controlIconCombat = html.find('.control-icon[data-action=combat]');
|
||||
|
@ -11,6 +11,9 @@ import { RdDDice } from "./rdd-dice.js";
|
||||
import { RdDItem } from "./item.js";
|
||||
import { Monnaie } from "./item-monnaie.js";
|
||||
import { RdDPossession } from "./rdd-possession.js";
|
||||
import { RdDNameGen } from "./rdd-namegen.js";
|
||||
import { RdDConfirm } from "./rdd-confirm.js";
|
||||
import { RdDActor } from "./actor.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// This table starts at 0 -> niveau -10
|
||||
@ -103,7 +106,7 @@ export class RdDUtility {
|
||||
/* -------------------------------------------- */
|
||||
static async init() {
|
||||
Hooks.on("renderChatMessage", async (app, html, msg) => RdDUtility.onRenderChatMessage(app, html, msg));
|
||||
Hooks.on('renderChatLog', (log, html, data) => RdDUtility.chatListeners(html));
|
||||
Hooks.on('renderChatLog', (log, html, chatLog) => RdDUtility.chatListeners(html));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -114,17 +117,58 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html',
|
||||
'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-sheet-categorie-competences-partial.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-effects-partial.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-oeuvre-partial.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-liste-blessures-partial.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html',
|
||||
// Conteneur/item in Actor sheet
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-conteneur.html',
|
||||
"systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-monnaie.html",
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-editor-notes-mj.html',
|
||||
// sous-parties de feuilles de personnages
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-buttons.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-etat.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/competence.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/combat.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/blessures.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/blessure.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queue.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-signes-draconiques.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-rencontres.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts-reserve.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-meditations.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-casestmr.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-journal.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/editor-notes-mj.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html',
|
||||
"systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-monnaie.html",
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-animaux.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.html',
|
||||
//Items
|
||||
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item-arme-sheet.html',
|
||||
@ -170,6 +214,7 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html',
|
||||
@ -198,6 +243,7 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-description.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html',
|
||||
@ -221,8 +267,10 @@ export class RdDUtility {
|
||||
];
|
||||
|
||||
Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null'));
|
||||
Handlebars.registerHelper('lowerFirst', str => Misc.lowerFirst(str ?? 'Null'));
|
||||
Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? 'NULL');
|
||||
Handlebars.registerHelper('le', str => Grammar.articleDetermine(str));
|
||||
Handlebars.registerHelper('apostrophe', (article, str) => Grammar.apostrophe(article, str));
|
||||
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str));
|
||||
Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args));
|
||||
Handlebars.registerHelper('buildConteneur', (objet) => { return new Handlebars.SafeString(RdDUtility.buildConteneur(objet)); });
|
||||
@ -231,37 +279,40 @@ export class RdDUtility {
|
||||
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
|
||||
Handlebars.registerHelper('typeTmr-name', coord => TMRUtility.typeTmrName(coord));
|
||||
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
|
||||
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
|
||||
|
||||
Handlebars.registerHelper('sortCompetence', competences => competences.sort((a, b) => {
|
||||
if (a.name.startsWith("Survie") && b.name.startsWith("Survie")) {
|
||||
if (a.name.includes("Cité")) return -1;
|
||||
if (b.name.includes("Cité")) return 1;
|
||||
if (a.name.includes("Extérieur")) return -1;
|
||||
if (b.name.includes("Extérieur")) return 1;
|
||||
Handlebars.registerHelper('filtreTriCompetences', competences => competences.filter(it => it.system.isVisible)
|
||||
.sort((a, b) => {
|
||||
if (a.name.startsWith("Survie") && b.name.startsWith("Survie")) {
|
||||
if (a.name.includes("Cité")) return -1;
|
||||
if (b.name.includes("Cité")) return 1;
|
||||
if (a.name.includes("Extérieur")) return -1;
|
||||
if (b.name.includes("Extérieur")) return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
if (a.system.categorie.startsWith("melee") && b.system.categorie.startsWith("melee")) {
|
||||
if (a.name.includes("Corps")) return -1;
|
||||
if (b.name.includes("Corps")) return 1;
|
||||
if (a.name.includes("Dague")) return -1;
|
||||
if (b.name.includes("Dague")) return 1;
|
||||
if (a.name.includes("Esquive")) return -1;
|
||||
if (b.name.includes("Esquive")) return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
if (a.name.startsWith("Voie") && b.name.startsWith("Voie")) {
|
||||
if (a.name.includes("Oniros")) return -1;
|
||||
if (b.name.includes("Oniros")) return 1;
|
||||
if (a.name.includes("Hypnos")) return -1;
|
||||
if (b.name.includes("Hypnos")) return 1;
|
||||
if (a.name.includes("Narcos")) return -1;
|
||||
if (b.name.includes("Narcos")) return 1;
|
||||
if (a.name.includes("Thanatos")) return -1;
|
||||
if (b.name.includes("Thanatos")) return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
if (a.data.categorie.startsWith("melee") && b.data.categorie.startsWith("melee")) {
|
||||
if (a.name.includes("Corps")) return -1;
|
||||
if (b.name.includes("Corps")) return 1;
|
||||
if (a.name.includes("Dague")) return -1;
|
||||
if (b.name.includes("Dague")) return 1;
|
||||
if (a.name.includes("Esquive")) return -1;
|
||||
if (b.name.includes("Esquive")) return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
if (a.name.startsWith("Voie") && b.name.startsWith("Voie")) {
|
||||
if (a.name.includes("Oniros")) return -1;
|
||||
if (b.name.includes("Oniros")) return 1;
|
||||
if (a.name.includes("Hypnos")) return -1;
|
||||
if (b.name.includes("Hypnos")) return 1;
|
||||
if (a.name.includes("Narcos")) return -1;
|
||||
if (b.name.includes("Narcos")) return 1;
|
||||
if (a.name.includes("Thanatos")) return -1;
|
||||
if (b.name.includes("Thanatos")) return 1;
|
||||
return a.name.localeCompare(b.name);
|
||||
}
|
||||
return a.name.localeCompare(b.name);
|
||||
}));
|
||||
})
|
||||
);
|
||||
|
||||
return loadTemplates(templatePaths);
|
||||
}
|
||||
@ -274,7 +325,7 @@ export class RdDUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async selectObjetType(actorSheet) {
|
||||
let typeObjets = RdDItem.getTypeObjetsEquipement();
|
||||
let typeObjets = RdDItem.getTypesObjetsEquipement();
|
||||
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>`
|
||||
@ -326,8 +377,8 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static checkNull(items) {
|
||||
if (items && items.length) {
|
||||
static arrayOrEmpty(items) {
|
||||
if (items?.length) {
|
||||
return items;
|
||||
}
|
||||
return [];
|
||||
@ -356,48 +407,50 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static filterItemsPerTypeForSheet(formData) {
|
||||
static filterItemsPerTypeForSheet(formData, itemTypes) {
|
||||
|
||||
RdDUtility.filterEquipementParType(formData);
|
||||
RdDUtility.filterEquipementParType(formData, itemTypes);
|
||||
|
||||
formData.sorts = this.checkNull(formData.itemsByType['sort']);
|
||||
formData.signesdraconiques = this.checkNull(formData.itemsByType['signedraconique']);
|
||||
formData.queues = this.checkNull(formData.itemsByType['queue']);
|
||||
formData.souffles = this.checkNull(formData.itemsByType['souffle']);
|
||||
formData.ombres = this.checkNull(formData.itemsByType['ombre']);
|
||||
formData.tetes = this.checkNull(formData.itemsByType['tete']);
|
||||
formData.taches = this.checkNull(formData.itemsByType['tache']);
|
||||
formData.meditations = this.checkNull(formData.itemsByType['meditation']);
|
||||
formData.chants = this.checkNull(formData.itemsByType['chant']);
|
||||
formData.danses = this.checkNull(formData.itemsByType['danse']);
|
||||
formData.musiques = this.checkNull(formData.itemsByType['musique']);
|
||||
formData.oeuvres = this.checkNull(formData.itemsByType['oeuvre']);
|
||||
formData.jeux = this.checkNull(formData.itemsByType['jeu']);
|
||||
formData.sorts = this.arrayOrEmpty(itemTypes['sort']);
|
||||
formData.casestmr = this.arrayOrEmpty(itemTypes['casetmr']);
|
||||
formData.signesdraconiques = this.arrayOrEmpty(itemTypes['signedraconique']);
|
||||
formData.queues = this.arrayOrEmpty(itemTypes['queue']);
|
||||
formData.souffles = this.arrayOrEmpty(itemTypes['souffle']);
|
||||
formData.ombres = this.arrayOrEmpty(itemTypes['ombre']);
|
||||
formData.tetes = this.arrayOrEmpty(itemTypes['tete']);
|
||||
formData.taches = this.arrayOrEmpty(itemTypes['tache']);
|
||||
formData.meditations = this.arrayOrEmpty(itemTypes['meditation']);
|
||||
formData.chants = this.arrayOrEmpty(itemTypes['chant']);
|
||||
formData.danses = this.arrayOrEmpty(itemTypes['danse']);
|
||||
formData.musiques = this.arrayOrEmpty(itemTypes['musique']);
|
||||
formData.oeuvres = this.arrayOrEmpty(itemTypes['oeuvre']);
|
||||
formData.jeux = this.arrayOrEmpty(itemTypes['jeu']);
|
||||
|
||||
formData.recettescuisine = this.checkNull(formData.itemsByType['recettecuisine']);
|
||||
formData.recettesAlchimiques = this.checkNull(formData.itemsByType['recettealchimique']);
|
||||
formData.maladies = this.checkNull(formData.itemsByType['maladie']);
|
||||
formData.poisons = this.checkNull(formData.itemsByType['poison']);
|
||||
formData.possessions = this.checkNull(formData.itemsByType['possession']);
|
||||
formData.recettescuisine = this.arrayOrEmpty(itemTypes['recettecuisine']);
|
||||
formData.recettesAlchimiques = this.arrayOrEmpty(itemTypes['recettealchimique']);
|
||||
formData.maladies = this.arrayOrEmpty(itemTypes['maladie']);
|
||||
formData.poisons = this.arrayOrEmpty(itemTypes['poison']);
|
||||
formData.possessions = this.arrayOrEmpty(itemTypes['possession']);
|
||||
formData.maladiesPoisons = formData.maladies.concat(formData.poisons);
|
||||
formData.competences = (formData.itemsByType.competence ?? []).concat(formData.itemsByType.competencecreature ?? []);
|
||||
formData.competences = (itemTypes['competence'] ?? []).concat(itemTypes['competencecreature'] ?? []);
|
||||
formData.sortsReserve = this.arrayOrEmpty(itemTypes['sortreserve']);
|
||||
}
|
||||
|
||||
static filterEquipementParType(formData) {
|
||||
formData.conteneurs = this.checkNull(formData.itemsByType['conteneur']);
|
||||
static filterEquipementParType(formData, itemTypes) {
|
||||
formData.conteneurs = this.arrayOrEmpty(itemTypes['conteneur']);
|
||||
|
||||
formData.materiel = this.checkNull(formData.itemsByType['objet']);
|
||||
formData.armes = this.checkNull(formData.itemsByType['arme']);
|
||||
formData.armures = this.checkNull(formData.itemsByType['armure']);
|
||||
formData.munitions = this.checkNull(formData.itemsByType['munition']);
|
||||
formData.livres = this.checkNull(formData.itemsByType['livre']);
|
||||
formData.potions = this.checkNull(formData.itemsByType['potion']);
|
||||
formData.ingredients = this.checkNull(formData.itemsByType['ingredient']);
|
||||
formData.herbes = this.checkNull(formData.itemsByType['herbe']);
|
||||
formData.monnaie = this.checkNull(formData.itemsByType['monnaie']);
|
||||
formData.materiel = this.arrayOrEmpty(itemTypes['objet']);
|
||||
formData.armes = this.arrayOrEmpty(itemTypes['arme']);
|
||||
formData.armures = this.arrayOrEmpty(itemTypes['armure']);
|
||||
formData.munitions = this.arrayOrEmpty(itemTypes['munition']);
|
||||
formData.livres = this.arrayOrEmpty(itemTypes['livre']);
|
||||
formData.potions = this.arrayOrEmpty(itemTypes['potion']);
|
||||
formData.ingredients = this.arrayOrEmpty(itemTypes['ingredient']);
|
||||
formData.herbes = this.arrayOrEmpty(itemTypes['herbe']);
|
||||
formData.monnaie = this.arrayOrEmpty(itemTypes['monnaie']);
|
||||
formData.monnaie.sort(Monnaie.triValeurDenier());
|
||||
formData.nourritureboissons = this.checkNull(formData.itemsByType['nourritureboisson']);
|
||||
formData.gemmes = this.checkNull(formData.itemsByType['gemme']);
|
||||
formData.nourritureboissons = this.arrayOrEmpty(itemTypes['nourritureboisson']);
|
||||
formData.gemmes = this.arrayOrEmpty(itemTypes['gemme']);
|
||||
|
||||
formData.objets = formData.conteneurs
|
||||
.concat(formData.materiel)
|
||||
@ -419,7 +472,7 @@ export class RdDUtility {
|
||||
// Attribution des objets aux conteneurs
|
||||
for (let conteneur of conteneurs) {
|
||||
conteneur.subItems = [];
|
||||
for (let id of conteneur.data.contenu ?? []) {
|
||||
for (let id of conteneur.system.contenu ?? []) {
|
||||
let objet = objets.find(objet => (id == objet._id));
|
||||
if (objet) {
|
||||
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template
|
||||
@ -429,27 +482,26 @@ export class RdDUtility {
|
||||
}
|
||||
}
|
||||
for (let conteneur of conteneurs) {
|
||||
conteneur.data.encTotal = RdDUtility.calculEncContenu(conteneur, objets);
|
||||
conteneur.system.encTotal = RdDUtility.calculEncContenu(conteneur, objets);
|
||||
}
|
||||
return objetVersConteneur;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static calculEncContenu(conteneur, objets) {
|
||||
const itemData = Misc.data(conteneur);
|
||||
const contenuDatas = (itemData.data.contenu ?? []).filter(id => id != undefined)
|
||||
.map(id => Misc.data(objets.find(it => (id == it._id))))
|
||||
const contenus = (conteneur.system.contenu ?? []).filter(id => id != undefined)
|
||||
.map(id => objets.find(it => (id == it.id)))
|
||||
.filter(it => it);
|
||||
let enc = Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
|
||||
for (let itemData of contenuDatas) {
|
||||
if (itemData.type == 'conteneur') {
|
||||
enc += RdDUtility.calculEncContenu(itemData, objets);
|
||||
let enc = Number(conteneur.system.encombrement ?? 0) * Number(conteneur.system.quantite ?? 1);
|
||||
for (let contenu of contenus) {
|
||||
if (contenu.type == 'conteneur') {
|
||||
enc += RdDUtility.calculEncContenu(contenu, objets);
|
||||
}
|
||||
else {
|
||||
enc += Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
|
||||
enc += Number(contenu.system.encombrement ?? 0) * Number(contenu.system.quantite ?? 1)
|
||||
}
|
||||
}
|
||||
return enc;
|
||||
return enc
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -462,34 +514,32 @@ export class RdDUtility {
|
||||
/** Construit la structure récursive des conteneurs, avec imbrication potentielle
|
||||
*
|
||||
*/
|
||||
static buildConteneur(objet, niveau) {
|
||||
if (!niveau) niveau = 1;
|
||||
objet.niveau = niveau;
|
||||
//console.log("OBJ:", objet);
|
||||
let str = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-conteneur.html']({ item: objet });
|
||||
if (objet.type == 'conteneur') {
|
||||
const afficherContenu = this.getAfficheContenu(objet._id);
|
||||
str = str + RdDUtility.buildContenu(objet, niveau, afficherContenu);
|
||||
}
|
||||
return str;
|
||||
static buildConteneur(objet, profondeur) {
|
||||
if (!profondeur) profondeur = 1;
|
||||
objet.niveau = profondeur;
|
||||
const isConteneur = objet.type == 'conteneur';
|
||||
const isOuvert = isConteneur && this.getAfficheContenu(objet._id);
|
||||
const isVide = isConteneur && objet.system.contenu.length == 0;
|
||||
const conteneur = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html']({
|
||||
item: objet,
|
||||
vide: isVide,
|
||||
ouvert: isOuvert
|
||||
});
|
||||
const contenu = isConteneur ? RdDUtility.buildContenu(objet, profondeur, isOuvert) : '';
|
||||
return conteneur + contenu;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static buildContenu(objet, niveau, afficherContenu) {
|
||||
if (!niveau) niveau = 1;
|
||||
objet.niveau = niveau;
|
||||
let strContenu = "";
|
||||
static buildContenu(objet, profondeur, afficherContenu) {
|
||||
if (!profondeur) profondeur = 1;
|
||||
objet.niveau = profondeur;
|
||||
const display = afficherContenu ? 'item-display-show' : 'item-display-hide';
|
||||
//console.log("ITEM DISPLAYED", objet );
|
||||
if (afficherContenu) {
|
||||
strContenu = "<ul class='item-list alterne-list item-display-show list-item-margin" + niveau + "'>";
|
||||
} else {
|
||||
strContenu = "<ul class='item-list alterne-list item-display-hide list-item-margin" + niveau + "'>";
|
||||
}
|
||||
let strContenu = `<ul class='item-list alterne-list ${display} list-item-margin${profondeur}'>`;
|
||||
for (let subItem of objet.subItems) {
|
||||
strContenu = strContenu + this.buildConteneur(subItem, niveau + 1);
|
||||
strContenu += this.buildConteneur(subItem, profondeur + 1);
|
||||
}
|
||||
strContenu = strContenu + "</ul>";
|
||||
return strContenu;
|
||||
return strContenu + "</ul>";
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -604,7 +654,68 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static selectEncaissement(degats, mortalite) {
|
||||
static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) {
|
||||
let formula = "2d10";
|
||||
|
||||
// Chaque dé fait au minmum la difficulté libre
|
||||
if (ReglesOptionelles.isUsing('degat-minimum-malus-libre')) {
|
||||
if (rollData.diffLibre < 0) {
|
||||
let valeurMin = Math.abs(rollData.diffLibre);
|
||||
formula += "min" + valeurMin;
|
||||
}
|
||||
}
|
||||
// Chaque dé fait au minmum la difficulté libre
|
||||
if (ReglesOptionelles.isUsing('degat-ajout-malus-libre')) {
|
||||
if (rollData.diffLibre < 0) {
|
||||
let valeurMin = Math.abs(rollData.diffLibre);
|
||||
formula += "+" + valeurMin;
|
||||
}
|
||||
}
|
||||
|
||||
let roll = await RdDDice.roll(formula, options);
|
||||
|
||||
// 1 dé fait au minmum la difficulté libre
|
||||
if (ReglesOptionelles.isUsing('degat-minimum-malus-libre-simple')) {
|
||||
if (rollData.diffLibre < 0) {
|
||||
let valeurMin = Math.abs(rollData.diffLibre);
|
||||
if (roll.terms[0].results[0].result < valeurMin) {
|
||||
roll.terms[0].results[0].result = valeurMin;
|
||||
} else if (roll.terms[0].results[1].result < valeurMin) {
|
||||
roll.terms[0].results[1].result = valeurMin;
|
||||
}
|
||||
roll._total = roll.terms[0].results[0].result + roll.terms[0].results[1].result;
|
||||
}
|
||||
}
|
||||
|
||||
return await RdDUtility.prepareEncaissement(rollData, roll, armure);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async prepareEncaissement(rollData, roll, armure) {
|
||||
const jetTotal = roll.total + rollData.dmg.total - armure;
|
||||
let encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite);
|
||||
let over20 = Math.max(jetTotal - 20, 0);
|
||||
encaissement.dmg = rollData.dmg;
|
||||
encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type);
|
||||
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;';
|
||||
encaissement.roll = roll;
|
||||
encaissement.armure = armure;
|
||||
encaissement.total = jetTotal;
|
||||
encaissement.vie = await RdDUtility._evaluatePerte(encaissement.vie, over20);
|
||||
encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20);
|
||||
encaissement.penetration = rollData.arme?.system.penetration ?? 0;
|
||||
encaissement.blessures = (
|
||||
encaissement.critiques> 0 ? "Critique":
|
||||
encaissement.graves> 0 ? "Grave":
|
||||
encaissement.legeres> 0 ? "Légère":
|
||||
encaissement.eraflures>0 ? "Contusions/Eraflures":
|
||||
'Aucune'
|
||||
);
|
||||
return encaissement;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _selectEncaissement(degats, mortalite) {
|
||||
const table = definitionsEncaissement[mortalite] === undefined ? definitionsEncaissement["mortel"] : definitionsEncaissement[mortalite];
|
||||
for (let encaissement of table) {
|
||||
if ((encaissement.minimum === undefined || encaissement.minimum <= degats)
|
||||
@ -615,6 +726,13 @@ export class RdDUtility {
|
||||
return duplicate(table[0]);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async _evaluatePerte(formula, over20) {
|
||||
let perte = new Roll(formula, { over20: over20 });
|
||||
await perte.evaluate({ async: true });
|
||||
return perte.total;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static currentFatigueMalus(value, max) {
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
@ -634,6 +752,23 @@ export class RdDUtility {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async loadItems(filter, compendium) {
|
||||
let items = game.items.filter(filter);
|
||||
if (compendium) {
|
||||
const ids = items.map(it => it.id);
|
||||
const names = items.map(it => it.name.toLowerCase());
|
||||
items = items.concat(await RdDUtility.loadCompendium(compendium, it => !ids.includes(it.id) && !names.includes(it.name.toLowerCase()) && filter(it)));
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async loadCompendium(compendium, filter = it => true) {
|
||||
let compendiumData = await RdDUtility.loadCompendiumData(compendium);
|
||||
return compendiumData.filter(filter);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async loadCompendiumData(compendium) {
|
||||
const pack = game.packs.get(compendium);
|
||||
@ -641,15 +776,9 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async loadCompendium(compendium, filter = item => true) {
|
||||
let compendiumData = await RdDUtility.loadCompendiumData(compendium);
|
||||
return compendiumData.filter(filter);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async responseNombreAstral(data) {
|
||||
let actor = game.actors.get(data.id);
|
||||
actor.ajouteNombreAstral(data);
|
||||
static async responseNombreAstral(callData) {
|
||||
let actor = game.actors.get(callData.id);
|
||||
actor.ajouteNombreAstral(callData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -666,7 +795,7 @@ export class RdDUtility {
|
||||
case "msg_tmr_move":
|
||||
let actor = game.actors.get(sockmsg.data.actorId);
|
||||
if (actor.isOwner || game.user.isGM) {
|
||||
actor.refreshTMRView(sockmsg.data.tmrPos);
|
||||
actor.refreshTMRView();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -681,18 +810,19 @@ export class RdDUtility {
|
||||
let coord = event.currentTarget.attributes['data-tmr-coord'].value;
|
||||
let actorId = event.currentTarget.attributes['data-actor-id'].value;
|
||||
let actor = game.actors.get(actorId);
|
||||
actor.tmrApp.forceDemiRevePosition(coord);
|
||||
actor.tmrApp.positionnerDemiReve(coord);
|
||||
});
|
||||
// Gestion spécifique des sorts en réserve multiples (ie têtes)
|
||||
html.on("click", '#sort-reserve', event => {
|
||||
html.on("click", '.declencher-sort-reserve', event => {
|
||||
let coord = event.currentTarget.attributes['data-tmr-coord'].value;
|
||||
let sortId = event.currentTarget.attributes['data-sort-id'].value;
|
||||
let actorId = event.currentTarget.attributes['data-actor-id'].value;
|
||||
let actor = game.actors.get(actorId);
|
||||
actor.tmrApp.lancerSortEnReserve(coord, sortId);
|
||||
// TODO: supprimer le message?
|
||||
});
|
||||
|
||||
// gestion bouton tchat Acheter
|
||||
// gestion bouton tchat Possession
|
||||
html.on("click", '.defense-possession', event => {
|
||||
let attackerId = event.currentTarget.attributes['data-attackerId'].value
|
||||
let defenderId = event.currentTarget.attributes['data-defenderId'].value
|
||||
@ -701,7 +831,13 @@ export class RdDUtility {
|
||||
});
|
||||
|
||||
// gestion bouton tchat Acheter
|
||||
html.on("click", '.button-acheter', event => DialogItemAchat.onButtonAcheter(event));
|
||||
html.on("click", '.button-acheter', event => {
|
||||
const venteData = DialogItemAchat.venteData(event.currentTarget);
|
||||
if (venteData) {
|
||||
DialogItemAchat.onAcheter(venteData);
|
||||
}
|
||||
});
|
||||
html.on("click", '.button-creer-acteur', event => RdDNameGen.onCreerActeur(event));
|
||||
|
||||
// Gestion du bouton payer
|
||||
html.on("click", '.payer-button', event => {
|
||||
@ -746,7 +882,7 @@ export class RdDUtility {
|
||||
static getSelectedActor(msgPlayer = undefined) {
|
||||
if (canvas.tokens.controlled.length == 1) {
|
||||
let token = canvas.tokens.controlled[0];
|
||||
if (token.actor && token.data.actorLink) {
|
||||
if (token.actor) {
|
||||
return token.actor;
|
||||
}
|
||||
if (msgPlayer != undefined) {
|
||||
@ -769,7 +905,7 @@ export class RdDUtility {
|
||||
static createMonnaie(name, valeur_deniers, img = "", enc = 0.01) {
|
||||
let piece = {
|
||||
name: name, type: 'monnaie', img: img, _id: randomID(16),
|
||||
data: {
|
||||
dasystemta: {
|
||||
quantite: 0,
|
||||
valeur_deniers: valeur_deniers,
|
||||
encombrement: enc,
|
||||
@ -821,80 +957,57 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static confirmerSuppressionSubacteur(actorSheet, li) {
|
||||
let actorId = li.data("actor-id");
|
||||
let actor = game.actors.get(actorId);
|
||||
let msgTxt = "<p>Etes vous certain de vouloir supprimer le lien vers ce véhicule/monture/suivant : " + actor.data.name + " ?</p>";
|
||||
let d = new Dialog({
|
||||
title: "Confirmer la suppression du lien",
|
||||
content: msgTxt,
|
||||
buttons: {
|
||||
delete: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: "Supprimer le lien",
|
||||
callback: () => {
|
||||
console.log("Delete : ", actorId);
|
||||
actorSheet.actor.removeSubacteur(actorId);
|
||||
li.slideUp(200, () => actorSheet.render(false));
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: "Annuler"
|
||||
}
|
||||
},
|
||||
default: "cancel"
|
||||
});
|
||||
d.render(true);
|
||||
static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete) {
|
||||
RdDConfirm.confirmer({
|
||||
settingConfirmer: "confirmation-supprimer-lien-acteur",
|
||||
content: `<p>Etes vous certain de vouloir supprimer le lien vers ${subActor.name} ?</p>`,
|
||||
title: 'Confirmer la suppression',
|
||||
buttonLabel: 'Supprimer le lien',
|
||||
onAction: () => {
|
||||
console.log('Delete : ', subActor.id);
|
||||
sheet.actor.removeSubacteur(subActor.id);
|
||||
RdDUtility.slideOnDelete(sheet, htmlToDelete);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async confirmerSuppression(actorSheet, li) {
|
||||
let itemId = li.data("item-id");
|
||||
let objet = actorSheet.actor.getObjet(itemId);
|
||||
|
||||
if (objet.type == 'monnaie' && Monnaie.isSystemMonnaie(objet)) {
|
||||
ui.notifications.warn("Suppression des monnaies de base impossible");
|
||||
return;
|
||||
}
|
||||
|
||||
let msgTxt = "<p>Etes vous certain de vouloir supprimer cet objet ?";
|
||||
let buttons = {
|
||||
delete: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: "Supprimer l'objet",
|
||||
callback: () => {
|
||||
console.log("Delete : ", itemId);
|
||||
actorSheet.actor.deleteEmbeddedDocuments('Item', [itemId]);
|
||||
li.slideUp(200, () => actorSheet.render(false));
|
||||
}
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: "Annuler"
|
||||
static async confirmerSuppressionItem(sheet, item, htmlToDelete) {
|
||||
const itemId = item.id;
|
||||
const confirmationSuppression = {
|
||||
settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(),
|
||||
content: `<p>Etes vous certain de vouloir supprimer: ${item.name}?</p>`,
|
||||
title: `Supprimer ${item.name}`,
|
||||
buttonLabel: "Supprimer",
|
||||
onAction: () => {
|
||||
console.log('Delete : ', itemId);
|
||||
sheet.actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false });
|
||||
RdDUtility.slideOnDelete(sheet, htmlToDelete);
|
||||
}
|
||||
};
|
||||
if (item.isConteneurNonVide()) {
|
||||
confirmationSuppression.content += `<p>Ce conteneur n'est pas vide. Que voulez vous supprimer?</p>`;
|
||||
confirmationSuppression.settingConfirmer = undefined;
|
||||
RdDConfirm.confirmer(confirmationSuppression,
|
||||
{
|
||||
'deleteall': {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: "Supprimer conteneur et contenu",
|
||||
callback: () => {
|
||||
console.log("Delete : ", itemId);
|
||||
sheet.actor.deleteAllConteneur(itemId, { renderSheet: false });
|
||||
RdDUtility.slideOnDelete(sheet, htmlToDelete);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
const docData = Misc.data(objet);
|
||||
if (docData.type == 'conteneur' && docData.data.contenu.length > 0) {
|
||||
msgTxt += "<br>Ce conteneur n'est pas vide. Choisissez l'option de suppression";
|
||||
buttons['deleteall'] = {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: "Supprimer le conteneur et tout son contenu",
|
||||
callback: () => {
|
||||
console.log("Delete : ", itemId);
|
||||
actorSheet.actor.deleteAllConteneur(itemId);
|
||||
li.slideUp(200, () => actorSheet.render(false));
|
||||
}
|
||||
}
|
||||
else {
|
||||
RdDConfirm.confirmer(confirmationSuppression)
|
||||
}
|
||||
msgTxt += "</p>";
|
||||
let d = new Dialog({
|
||||
title: "Confirmer la suppression",
|
||||
content: msgTxt,
|
||||
buttons: buttons,
|
||||
default: "cancel"
|
||||
});
|
||||
d.render(true);
|
||||
}
|
||||
|
||||
static slideOnDelete(sheet, htmlToDelete) {
|
||||
return htmlToDelete.slideUp(200, () => sheet.render(false));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -2,27 +2,42 @@ import { SYSTEM_RDD } from "./constants.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
const listeReglesOptionelles = [
|
||||
{ name: 'recul', group: 'Règles de combat', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
|
||||
{ name: 'resistanceArmeParade', group: 'Règles de combat', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" },
|
||||
{ name: 'deteriorationArmure', group: 'Règles de combat', descr: "Tenir compte de la détérioration des armures" },
|
||||
{ name: 'defenseurDesarme', group: 'Règles de combat', descr: "Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier" },
|
||||
{ name: 'categorieParade', group: 'Règles de combat', descr: "Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes" },
|
||||
{ name: 'tripleSignificative', group: 'Règles de combat', descr: "En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès" },
|
||||
{ name: 'degat-minimum-malus-libre-simple', group: 'Règles de combat', descr: "Le malus libre d'attaque remplace une des valeurs de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, si 1 résultat est inférieur à 4, alors il devient 4.", default: false },
|
||||
{ name: 'degat-minimum-malus-libre', group: 'Règles de combat', descr: "Le malus libre d'attaque remplace une valeur de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, tout résultat inférieur à 4 devient 4.", default: false },
|
||||
{ name: 'degat-ajout-malus-libre', group: 'Règles de combat', descr: "Le malus libre d'attaque s'ajoute au jet d'encaissement et aux autres bonus. Exemple : la difficulté libre de l'attaquant est de -4. Le jet d'encaissement est effectué à 2d10+4, plus les bonus de situation et d'armes.", default: false },
|
||||
{ name: 'astrologie', group: 'Règles générales', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels", default: true },
|
||||
{ name: 'afficher-prix-joueurs', group: 'Règles générales', descr: "Afficher le prix de l'équipement des joueurs", default: true },
|
||||
{ name: 'appliquer-fatigue', group: 'Règles générales', descr: "Appliquer les règles de fatigue", default: true },
|
||||
{ name: 'afficher-colonnes-reussite', group: 'Règles générales', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
|
||||
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
|
||||
{ group: 'Règles de combat', name: 'resistanceArmeParade', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" },
|
||||
{ group: 'Règles de combat', name: 'deteriorationArmure', descr: "Tenir compte de la détérioration des armures" },
|
||||
{ group: 'Règles de combat', name: 'defenseurDesarme', descr: "Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier" },
|
||||
{ group: 'Règles de combat', name: 'categorieParade', descr: "Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes" },
|
||||
{ group: 'Règles de combat', name: 'tripleSignificative', descr: "En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès" },
|
||||
{ group: 'Règles de combat', name: 'degat-minimum-malus-libre-simple', descr: "Le malus libre d'attaque remplace une des valeurs de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, si le plus petit dé est inférieur à 4, alors il devient 4.", default: false },
|
||||
{ group: 'Règles de combat', name: 'degat-minimum-malus-libre', descr: "Le malus libre d'attaque remplace une valeur de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, tout résultat inférieur à 4 devient 4.", default: false },
|
||||
{ group: 'Règles de combat', name: 'degat-ajout-malus-libre', descr: "Le malus libre d'attaque s'ajoute au jet d'encaissement et aux autres bonus. Exemple : la difficulté libre de l'attaquant est de -4. Le jet d'encaissement est effectué à 2d10+4, plus les bonus de situation et d'armes.", default: false },
|
||||
{ group: 'Règles de combat', name: 'validation-encaissement-gr', descr: "Le Gardien des Rêves doit valider les jets d'encaissement et peut les changer.", default: false },
|
||||
|
||||
{ group: 'Règles générales', name: 'astrologie', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels"},
|
||||
{ group: 'Règles générales', name: 'afficher-prix-joueurs', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true},
|
||||
{ group: 'Règles générales', name: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"},
|
||||
{ group: 'Règles générales', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
|
||||
|
||||
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-equipement', descr: "Confirmer la suppression des équipements", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-oeuvre', descr: "Confirmer la suppression des oeuvres", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-connaissance', descr: "Confirmer la suppression des connaissances", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-draconique', descr: "Confirmer la suppression des queues, souffles, têtes", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-effet', descr: "Confirmer la suppression des effets", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-competence', descr: "Confirmer la suppression des compétences", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-autres', descr: "Confirmer la suppression des autres types d'Objets", scope: "client"},
|
||||
];
|
||||
|
||||
const uniquementJoueur = listeReglesOptionelles.filter(it => it.uniquementJoueur).map(it=>it.name);
|
||||
|
||||
export class ReglesOptionelles extends FormApplication {
|
||||
static init() {
|
||||
for (const regle of listeReglesOptionelles) {
|
||||
const name = regle.name;
|
||||
const id = ReglesOptionelles._getIdRegle(name);
|
||||
game.settings.register(SYSTEM_RDD, id, { name: id, scope: "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean });
|
||||
game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean });
|
||||
}
|
||||
|
||||
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
|
||||
@ -30,8 +45,7 @@ export class ReglesOptionelles extends FormApplication {
|
||||
label: "Choix des règles optionelles",
|
||||
hint: "Ouvre la fenêtre de sélection des règles optionelles",
|
||||
icon: "fas fa-bars",
|
||||
type: ReglesOptionelles,
|
||||
restricted: true
|
||||
type: ReglesOptionelles
|
||||
});
|
||||
}
|
||||
|
||||
@ -49,7 +63,7 @@ export class ReglesOptionelles extends FormApplication {
|
||||
id: "optional-settings",
|
||||
template: "systems/foundryvtt-reve-de-dragon/templates/regles-optionelles.html",
|
||||
height: 600,
|
||||
width: 350,
|
||||
width: 450,
|
||||
minimizable: false,
|
||||
closeOnSubmit: true,
|
||||
title: "Règles optionnelles"
|
||||
@ -59,10 +73,10 @@ export class ReglesOptionelles extends FormApplication {
|
||||
|
||||
getData() {
|
||||
let formData = super.getData();
|
||||
const regles = listeReglesOptionelles.map(it => {
|
||||
const regles = listeReglesOptionelles.filter(it => game.user.isGM || it.scope == "client").map(it => {
|
||||
it = duplicate(it);
|
||||
it.id = ReglesOptionelles._getIdRegle(it.name);
|
||||
it.active = ReglesOptionelles.isUsing(it.name);
|
||||
it.active = ReglesOptionelles.isSet(it.name);
|
||||
return it;
|
||||
});
|
||||
formData.regles = regles;
|
||||
@ -71,9 +85,20 @@ export class ReglesOptionelles extends FormApplication {
|
||||
}
|
||||
|
||||
static isUsing(name) {
|
||||
if (game.user.isGM && uniquementJoueur.includes(name)) {
|
||||
return true;
|
||||
}
|
||||
return ReglesOptionelles.isSet(name);
|
||||
}
|
||||
|
||||
static isSet(name) {
|
||||
return game.settings.get(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name));
|
||||
}
|
||||
|
||||
static set(name, value) {
|
||||
return game.settings.set(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name), value ? true: false);
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
html.find(".select-option").click((event) => {
|
||||
if (event.currentTarget.attributes.name) {
|
||||
|
@ -19,9 +19,9 @@ import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
*/
|
||||
export const referenceAjustements = {
|
||||
competence: {
|
||||
isUsed: (rollData, actor) => Misc.data(rollData.competence),
|
||||
getLabel: (rollData, actor) => Misc.data(rollData.competence)?.name,
|
||||
getValue: (rollData, actor) => Misc.data(rollData.competence)?.data?.niveau,
|
||||
isUsed: (rollData, actor) => rollData.competence,
|
||||
getLabel: (rollData, actor) => rollData.competence?.name,
|
||||
getValue: (rollData, actor) => rollData.competence?.system?.niveau,
|
||||
},
|
||||
meditation: {
|
||||
isUsed: (rollData, actor) => rollData.meditation,
|
||||
@ -33,7 +33,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 ?? Misc.data(rollData.competence)?.data.default_diffLibre ?? 0
|
||||
: rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0
|
||||
},
|
||||
diffConditions: {
|
||||
isUsed: (rollData, actor) => rollData.diffConditions != undefined,
|
||||
@ -95,10 +95,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) => 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,
|
||||
isVisible: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
|
||||
isUsed: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
|
||||
getLabel: (rollData, actor) => "Ecaille d'Efficacité: ",
|
||||
getValue: (rollData, actor) => Math.max(Number(Misc.data(rollData.arme)?.data.ecaille_efficacite), 0),
|
||||
getValue: (rollData, actor) => Math.max(Number(rollData.arme?.system.ecaille_efficacite), 0),
|
||||
},
|
||||
finesse: {
|
||||
isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData),
|
||||
|
@ -1,26 +1,41 @@
|
||||
import { SYSTEM_RDD } from "./constants.js";
|
||||
|
||||
const rddStatusEffects = [
|
||||
{ rdd: true, id: 'stun', label: 'EFFECT.StatusStunned', icon: 'icons/svg/stoned.svg', "duration.rounds": 1 },
|
||||
{ rdd: true, id: 'bleeding', label: 'EFFECT.StatusBleeding', icon: 'icons/svg/blood.svg' },
|
||||
{ rdd: true, id: 'prone', label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg' },
|
||||
{ rdd: true, id: 'grappling', tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' },
|
||||
{ rdd: true, id: 'grappled', tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' },
|
||||
{ rdd: true, id: 'restrain', label: 'EFFECT.StatusRestrained', icon: 'icons/svg/net.svg' },
|
||||
{ rdd: true, id: 'unconscious', label: 'EFFECT.StatusUnconscious', icon: 'icons/svg/unconscious.svg' },
|
||||
{ rdd: true, id: 'blind', label: 'EFFECT.StatusBlind', icon: 'icons/svg/blind.svg' },
|
||||
{ rdd: true, id: 'comma', label: 'EFFECT.StatusComma', icon: 'icons/svg/skull.svg' },
|
||||
{ rdd: true, id: 'dead', label: 'EFFECT.StatusDead', icon: 'icons/svg/skull.svg' },
|
||||
{ rdd: true, id: 'demi-reve', label: 'EFFECT.StatusDemiReve', icon: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd12.svg' }
|
||||
];
|
||||
const demiReveStatusEffect = rddStatusEffects.find(it => it.label == 'EFFECT.StatusDemiReve');
|
||||
export const STATUSES = {
|
||||
StatusStunned : 'stun',
|
||||
StatusBleeding: 'bleeding',
|
||||
StatusProne: 'prone',
|
||||
StatusGrappling: 'grappling',
|
||||
StatusGrappled: 'grappled',
|
||||
StatusRestrained: 'restrain',
|
||||
StatusUnconscious: 'unconscious',
|
||||
StatusBlind: 'blind',
|
||||
StatusComma: 'comma',
|
||||
StatusDead: 'dead',
|
||||
StatusDemiReve: 'demi-reve',
|
||||
}
|
||||
|
||||
const statusDemiSurprise = new Set(['EFFECT.StatusStunned', 'EFFECT.StatusProne', 'EFFECT.StatusRestrain']);
|
||||
const statusSurpriseTotale = new Set(['EFFECT.StatusUnconscious', 'EFFECT.StatusBlind', 'EFFECT.StatusComma']);
|
||||
const rddStatusEffects = [
|
||||
{ rdd: true, id: STATUSES.StatusStunned, label: 'EFFECT.StatusStunned', icon: 'icons/svg/stoned.svg', "duration.rounds": 1 },
|
||||
{ rdd: true, id: STATUSES.StatusBleeding, label: 'EFFECT.StatusBleeding', icon: 'icons/svg/blood.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusProne, label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' },
|
||||
{ rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' },
|
||||
{ rdd: true, id: STATUSES.StatusRestrained, label: 'EFFECT.StatusRestrained', icon: 'icons/svg/net.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusUnconscious, label: 'EFFECT.StatusUnconscious', icon: 'icons/svg/unconscious.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusBlind, label: 'EFFECT.StatusBlind', icon: 'icons/svg/blind.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusComma, label: 'EFFECT.StatusComma', icon: 'icons/svg/skull.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusDead, label: 'EFFECT.StatusDead', icon: 'icons/svg/skull.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusDemiReve, label: 'EFFECT.StatusDemiReve', icon: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd12.svg' }
|
||||
];
|
||||
const demiReveStatusEffect = rddStatusEffects.find(it => it.id == STATUSES.StatusDemiReve);
|
||||
|
||||
const statusDemiSurprise = [STATUSES.StatusStunned, STATUSES.StatusProne, STATUSES.StatusRestrained];
|
||||
const statusSurpriseTotale = [STATUSES.StatusUnconscious, STATUSES.StatusBlind, STATUSES.StatusComma];
|
||||
|
||||
export class StatusEffects {
|
||||
static onReady() {
|
||||
const rddStatusIds = rddStatusEffects.map(it => it.id);
|
||||
rddStatusEffects.forEach(it => it.flags = { core: { statusId: it.id } });
|
||||
const defaultStatusEffectIds = CONFIG.statusEffects.map(it => it.id);
|
||||
game.settings.register(SYSTEM_RDD, "use-status-effects", {
|
||||
name: "use-status-effects",
|
||||
@ -47,40 +62,36 @@ export class StatusEffects {
|
||||
|
||||
static valeurSurprise(effect, isCombat) {
|
||||
// const id = StatusEffects.statusId(effect);
|
||||
if (statusSurpriseTotale.has(effect.label)) {
|
||||
if (statusSurpriseTotale.includes(effect.flags?.core?.statusId)) {
|
||||
return 2;
|
||||
}
|
||||
return statusDemiSurprise.has(effect.label) || (isCombat && effect.label == demiReveStatusEffect.label) ? 1 : 0;
|
||||
}
|
||||
|
||||
static setMandatoryRdd() {
|
||||
CONFIG.statusEffects.filter(it => statusDemiSurprise.has(it.id) || statusSurpriseTotale.has(it.id))
|
||||
.forEach(it => it.rdd = true);
|
||||
return statusDemiSurprise.includes(effect.flags?.core?.statusId) || (isCombat && effect.flags?.core?.statusId == STATUSES.StatusDemiReve) ? 1 : 0;
|
||||
}
|
||||
|
||||
static _getUseStatusEffects() {
|
||||
const setting = game.settings.get(SYSTEM_RDD, "use-status-effects");
|
||||
return setting ? new Set(setting.split(',')) : new Set();
|
||||
return setting ? setting.split(',') : [];
|
||||
}
|
||||
|
||||
static _setUseStatusEffects(useStatusEffects) {
|
||||
static _setUseStatusEffects(statusIds) {
|
||||
if (game.user.isGM) {
|
||||
game.settings.set(SYSTEM_RDD, "use-status-effects", StatusEffects._toSetting(useStatusEffects));
|
||||
game.settings.set(SYSTEM_RDD, "use-status-effects", StatusEffects._toSetting(statusIds));
|
||||
}
|
||||
|
||||
for (let effect of CONFIG.RDD.allEffects) {
|
||||
effect.active = effect.rdd || useStatusEffects.has(effect.id);
|
||||
effect.active = effect.rdd || statusIds.includes(effect.flags?.core?.statusId);
|
||||
}
|
||||
CONFIG.statusEffects = CONFIG.RDD.allEffects.filter(it => it.active);
|
||||
}
|
||||
|
||||
static _toSetting(useStatusEffects) {
|
||||
return Array.from(useStatusEffects).join();
|
||||
static _toSetting(statusIds) {
|
||||
return statusIds.join();
|
||||
}
|
||||
|
||||
static status(label) {
|
||||
return rddStatusEffects.find(it => it.label == label) ?? { label: label };
|
||||
static status(statusId) {
|
||||
return rddStatusEffects.find(it => it.flags?.core?.statusId == statusId);
|
||||
}
|
||||
|
||||
static demiReve() {
|
||||
return demiReveStatusEffect;
|
||||
}
|
||||
@ -106,8 +117,10 @@ class StatusEffectsSettings extends FormApplication {
|
||||
}
|
||||
|
||||
getData() {
|
||||
const used = StatusEffects._getUseStatusEffects();
|
||||
let formData = super.getData();
|
||||
formData.effects = CONFIG.RDD.allEffects;
|
||||
formData.effects = duplicate(CONFIG.RDD.allEffects);
|
||||
formData.effects.forEach(it => it.active = used.includes(it.id))
|
||||
return formData;
|
||||
}
|
||||
|
||||
@ -118,10 +131,10 @@ class StatusEffectsSettings extends FormApplication {
|
||||
let selected = StatusEffects._getUseStatusEffects();
|
||||
let isChecked = event.currentTarget.checked;
|
||||
if (isChecked) {
|
||||
selected.add(id);
|
||||
selected.push(id);
|
||||
}
|
||||
else {
|
||||
selected.delete(id);
|
||||
selected = selected.filter(it => it != id)
|
||||
}
|
||||
StatusEffects._setUseStatusEffects(selected);
|
||||
}
|
||||
|
@ -8,9 +8,14 @@ import { TMRType } from "./tmr-utility.js";
|
||||
const typeRencontres = {
|
||||
|
||||
messager: {
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`,
|
||||
msgEchec: (rencData) => `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`,
|
||||
postSucces: (tmrDialog, rencData) => {
|
||||
msgSucces: async (rencData) => {
|
||||
if (rencData.actor.isTMRCache()){
|
||||
return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort, mais vous ne savez pas où vous êtes.`;
|
||||
}
|
||||
return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`;
|
||||
},
|
||||
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`,
|
||||
postSucces: async (tmrDialog, rencData) => {
|
||||
tmrDialog.setStateRencontre(rencData.rencontre.type);
|
||||
tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
|
||||
},
|
||||
@ -28,9 +33,14 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
passeur: {
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} vous propose de vous transporter à ${rencData.rencontre.force} cases des ${rencData.tmr.label}.`,
|
||||
msgEchec: (rencData) => `Le prix que demande le ${rencData.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`,
|
||||
postSucces: (tmrDialog, rencData) => {
|
||||
msgSucces: async (rencData) => {
|
||||
if (rencData.actor.isTMRCache()){
|
||||
return `Le ${rencData.rencontre.name} vous propose de vous transporter, mais vous ne savez pas où vous êtes.`;
|
||||
}
|
||||
return `Le ${rencData.rencontre.name} vous propose de vous transporter à ${rencData.rencontre.force} cases des ${rencData.tmr.label}.`;
|
||||
},
|
||||
msgEchec: async (rencData)=> `Le prix que demande le ${rencData.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`,
|
||||
postSucces: async (tmrDialog, rencData) => {
|
||||
tmrDialog.setStateRencontre(rencData.rencontre.type);
|
||||
tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
|
||||
},
|
||||
@ -49,9 +59,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
fleur: {
|
||||
msgSucces: (rencData) => `Vous cueillez la ${rencData.rencontre.name}, son parfum vous apporte ${rencData.rencontre.force} points de Rêve.`,
|
||||
msgEchec: (rencData) => `La ${rencData.rencontre.name} se fâne et disparaît entre vos doigts.`,
|
||||
postSucces: (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(rencData.rencontre.force),
|
||||
msgSucces: async (rencData) => `Vous cueillez la ${rencData.rencontre.name}, son parfum vous apporte ${rencData.rencontre.force} points de Rêve.`,
|
||||
msgEchec: async (rencData)=> `La ${rencData.rencontre.name} se fâne et disparaît entre vos doigts.`,
|
||||
postSucces: async (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(rencData.rencontre.force),
|
||||
poesieSucces: {
|
||||
reference: "L'Ennemi, Charles Baudelaire",
|
||||
extrait: `Et qui sait si les fleurs nouvelles que je rêve
|
||||
@ -66,9 +76,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
mangeur: {
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} claque de sa machoire dans le vide avant de fuir.`,
|
||||
msgEchec: (rencData) => `Le ${rencData.rencontre.name} croque votre Rêve ! Il emporte ${rencData.rencontre.force} de vos points de rêve actuels`,
|
||||
postEchec: (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(-rencData.rencontre.force),
|
||||
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} claque de sa machoire dans le vide avant de fuir.`,
|
||||
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} croque votre Rêve ! Il emporte ${rencData.rencontre.force} de vos points de rêve actuels`,
|
||||
postEchec: async (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(-rencData.rencontre.force),
|
||||
poesieSucces: {
|
||||
reference: "Conseil, Victor Hugo",
|
||||
extrait: `Rois ! la bure est souvent jalouse du velours.
|
||||
@ -85,16 +95,17 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
changeur: {
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[rencData.tmr.type].name} de votre choix en échange de sa liberté.`,
|
||||
msgEchec: (rencData) => {
|
||||
rencData.newTMR = TMRUtility.getTMRAleatoire(it => it.type = rencData.tmr.type);
|
||||
return `Le ${rencData.rencontre.name} vous embobine avec des promesses, et vous transporte en ${rencData.newTMR.label} sans attendre votre avis.`;
|
||||
},
|
||||
postSucces: (tmrDialog, rencData) => {
|
||||
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[rencData.tmr.type].name} de votre choix en échange de sa liberté.`,
|
||||
msgEchec: async (rencData) => `Le ${rencData.rencontre.name} vous embobine avec des promesses, et vous transporte sur une autre ${TMRType[rencData.tmr.type].name} sans attendre votre avis.`,
|
||||
postSucces: async (tmrDialog, rencData) => {
|
||||
tmrDialog.setStateRencontre(rencData.rencontre.type);
|
||||
tmrDialog.choisirCaseType(rencData.tmr.type);
|
||||
},
|
||||
postEchec: (tmrDialog, rencData) => tmrDialog.forceDemiRevePosition(rencData.newTMR.coord),
|
||||
postEchec: async (tmrDialog, rencData) => {
|
||||
const newTMR = await TMRUtility.getTMRAleatoire(it => it.type == rencData.tmr.type && it.coord != rencData.tmr.coord);
|
||||
await tmrDialog.actor.forcerPositionTMRInconnue(newTMR);
|
||||
tmrDialog.positionnerDemiReve(newTMR.coord);
|
||||
},
|
||||
poesieSucces: {
|
||||
reference: "Caligula - IIIème chant, Gérard de Nerval",
|
||||
extrait: `Allez, que le caprice emporte
|
||||
@ -111,9 +122,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
briseur: {
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`,
|
||||
msgEchec: (rencData) => `Le ${rencData.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`,
|
||||
postEchec: (tmrDialog, rencData) => tmrDialog.close(),
|
||||
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`,
|
||||
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`,
|
||||
postEchec: async (tmrDialog, rencData) => tmrDialog.close(),
|
||||
poesieSucces: {
|
||||
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||
extrait: `La légende affirme que ce sont les Gnomes qui furent
|
||||
@ -134,8 +145,8 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
reflet: {
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} s'estompe dans l'oubli.`,
|
||||
msgEchec: (rencData) => `Vous êtes submergé par un ${rencData.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`,
|
||||
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} s'estompe dans l'oubli.`,
|
||||
msgEchec: async (rencData)=> `Vous êtes submergé par un ${rencData.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`,
|
||||
poesieSucces: {
|
||||
reference: "Une charogne, Charles Baudelaire",
|
||||
extrait: `Les formes s'effaçaient et n'étaient plus qu'un rêve,
|
||||
@ -152,9 +163,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
passeurfou: {
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`,
|
||||
msgEchec: (rencData) => TMRRencontres.msgEchecPasseurFou(rencData),
|
||||
postEchec: (tmrDialog, rencData) => TMRRencontres.postEchecPasseurFou(tmrDialog, rencData),
|
||||
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`,
|
||||
msgEchec: async (rencData)=> TMRRencontres.msgEchecPasseurFou(rencData),
|
||||
postEchec: async (tmrDialog, rencData) => TMRRencontres.postEchecPasseurFou(tmrDialog, rencData),
|
||||
poesieSucces: {
|
||||
reference: "Un Fou et un Sage, Jean de La Fontaine",
|
||||
extrait: `Certain Fou poursuivait à coups de pierre un Sage.
|
||||
@ -174,9 +185,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
tbblanc: {
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`,
|
||||
msgEchec: (rencData) => `Le souffle du ${rencData.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`,
|
||||
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 1),
|
||||
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`,
|
||||
msgEchec: async (rencData)=> `Le souffle du ${rencData.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`,
|
||||
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 1),
|
||||
poesieSucces: {
|
||||
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||
extrait: `Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement
|
||||
@ -191,9 +202,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
tbnoir: {
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`,
|
||||
msgEchec: (rencData) => `Le ${rencData.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`,
|
||||
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 2),
|
||||
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`,
|
||||
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`,
|
||||
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 2),
|
||||
poesieSucces: {
|
||||
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||
extrait: `Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les
|
||||
@ -207,9 +218,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
tbrouge: {
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`,
|
||||
msgEchec: (rencData) => `Le ${rencData.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`,
|
||||
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, rencData),
|
||||
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`,
|
||||
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`,
|
||||
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, rencData),
|
||||
poesieSucces: {
|
||||
reference: "Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet",
|
||||
extrait: `Qu'est-ce de votre vie ? un tourbillon rouant
|
||||
@ -228,10 +239,10 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
rdd: {
|
||||
msgSucces: (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${rencData.rencontre.force} points de rêve`,
|
||||
msgEchec: (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${rencData.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`,
|
||||
postSucces: (tmrDialog, rencData) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, rencData),
|
||||
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, rencData),
|
||||
msgSucces: async (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${rencData.rencontre.force} points de rêve`,
|
||||
msgEchec: async (rencData)=> `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${rencData.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`,
|
||||
postSucces: async (tmrDialog, rencData) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, rencData),
|
||||
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, rencData),
|
||||
poesieSucces: {
|
||||
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||
extrait: `Le monde est Rêve de Dragons, mais nous ne savons
|
||||
@ -404,7 +415,7 @@ export class TMRRencontres {
|
||||
static async gererRencontre(tmrDialog, rencData) {
|
||||
let gestion = TMRRencontres.getGestionRencontre(rencData.rencontre.type);
|
||||
if (rencData.rolled.isSuccess) {
|
||||
rencData.message = gestion.msgSucces(rencData);
|
||||
rencData.message = await gestion.msgSucces(rencData);
|
||||
if (rencData.nbRounds > 1) {
|
||||
rencData.message += ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
|
||||
}
|
||||
@ -412,7 +423,7 @@ export class TMRRencontres {
|
||||
return gestion.postSucces;
|
||||
}
|
||||
|
||||
rencData.message = gestion.msgEchec(rencData);
|
||||
rencData.message = await gestion.msgEchec(rencData);
|
||||
if (rencData.nbRounds > 1) {
|
||||
rencData.message += ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
|
||||
}
|
||||
@ -422,9 +433,9 @@ export class TMRRencontres {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async msgEchecPasseurFou(tmrData) {
|
||||
tmrData.sortReserve = Misc.templateData(tmrData.actor).reve.reserve.list[0];
|
||||
tmrData.sortReserve = RdDDice.rollOneOf(tmrData.actor.itemTypes['sortreserve']);
|
||||
if (tmrData.sortReserve) {
|
||||
// Passeur fou positionne sur la case d'un ort en réserve // TODO : Choisir le sort le plus loin ou au hasard
|
||||
// Passeur fou positionne sur la case d'un sort en réserve
|
||||
tmrData.newTMR = TMRUtility.getTMR(tmrData.sortReserve.coord);
|
||||
} else {
|
||||
// Déplacement aléatoire de la force du Passeur Fou
|
||||
@ -444,7 +455,7 @@ export class TMRRencontres {
|
||||
if (tmrData.sortReserve) {
|
||||
await tmrDialog.processSortReserve(tmrData.sortReserve);
|
||||
}
|
||||
await tmrDialog.forceDemiRevePosition(tmrData.newTMR.coord);
|
||||
await tmrDialog.positionnerDemiReve(tmrData.newTMR.coord);
|
||||
if (tmrData.sortReserve) {
|
||||
tmrDialog.close();
|
||||
}
|
||||
@ -457,25 +468,25 @@ export class TMRRencontres {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onPostEchecTourbillonRouge(tmrDialog, data) {
|
||||
await data.actor.reveActuelIncDec(-2); // -2 pts de Reve a chaque itération
|
||||
TMRRencontres._toubillonner(tmrDialog, data.actor, 4);
|
||||
await data.actor.santeIncDec("vie", -1); // Et -1 PV
|
||||
static async onPostEchecTourbillonRouge(tmrDialog, rencontre) {
|
||||
await rencontre.actor.reveActuelIncDec(-2); // -2 pts de Reve a chaque itération
|
||||
TMRRencontres._toubillonner(tmrDialog, rencontre.actor, 4);
|
||||
await rencontre.actor.santeIncDec("vie", -1); // Et -1 PV
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async _toubillonner(tmrDialog, actor, cases) {
|
||||
let coord = Misc.templateData(actor).reve.tmrpos.coord;
|
||||
let coord = actor.system.reve.tmrpos.coord;
|
||||
for (let i = 0; i < cases; i++) {
|
||||
coord = await TMRUtility.deplaceTMRAleatoire(actor, coord).coord;
|
||||
}
|
||||
await tmrDialog.forceDemiRevePosition(coord)
|
||||
await tmrDialog.positionnerDemiReve(coord)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onPostSuccessReveDeDragon(tmrDialog, tmrData) {
|
||||
if (tmrData.rolled.isPart) {
|
||||
await tmrData.actor.appliquerAjoutExperience(tmrData, true);
|
||||
await tmrData.actor.appliquerAjoutExperience(tmrData);
|
||||
}
|
||||
await tmrData.actor.resultCombatReveDeDragon(tmrData);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ import { TMRRencontres } from "./tmr-rencontres.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { tmrConstants } from "./tmr-constants.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const TMRMapping = {
|
||||
@ -12,7 +11,7 @@ const TMRMapping = {
|
||||
D1: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||||
E1: { type: "monts", label: "Monts de Kanaï" },
|
||||
F1: { type: "cite", label: "Cité Glauque" },
|
||||
G1: { type: "desolation", label: "Désolation de Demain" },
|
||||
G1: { type: "desolation", label: "Désolation de Jamais" },
|
||||
H1: { type: "lac", label: "Lac d’Anticalme" },
|
||||
I1: { type: "plaines", label: "Plaines Grises" },
|
||||
J1: { type: "monts", label: "Monts Fainéants" },
|
||||
@ -70,7 +69,7 @@ const TMRMapping = {
|
||||
F5: { type: "cite", label: "Cité de Panople" },
|
||||
G5: { type: "pont", label: "Pont d’Ik" },
|
||||
H5: { type: "desert", label: "Désert de Krane" },
|
||||
I5: { type: "desolation", label: "Désolation de Demain" },
|
||||
I5: { type: "desolation", label: "Désolation de Toujours" },
|
||||
J5: { type: "marais", label: "Marais de Jab" },
|
||||
K5: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||||
L5: { type: "collines", label: "Collines Suaves" },
|
||||
@ -86,9 +85,9 @@ const TMRMapping = {
|
||||
H6: { type: "monts", label: "Monts Gurdes" },
|
||||
I6: { type: "necropole", label: "Nécropole de Xotar" },
|
||||
J6: { type: "lac", label: "Lac d’Iaupe" },
|
||||
K6: { type: "desolation", label: "Désolation de Demain" },
|
||||
K6: { type: "desolation", label: "Désolation de Poor" },
|
||||
L6: { type: "foret", label: "Forêt Gueuse" },
|
||||
M6: { type: "desolation", label: "Désolation de Demain" },
|
||||
M6: { type: "desolation", label: "Désolation de Presque" },
|
||||
|
||||
A7: { type: "plaines", label: "Plaines de l’Arc" },
|
||||
B7: { type: "marais", label: "Marais Bluants" },
|
||||
@ -124,7 +123,7 @@ const TMRMapping = {
|
||||
D9: { type: "pont", label: "Pont d’Orx" },
|
||||
E9: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||||
F9: { type: "plaines", label: "Plaines de Foe" },
|
||||
G9: { type: "desolation", label: "Désolation de Demain" },
|
||||
G9: { type: "desolation", label: "Désolation de Sel" },
|
||||
H9: { type: "collines", label: "Collines de Noirseul" },
|
||||
I9: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||||
J9: { type: "marais", label: "Marais Gronchants" },
|
||||
@ -146,10 +145,10 @@ const TMRMapping = {
|
||||
L10: { type: "desert", label: "Désert de Nicrop" },
|
||||
M10: { type: "foret", label: "Forêt de Jajou" },
|
||||
|
||||
A11: { type: "desolation", label: "Désolation de Demain" },
|
||||
A11: { type: "desolation", label: "Désolation d’Hier" },
|
||||
B11: { type: "cite", label: "Cité de Brilz" },
|
||||
C11: { type: "pont", label: "Pont de Roï" },
|
||||
D11: { type: "desolation", label: "Désolation de Demain" },
|
||||
D11: { type: "desolation", label: "Désolation de Partout" },
|
||||
E11: { type: "lac", label: "Lac de Glinster" },
|
||||
F11: { type: "cite", label: "Cité de Noape" },
|
||||
G11: { type: "fleuve", label: "Fleuve de l'Oubli" },
|
||||
@ -170,7 +169,7 @@ const TMRMapping = {
|
||||
H12: { type: "collines", label: "Collines de Tooth" },
|
||||
I12: { type: "gouffre", label: "Gouffre Abimeux" },
|
||||
J12: { type: "cite", label: "Cité Folle" },
|
||||
K12: { type: "desolation", label: "Désolation de Demain" },
|
||||
K12: { type: "desolation", label: "Désolation d’Amour" },
|
||||
L12: { type: "plaines", label: "Plaines Venteuses" },
|
||||
M12: { type: "collines", label: "Collines Révulsantes" },
|
||||
|
||||
@ -181,7 +180,7 @@ const TMRMapping = {
|
||||
E13: { type: "plaines", label: "Plaines de Xnez" },
|
||||
F13: { type: "foret", label: "Forêt des Cris" },
|
||||
G13: { type: "plaines", label: "Plaines Calcaires" },
|
||||
H13: { type: "desolation", label: "Désolation de Demain" },
|
||||
H13: { type: "desolation", label: "Désolation de Rien" },
|
||||
I13: { type: "monts", label: "Monts Bigleux" },
|
||||
J13: { type: "gouffre", label: "Gouffre de Gromph" },
|
||||
K13: { type: "foret", label: "Forêt de Kluth" },
|
||||
@ -200,8 +199,8 @@ const TMRMapping = {
|
||||
J14: { type: "desert", label: "Désert de Sank" },
|
||||
K14: { type: "necropole", label: "Nécropole d’Antinéar" },
|
||||
L14: { type: "plaines", label: "Plaines de Jislith" },
|
||||
M14: { type: "desolation", label: "Désolation de Demain" },
|
||||
|
||||
M14: { type: "desolation", label: "Désolation d’Après" },
|
||||
|
||||
A15: { type: "cite", label: "Cité de Mielh" },
|
||||
C15: { type: "plaines", label: "Plaines de Toué" },
|
||||
E15: { type: "foret", label: "Forêt des Furies" },
|
||||
@ -292,12 +291,18 @@ export class TMRUtility {
|
||||
static typeTmrName(type) {
|
||||
return Misc.upperFirst(TMRType[Grammar.toLowerCaseNoAccent(type)].name);
|
||||
}
|
||||
static listSelectedTMR(typesTMR) {
|
||||
|
||||
static buildSelectionTypesTMR(typesTMR) {
|
||||
typesTMR= typesTMR?? [];
|
||||
return Object.values(TMRType).map(value => Misc.upperFirst(value.name))
|
||||
.sort()
|
||||
.map(name => { return { name: name, selected: typesTMR.includes(name) } });
|
||||
}
|
||||
|
||||
static buildListTypesTMRSelection(selectionTMRs) {
|
||||
return selectionTMRs.filter(it => it.selected).map(it => it.name).join(" ");
|
||||
}
|
||||
|
||||
static isCaseHumide(tmr) {
|
||||
return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais';
|
||||
}
|
||||
@ -380,18 +385,6 @@ export class TMRUtility {
|
||||
return await RdDDice.rollOneOf(TMRUtility.filterTMR(filter))
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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);
|
||||
if (tmrDescr.type == 'fleuve') { // Gestion de la reserve en Fleuve
|
||||
return reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve');
|
||||
}
|
||||
// Reserve sur un case "normale"
|
||||
return reserveList.filter(it => it.coord == coord);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** Returns a list of case inside a given distance
|
||||
*
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Grammar } from "../grammar.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDDice } from "../rdd-dice.js";
|
||||
import { TMRUtility } from "../tmr-utility.js";
|
||||
import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js";
|
||||
@ -32,14 +31,14 @@ export class Conquete extends Draconique {
|
||||
}
|
||||
|
||||
async _creerConquete(actor, queue) {
|
||||
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => Misc.data(it).data.coord);
|
||||
let existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
||||
let possibles = TMRUtility.filterTMR(tmr => !TMRUtility.isCaseHumide(tmr) && !existants.includes(tmr.coord));
|
||||
let conquete = await RdDDice.rollOneOf(possibles);
|
||||
await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue.id);
|
||||
}
|
||||
|
||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
|
||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.system.sourceid]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ export class Debordement extends Draconique {
|
||||
match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('debordement'); }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, souffle) {
|
||||
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
||||
const tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord)));
|
||||
await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr, souffle.id);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ export class Desorientation extends Draconique {
|
||||
}
|
||||
|
||||
_typesPossibles(actor) {
|
||||
const dejaDesorientes = Misc.distinct(actor.data.items.filter(it => this.isCase(it)).map(it => it.type));
|
||||
const dejaDesorientes = Misc.distinct(actor.items.filter(it => this.isCase(it)).map(it => it.type));
|
||||
return Object.keys(TMRType).filter(it => !dejaDesorientes.includes(it));
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ export class Desorientation extends Draconique {
|
||||
}
|
||||
|
||||
async _creerCasesTmr(actor, type, souffle) {
|
||||
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
||||
let tmrs = TMRUtility.filterTMR(it => it.type == type && !existants.includes(it.coord));
|
||||
for (let tmr of tmrs) {
|
||||
await this.createCaseTmr(actor, 'Désorientation: ' + tmr.label, tmr, souffle.id);
|
||||
|
@ -9,13 +9,13 @@ const registeredEffects = [
|
||||
* Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR
|
||||
*/
|
||||
export class Draconique {
|
||||
static isCaseTMR(itemData) { return itemData.type == 'casetmr'; }
|
||||
static isQueueDragon(itemData) { return itemData.type == 'queue' || itemData.type == 'ombre'; }
|
||||
static isSouffleDragon(itemData) { return itemData.type == 'souffle'; }
|
||||
static isTeteDragon(itemData) { return itemData.type == 'tete'; }
|
||||
static isQueueSouffle(itemData) { return Draconique.isQueueDragon(itemData) || Draconique.isSouffleDragon(itemData); }
|
||||
static isCaseTMR(item) { return item.type == 'casetmr'; }
|
||||
static isQueueDragon(item) { return item.type == 'queue' || item.type == 'ombre'; }
|
||||
static isSouffleDragon(item) { return item.type == 'souffle'; }
|
||||
static isTeteDragon(item) { return item.type == 'tete'; }
|
||||
static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); }
|
||||
|
||||
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.data.coord); }
|
||||
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.system.coord); }
|
||||
|
||||
static register(draconique) {
|
||||
registeredEffects[draconique.code()] = draconique;
|
||||
@ -38,8 +38,7 @@ export class Draconique {
|
||||
* @returns true si l'item correspond
|
||||
*/
|
||||
match(item) {
|
||||
const itemData = Misc.data(item);
|
||||
return Draconique.isQueueDragon(itemData) || Draconique.isSouffleDragon(itemData) || Draconique.isTeteDragon(itemData);
|
||||
return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item) || Draconique.isTeteDragon(item);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,9 +93,8 @@ export class Draconique {
|
||||
token[type ?? this.code()] = linkData;
|
||||
pixiTMR.addTooltip(token.sprite, this.tooltip(linkData));
|
||||
return token;
|
||||
|
||||
return sprite;
|
||||
}
|
||||
|
||||
/**
|
||||
* factory d'élément graphique PIXI correpsondant à l'objet draconique
|
||||
* @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks.
|
||||
@ -116,34 +114,32 @@ export class Draconique {
|
||||
* @param {*} coord les coordonnées d'une case. Si undefined toute case du type correspondra,
|
||||
*/
|
||||
isCase(item, coord = undefined) {
|
||||
const itemData = Misc.data(item);
|
||||
return Draconique.isCaseTMR(itemData) && itemData.data.specific == this.code() && (coord ? itemData.data.coord == coord : true);
|
||||
return Draconique.isCaseTMR(item) && item.system.specific == this.code() && (coord ? item.system.coord == coord : true);
|
||||
}
|
||||
|
||||
find(list, coord = undefined) {
|
||||
return list.find(c => this.isCase(Misc.data(c), coord));
|
||||
return list.find(c => this.isCase(c, coord));
|
||||
}
|
||||
|
||||
async createCaseTmr(actor, label, tmr, sourceId = undefined) {
|
||||
const casetmrData = {
|
||||
name: label, type: 'casetmr', img: this.img(),
|
||||
data: { coord: tmr.coord, specific: this.code(), sourceid: sourceId }
|
||||
system: { coord: tmr.coord, specific: this.code(), sourceid: sourceId }
|
||||
};
|
||||
await actor.createEmbeddedDocuments('Item', [casetmrData]);
|
||||
}
|
||||
|
||||
async deleteCasesTmr(actor, draconique) {
|
||||
let caseTmrs = actor.data.items.filter(it => this.isCaseForSource(it, draconique));
|
||||
let caseTmrs = actor.items.filter(it => this.isCaseForSource(it, draconique));
|
||||
await actor.deleteEmbeddedDocuments('Item', caseTmrs.map(it => it.id));
|
||||
}
|
||||
|
||||
isCaseForSource(item, draconique) {
|
||||
const itemData = Misc.data(item);
|
||||
return Draconique.isCaseTMR(itemData) && itemData.data.specific == this.code() && itemData.data.sourceid == draconique.id;
|
||||
return Draconique.isCaseTMR(item) && item.system.specific == this.code() && item.system.sourceid == draconique.id;
|
||||
}
|
||||
|
||||
async onVisiteSupprimer(actor, tmr, onRemoveToken) {
|
||||
let existants = actor.data.items.filter(it => this.isCase(it, tmr.coord));
|
||||
let existants = actor.items.filter(it => this.isCase(it, tmr.coord));
|
||||
await actor.deleteEmbeddedDocuments('Item', existants.map(it => it.id));
|
||||
for (let casetmr of existants) {
|
||||
onRemoveToken(tmr, casetmr);
|
||||
|
@ -95,7 +95,7 @@ export class EffetsDraconiques {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isSortImpossible(actor) {
|
||||
return actor.data.items.find(it =>
|
||||
return actor.items.find(it =>
|
||||
EffetsDraconiques.conquete.match(it) ||
|
||||
EffetsDraconiques.periple.match(it) ||
|
||||
EffetsDraconiques.urgenceDraconique.match(it) ||
|
||||
@ -104,7 +104,7 @@ export class EffetsDraconiques {
|
||||
}
|
||||
|
||||
static isSortReserveImpossible(actor) {
|
||||
return actor.data.items.find(it =>
|
||||
return actor.items.find(it =>
|
||||
EffetsDraconiques.conquete.match(it) ||
|
||||
EffetsDraconiques.periple.match(it) ||
|
||||
EffetsDraconiques.pelerinage.match(it)
|
||||
@ -112,7 +112,7 @@ export class EffetsDraconiques {
|
||||
}
|
||||
|
||||
static filterItems(actor, filter, name) {
|
||||
return actor.data.items.filter(filter)
|
||||
return actor.filterItems(filter)
|
||||
.filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||
}
|
||||
|
||||
@ -150,11 +150,11 @@ export class EffetsDraconiques {
|
||||
}
|
||||
|
||||
static isPontImpraticable(actor) {
|
||||
return actor.data.items.find(it => EffetsDraconiques.pontImpraticable.match(it));
|
||||
return actor.items.find(it => EffetsDraconiques.pontImpraticable.match(it));
|
||||
}
|
||||
|
||||
static isUrgenceDraconique(actor) {
|
||||
return actor.data.items.find(it => EffetsDraconiques.urgenceDraconique.match(it));
|
||||
return actor.items.find(it => EffetsDraconiques.urgenceDraconique.match(it));
|
||||
}
|
||||
|
||||
static isPeage(actor) {
|
||||
|
@ -30,7 +30,7 @@ export class FermetureCites extends Draconique {
|
||||
}
|
||||
|
||||
async _fermerLesCites(actor, souffle) {
|
||||
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
let existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
||||
let ouvertes = TMRUtility.filterTMR(it => it.type == 'cite' && !existants.includes(it.coord));
|
||||
for (let tmr of ouvertes) {
|
||||
await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr, souffle.id);
|
||||
|
@ -33,7 +33,7 @@ export class Pelerinage extends Draconique {
|
||||
}
|
||||
|
||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
|
||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.system.sourceid]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ export class PixiTMR {
|
||||
for (const [name, img] of Object.entries(PixiTMR.textures)) {
|
||||
loader = loader.add(name, img);
|
||||
}
|
||||
loader.onLoad.add((error, resaon) => { console.log("ERROR", error, resaon) });
|
||||
loader.onError.add((error, reason) => { console.log("ERROR", error, reason) });
|
||||
loader.load( (loader, resources) => {
|
||||
onLoad(loader, resources);
|
||||
for (let onAnimate of this.callbacksOnAnimate) {
|
||||
|
@ -30,7 +30,7 @@ export class PresentCites extends Draconique {
|
||||
}
|
||||
|
||||
async _ajouterPresents(actor, tete) {
|
||||
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
let existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
||||
if (existants.length > 0) {
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||
|
@ -12,8 +12,8 @@ export class ReserveExtensible extends Draconique {
|
||||
match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes("reserve extensible"); }
|
||||
manualMessage() { return "Vous pouvez re-configurer votre Réserve extensible" }
|
||||
async onActorCreateOwned(actor, tete) {
|
||||
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
const tmr = await TMRUtility.getTMRAleatoire(it => !(it.type == 'fleuve' || existants.includes(it.coord)));
|
||||
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
||||
const tmr = await TMRUtility.getTMRAleatoire(it => !(it.type == 'fleuve' || existants.includes(it.system.coord)));
|
||||
await this.createCaseTmr(actor, "Nouvelle Réserve extensible", tmr, tete.id);
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,8 @@ export class SortReserve extends Draconique {
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, item) { }
|
||||
|
||||
code() { return 'sort' }
|
||||
tooltip(sort) { return `${sort.name}, r${sort.data.ptreve_reel}` }
|
||||
code() { return 'sortreserve' }
|
||||
tooltip(sort) { return `${sort.name}, r${sort.system.ptreve}` }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/scroll.webp' }
|
||||
|
||||
createSprite(pixiTMR) {
|
||||
|
@ -13,8 +13,8 @@ export class TrouNoir extends Draconique {
|
||||
manualMessage() { return false }
|
||||
|
||||
async onActorCreateOwned(actor, souffle) {
|
||||
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
const tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord)));
|
||||
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
||||
const tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.system.coord)));
|
||||
await this.createCaseTmr(actor, 'Trou noir: ' + tmr.label, tmr, souffle.id);
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@ export class UrgenceDraconique extends Draconique {
|
||||
match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, queue) {
|
||||
const coordSortsReserve = (Misc.templateData(actor).reve.reserve?.list.map(it => it.coord)) ?? [];
|
||||
const coordSortsReserve = (actor.system.reve.reserve?.list.map(it => it.coord)) ?? [];
|
||||
if (coordSortsReserve.length == 0) {
|
||||
// La queue se transforme en idée fixe
|
||||
const ideeFixe = await RdDRollTables.getIdeeFixe();
|
||||
@ -37,7 +37,7 @@ export class UrgenceDraconique extends Draconique {
|
||||
}
|
||||
|
||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
|
||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.system.sourceid]);
|
||||
}
|
||||
|
||||
code() { return 'urgence' }
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,27 +1,29 @@
|
||||
{"_id":"0zRL8bOpCXNQnIR4","name":"Ruade","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":4,"description":null,"categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[]}
|
||||
{"_id":"4GmpkphbsmQjvVVK","name":"Escalade","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":false,"dommages":0,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.webp","effects":[]}
|
||||
{"_id":"6DK46pyO0hzEuuUg","name":"Morsure","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[]}
|
||||
{"_id":"BjqRrGtHtTzuNpZB","name":"Griffes et Crocs","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[]}
|
||||
{"_id":"CYpxxf1uTa78NWR9","name":"Esquive","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"dommages":0,"iscombat":false,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","effects":[]}
|
||||
{"_id":"JTuBQCPdumw3DfxH","name":"Crête","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"dommages":3,"iscombat":true,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-crete.webp","effects":[]}
|
||||
{"_id":"Kt7WlB5Ui97X211z","name":"Vol","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"dommages":0,"iscombat":false,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-vol.webp","effects":[]}
|
||||
{"_id":"LWQHz5ymNBzh6ZEr","name":"Cornes","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":2,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-corne.webp","effects":[]}
|
||||
{"_id":"NctG7suzvGE7ZZzj","name":"Bras-bouches","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":2,"description":"","categorie_parade":"epees-lourdes","isparade":true,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-brasbouche.webp","effects":[]}
|
||||
{"_id":"OzHBowOMADRwcVXR","name":"Pierre Tenue","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":2,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierretenue.webp","effects":[]}
|
||||
{"_id":"PCwbR6lghjydTj93","name":"Grande morsure","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"categorie_parade":"","niveau":0,"carac_value":0,"iscombat":true,"isparade":false,"dommages":2,"description":"","default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[]}
|
||||
{"_id":"PrVuVpwuYaZtwRUi","name":"Piétinement","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":4,"description":null,"categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[]}
|
||||
{"_id":"RAnasKnoA3OQgwfv","name":"Pinces","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":3,"description":"","categorie_parade":"epees-lourdes","isparade":true,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pinces.webp","effects":[]}
|
||||
{"_id":"XgfRxSj8Ty1d3JFM","name":"Mandibules","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":2,"description":"","carac-value":null,"categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-mandibules.webp","effects":[]}
|
||||
{"_id":"Zpl2Bi451vB3r91W","name":"Coup de pied","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":3,"description":null,"categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-coup_de_pied.webp","effects":[]}
|
||||
{"_id":"efl1HdDSKpBfImQ1","name":"Pierre Lancée","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierrelancee.webp","effects":[]}
|
||||
{"_id":"h9ASt4vrvEgxfj7j","name":"Tronçonneuse","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":10,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-tronconneuse.webp","effects":[]}
|
||||
{"_id":"jhua9kkCs55OV7Yl","name":"Grandes griffes","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"categorie_parade":"sans-armes","niveau":0,"carac_value":0,"iscombat":true,"isparade":true,"dommages":2,"description":"","default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[]}
|
||||
{"_id":"lzEdMrKXbOYrWG5S","name":"Vigilance","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":false,"dommages":0,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[]}
|
||||
{"_id":"ndNshntOYb1JFNqi","name":"Serres","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":2,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-serres.webp","effects":[]}
|
||||
{"_id":"os88Rsp7mBkahqmh","name":"Bec","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":0,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp","effects":[]}
|
||||
{"_id":"qilRzXpVaGceNmQp","name":"Dague","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","categorie_parade":"dagues","isparade":true,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dague.webp","effects":[]}
|
||||
{"_id":"qrd9AoZzFgyzFBxz","name":"Griffes","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"categorie_parade":"sans-armes","niveau":0,"carac_value":0,"iscombat":true,"isparade":true,"dommages":1,"description":"","default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[]}
|
||||
{"_id":"sUdXhpuVVOAlcVpo","name":"Pickpocket","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":false,"dommages":0,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_pickpocket.webp","effects":[]}
|
||||
{"_id":"shsUV8UpU18c0RJK","name":"Course","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":false,"dommages":0,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","effects":[]}
|
||||
{"_id":"yBUVTjTXYfwvzusb","name":"Saut","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":false,"dommages":0,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","effects":[]}
|
||||
{"_id":"yDHZfK4RmwQW4YaW","name":"Discrétion","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":false,"dommages":0,"description":"","categorie_parade":"","isparade":false,"default_diffLibre":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.webp","effects":[]}
|
||||
{"_id":"0zRL8bOpCXNQnIR4","name":"Ruade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.0zRL8bOpCXNQnIR4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":4,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"4GmpkphbsmQjvVVK","name":"Escalade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.4GmpkphbsmQjvVVK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"6DK46pyO0hzEuuUg","name":"Morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.6DK46pyO0hzEuuUg"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"generale","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":14,"iscombat":true,"isparade":false,"ispossession":true,"dommages":0,"description":"<p>L'entité tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie":"melee"},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624948267,"modifiedTime":1663625011162,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"9u16zxXRurCtxuOX","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
|
||||
{"_id":"BjqRrGtHtTzuNpZB","name":"Griffes et Crocs","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"CYpxxf1uTa78NWR9","name":"Esquive","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.CYpxxf1uTa78NWR9"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"JTuBQCPdumw3DfxH","name":"Crête","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.JTuBQCPdumw3DfxH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-crete.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":3,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"Kt7WlB5Ui97X211z","name":"Vol","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Kt7WlB5Ui97X211z"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-vol.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"LWQHz5ymNBzh6ZEr","name":"Cornes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.LWQHz5ymNBzh6ZEr"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-corne.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"NctG7suzvGE7ZZzj","name":"Bras-bouches","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.NctG7suzvGE7ZZzj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-brasbouche.webp","effects":[],"system":{"categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"OzHBowOMADRwcVXR","name":"Pierre Tenue","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.OzHBowOMADRwcVXR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierretenue.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"PCwbR6lghjydTj93","name":"Grande morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.PCwbR6lghjydTj93"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"PrVuVpwuYaZtwRUi","name":"Piétinement","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.PrVuVpwuYaZtwRUi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":4,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"RAnasKnoA3OQgwfv","name":"Pinces","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.RAnasKnoA3OQgwfv"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pinces.webp","effects":[],"system":{"categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":3,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"XgfRxSj8Ty1d3JFM","name":"Mandibules","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.XgfRxSj8Ty1d3JFM"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-mandibules.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","carac-value":null,"categorie":"generale","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"Zpl2Bi451vB3r91W","name":"Coup de pied","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Zpl2Bi451vB3r91W"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-coup_de_pied.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":3,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":14,"iscombat":true,"isparade":false,"ispossession":true,"dommages":0,"description":"<p>L'entité tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie":"draconic"},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624976822,"modifiedTime":1663625011162,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"duVgxI3Cdko0KzAj","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
|
||||
{"_id":"efl1HdDSKpBfImQ1","name":"Pierre Lancée","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.efl1HdDSKpBfImQ1"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierrelancee.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"lancer","isnaturelle":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"h9ASt4vrvEgxfj7j","name":"Tronçonneuse","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.h9ASt4vrvEgxfj7j"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-tronconneuse.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":10,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"jhua9kkCs55OV7Yl","name":"Grandes griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.jhua9kkCs55OV7Yl"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"lzEdMrKXbOYrWG5S","name":"Vigilance","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.lzEdMrKXbOYrWG5S"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"ndNshntOYb1JFNqi","name":"Serres","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.ndNshntOYb1JFNqi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-serres.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"os88Rsp7mBkahqmh","name":"Bec","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.os88Rsp7mBkahqmh"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"qilRzXpVaGceNmQp","name":"Dague","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.qilRzXpVaGceNmQp"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dague.webp","effects":[],"system":{"categorie_parade":"dagues","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"qrd9AoZzFgyzFBxz","name":"Griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.qrd9AoZzFgyzFBxz"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"sUdXhpuVVOAlcVpo","name":"Pickpocket","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.sUdXhpuVVOAlcVpo"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_pickpocket.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"shsUV8UpU18c0RJK","name":"Course","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.shsUV8UpU18c0RJK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"yBUVTjTXYfwvzusb","name":"Saut","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yBUVTjTXYfwvzusb"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":"","categorie":"generale"},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"yDHZfK4RmwQW4YaW","name":"Discrétion","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yDHZfK4RmwQW4YaW"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
|
@ -12,3 +12,4 @@
|
||||
{"_id":"gPOQd9NI7AFH0whX","name":"Epée Bâtarde","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":4,"description":"","carac-value":null,"categorie_parade":"epees-lourdes","isparade":true},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-humanoides.YTKld5ggDsHqwYoR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_epee_1_main.webp","effects":[]}
|
||||
{"_id":"j1xHCzfIeYKgXxoH","name":"Morsure","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[]}
|
||||
{"_id":"lDZ3qUPKN35ob5TH","name":"Grande morsure","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"categorie_parade":"","niveau":0,"carac_value":0,"iscombat":true,"isparade":false,"dommages":2,"description":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[]}
|
||||
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":-4,"categorie":"melee","carac_value":14,"iscombat":true,"isnaturelle":true,"ispossession":true,"dommages":0,"description":"<p>L'entité tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","isparade":false},"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.22","coreVersion":"10.286","createdTime":1663624976822,"modifiedTime":1664918524164,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"folder":null,"sort":0,"_id":"wDHR5UHWq568lfGa"}
|
||||
|
@ -1,40 +1,40 @@
|
||||
{"name":"Idée fixe : Anorexie. Ne rien avaler, ni solide, ni liquide, pas même une potion","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"anorexie.webp","effects":[],"_id":"0uc2pMIGL03Hq2Hn"}
|
||||
{"name":"Désir lancinant : Briser un objet de verre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"briser_verre.webp","effects":[],"_id":"1l59lWbtvYp74OTb"}
|
||||
{"name":"Idée fixe : Cracher dans toute nourriture ou boisson aperçue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"cracher_nourriture.webp","effects":[],"_id":"22EQLBJfHVYs96iC"}
|
||||
{"name":"Idée fixe : Éteindre tout feu rencontré (feu de camp, torche, lanterne, etc.)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"eteindre_feu.webp","effects":[],"_id":"2Rtm78bMKPy8eG4q"}
|
||||
{"name":"Désir lancinant : Danser avec un(e) partenaire inconnu(e) (Beauté 13 minimum)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"danser_inconnu.webp","effects":[],"_id":"2i3PndTKG1n3hEUU"}
|
||||
{"name":"Idée fixe : Traîner son épée en laisse (ou sa meilleure arme)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"trainer_laisse.webp","effects":[],"_id":"2j1q9e07ZLlIQDYl"}
|
||||
{"name":"Désir lancinant : Gagner de l’argent (minimum 10 deniers)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"gagner_argent.webp","effects":[],"_id":"3BcC8lSsP5WIyva7"}
|
||||
{"name":"Désir lancinant : Mégalomanie. Être acclamé par un minimum de 10 personnes","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"megalomanie.webp","effects":[],"_id":"3ZjwYyQRatCMnBCi"}
|
||||
{"name":"Idée fixe : Avoir le visage noirci à la cendre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"avoir_visage.webp","effects":[],"_id":"6G0lF06jSryTduAt"}
|
||||
{"name":"Idée fixe : Ne marcher qu’à quatre pattes","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"marcher_quatre_pattes.webp","effects":[],"_id":"7TKsit2Mv9mWGq3C"}
|
||||
{"name":"Désir lancinant : Acquérir une chèvre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"acqu%C3%A9rir_chevre.webp","effects":[],"_id":"8sLXQBqo8XwjAFG0"}
|
||||
{"name":"Idée fixe : Garder les yeux bandés","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"garder_yeux.webp","effects":[],"_id":"E902EEYZHg3zFKq6"}
|
||||
{"name":"Désir lancinant : Danser nu sous la pluie","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"danser_pluie.webp","effects":[],"_id":"F6qL4d4g3qjh045R"}
|
||||
{"name":"Idée fixe : Garder sur soi 3d6 kilos de cailloux","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"garder_cailloux.webp","effects":[],"_id":"F8G3rdU1nfJzYwYR"}
|
||||
{"name":"Désir lancinant : Se faire raser la tête","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"raser_tete.webp","effects":[],"_id":"HSNOvBR890dsEDw2"}
|
||||
{"name":"Idée fixe : Aller tout nu, sans porter le moindre paquet ni objet","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"aller_nu.webp","effects":[],"_id":"I0CtQ05xFW6ghcdP"}
|
||||
{"name":"Idée fixe : Boulimie. Manger au moins un point de sust. par heure","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"boulimie.webp","effects":[],"_id":"JcTX8qMS0z8bmdVt"}
|
||||
{"name":"Désir lancinant : Passer une nuit sur une échelle","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"nuit_echelle.webp","effects":[],"_id":"LlELEB0FhymLx6VM"}
|
||||
{"name":"Idée fixe : Refuser de monter dans les TMR","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"refuser_tmr.webp","effects":[],"_id":"NpTDqICR7ZuToQrg"}
|
||||
{"name":"Désir lancinant : Masochisme. Perdre 3 points d’endurance minimum en 1 round","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"masochisme.webp","effects":[],"_id":"NzJJNK0YMAbobu0p"}
|
||||
{"name":"Désir lancinant : Casser 3d6 oeufs en les jetant à terre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"casser_oeufs.webp","effects":[],"_id":"OjG8XRbeYtq2jcgB"}
|
||||
{"name":"Désir lancinant : Traire une vache","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"traire_vache.webp","effects":[],"_id":"QHUOwjMR6AvepGPm"}
|
||||
{"name":"Désir lancinant : Pisser dans un violon (luth, mandoline, etc.)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"pisser_violon.webp","effects":[],"_id":"S8PVNgxb7TcFXq9g"}
|
||||
{"name":"Désir lancinant : Manger du poisson","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"manger_poisson.webp","effects":[],"_id":"SY0SsWtZdxSodMcl"}
|
||||
{"name":"Idée fixe : Ne pas franchir de porte. (On peut franchir une fenêtre)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"pas-franchir.webp","effects":[],"_id":"UUTbsktTcxsIe5L5"}
|
||||
{"name":"Idée fixe : Refuser de se délester du moindre objet, ni donner ni prêter","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"refuser_delester.webp","effects":[],"_id":"VChJbtGFtWoiFNky"}
|
||||
{"name":"Idée fixe : Ne s’exprimer que par des cris d’animaux (meuh ! coin-coin ! etc.)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"exprimer_cris.webp","effects":[],"_id":"YCHBbRLiMzTH7IBj"}
|
||||
{"name":"Idée fixe : Vider sur sa tête toute fiole ou flacon aperçu","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"verser_flacon.webp","effects":[],"_id":"afGp9CewfyJKecEE"}
|
||||
{"name":"Désir lancinant : Faire des bulles de savon","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"bulles_savon.webp","effects":[],"_id":"df5oN8Ub3dWTVxNj"}
|
||||
{"name":"Désir lancinant : Entendre braire un âne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"entendre_ane.webp","effects":[],"_id":"diCCimukdNM6bPub"}
|
||||
{"name":"Désir lancinant : Se rouler dans la boue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"se_rouler_boue.webp","effects":[],"_id":"el4lofhhSucMv5xv"}
|
||||
{"name":"Idée fixe : Ne dire que «non» ou négation analogue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"dire_non.webp","effects":[],"_id":"gMmqdJ9I7Mt8Tg3f"}
|
||||
{"name":"Désir lancinant : Manger des champignons","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"manger_champignons.webp","effects":[],"_id":"gadh6aI5iCM82qpP"}
|
||||
{"name":"Idée fixe : Refuser de se déplacer autrement que porté","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"refuser_deplacer.webp","effects":[],"_id":"hghw6Cldrad1CIiJ"}
|
||||
{"name":"Idée fixe : Garder une main sur la tête","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"garder_main.webp","effects":[],"_id":"iPYPgxL2uUnphStc"}
|
||||
{"name":"Idée fixe : Appeler les hommes «madame» et les femmes «messire»","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"appeler_hommes_femmes.webp","effects":[],"_id":"j2xIrFWYqhDM4TcN"}
|
||||
{"name":"Désir lancinant : Se soûler (minimum pas frais)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"se_souler.webp","effects":[],"_id":"jShpKV8mVcqWmYvp"}
|
||||
{"name":"Désir lancinant : Construire une cabane","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"construire_cabane.webp","effects":[],"_id":"mN0yghXkFfj2YctJ"}
|
||||
{"name":"Désir lancinant : Embrasser un cochon sur le groin","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"embrasser_cochon.webp","effects":[],"_id":"sjXBBr85OBk4Yg4t"}
|
||||
{"name":"Idée fixe : Faire le mort","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"faire_mort.webp","effects":[],"_id":"xa4t9Lbt6uLEjap6"}
|
||||
{"name":"Idée fixe : Anorexie. Ne rien avaler, ni solide, ni liquide, pas même une potion","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"0uc2pMIGL03Hq2Hn"}
|
||||
{"name":"Désir lancinant : Briser un objet de verre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"1l59lWbtvYp74OTb"}
|
||||
{"name":"Idée fixe : Cracher dans toute nourriture ou boisson aperçue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"22EQLBJfHVYs96iC"}
|
||||
{"name":"Idée fixe : Éteindre tout feu rencontré (feu de camp, torche, lanterne, etc.)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"2Rtm78bMKPy8eG4q"}
|
||||
{"name":"Désir lancinant : Danser avec un(e) partenaire inconnu(e) (Beauté 13 minimum)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"2i3PndTKG1n3hEUU"}
|
||||
{"name":"Idée fixe : Traîner son épée en laisse (ou sa meilleure arme)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"2j1q9e07ZLlIQDYl"}
|
||||
{"name":"Désir lancinant : Gagner de l’argent (minimum 10 deniers)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"3BcC8lSsP5WIyva7"}
|
||||
{"name":"Désir lancinant : Mégalomanie. Être acclamé par un minimum de 10 personnes","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"3ZjwYyQRatCMnBCi"}
|
||||
{"name":"Idée fixe : Avoir le visage noirci à la cendre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"6G0lF06jSryTduAt"}
|
||||
{"name":"Idée fixe : Ne marcher qu’à quatre pattes","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"7TKsit2Mv9mWGq3C"}
|
||||
{"name":"Désir lancinant : Acquérir une chèvre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"8sLXQBqo8XwjAFG0"}
|
||||
{"name":"Idée fixe : Garder les yeux bandés","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"E902EEYZHg3zFKq6"}
|
||||
{"name":"Désir lancinant : Danser nu sous la pluie","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"F6qL4d4g3qjh045R"}
|
||||
{"name":"Idée fixe : Garder sur soi 3d6 kilos de cailloux","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"F8G3rdU1nfJzYwYR"}
|
||||
{"name":"Désir lancinant : Se faire raser la tête","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"HSNOvBR890dsEDw2"}
|
||||
{"name":"Idée fixe : Aller tout nu, sans porter le moindre paquet ni objet","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"I0CtQ05xFW6ghcdP"}
|
||||
{"name":"Idée fixe : Boulimie. Manger au moins un point de sust. par heure","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"JcTX8qMS0z8bmdVt"}
|
||||
{"name":"Désir lancinant : Passer une nuit sur une échelle","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"LlELEB0FhymLx6VM"}
|
||||
{"name":"Idée fixe : Refuser de monter dans les TMR","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"NpTDqICR7ZuToQrg"}
|
||||
{"name":"Désir lancinant : Masochisme. Perdre 3 points d’endurance minimum en 1 round","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"NzJJNK0YMAbobu0p"}
|
||||
{"name":"Désir lancinant : Casser 3d6 oeufs en les jetant à terre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"OjG8XRbeYtq2jcgB"}
|
||||
{"name":"Désir lancinant : Traire une vache","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"QHUOwjMR6AvepGPm"}
|
||||
{"name":"Désir lancinant : Pisser dans un violon (luth, mandoline, etc.)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"S8PVNgxb7TcFXq9g"}
|
||||
{"name":"Désir lancinant : Manger du poisson","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"SY0SsWtZdxSodMcl"}
|
||||
{"name":"Idée fixe : Ne pas franchir de porte. (On peut franchir une fenêtre)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"UUTbsktTcxsIe5L5"}
|
||||
{"name":"Idée fixe : Refuser de se délester du moindre objet, ni donner ni prêter","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"VChJbtGFtWoiFNky"}
|
||||
{"name":"Idée fixe : Ne s’exprimer que par des cris d’animaux (meuh ! coin-coin ! etc.)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"YCHBbRLiMzTH7IBj"}
|
||||
{"name":"Idée fixe : Vider sur sa tête toute fiole ou flacon aperçu","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"afGp9CewfyJKecEE"}
|
||||
{"name":"Désir lancinant : Faire des bulles de savon","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"df5oN8Ub3dWTVxNj"}
|
||||
{"name":"Désir lancinant : Entendre braire un âne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"diCCimukdNM6bPub"}
|
||||
{"name":"Désir lancinant : Se rouler dans la boue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"el4lofhhSucMv5xv"}
|
||||
{"name":"Idée fixe : Ne dire que «non» ou négation analogue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"gMmqdJ9I7Mt8Tg3f"}
|
||||
{"name":"Désir lancinant : Manger des champignons","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"gadh6aI5iCM82qpP"}
|
||||
{"name":"Idée fixe : Refuser de se déplacer autrement que porté","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"hghw6Cldrad1CIiJ"}
|
||||
{"name":"Idée fixe : Garder une main sur la tête","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"iPYPgxL2uUnphStc"}
|
||||
{"name":"Idée fixe : Appeler les hommes «madame» et les femmes «messire»","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"j2xIrFWYqhDM4TcN"}
|
||||
{"name":"Désir lancinant : Se soûler (minimum pas frais)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},""img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"jShpKV8mVcqWmYvp"}
|
||||
{"name":"Désir lancinant : Construire une cabane","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"mN0yghXkFfj2YctJ"}
|
||||
{"name":"Désir lancinant : Embrasser un cochon sur le groin","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"sjXBBr85OBk4Yg4t"}
|
||||
{"name":"Idée fixe : Faire le mort","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"queue","data":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","refoulement":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"xa4t9Lbt6uLEjap6"}
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,9 +1,9 @@
|
||||
{"_id":"0ZW71u9G8fqnyNfy","name":"Drakkar","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"vehicule","data":{"categorie":"Bateau","resistance":28,"structure":12,"vitesse":"3/2/1","bonus":"(10)/+10/+14","manoeuvrabilite":"0/-2/-4","equipage":8,"capacite_encombrement":150,"description":"Description ...","notesmj":"Notes du MJ"},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/drakkar.webp","token":{"flags":{},"name":"Drakkar","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/drakkar_token.webp","tint":"","width":10,"height":10,"scale":1,"mirrorX":false,"mirrorY":false,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightColor":"","lightAlpha":1,"lightAnimation":{"type":"","speed":5,"intensity":5},"actorId":"0ZW71u9G8fqnyNfy","actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":""},"bar2":{"attribute":""},"randomImg":false},"items":[],"effects":[]}
|
||||
{"_id":"5FWY38a5emYmqisa","name":"Cariole","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"vehicule","data":{"categorie":"Cariole à Bras","resistance":10,"structure":6,"vitesse":"","bonus":"","manoeuvrabilite":"","equipage":1,"capacite_encombrement":50,"description":"Description ...","notesmj":"Notes du MJ"},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/cariole.webp","token":{"flags":{},"name":"Cariole","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/cariole_token.webp","tint":"","width":2,"height":2,"scale":1,"mirrorX":false,"mirrorY":false,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightColor":"","lightAlpha":1,"lightAnimation":{"type":"","speed":5,"intensity":5},"actorId":"5FWY38a5emYmqisa","actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":""},"bar2":{"attribute":""},"randomImg":false},"items":[],"effects":[]}
|
||||
{"_id":"C0JpbzQSELoml971","name":"Canot","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"vehicule","data":{"categorie":"Barque","resistance":14,"structure":6,"vitesse":"","bonus":"(2)/+3/+5","manoeuvrabilite":"","equipage":1,"capacite_encombrement":50,"description":"Description ...","notesmj":"Notes du MJ"},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/canot.webp","token":{"flags":{},"name":"Canot","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/canot_token.webp","tint":"","width":3,"height":3,"scale":1,"mirrorX":false,"mirrorY":false,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightColor":"","lightAlpha":1,"lightAnimation":{"type":"","speed":5,"intensity":5},"actorId":"C0JpbzQSELoml971","actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":""},"bar2":{"attribute":""},"randomImg":false},"items":[],"effects":[]}
|
||||
{"_id":"PoQUTsNThYDp6XAW","name":"Nef","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"vehicule","data":{"categorie":"Bateau","resistance":30,"structure":14,"vitesse":"5/4/2","bonus":"","manoeuvrabilite":"0/-3/-4","equipage":12,"capacite_encombrement":200,"description":"Description ...","notesmj":"Notes du MJ"},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/nef.webp","token":{"flags":{},"name":"Nef","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/nef_token.webp","tint":"","width":13,"height":13,"scale":1,"mirrorX":false,"mirrorY":false,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightColor":"","lightAlpha":1,"lightAnimation":{"type":"","speed":5,"intensity":5},"actorId":"PoQUTsNThYDp6XAW","actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":""},"bar2":{"attribute":""},"randomImg":false},"items":[],"effects":[]}
|
||||
{"_id":"RFOYL8HBUxd32DXS","name":"Galère","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"vehicule","data":{"categorie":"Bateau","resistance":36,"structure":14,"vitesse":"2/2/1","bonus":"(12)/+12/+16","manoeuvrabilite":"0/-4/-6","equipage":10,"capacite_encombrement":300,"description":"Description ...","notesmj":"Notes du MJ"},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/galere.webp","token":{"flags":{},"name":"Galère","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/galere_token.webp","tint":"","width":14,"height":14,"scale":1,"mirrorX":false,"mirrorY":false,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightColor":"","lightAlpha":1,"lightAnimation":{"type":"","speed":5,"intensity":5},"actorId":"RFOYL8HBUxd32DXS","actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":""},"bar2":{"attribute":""},"randomImg":false},"items":[],"effects":[]}
|
||||
{"_id":"TDpSn7GawJ1LCHp7","name":"Charette","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"vehicule","data":{"categorie":"Chariot","resistance":16,"structure":8,"vitesse":"","bonus":"","manoeuvrabilite":"","equipage":1,"capacite_encombrement":100,"description":"Description ...","notesmj":"Notes du MJ"},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/charette.webp","token":{"flags":{},"name":"Charette","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/charette_token.webp","tint":"","width":3,"height":3,"scale":1.1,"mirrorX":false,"mirrorY":false,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightColor":"","lightAlpha":1,"lightAnimation":{"type":"","speed":5,"intensity":5},"actorId":"TDpSn7GawJ1LCHp7","actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":""},"bar2":{"attribute":""},"randomImg":false},"items":[],"effects":[]}
|
||||
{"_id":"ZiyRDzz3gGzlpLIc","name":"Barque","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"vehicule","data":{"categorie":"Barque","resistance":20,"structure":10,"vitesse":"3/2/1","bonus":"(4)/+4/+6","manoeuvrabilite":"0/0/-4","equipage":4,"capacite_encombrement":100,"description":"Description ...","notesmj":"Notes du MJ"},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/barque.webp","token":{"flags":{},"name":"Barque","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/barque_token.webp","tint":"","width":6,"height":6,"scale":1,"mirrorX":false,"mirrorY":false,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightColor":"","lightAlpha":1,"lightAnimation":{"type":"","speed":5,"intensity":5},"actorId":"ZiyRDzz3gGzlpLIc","actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":""},"bar2":{"attribute":""},"randomImg":false},"items":[],"effects":[]}
|
||||
{"_id":"gM77co80kmpVsYg6","name":"Posé par terre","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"vehicule","data":{"categorie":"Autre","resistance":0,"structure":0,"vitesse":"","bonus":"","manoeuvrabilite":"","equipage":0,"capacite_encombrement":100,"description":"<p>Déposer ici les objets que vous voulez échanger avec d'autres joueurs</p>","notesmj":""},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp","token":{"flags":{},"name":"Posé par terre","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp","tint":"","width":1,"height":1,"scale":1,"mirrorX":false,"mirrorY":false,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightColor":"","lightAlpha":1,"lightAnimation":{"type":"","speed":5,"intensity":5},"actorId":"gM77co80kmpVsYg6","actorLink":true,"disposition":0,"displayBars":0,"bar1":{"attribute":""},"bar2":{"attribute":""},"randomImg":false},"items":[],"effects":[]}
|
||||
{"_id":"idyDmDWYpQ4Eppen","name":"Chariot","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"vehicule","data":{"categorie":"Chariot","resistance":20,"structure":10,"vitesse":"","bonus":"","manoeuvrabilite":"","equipage":1,"capacite_encombrement":150,"description":"Description ...","notesmj":"Notes du MJ"},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/chariot.webp","token":{"flags":{},"name":"Chariot","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/chariot_token.webp","tint":"","width":4,"height":4,"scale":1.4,"mirrorX":false,"mirrorY":false,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightColor":"","lightAlpha":1,"lightAnimation":{"type":"","speed":5,"intensity":5},"actorId":"idyDmDWYpQ4Eppen","actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":""},"bar2":{"attribute":""},"randomImg":false},"items":[],"effects":[]}
|
||||
{"_id":"0ZW71u9G8fqnyNfy","name":"Drakkar","type":"vehicule","sort":100001,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.vehicules.0ZW71u9G8fqnyNfy"}},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/drakkar.webp","items":[],"effects":[],"system":{"categorie":"Bateau","resistance":28,"structure":12,"vitesse":"3/2/1","bonus":"(10)/+10/+14","manoeuvrabilite":"0/-2/-4","equipage":8,"capacite_encombrement":150,"etat":{"resistance":{"type":"number","max":28,"value":28,"label":"Résistance","derivee":false},"structure":{"type":"number","max":12,"value":12,"label":"Structure","derivee":false}},"description":"Description ...","race":"","notesmj":"Notes du MJ"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"prototypeToken":{"flags":{},"name":"Drakkar","displayName":0,"width":10,"height":10,"lockRotation":false,"rotation":0,"actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":"sante.vie"},"bar2":{"attribute":"sante.endurance"},"randomImg":false,"light":{"dim":0,"bright":0,"angle":360,"color":null,"alpha":1,"animation":{"type":null,"speed":5,"intensity":5,"reverse":false},"coloration":1,"attenuation":0.5,"luminosity":0.5,"saturation":0,"contrast":0,"shadows":0,"darkness":{"min":0,"max":1}},"texture":{"src":"systems/foundryvtt-reve-de-dragon/icons/vehicules/drakkar_token.webp","tint":null,"scaleX":1,"scaleY":1,"offsetX":0,"offsetY":0,"rotation":0},"sight":{"angle":360,"enabled":false,"range":0,"brightness":1,"visionMode":"basic","color":null,"attenuation":0.1,"saturation":0,"contrast":0},"alpha":1,"detectionModes":[]},"folder":null,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.21","coreVersion":"10.286","createdTime":1664231097623,"modifiedTime":1664231486338,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"5FWY38a5emYmqisa","name":"Cariole","type":"vehicule","sort":100001,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.vehicules.5FWY38a5emYmqisa"}},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/cariole.webp","items":[],"effects":[],"system":{"categorie":"Cariole à Bras","resistance":10,"structure":6,"vitesse":"","bonus":"","manoeuvrabilite":"","equipage":1,"capacite_encombrement":50,"etat":{"resistance":{"type":"number","max":10,"value":10,"label":"Résistance","derivee":false},"structure":{"type":"number","max":6,"value":6,"label":"Structure","derivee":false}},"description":"Description ...","race":"","notesmj":"Notes du MJ"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"prototypeToken":{"flags":{},"name":"Cariole","displayName":0,"width":2,"height":2,"lockRotation":false,"rotation":0,"actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":"sante.vie"},"bar2":{"attribute":"sante.endurance"},"randomImg":false,"light":{"dim":0,"bright":0,"angle":360,"color":null,"alpha":1,"animation":{"type":null,"speed":5,"intensity":5,"reverse":false},"coloration":1,"attenuation":0.5,"luminosity":0.5,"saturation":0,"contrast":0,"shadows":0,"darkness":{"min":0,"max":1}},"texture":{"src":"systems/foundryvtt-reve-de-dragon/icons/vehicules/cariole_token.webp","tint":null,"scaleX":1,"scaleY":1,"offsetX":0,"offsetY":0,"rotation":0},"sight":{"angle":360,"enabled":false,"range":0,"brightness":1,"visionMode":"basic","color":null,"attenuation":0.1,"saturation":0,"contrast":0},"alpha":1,"detectionModes":[]},"folder":null,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.21","coreVersion":"10.286","createdTime":1664231097624,"modifiedTime":1664231486337,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"C0JpbzQSELoml971","name":"Canot","type":"vehicule","sort":100001,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.vehicules.C0JpbzQSELoml971"}},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/canot.webp","items":[],"effects":[],"system":{"categorie":"Barque","resistance":14,"structure":6,"vitesse":"","bonus":"(2)/+3/+5","manoeuvrabilite":"","equipage":1,"capacite_encombrement":50,"etat":{"resistance":{"type":"number","max":14,"value":14,"label":"Résistance","derivee":false},"structure":{"type":"number","max":6,"value":6,"label":"Structure","derivee":false}},"description":"Description ...","race":"","notesmj":"Notes du MJ"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"prototypeToken":{"flags":{},"name":"Canot","displayName":0,"width":3,"height":3,"lockRotation":false,"rotation":0,"actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":"sante.vie"},"bar2":{"attribute":"sante.endurance"},"randomImg":false,"light":{"dim":0,"bright":0,"angle":360,"color":null,"alpha":1,"animation":{"type":null,"speed":5,"intensity":5,"reverse":false},"coloration":1,"attenuation":0.5,"luminosity":0.5,"saturation":0,"contrast":0,"shadows":0,"darkness":{"min":0,"max":1}},"texture":{"src":"systems/foundryvtt-reve-de-dragon/icons/vehicules/canot_token.webp","tint":null,"scaleX":1,"scaleY":1,"offsetX":0,"offsetY":0,"rotation":0},"sight":{"angle":360,"enabled":false,"range":0,"brightness":1,"visionMode":"basic","color":null,"attenuation":0.1,"saturation":0,"contrast":0},"alpha":1,"detectionModes":[]},"folder":null,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.21","coreVersion":"10.286","createdTime":1664231097625,"modifiedTime":1664231486336,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"PoQUTsNThYDp6XAW","name":"Nef","type":"vehicule","sort":100001,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.vehicules.PoQUTsNThYDp6XAW"}},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/nef.webp","items":[],"effects":[],"system":{"categorie":"Bateau","resistance":30,"structure":14,"vitesse":"5/4/2","bonus":"","manoeuvrabilite":"0/-3/-4","equipage":12,"capacite_encombrement":200,"etat":{"resistance":{"type":"number","max":30,"value":30,"label":"Résistance","derivee":false},"structure":{"type":"number","max":14,"value":14,"label":"Structure","derivee":false}},"description":"Description ...","race":"","notesmj":"Notes du MJ"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"prototypeToken":{"flags":{},"name":"Nef","displayName":0,"width":13,"height":13,"lockRotation":false,"rotation":0,"actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":"sante.vie"},"bar2":{"attribute":"sante.endurance"},"randomImg":false,"light":{"dim":0,"bright":0,"angle":360,"color":null,"alpha":1,"animation":{"type":null,"speed":5,"intensity":5,"reverse":false},"coloration":1,"attenuation":0.5,"luminosity":0.5,"saturation":0,"contrast":0,"shadows":0,"darkness":{"min":0,"max":1}},"texture":{"src":"systems/foundryvtt-reve-de-dragon/icons/vehicules/nef_token.webp","tint":null,"scaleX":1,"scaleY":1,"offsetX":0,"offsetY":0,"rotation":0},"sight":{"angle":360,"enabled":false,"range":0,"brightness":1,"visionMode":"basic","color":null,"attenuation":0.1,"saturation":0,"contrast":0},"alpha":1,"detectionModes":[]},"folder":null,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.21","coreVersion":"10.286","createdTime":1664231097626,"modifiedTime":1664231486339,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"RFOYL8HBUxd32DXS","name":"Galère","type":"vehicule","sort":100001,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.vehicules.RFOYL8HBUxd32DXS"}},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/galere.webp","items":[],"effects":[],"system":{"categorie":"Bateau","resistance":36,"structure":14,"vitesse":"2/2/1","bonus":"(12)/+12/+16","manoeuvrabilite":"0/-4/-6","equipage":10,"capacite_encombrement":300,"etat":{"resistance":{"type":"number","max":36,"value":36,"label":"Résistance","derivee":false},"structure":{"type":"number","max":14,"value":14,"label":"Structure","derivee":false}},"description":"Description ...","race":"","notesmj":"Notes du MJ"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"prototypeToken":{"flags":{},"name":"Galère","displayName":0,"width":14,"height":14,"lockRotation":false,"rotation":0,"actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":"sante.vie"},"bar2":{"attribute":"sante.endurance"},"randomImg":false,"light":{"dim":0,"bright":0,"angle":360,"color":null,"alpha":1,"animation":{"type":null,"speed":5,"intensity":5,"reverse":false},"coloration":1,"attenuation":0.5,"luminosity":0.5,"saturation":0,"contrast":0,"shadows":0,"darkness":{"min":0,"max":1}},"texture":{"src":"systems/foundryvtt-reve-de-dragon/icons/vehicules/galere_token.webp","tint":null,"scaleX":1,"scaleY":1,"offsetX":0,"offsetY":0,"rotation":0},"sight":{"angle":360,"enabled":false,"range":0,"brightness":1,"visionMode":"basic","color":null,"attenuation":0.1,"saturation":0,"contrast":0},"alpha":1,"detectionModes":[]},"folder":null,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.21","coreVersion":"10.286","createdTime":1664231097627,"modifiedTime":1664231486339,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"TDpSn7GawJ1LCHp7","name":"Charette","type":"vehicule","sort":100001,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.vehicules.TDpSn7GawJ1LCHp7"}},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/charette.webp","items":[],"effects":[],"system":{"categorie":"Chariot","resistance":16,"structure":8,"vitesse":"","bonus":"","manoeuvrabilite":"","equipage":1,"capacite_encombrement":100,"etat":{"resistance":{"type":"number","max":16,"value":16,"label":"Résistance","derivee":false},"structure":{"type":"number","max":8,"value":8,"label":"Structure","derivee":false}},"description":"Description ...","race":"","notesmj":"Notes du MJ"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"prototypeToken":{"flags":{},"name":"Charette","displayName":0,"width":3,"height":3,"lockRotation":false,"rotation":0,"actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":"sante.vie"},"bar2":{"attribute":"sante.endurance"},"randomImg":false,"light":{"dim":0,"bright":0,"angle":360,"color":null,"alpha":1,"animation":{"type":null,"speed":5,"intensity":5,"reverse":false},"coloration":1,"attenuation":0.5,"luminosity":0.5,"saturation":0,"contrast":0,"shadows":0,"darkness":{"min":0,"max":1}},"texture":{"src":"systems/foundryvtt-reve-de-dragon/icons/vehicules/charette_token.webp","tint":null,"scaleX":1.1,"scaleY":1.1,"offsetX":0,"offsetY":0,"rotation":0},"sight":{"angle":360,"enabled":false,"range":0,"brightness":1,"visionMode":"basic","color":null,"attenuation":0.1,"saturation":0,"contrast":0},"alpha":1,"detectionModes":[]},"folder":null,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.21","coreVersion":"10.286","createdTime":1664231097629,"modifiedTime":1664231486337,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"ZiyRDzz3gGzlpLIc","name":"Barque","type":"vehicule","sort":100001,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.vehicules.ZiyRDzz3gGzlpLIc"}},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/barque.webp","items":[],"effects":[],"system":{"categorie":"Barque","resistance":20,"structure":10,"vitesse":"3/2/1","bonus":"(4)/+4/+6","manoeuvrabilite":"0/0/-4","equipage":4,"capacite_encombrement":100,"etat":{"resistance":{"type":"number","max":20,"value":20,"label":"Résistance","derivee":false},"structure":{"type":"number","max":10,"value":10,"label":"Structure","derivee":false}},"description":"Description ...","race":"","notesmj":"Notes du MJ"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"prototypeToken":{"flags":{},"name":"Barque","displayName":0,"width":6,"height":6,"lockRotation":false,"rotation":0,"actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":"sante.vie"},"bar2":{"attribute":"sante.endurance"},"randomImg":false,"light":{"dim":0,"bright":0,"angle":360,"color":null,"alpha":1,"animation":{"type":null,"speed":5,"intensity":5,"reverse":false},"coloration":1,"attenuation":0.5,"luminosity":0.5,"saturation":0,"contrast":0,"shadows":0,"darkness":{"min":0,"max":1}},"texture":{"src":"systems/foundryvtt-reve-de-dragon/icons/vehicules/barque_token.webp","tint":null,"scaleX":1,"scaleY":1,"offsetX":0,"offsetY":0,"rotation":0},"sight":{"angle":360,"enabled":false,"range":0,"brightness":1,"visionMode":"basic","color":null,"attenuation":0.1,"saturation":0,"contrast":0},"alpha":1,"detectionModes":[]},"folder":null,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.21","coreVersion":"10.286","createdTime":1664231097629,"modifiedTime":1664231486336,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"gM77co80kmpVsYg6","name":"Posé par terre","type":"vehicule","sort":100001,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.vehicules.gM77co80kmpVsYg6"}},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp","items":[],"effects":[],"system":{"categorie":"Autre","resistance":0,"structure":0,"vitesse":"","bonus":"","manoeuvrabilite":"","equipage":0,"capacite_encombrement":100,"etat":{"resistance":{"type":"number","max":0,"value":0,"label":"Résistance","derivee":false},"structure":{"type":"number","max":0,"value":0,"label":"Structure","derivee":false}},"description":"<p>Déposer ici les objets que vous voulez échanger avec d'autres joueurs</p>","race":"","notesmj":""},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"prototypeToken":{"flags":{},"name":"Posé par terre","displayName":0,"width":1,"height":1,"lockRotation":false,"rotation":0,"actorLink":true,"disposition":0,"displayBars":0,"bar1":{"attribute":"sante.vie"},"bar2":{"attribute":"sante.endurance"},"randomImg":false,"light":{"dim":0,"bright":0,"angle":360,"color":null,"alpha":1,"animation":{"type":null,"speed":5,"intensity":5,"reverse":false},"coloration":1,"attenuation":0.5,"luminosity":0.5,"saturation":0,"contrast":0,"shadows":0,"darkness":{"min":0,"max":1}},"texture":{"src":"systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp","tint":null,"scaleX":1,"scaleY":1,"offsetX":0,"offsetY":0,"rotation":0},"sight":{"angle":360,"enabled":false,"range":0,"brightness":1,"visionMode":"basic","color":null,"attenuation":0.1,"saturation":0,"contrast":0},"alpha":1,"detectionModes":[]},"folder":null,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.21","coreVersion":"10.286","createdTime":1664231097630,"modifiedTime":1664231486340,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"idyDmDWYpQ4Eppen","name":"Chariot","type":"vehicule","sort":100001,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.vehicules.idyDmDWYpQ4Eppen"}},"img":"systems/foundryvtt-reve-de-dragon/icons/vehicules/chariot.webp","items":[],"effects":[],"system":{"categorie":"Chariot","resistance":20,"structure":10,"vitesse":"","bonus":"","manoeuvrabilite":"","equipage":1,"capacite_encombrement":150,"etat":{"resistance":{"type":"number","max":20,"value":20,"label":"Résistance","derivee":false},"structure":{"type":"number","max":10,"value":10,"label":"Structure","derivee":false}},"description":"Description ...","race":"","notesmj":"Notes du MJ"},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"prototypeToken":{"flags":{},"name":"Chariot","displayName":0,"width":4,"height":4,"lockRotation":false,"rotation":0,"actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":"sante.vie"},"bar2":{"attribute":"sante.endurance"},"randomImg":false,"light":{"dim":0,"bright":0,"angle":360,"color":null,"alpha":1,"animation":{"type":null,"speed":5,"intensity":5,"reverse":false},"coloration":1,"attenuation":0.5,"luminosity":0.5,"saturation":0,"contrast":0,"shadows":0,"darkness":{"min":0,"max":1}},"texture":{"src":"systems/foundryvtt-reve-de-dragon/icons/vehicules/chariot_token.webp","tint":null,"scaleX":1.4,"scaleY":1.4,"offsetX":0,"offsetY":0,"rotation":0},"sight":{"angle":360,"enabled":false,"range":0,"brightness":1,"visionMode":"basic","color":null,"attenuation":0.1,"saturation":0,"contrast":0},"alpha":1,"detectionModes":[]},"folder":null,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.21","coreVersion":"10.286","createdTime":1664231097632,"modifiedTime":1664231486338,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
|
File diff suppressed because one or more lines are too long
71
styles/img/ui/appel-chance.svg
Normal file
71
styles/img/ui/appel-chance.svg
Normal file
@ -0,0 +1,71 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="80.64064mm"
|
||||
height="87.145065mm"
|
||||
viewBox="0 0 80.64064 87.145065"
|
||||
version="1.1"
|
||||
id="svg857"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
|
||||
sodipodi:docname="appel-chance.svg">
|
||||
<defs
|
||||
id="defs851" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="2.3758788"
|
||||
inkscape:cx="275.41114"
|
||||
inkscape:cy="237.41072"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:current-layer="layer1"
|
||||
inkscape:document-rotation="0"
|
||||
showgrid="false"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2054"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata854">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(-65.513013,-104.59413)">
|
||||
<g
|
||||
id="g7"
|
||||
transform="matrix(0.26458333,0,0,0.26458333,66.057598,105.25559)"
|
||||
style="image-rendering:auto;fill:#ffffff;stroke:none">
|
||||
<title
|
||||
id="title4">Layer 1</title>
|
||||
<path
|
||||
fill="#ffffff"
|
||||
fill-rule="evenodd"
|
||||
stroke="#000000"
|
||||
stroke-width="8"
|
||||
id="path2"
|
||||
d="m 206.5,1.5 q 8.5,0 15,3 6.5,3 12.25,8.25 5.75,5.25 12.5,15.5 Q 253,38.5 259.5,43 266,47.5 273.75,52.25 281.5,57 285.5,63 q 4,6 5.75,11.5 1.75,5.5 0,18 -1.75,12.5 -5.75,20 -4,7.5 -12.75,14.25 -8.75,6.75 -17.25,10.75 -8.5,4 -15,6 -6.5,2 -28.75,4.25 -22.25,2.25 -23,3 l -0.75,0.75 0.5,1.25 q 0.5,1.25 32,0.5 31.5,-0.75 43.5,2.75 12,3.5 18.25,8.25 6.25,4.75 9.75,10.25 3.5,5.5 5.5,10.5 2,5 0.5,19.5 -1.5,14.5 -4.75,19.75 -3.25,5.25 -3.75,6.5 l -0.5,1.25 -4.25,2.5 q -4.25,2.5 -10.25,10.5 -6,8 -10,16.5 -4,8.5 -6.75,12.25 -2.75,3.75 -5.25,5.5 -2.5,1.75 -4,4 -1.5,2.25 -9.5,6.25 -8,4 -18.5,2.5 Q 210,290.5 202.75,285.25 195.5,280 190.5,275 q -5,-5 -10.25,-12.25 -5.25,-7.25 -7,-10.5 Q 171.5,249 169,237 q -2.5,-12 -5.5,-21 l -3,-9 -1.5,6.5 q -1.5,6.5 0,28.5 1.5,22 6.5,35 5,13 9.25,18.25 4.25,5.25 10,10.5 5.75,5.25 4.75,10.75 -1,5.5 -1.25,5.75 L 188,322.5 181,321 q -7,-1.5 -13.75,-7.25 Q 160.5,308 156,301.5 q -4.5,-6.5 -8.5,-17 -4,-10.5 -5.5,-20.5 -1.5,-10 -0.25,-36.25 l 1.25,-26.25 -3.25,0.75 q -3.25,0.75 -4.75,5.25 -1.5,4.5 -5.5,29.5 -4,25 -8,32.5 -4,7.5 -7.25,10.75 -3.25,3.25 -8.25,6.75 -5,3.5 -11,5.5 -6,2 -19,0.5 Q 63,291.5 57,288 51,284.5 43.25,274.75 35.5,265 31.75,257 L 28,249 26.5,247.75 Q 25,246.5 20.75,242.75 16.5,239 10,230.5 3.5,222 2.5,219 1.5,216 3,202.5 4.5,189 9.5,181 14.5,173 21.75,167.25 29,161.5 37,158.5 q 8,-3 36.5,-3.5 28.5,-0.5 30.75,-2.75 l 2.25,-2.25 -1.25,-1.25 Q 104,147.5 74,145 44,142.5 30.5,136.5 17,130.5 11.75,125.25 6.5,120 4.5,116.5 2.5,113 2,103.5 1.5,94 5.25,84.75 9,75.5 21.5,65 34,54.5 35,54.25 L 36,54 37.5,51.25 Q 39,48.5 46.25,39.25 53.5,30 57.25,25.75 61,21.5 68,16 75,10.5 83,8 91,5.5 97,6 q 6,0.5 14,4 8,3.5 14.25,9.25 6.25,5.75 9.25,12.25 3,6.5 4.5,15.5 1.5,9 4.25,34 2.75,25 3.75,25 h 1 l 0.75,-2.5 Q 149.5,101 151.5,72 153.5,43 155,39.5 156.5,36 162.25,27.75 168,19.5 176,13.5 q 8,-6 15,-9 7,-3 15.5,-3 z"
|
||||
style="fill:#ffffff;stroke:none" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
@ -65,7 +65,11 @@
|
||||
--debug-box-shadow-blue: inset 0 0 2px blue;
|
||||
--debug-box-shadow-green: inset 0 0 2px green;
|
||||
|
||||
/* =================== 3. some constants ============ */
|
||||
/* =================== 3. some constants ============ */
|
||||
--color-controls:rgba(0, 0, 0, 0.9);
|
||||
--color-controls-hover:rgba(255, 255, 128, 0.7);
|
||||
--color-control-border-hover:rgba(255, 128, 0, 0.8);
|
||||
--color-gold: rgba(191, 149, 63, 0.8);
|
||||
--gradient-gold: linear-gradient(30deg, rgba(191, 149, 63, 0.3), rgba(252, 246, 186, 0.3), rgba(179, 135, 40, 0.3), rgba(251, 245, 183, 0.3), rgba(170, 119, 28, 0.3));
|
||||
--gradient-silver: linear-gradient(30deg, rgba(61, 55, 93, 0.3), rgba(178, 179, 196, 0.3), rgba(59, 62, 63, 0.6), rgba(206, 204, 199, 0.3), rgba(61, 46, 49, 0.3));
|
||||
--gradient-green: linear-gradient(30deg, rgba(7, 76, 0, 0.3), rgba(66, 163, 65, 0.2), rgba(184, 226, 163, 0.1), rgba(66, 163, 65, 0.2), rgba(184, 226, 163, 0.3));
|
||||
@ -89,7 +93,7 @@
|
||||
.sheet nav.sheet-tabs {
|
||||
font-family: "CaslonAntique";
|
||||
} /* For nav and title */
|
||||
.window-app input, .foundryvtt-reve-de-dragon .item-form, .sheet header.sheet-header .flex-group-center.flex-compteurs, .sheet header.sheet-header .flex-group-center.flex-fatigue, select, button, .item-checkbox, #sidebar, #players, #navigation #nav-toggle {
|
||||
.window-app input, .foundryvtt-reve-de-dragon .item-form, .sheet header.sheet-header .flex-compteurs, .sheet header.sheet-header .flex-group-center.flex-fatigue, select, button, .item-checkbox, #sidebar, #players, #navigation #nav-toggle {
|
||||
font-family: "CaslonAntique"; /* For sheet parts */
|
||||
}
|
||||
|
||||
@ -104,6 +108,9 @@
|
||||
.strong-text{
|
||||
font-weight: bold;
|
||||
}
|
||||
i:is(.fas, .far) {
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.tabs .item.active, .blessures-list li ul li:first-child:hover, a:hover {
|
||||
text-shadow: 1px 0px 0px #ff6600;
|
||||
@ -225,6 +232,69 @@ table {border: 1px solid #7a7971;}
|
||||
flex-grow : 3;
|
||||
}
|
||||
/* Styles limited to foundryvtt-reve-de-dragon sheets */
|
||||
.equipement-nom {
|
||||
flex-grow : 4;
|
||||
margin: 0;
|
||||
justify-content: center;
|
||||
text-align: left;
|
||||
}
|
||||
.equipement-detail {
|
||||
margin: 0;
|
||||
flex: 'flex-shrink' ;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
.equipement-actions {
|
||||
margin: 0;
|
||||
flex-grow: 2;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: left;
|
||||
}
|
||||
.blessure-control {
|
||||
flex-grow: 1;
|
||||
flex-direction: row;
|
||||
}
|
||||
.blessure-soins {
|
||||
flex-direction: row;
|
||||
align-content: flex-start;
|
||||
justify-content: flex-start;
|
||||
margin-right: 2px;
|
||||
margin-left: 2px;
|
||||
padding: 2px;
|
||||
}
|
||||
input:is(.blessure-psdone, .blessure-scdone) {
|
||||
width: 20px;
|
||||
}
|
||||
input:is(.blessure-premiers_soins, .blessure-soins_complets) {
|
||||
width: calc(100% - 25px);
|
||||
}
|
||||
.blessure-jours {
|
||||
flex-direction: row;
|
||||
align-content: flex-start;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.blessure-localisation {
|
||||
flex-direction: row;
|
||||
align-content: flex-start;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.blessure-inactive {
|
||||
color:rgba(150, 150, 150, 0.4);
|
||||
}
|
||||
.blessure-active-legere {
|
||||
color:rgba(60, 60, 60, 0.9);
|
||||
text-shadow: 1px 1px 4px rgba(60, 60, 60, 1);
|
||||
}
|
||||
.blessure-active-grave {
|
||||
color: rgba(218, 126, 21, 0.9);
|
||||
text-shadow: 1px 1px 4px rgba(60, 60, 60, 1);
|
||||
}
|
||||
.blessure-active-critique {
|
||||
color: rgba(173, 36, 26, 0.9);
|
||||
text-shadow: 1px 1px 4px rgba(60, 60, 60, 1);
|
||||
}
|
||||
|
||||
.foundryvtt-reve-de-dragon .sheet-header {
|
||||
-webkit-box-flex: 0;
|
||||
@ -262,18 +332,12 @@ table {border: 1px solid #7a7971;}
|
||||
}
|
||||
.button-img {
|
||||
vertical-align: baseline;
|
||||
width: 8%;
|
||||
height: 8%;
|
||||
max-height: 48px;
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
max-height: 36px;
|
||||
border-width: 0;
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
}
|
||||
.button-img:hover {
|
||||
color: rgba(255, 255, 128, 0.7);
|
||||
border: 1px solid rgba(255, 128, 0, 0.8);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.button-effect-img {
|
||||
vertical-align: baseline;
|
||||
width: 16px;
|
||||
@ -281,9 +345,16 @@ table {border: 1px solid #7a7971;}
|
||||
height: 16;
|
||||
border-width: 0;
|
||||
}
|
||||
.button-effect-img:hover {
|
||||
color: rgba(255, 255, 128, 0.7);
|
||||
border: 1px solid rgba(255, 128, 0, 0.8);
|
||||
.small-button-direction {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
border: 0;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
:is(.button-img,.button-effect-img:hover,.small-button-direction):hover {
|
||||
color: var(--color-controls-hover);
|
||||
border: 1px solid var(--color-control-border-hover);
|
||||
text-shadow: 1px 0px 0px #ff6600;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@ -294,18 +365,6 @@ table {border: 1px solid #7a7971;}
|
||||
vertical-align: bottom;
|
||||
}
|
||||
|
||||
.small-button-direction {
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
border: 0;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.small-button-direction:hover {
|
||||
color: rgba(255, 255, 128, 0.7);
|
||||
border: 1px solid rgba(255, 128, 0, 0.8);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.foundryvtt-reve-de-dragon .sheet-header .header-fields {
|
||||
-webkit-box-flex: 1;
|
||||
-ms-flex: 1;
|
||||
@ -346,25 +405,32 @@ table {border: 1px solid #7a7971;}
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .competence {
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .caracteristique {
|
||||
flex-wrap: nowrap;
|
||||
justify-content: stretch;
|
||||
}
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .competence > .carac-label {
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .caracteristique.streched {
|
||||
flex-wrap: nowrap;
|
||||
justify-content: stretch;
|
||||
flex-basis: 7.5em;
|
||||
width: max-content;
|
||||
}
|
||||
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .caracteristique > .carac-label {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .competence > .attribut-label {
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .caracteristique > .attribut-label {
|
||||
flex-basis: 50%;
|
||||
}
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .competence > .competence-value.total {
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .caracteristique > .competence-value.total {
|
||||
flex-grow: 1;
|
||||
text-align: right;
|
||||
}
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .competence > .utiliser-attribut {
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .caracteristique > .utiliser-attribut {
|
||||
flex-basis: available;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .competence > * {
|
||||
.rdd.sheet .window-content .sheet-body .carac-list .caracteristique > * {
|
||||
flex-basis: 13%;
|
||||
flex-grow: 0;
|
||||
}
|
||||
@ -434,20 +500,6 @@ table {border: 1px solid #7a7971;}
|
||||
border-bottom: 1px solid #BBB;
|
||||
}
|
||||
|
||||
.blessure-inactive {
|
||||
color:rgba(150, 150, 150, 0.4)
|
||||
}
|
||||
.blessure-active-legere {
|
||||
color:rgba(60, 60, 60, 0.9);
|
||||
text-shadow: rgba(60, 60, 60, 0.7);
|
||||
}
|
||||
.blessure-active-grave {
|
||||
color:rgba(218, 126, 21, 0.9);
|
||||
}
|
||||
.blessure-active-critique {
|
||||
color:rgba(173, 36, 26, 0.9);
|
||||
|
||||
}
|
||||
.foundryvtt-reve-de-dragon .items-list .item .item-image {
|
||||
-webkit-box-flex: 0;
|
||||
-ms-flex: 0 0 24px;
|
||||
@ -469,13 +521,18 @@ table {border: 1px solid #7a7971;}
|
||||
flex: 0 0 86px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.competence-list .item-controls {
|
||||
display: contents !important;
|
||||
}
|
||||
.competence-list .item-controls.hidden-controls {
|
||||
display: none !important;
|
||||
}
|
||||
.item-controls i:is(.fas,.far) {
|
||||
color: var(--color-controls);
|
||||
}
|
||||
.item-controls i:is(.fas,.far):hover {
|
||||
opacity: 0.7 ;
|
||||
}
|
||||
|
||||
.rdddialog .dialog-roll-sort s{
|
||||
width: 600px;
|
||||
@ -567,7 +624,7 @@ table {border: 1px solid #7a7971;}
|
||||
color: rgba(255, 255, 255, 0.75);
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
border: 0 none;
|
||||
margin-bottom: 0.25rem;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
|
||||
.window-app .window-content, .window-app.sheet .window-content .sheet-body{
|
||||
@ -582,7 +639,14 @@ section.sheet-body{padding: 0.25rem 0.5rem;}
|
||||
margin: 0.5rem 0 0.5rem 0.5rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sheet header.sheet-header h1 {
|
||||
flex: 3;
|
||||
}
|
||||
.sheet header.sheet-header img.button-img{
|
||||
height: 48px;
|
||||
padding: 1px;
|
||||
margin: 1px;
|
||||
}
|
||||
.sheet nav.sheet-tabs {
|
||||
font-size: 0.65rem;
|
||||
font-weight: bold;
|
||||
@ -601,7 +665,7 @@ section.sheet-body{padding: 0.25rem 0.5rem;}
|
||||
|
||||
nav.sheet-tabs .item {
|
||||
position: relative;
|
||||
padding: 0 0.25rem;
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
|
||||
nav.sheet-tabs .item:after {
|
||||
@ -624,14 +688,22 @@ section.sheet-body:after {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.sheet header.sheet-header .flex-compteurs {text-align: right;}
|
||||
.sheet header.sheet-header .flex-compteurs { text-align: right; max-width: max-content;}
|
||||
.sheet header.sheet-header .resource-content {width: 2rem;}
|
||||
|
||||
.ctn-vie span, .ctn-endu span, .ctn-fatigue span, .ctn-reve span {
|
||||
li label.compteur {
|
||||
display: inline-block;
|
||||
flex-direction: row;
|
||||
}
|
||||
.compteur span {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
width: 2rem;
|
||||
}
|
||||
.compteur a i:is(.fas,.far):hover {
|
||||
opacity: 0.7 ;
|
||||
}
|
||||
|
||||
.select-diff {
|
||||
display: inline-block;
|
||||
text-align: left;
|
||||
@ -644,17 +716,6 @@ section.sheet-body:after {
|
||||
max-width: 90%;
|
||||
}
|
||||
|
||||
.plus-moins {
|
||||
display: inline-block;
|
||||
width: 1.25rem;
|
||||
background: rgba(30, 25, 20, 1);
|
||||
text-align: center;
|
||||
border: 1px solid rgba(72, 46, 28, 1);
|
||||
border-radius: 0.25rem;
|
||||
line-height: 1.25rem;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.alchimie-tache {
|
||||
font-weight: bold;
|
||||
background: rgb(182, 180, 179);
|
||||
@ -711,10 +772,13 @@ ul, ol {
|
||||
ul, li {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
.sheet .caracteristique li {
|
||||
margin: 0.1rem;
|
||||
padding: 0.2rem;
|
||||
}
|
||||
.sheet li {
|
||||
margin: 0.125rem;
|
||||
padding: 0.25rem;
|
||||
margin: 0.1rem;
|
||||
padding: 0.1rem;
|
||||
}
|
||||
.header-fields li {
|
||||
margin: 0;
|
||||
@ -731,23 +795,19 @@ ul, li {
|
||||
background: rgb(160, 130, 100, 0.05);
|
||||
}
|
||||
.xp-level-up {
|
||||
margin: 0.125rem;
|
||||
margin: 0.1rem;
|
||||
box-shadow: inset 0px 0px 1px #00000096;
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.125rem;
|
||||
padding: 0.1rem;
|
||||
flex: 1 1 5rem;
|
||||
background: var(--gradient-gold) !important;
|
||||
}
|
||||
.niveau-archetype {
|
||||
background: var(--gradient-silver-light) !important;
|
||||
}
|
||||
.fa-arrow-alt-circle-up.allouer-stress {
|
||||
color: rgba(83, 60, 14, 0.8);
|
||||
.item-controls i.fas.allouer-stress.level-up {
|
||||
color: var(--color-gold);
|
||||
}
|
||||
.fa-arrow-alt-circle-up.allouer-stress-level-up {
|
||||
color: rgba(191, 149, 63, 0.8);
|
||||
}
|
||||
|
||||
.blessures-list ul {
|
||||
display: flex;
|
||||
}
|
||||
@ -766,18 +826,18 @@ ul, li {
|
||||
font-weight: bold;
|
||||
}
|
||||
.list-item {
|
||||
margin: 0.125rem;
|
||||
margin: 0.1rem;
|
||||
box-shadow: inset 0px 0px 1px #00000096;
|
||||
border-radius: 0.25rem;
|
||||
padding: 0.125rem;
|
||||
padding: 0.1rem;
|
||||
flex: 1 1 5rem;
|
||||
display: flex !important;
|
||||
align-items: baseline !important;
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
margin: 0.125rem;
|
||||
padding: 0.125rem;
|
||||
margin: 0.1rem;
|
||||
padding: 0.1rem;
|
||||
flex: 1 1 5rem;
|
||||
}
|
||||
|
||||
@ -801,28 +861,54 @@ ul, li {
|
||||
background: rgb(200, 10, 100, 0.25);
|
||||
}
|
||||
|
||||
.item-quantite {
|
||||
margin-left: 0.5rem;
|
||||
.item-column {
|
||||
margin-left: 0.2rem;
|
||||
margin-right: 0.2rem;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.list-item-margin1 {
|
||||
margin-left: 1rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
.list-item-margin2 {
|
||||
margin-left: 2rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
.list-item-margin3 {
|
||||
margin-left: 3rem;
|
||||
margin-left: 1.5rem;
|
||||
}
|
||||
.list-item-margin4 {
|
||||
margin-left: 4rem;
|
||||
margin-left: 2rem;
|
||||
}
|
||||
.list-item-margin5 {
|
||||
margin-left: 2.5rem;
|
||||
}
|
||||
.list-item-margin6 {
|
||||
margin-left: 3rem;
|
||||
}
|
||||
|
||||
.grid-select-type-tmr {
|
||||
display: grid;
|
||||
grid-column: span 4 / span 4;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 0.1rem;
|
||||
margin: 0.1rem;
|
||||
padding: 0;
|
||||
}
|
||||
.grid-select-actor {
|
||||
display: grid;
|
||||
grid-column: span 2 / span 2;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 0.1rem;
|
||||
margin: 0.1rem;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.sheet-competence-img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
flex-grow: 0;
|
||||
margin-right: 0.25rem;
|
||||
margin-right: 0.2rem;
|
||||
vertical-align: bottom;
|
||||
}
|
||||
.competence-column {
|
||||
@ -866,20 +952,26 @@ ul, li {
|
||||
.competence-value {
|
||||
flex-grow: 0;
|
||||
flex-basis: 2rem;
|
||||
margin-right: 0.25rem;
|
||||
margin-left: 0.25rem;
|
||||
margin-right: 0.2rem;
|
||||
margin-left: 0.2rem;
|
||||
}
|
||||
.initiative-value {
|
||||
flex-grow: 0;
|
||||
flex-basis: 3rem;
|
||||
margin-right: 0.2rem;
|
||||
margin-left: 0.2rem;
|
||||
}
|
||||
.description-value {
|
||||
flex-grow: 0;
|
||||
flex-basis: 4rem;
|
||||
margin-right: 0.25rem;
|
||||
margin-left: 0.25rem;
|
||||
margin-right: 0.2rem;
|
||||
margin-left: 0.2rem;
|
||||
}
|
||||
.competence-xp {
|
||||
flex-grow: 0;
|
||||
flex-basis: 2rem;
|
||||
margin-right: 0.25rem;
|
||||
margin-left: 0.25rem;
|
||||
margin-right: 0.2rem;
|
||||
margin-left: 0.2rem;
|
||||
}
|
||||
.blessures-title {
|
||||
font-weight: bold;
|
||||
@ -887,23 +979,6 @@ ul, li {
|
||||
.alchimie-title {
|
||||
font-weight: bold;
|
||||
}
|
||||
.blessure-data {
|
||||
flex-direction: row;
|
||||
align-content: flex-start;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.blessures-soins {
|
||||
flex-grow: 0;
|
||||
flex-basis: 32px;
|
||||
margin-right: 4px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.blessures-loc {
|
||||
flex-grow: 0;
|
||||
flex-basis: 96px;
|
||||
margin-right: 4px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
.pointsreve-value {
|
||||
flex-grow: 0;
|
||||
flex-basis: 64px;
|
||||
@ -957,7 +1032,7 @@ ul, li {
|
||||
flex-basis: auto;
|
||||
padding: 0;
|
||||
line-height: 1rem;
|
||||
margin: 0.25rem;
|
||||
margin: 0.2rem;
|
||||
}
|
||||
.control-icon.tokenhudicon.right {
|
||||
margin-left: 8px;
|
||||
@ -975,7 +1050,7 @@ ul, li {
|
||||
border-left: none;
|
||||
font-weight: 500;
|
||||
font-size: 1rem;
|
||||
color: black;
|
||||
color: var(--color-controls);
|
||||
padding-top: 5px;
|
||||
margin-right: 0px;
|
||||
width: 45px;
|
||||
@ -1054,7 +1129,7 @@ ul, li {
|
||||
.table-fatigue .fatigue-malus {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
.flex-actions-bar {
|
||||
.flex-actions-bar {
|
||||
flex-grow: 2;
|
||||
}
|
||||
|
||||
@ -1075,7 +1150,7 @@ ul, li {
|
||||
.sidebar-tab .directory-list .entity {
|
||||
border-top: 1px dashed rgba(0,0,0,0.25);
|
||||
border-bottom: 0 none;
|
||||
padding: 0.25rem 0;
|
||||
padding: 0.2rem 0;
|
||||
}
|
||||
|
||||
.sidebar-tab .directory-list .entity:hover {
|
||||
@ -1124,9 +1199,16 @@ ul, li {
|
||||
|
||||
}
|
||||
|
||||
#sidebar #sidebar-tabs i.fa-comments:before, #sidebar #sidebar-tabs i.fa-fist-raised:before, #sidebar #sidebar-tabs i.fa-users:before, #sidebar #sidebar-tabs i.fa-map:before, #sidebar #sidebar-tabs i.fa-suitcase:before, #sidebar #sidebar-tabs i.fa-book-open:before, #sidebar #sidebar-tabs i.fa-th-list:before, #sidebar #sidebar-tabs i.fa-music:before, #sidebar #sidebar-tabs i.fa-atlas:before, #sidebar #sidebar-tabs i.fa-cogs:before {content: "";}
|
||||
#sidebar #sidebar-tabs i:is(
|
||||
.fa-comments, .fa-fist-raised, .fa-swords,
|
||||
.fa-users, .fa-user, .fa-map, .fa-suitcase,
|
||||
.fa-book-open, .fa-th-list, .fa-music,
|
||||
.fa-atlas,.fa-cogs
|
||||
):before {content: "";}
|
||||
#sidebar #sidebar-tabs i.fa-comments {background: url("img/ui/icon_sidebar_chat.svg") no-repeat;}
|
||||
#sidebar #sidebar-tabs i.fa-fist-raised {background: url("img/ui/icon_sidebar_fight.svg") no-repeat;}
|
||||
#sidebar #sidebar-tabs i.fa-swords {background: url("img/ui/icon_sidebar_fight.svg") no-repeat;}
|
||||
#sidebar #sidebar-tabs i.fa-user {background: url("img/ui/icon_sidebar_actor.svg") no-repeat;}
|
||||
#sidebar #sidebar-tabs i.fa-users {background: url("img/ui/icon_sidebar_actor.svg") no-repeat;}
|
||||
#sidebar #sidebar-tabs i.fa-map {background: url("img/ui/icon_sidebar_scene.svg") no-repeat;}
|
||||
#sidebar #sidebar-tabs i.fa-suitcase {background: url("img/ui/icon_sidebar_item.svg") no-repeat;}
|
||||
@ -1153,11 +1235,11 @@ ul, li {
|
||||
border-image-width: 4px;
|
||||
border-image-outset: 0px;
|
||||
}
|
||||
#controls .control-tools {
|
||||
max-height: calc(100vh - 156px);
|
||||
height: auto;
|
||||
#controls .control-tools {
|
||||
max-height: calc(100vh - 156px);
|
||||
height: auto;
|
||||
}
|
||||
#controls .scene-control.active, #controls .control-tool.active, #controls .scene-control:hover, #controls .control-tool:hover {
|
||||
#controls :is(.scene-control.active,.control-tool.active, .scene-control:hover, .control-tool:hover) {
|
||||
background: rgba(72, 46, 28, 1);
|
||||
background-origin: padding-box;
|
||||
border-image: url(img/ui/footer-button.webp) 10 repeat;
|
||||
@ -1343,8 +1425,8 @@ ul, li {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
.calendar-btn:hover {
|
||||
color: rgba(255, 255, 128, 0.7);
|
||||
border: 1px solid rgba(255, 128, 0, 0.8);
|
||||
color: var(--color-controls-hover);
|
||||
border: 1px solid var(--color-control-border-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
400
system.json
400
system.json
@ -1,38 +1,46 @@
|
||||
{
|
||||
"name": "foundryvtt-reve-de-dragon",
|
||||
"id": "foundryvtt-reve-de-dragon",
|
||||
"title": "Rêve de Dragon",
|
||||
"version": "10.0.28",
|
||||
"download": "https://www.uberwald.me/gitea/VincentVk/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.0.28.zip",
|
||||
"manifest": "https://www.uberwald.me/gitea/VincentVk/foundryvtt-reve-de-dragon/raw/v10/system.json",
|
||||
"compatibility": {
|
||||
"minimum": "10",
|
||||
"verified": "10.288"
|
||||
},
|
||||
"description": "Rêve de Dragon RPG for FoundryVTT",
|
||||
"author": "LeRatierBretonnien",
|
||||
"authors": [
|
||||
{
|
||||
"name": "LeRatierBretonnien"
|
||||
"name": "LeRatierBretonnien",
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "VincentVK"
|
||||
"name": "VincentVK",
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "Grendel"
|
||||
"name": "Grendel",
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "Michael Nonne"
|
||||
"name": "Michael Nonne",
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "Mandar"
|
||||
"name": "Mandar",
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "Fred"
|
||||
"name": "Fred",
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "Fab"
|
||||
"name": "Fab",
|
||||
"flags": {}
|
||||
}
|
||||
],
|
||||
"url": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/",
|
||||
"license": "LICENSE.txt",
|
||||
"flags": {},
|
||||
"version": "1.5.75",
|
||||
"minimumCoreVersion": "0.8.0",
|
||||
"compatibleCoreVersion": "9",
|
||||
"scripts": [],
|
||||
"esmodules": [
|
||||
"module/rdd-main.js"
|
||||
],
|
||||
@ -44,12 +52,13 @@
|
||||
"lang": "en",
|
||||
"name": "English",
|
||||
"path": "lang/fr.json",
|
||||
"unreal": "this is a trick"
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"lang": "fr",
|
||||
"name": "Français",
|
||||
"path": "lang/fr.json"
|
||||
"path": "lang/fr.json",
|
||||
"flags": {}
|
||||
}
|
||||
],
|
||||
"packs": [
|
||||
@ -57,453 +66,276 @@
|
||||
"name": "competences",
|
||||
"label": "Compétences",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/competences.db",
|
||||
"path": "packs/competences.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"compétences"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "arts-et-divertissements",
|
||||
"label": "Arts et Divertissements",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/arts-et-divertissements.db",
|
||||
"path": "packs/arts-et-divertissements.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"recette",
|
||||
"cuisine",
|
||||
"danse",
|
||||
"musique",
|
||||
"chant",
|
||||
"jeux"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "competences-creatures",
|
||||
"label": "Compétences de Créatures",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/competences-creatures.db",
|
||||
"path": "packs/competences-creatures.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"compétences",
|
||||
"créatures"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "competences-entites",
|
||||
"label": "Compétences des Entités",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/competences-entites.db",
|
||||
"path": "packs/competences-entites.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"compétences",
|
||||
"entités"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "sorts-oniros",
|
||||
"label": "Sorts d'Oniros",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/sorts-oniros.db",
|
||||
"path": "packs/sorts-oniros.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"sorts"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "sorts-hypnos",
|
||||
"label": "Sorts d'Hypnos",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/sorts-hypnos.db",
|
||||
"path": "packs/sorts-hypnos.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"sorts"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "sorts-narcos",
|
||||
"label": "Sorts de Narcos",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/sorts-narcos.db",
|
||||
"path": "packs/sorts-narcos.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"sorts"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "sorts-thanatos",
|
||||
"label": "Sorts de Thanatos",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/sorts-thanatos.db",
|
||||
"path": "packs/sorts-thanatos.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"sorts"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "equipement",
|
||||
"label": "Equipement",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/equipement.db",
|
||||
"path": "packs/equipement.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"équipement",
|
||||
"objet"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "maladies-et-poisons",
|
||||
"label": "Maladies & Poisons",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/maladies-et-poisons.db",
|
||||
"path": "packs/maladies-et-poisons.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"maladie",
|
||||
"poison"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "rappel-des-regles",
|
||||
"label": "Rappels des Règles",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/rappel-des-regles.db",
|
||||
"path": "packs/rappel-des-regles.db",
|
||||
"type": "JournalEntry",
|
||||
"tags": [
|
||||
"journal",
|
||||
"règles"
|
||||
],
|
||||
"entity": "JournalEntry",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "queues-de-dragon",
|
||||
"label": "Queues de Dragon",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/queues-de-dragon.db",
|
||||
"path": "packs/queues-de-dragon.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"queue"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "ombres-de-thanatos",
|
||||
"label": "Ombres de Thanatos",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/ombres-de-thanatos.db",
|
||||
"path": "packs/ombres-de-thanatos.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"ombre"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "souffles-de-dragon",
|
||||
"label": "Souffles de Dragon",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/souffles-de-dragon.db",
|
||||
"path": "packs/souffles-de-dragon.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"souffle"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "tarot-draconique",
|
||||
"label": "Tarot Draconique",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/tarot-draconique.db",
|
||||
"path": "packs/tarot-draconique.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"tarot"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "tetes-de-dragon-pour-haut-revants",
|
||||
"label": "Têtes de Dragon (Hauts-Rêvants)",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/tetes-de-dragon-pour-haut-revants.db",
|
||||
"path": "packs/tetes-de-dragon-pour-haut-revants.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"tête"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "tetes-de-dragon-pour-tous-personnages",
|
||||
"label": "Têtes de Dragon (Tous Personnages)",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/tetes-de-dragon-pour-tous-personnages.db",
|
||||
"path": "packs/tetes-de-dragon-pour-tous-personnages.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"item",
|
||||
"tête"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "tables-diverses",
|
||||
"label": "Tables Diverses",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/tables-diverses.db",
|
||||
"path": "packs/tables-diverses.db",
|
||||
"type": "RollTable",
|
||||
"tags": [
|
||||
"table",
|
||||
"tables"
|
||||
],
|
||||
"entity": "RollTable",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "animaux",
|
||||
"label": "Animaux",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/animaux.db",
|
||||
"path": "packs/animaux.db",
|
||||
"type": "Actor",
|
||||
"tags": [
|
||||
"animaux",
|
||||
"creature"
|
||||
],
|
||||
"entity": "Actor",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "voyageurs",
|
||||
"label": "Voyageurs",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/voyageurs.db",
|
||||
"path": "packs/voyageurs.db",
|
||||
"type": "Actor",
|
||||
"tags": [
|
||||
"voyageur",
|
||||
"profils"
|
||||
],
|
||||
"entity": "Actor",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "vehicules",
|
||||
"label": "Véhicules",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/vehicules.db",
|
||||
"path": "packs/vehicules.db",
|
||||
"type": "Actor",
|
||||
"tags": [
|
||||
"vehicule",
|
||||
"bateau",
|
||||
"charett",
|
||||
"chariot",
|
||||
"carriole",
|
||||
"barque"
|
||||
],
|
||||
"entity": "Actor",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "archetypes",
|
||||
"label": "Archetypes PNJs",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/archetypes.db",
|
||||
"path": "packs/archetypes.db",
|
||||
"type": "Actor",
|
||||
"tags": [
|
||||
"archetype",
|
||||
"pnj"
|
||||
],
|
||||
"entity": "Actor",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "humanoides",
|
||||
"label": "Humanoïdes",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/humanoides.db",
|
||||
"path": "packs/humanoides.db",
|
||||
"type": "Actor",
|
||||
"tags": [
|
||||
"humanoides",
|
||||
"pnj"
|
||||
],
|
||||
"entity": "Actor",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "entites",
|
||||
"label": "Entités de Cauchemar",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/entites-de-cauchemar.db",
|
||||
"path": "packs/entites-de-cauchemar.db",
|
||||
"type": "Actor",
|
||||
"tags": [
|
||||
"entités",
|
||||
"entite",
|
||||
"cauchemar",
|
||||
"ecni",
|
||||
"eni"
|
||||
],
|
||||
"entity": "Actor",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "invocations",
|
||||
"label": "Invocation d'Hypnos",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/invocations.db",
|
||||
"path": "packs/invocations.db",
|
||||
"type": "Actor",
|
||||
"tags": [
|
||||
"hypnos",
|
||||
"invocation"
|
||||
],
|
||||
"entity": "Actor",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "botanique",
|
||||
"label": "Botanique",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/botanique.db",
|
||||
"path": "packs/botanique.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"plantes",
|
||||
"champignons",
|
||||
"herbes"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "taches-courantes",
|
||||
"label": "Tâches courantes",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/taches-courantes.db",
|
||||
"path": "packs/taches-courantes.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"taches"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "meditations-et-ecrits",
|
||||
"label": "Méditations et Ecrits",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/meditations-et-ecrits.db",
|
||||
"path": "packs/meditations-et-ecrits.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"meditations",
|
||||
"méditations",
|
||||
"livres",
|
||||
"livre",
|
||||
"méditation",
|
||||
"écrits",
|
||||
"écrit"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "recettes-alchimiques",
|
||||
"label": "Recettes Alchimiques",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/recettes-alchimiques.db",
|
||||
"path": "packs/recettes-alchimiques.db",
|
||||
"type": "Item",
|
||||
"tags": [
|
||||
"recettes",
|
||||
"recette",
|
||||
"alchimie",
|
||||
"alchimique",
|
||||
"potion"
|
||||
],
|
||||
"entity": "Item",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
"name": "scenes-rdd",
|
||||
"label": "Scenes Reve de Dragon",
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"module": "foundryvtt-reve-de-dragon",
|
||||
"path": "./packs/scenes-rdd.db",
|
||||
"path": "packs/scenes-rdd.db",
|
||||
"type": "Scene",
|
||||
"tags": [
|
||||
"ecran",
|
||||
"scene"
|
||||
],
|
||||
"entity": "Scene",
|
||||
"private": false
|
||||
"private": false,
|
||||
"flags": {}
|
||||
}
|
||||
],
|
||||
"system": [],
|
||||
"dependencies": [],
|
||||
"socket": true,
|
||||
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v1.5/system.json",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-1.5.75.zip",
|
||||
"protected": false,
|
||||
"gridDistance": 1,
|
||||
"gridUnits": "m",
|
||||
"primaryTokenAttribute": "sante.vie",
|
||||
"secondaryTokenAttribute": "sante.endurance"
|
||||
}
|
||||
}
|
@ -31,13 +31,27 @@
|
||||
},
|
||||
"vehicule": {
|
||||
"categorie": "",
|
||||
"resistance": 0,
|
||||
"structure": 0,
|
||||
"vitesse": "",
|
||||
"bonus": "",
|
||||
"manoeuvrabilite": "",
|
||||
"equipage": 0,
|
||||
"capacite_encombrement": 0
|
||||
"capacite_encombrement": 0,
|
||||
"etat": {
|
||||
"resistance" : {
|
||||
"type": "number",
|
||||
"max": 20,
|
||||
"value": 20,
|
||||
"label": "Résistance",
|
||||
"derivee": false
|
||||
},
|
||||
"structure":{
|
||||
"type": "number",
|
||||
"max": 10,
|
||||
"value": 10,
|
||||
"label": "Structure",
|
||||
"derivee": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"entite": {
|
||||
"definition": {
|
||||
@ -224,7 +238,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"personnage": {
|
||||
"carac": {
|
||||
"taille": {
|
||||
"type": "number",
|
||||
@ -560,7 +574,7 @@
|
||||
}
|
||||
},
|
||||
"personnage": {
|
||||
"templates": [ "background", "common", "subacteurs" ]
|
||||
"templates": [ "personnage", "background", "subacteurs" ]
|
||||
},
|
||||
"creature": {
|
||||
"templates": [ "creature", "description" ]
|
||||
@ -576,7 +590,7 @@
|
||||
"types": ["objet", "arme", "armure", "conteneur", "competence", "sort", "herbe", "ingredient", "livre", "potion", "munition", "rencontresTMR", "queue", "ombre", "souffle",
|
||||
"tete", "competencecreature", "tarot", "monnaie", "nombreastral", "tache", "meditation", "casetmr", "recettealchimique",
|
||||
"musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre", "nourritureboisson", "signedraconique", "gemme",
|
||||
"possession" ],
|
||||
"possession", "sortreserve" ],
|
||||
"possession": {
|
||||
"typepossession": "",
|
||||
"possede": false,
|
||||
@ -679,9 +693,10 @@
|
||||
"categorie_parade": "",
|
||||
"niveau": 0,
|
||||
"default_diffLibre": 0,
|
||||
"categorie": "",
|
||||
"carac_value": 0,
|
||||
"iscombat": false,
|
||||
"isparade": false,
|
||||
"isnaturelle": true,
|
||||
"ispossession": false,
|
||||
"dommages": 0,
|
||||
"description": "Compétence : ...",
|
||||
@ -889,7 +904,7 @@
|
||||
"descriptionmj": ""
|
||||
},
|
||||
"oeuvre": {
|
||||
"default_carac": "",
|
||||
"default_carac": "",
|
||||
"competence": "",
|
||||
"niveau": 0,
|
||||
"reference": "",
|
||||
@ -943,6 +958,14 @@
|
||||
},
|
||||
"description": "",
|
||||
"descriptionmj": ""
|
||||
},
|
||||
"sortreserve": {
|
||||
"sortid" : "",
|
||||
"draconic": "",
|
||||
"coord": "",
|
||||
"ptreve": 0,
|
||||
"heurecible": "",
|
||||
"echectotal": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
<tr class="table-row alterne-row item" data-blessure-type="{{gravite}}" data-attribute={{key}} data-blessure-index="{{key}}" >
|
||||
<td class="item-control blessure-control" title="Blessure {{title}}" data-blessure-active="{{bless.active}}">
|
||||
{{#if bless.active}}
|
||||
<i class="fas fa-skull-crossbones blessure-active-{{gravite}}" name="blessure-{{gravite}}-{{key}}-active"></i>
|
||||
{{else}}
|
||||
<i class="fas fa-skull-crossbones blessure-inactive" name="blessure-{{gravite}}-{{key}}-active"></i>
|
||||
{{/if}}
|
||||
</td>
|
||||
<td>
|
||||
<input class="blessures-soins blessure-localisation" type="text" name="blessure-{{gravite}}-{{key}}-localisation" data-dtype="String" value="{{bless.loc}}"/>
|
||||
</td>
|
||||
<td>
|
||||
<input class="blessures-soins blessure-premiers_soins" type="text" name="blessure-{{gravite}}-{{key}}-premiers_soins" data-dtype="number" value="{{bless.premiers_soins}}"/>
|
||||
</td>
|
||||
<td>
|
||||
<input class="blessures-soins blessure-psdone" name="blessure-{{gravite}}-{{key}}-psdone" type="checkbox" name="bless.psdone" {{#if bless.psdone}}checked{{/if}}/>
|
||||
</td>
|
||||
<td>
|
||||
<input class="blessures-soins blessure-soins_complets" type="text" name="blessure-{{gravite}}-{{key}}-soins_complets" data-dtype="number" value="{{bless.soins_complets}}"/>
|
||||
</td>
|
||||
<td>
|
||||
<input class="blessures-soins blessure-scdone" name="blessure-{{gravite}}-{{key}}-scdone" type="checkbox" name="bless.scdone" {{#if bless.scdone}}checked{{/if}}/>
|
||||
</td>
|
||||
<td>
|
||||
<input class="blessures-soins blessure-jours" type="text" name="blessure-{{gravite}}-{{key}}-jours" name="jours" data-dtype="number" value="{{bless.jours}}"/>
|
||||
</td>
|
||||
</tr>
|
@ -2,33 +2,33 @@
|
||||
|
||||
{{!-- Sheet Header --}}
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{img}}" data-edit="img" title="{{name}}" />
|
||||
<div class="header-fields">
|
||||
<div class="flexrow">
|
||||
<h1 class="charname"><input name="name" type="text" value="{{name}}" placeholder="Name" /></h1>
|
||||
</div>
|
||||
<div class="flexrow flex-group-center flex-actions-bar">
|
||||
<div>
|
||||
<img class="profile-img" src="{{img}}" data-edit="img" title="{{name}}" />
|
||||
<h1 class="charname flex-grow"><input name="name" type="text" value="{{name}}" placeholder="Name" /></h1>
|
||||
<div class="flex-group-center">
|
||||
<span class="encaisser-direct"><a title="Encaisser des dommages"><img class="button-img" src="icons/svg/bones.svg" alt="Encaisser des dommages"/></a></span>
|
||||
<span class="gm-only remise-a-neuf"><a title="Remise à neuf"><img class="button-img" src="icons/svg/regen.svg" alt="Remise à neuf"/></a></span>
|
||||
{{#if @root.options.isGM}}
|
||||
<span class="remise-a-neuf"><a title="Remise à neuf"><img class="button-img" src="icons/svg/regen.svg" alt="Remise à neuf"/></a></span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flexrow">
|
||||
<div class="flexrow">
|
||||
<span>{{calc.resumeBlessures}}</span>
|
||||
<div class="flex-group-left flexrow">
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.html"}}
|
||||
<div class="flex-group-center">
|
||||
<span>
|
||||
{{calc.resumeBlessures}}
|
||||
‐ Etat Général : {{system.compteurs.etat.value}}
|
||||
</span>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html"}}
|
||||
</div>
|
||||
<div class="flexrow">
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor-sheet-effects-partial.html"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{{!-- Sheet Tab Navigation --}}
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item" data-tab="carac">Caractéristiques</a>
|
||||
<a class="item" data-tab="competences">Compétences</a>
|
||||
<a class="item" data-tab="blessures">Blessures</a>
|
||||
<a class="item" data-tab="items">Équipement</a>
|
||||
<a class="item" data-tab="description">Description</a>
|
||||
</nav>
|
||||
@ -36,126 +36,27 @@
|
||||
{{!-- Sheet Body --}}
|
||||
<section class="sheet-body">
|
||||
|
||||
{{!-- Carac Tab --}}
|
||||
{{!-- Carac & compétences --}}
|
||||
<div class="tab items" data-group="primary" data-tab="carac">
|
||||
<div class="flexrow">
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html"}}
|
||||
</div>
|
||||
<div class="grid grid-2col">
|
||||
<div class="flex-group-left flexcol">
|
||||
<ol class="carac-list alterne-list">
|
||||
{{#each data.carac as |carac key|}}
|
||||
<li class="flexrow list-item" data-attribute="{{key}}">
|
||||
{{#if (eq key 'taille')}}
|
||||
<span class="carac-label flexrow" name="data.carac.{{key}}.label">{{carac.label}}</span>
|
||||
{{else}}
|
||||
<span class="carac-label flexrow" name="data.carac.{{key}}.label"><a
|
||||
name={{key}}>{{carac.label}}</a></span>
|
||||
{{/if}}
|
||||
<input class="competence-value flexrow" type="text" name="data.carac.{{key}}.value"
|
||||
value="{{carac.value}}" data-dtype="{{carac.type}}" />
|
||||
</li>
|
||||
{{/each}}
|
||||
<li class="flexrow">
|
||||
<span class="carac-label" name="carac-total">Total Caractéristiques</span>
|
||||
{{log 'data-actor-creature' this}}
|
||||
<span class="competence-value" name="carac-total-value">{{calc.caracTotal}}</span>
|
||||
</li>
|
||||
</ol>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.html"}}
|
||||
</div>
|
||||
<div class="flex-group-left flexcol">
|
||||
<ol class="carac-list alterne-list">
|
||||
{{#each data.attributs as |attr key|}}
|
||||
<li class="flexrow list-item" data-attribute="{{key}}">
|
||||
<span class="carac-label" name="data.attributs.{{key}}.label">{{attr.label}}</span>
|
||||
<input type="text" name="data.attributs.{{key}}.value" value="{{attr.value}}" data-dtype="{{attr.type}}" />
|
||||
</li>
|
||||
{{/each}}
|
||||
<li class="flexrow list-item" data-attribute="vie">
|
||||
<span class="competence-label" name="data.sante.vie.label">Vie</span>
|
||||
<span class="flexrow" >
|
||||
<input type="text" name="data.sante.vie.value" value="{{data.sante.vie.value}}" data-dtype="Number" /> /
|
||||
<input type="text" name="data.sante.vie.max" value="{{data.sante.vie.max}}" data-dtype="Number" />
|
||||
</span>
|
||||
</li>
|
||||
<li class="flexrow list-item" data-attribute="endurance">
|
||||
<span class="competence-label" name="data.sante.endurance.label">Endurance</span>
|
||||
<span class="flexrow" >
|
||||
<input type="text" name="data.sante.endurance.value" value="{{data.sante.endurance.value}}" data-dtype="Number" /> /
|
||||
<input type="text" name="data.sante.endurance.max" value="{{data.sante.endurance.max}}" data-dtype="Number" />
|
||||
</span>
|
||||
</li>
|
||||
<li class="flexrow list-item" data-attribute="etat">
|
||||
<span class="competence-label" name="data.compteurs.etat.label">Etat Général</span>
|
||||
<input type="text" value="{{data.compteurs.etat.value}}" disabled />
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{!-- Compétences Tab --}}
|
||||
<div class="tab competences" data-group="primary" data-tab="competences">
|
||||
<div class="flexcol">
|
||||
<div class="flex-group-left flexcol competence-column">
|
||||
<ol class="item-list alterne-list">
|
||||
{{#each competences as |comp key|}}
|
||||
<li class="item flexrow list-item" data-item-id="{{comp._id}}">
|
||||
<a class="competence-label" name="{{comp.name}}">
|
||||
<img class="sheet-competence-img" src="{{comp.img}}"/>
|
||||
<span class="competence-label">{{comp.name}}</span>
|
||||
</a>
|
||||
<input class="competence-value creature-carac" type="text" compname="{{comp.name}}"
|
||||
value="{{comp.data.carac_value}}" data-dtype="number" />
|
||||
<input class="competence-value creature-niveau" type="text" compname="{{comp.name}}"
|
||||
value="{{numberFormat comp.data.niveau decimals=0 sign=true}}" data-dtype="number" />
|
||||
<input class="competence-value creature-dommages" type="text" compname="{{comp.name}}"
|
||||
value="{{numberFormat comp.data.dommages decimals=0 sign=true}}" data-dtype="number" />
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.html"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{!-- blessures Tab --}}
|
||||
<div class="tab blessures" data-group="primary" data-tab="blessures" style="height:200px">
|
||||
{{!-- Liste de blessures --}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-liste-blessures-partial.html" this}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/blessures.html"}}
|
||||
</div>
|
||||
|
||||
{{!-- Equipment Tab --}}
|
||||
<div class="tab items" data-group="primary" data-tab="items">
|
||||
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-monnaie.html" monnaie=monnaie}}
|
||||
|
||||
<span class="item-name"><h4>Equipement porté</h4></span>
|
||||
<span class="item-name">Encombrement total/max : {{numberFormat calc.encTotal decimals=2}} / {{data.attributs.encombrement.value}} <b>{{calc.surEncombrementMessage}}</b></span> -
|
||||
<span class="item-name"><a class="creer-un-objet">Créer un objet</a></span>
|
||||
{{#if options.isGM}}
|
||||
<span class="item-name"> - <a id="nettoyer-conteneurs">Vider tout les conteneurs</a></span>
|
||||
{{/if}}
|
||||
|
||||
<ul class="item-list alterne-list">
|
||||
<li class="competence-header flexrow">
|
||||
<img class="sheet-competence-img" src="{{img}}" title="Equipement"/>
|
||||
<span class="competence-title flex-grow">Nom</span>
|
||||
<span class="competence-title">Q.</span>
|
||||
<span class="competence-title">Enc.</span>
|
||||
<span class="competence-title flex-grow">Equiper/Editer/Suppr.</span>
|
||||
</li>
|
||||
{{#each objets as |item id|}}
|
||||
{{#unless item.estContenu}}
|
||||
{{#if (ne item.type 'conteneur')}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-conteneur.html" item=item }}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
{{#each conteneurs as |conteneur id|}}
|
||||
{{buildConteneur this}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/inventaire.html"}}
|
||||
</div>
|
||||
|
||||
{{!-- Biography Tab --}}
|
||||
@ -163,15 +64,15 @@
|
||||
|
||||
<div class="form-group">
|
||||
<span class="item-name"><h4>Race</h4></span>
|
||||
<input type="text" name="data.race" value="{{data.race}}" data-dtype="String" />
|
||||
<input type="text" name="system.race" value="{{system.race}}" data-dtype="String" />
|
||||
</div>
|
||||
|
||||
<div class="form-group editor">
|
||||
<div class="form-group editor">
|
||||
<span class="item-name"><h4>Description</h4>
|
||||
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
|
||||
{{editor description target="system.description" button=true owner=owner editable=true}}
|
||||
</div>
|
||||
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor-sheet-editor-notes-mj.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/editor-notes-mj.html"}}
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -2,142 +2,48 @@
|
||||
|
||||
{{!-- Sheet Header --}}
|
||||
<header class="sheet-header">
|
||||
<img class="profile-img" src="{{img}}" data-edit="img" title="{{name}}" />
|
||||
<div class="header-fields">
|
||||
<div class="flexrow">
|
||||
<img class="profile-img" src="{{img}}" data-edit="img" title="{{name}}" />
|
||||
<h1 class="charname"><input name="name" type="text" value="{{name}}" placeholder="Name" /></h1>
|
||||
</div>
|
||||
<div class="flexrow flex-group-center flex-actions-bar">
|
||||
<div>
|
||||
<div class="flex-group-center">
|
||||
<span class="encaisser-direct"><a title="Encaisser des dommages"><img class="button-img" src="icons/svg/bones.svg" alt="Encaisser des dommages"/></a></span>
|
||||
<span class="gm-only remise-a-neuf"><a title="Remise à neuf"><img class="button-img" src="icons/svg/regen.svg" alt="Remise à neuf"/></a></span>
|
||||
{{#if @root.options.isGM}}
|
||||
<span class="remise-a-neuf"><a title="Remise à neuf"><img class="button-img" src="icons/svg/regen.svg" alt="Remise à neuf"/></a></span>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-group-left flexrow">
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html"}}
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
{{!-- Sheet Tab Navigation --}}
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item" data-tab="carac">Caractéristiques</a>
|
||||
<a class="item" data-tab="competences">Compétences</a>
|
||||
<a class="item" data-tab="description">Description</a>
|
||||
</nav>
|
||||
|
||||
{{!-- Sheet Body --}}
|
||||
<section class="sheet-body">
|
||||
|
||||
{{!-- Carac Tab --}}
|
||||
<div class="tab items" data-group="primary" data-tab="carac">
|
||||
|
||||
<div class="items" data-group="primary" data-tab="carac">
|
||||
<div class="flexrow">
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html"}}
|
||||
</div>
|
||||
<div class="grid grid-2col">
|
||||
<div class="flex-group-left flexcol">
|
||||
<ol class="carac-list alterne-list">
|
||||
{{#each data.carac as |carac key|}}
|
||||
<li class="competence flexrow list-item" data-attribute="{{key}}">
|
||||
{{#if (eq key 'taille')}}
|
||||
<span class="carac-label flexrow" name="data.carac.{{key}}.label">{{carac.label}}</span>
|
||||
{{else}}
|
||||
<span class="carac-label flexrow" name="data.carac.{{key}}.label"><a
|
||||
name={{key}}>{{carac.label}}</a></span>
|
||||
{{/if}}
|
||||
<input class="competence-value flexrow" type="text" name="data.carac.{{key}}.value"
|
||||
value="{{carac.value}}" data-dtype="{{carac.type}}" />
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.html"}}
|
||||
</div>
|
||||
|
||||
<div class="flex-group-left flexcol">
|
||||
|
||||
<ol class="carac-list alterne-list">
|
||||
<li class="competence flexrow list-item">
|
||||
<span class="carac-label flexrow" name="catEntite">Catégorie : </span>
|
||||
<select name="data.definition.categorieentite" value="{{data.definition.categorieentite}}" data-dtype="String">
|
||||
{{#select data.definition.categorieentite}}
|
||||
<option value="cauchemar">Cauchemar</option>
|
||||
<option value="reve">Rêve</option>
|
||||
{{/select}}
|
||||
</select>
|
||||
</li>
|
||||
<li class="competence flexrow list-item">
|
||||
<span class="carac-label flexrow" name="typeEntite">Type d'entité : </span>
|
||||
<select name="data.definition.typeentite" value="{{data.definition.typeentite}}" data-dtype="String">
|
||||
{{#select data.definition.typeentite}}
|
||||
<option value="incarne">Incarnée</option>
|
||||
<option value="nonincarne">Non Incarnée</option>
|
||||
{{/select}}
|
||||
</select>
|
||||
</li>
|
||||
{{#each data.attributs as |attr key|}}
|
||||
<li class="competence flexrow list-item" data-attribute="{{key}}">
|
||||
<span class="carac-label flexrow" name="data.attributs.{{key}}.label">{{attr.label}} : </span>
|
||||
<span><input class="attribut-value flexrow" type="text" name="data.attributs.{{key}}.value"
|
||||
value="{{attr.value}}" data-dtype="{{attr.type}}" /></span>
|
||||
</li>
|
||||
{{/each}}
|
||||
<li class="competence flexrow list-item" data-attribute="endurance">
|
||||
<span class="competence-label flexrow" name="data.sante.endurance.label">Endurance : </span>
|
||||
<span><input class="sante-value flexrow" type="text" name="data.sante.endurance.value"
|
||||
value="{{data.sante.endurance.value}}" data-dtype="Number" /></span><span>/ </span>
|
||||
<span><input class="sante-value flexrow" type="text" name="data.sante.endurance.max"
|
||||
value="{{data.sante.endurance.max}}" data-dtype="Number" /></span>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{!-- Compétences Tab --}}
|
||||
<div class="tab competences" data-group="primary" data-tab="competences">
|
||||
|
||||
<div class="flexcol">
|
||||
|
||||
<div class="flex-group-left flexcol competence-column">
|
||||
<ol class="item-list alterne-list">
|
||||
{{#each competences as |comp key|}}
|
||||
<li class="item flexrow list-item" data-item-id="{{comp._id}}">
|
||||
<img class="sheet-competence-img" src="{{comp.img}}" />
|
||||
<span class="competence-label"><a>{{comp.name}}</a></span>
|
||||
<input class="competence-value creature-carac" type="text" compname="{{comp.name}}"
|
||||
value="{{comp.data.carac_value}}" data-dtype="number" />
|
||||
<input class="competence-value creature-niveau" type="text" compname="{{comp.name}}"
|
||||
value="{{numberFormat comp.data.niveau decimals=0 sign=true}}" data-dtype="number" />
|
||||
<input class="competence-value creature-dommages" type="text" compname="{{comp.name}}"
|
||||
value="{{numberFormat comp.data.dommages decimals=0 sign=true}}" data-dtype="number" />
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
|
||||
<div class="flex-group-left flexcol">
|
||||
<div class="flex-group-left flexcol competence-column">
|
||||
<ol class="item-list alterne-list">
|
||||
{{#each possessions as |possession key|}}
|
||||
<li class="item flexrow list-item" data-item-id="{{possession._id}}">
|
||||
<img class="sheet-competence-img" src="{{possession.img}}" />
|
||||
<span class="competence-label">{{possession.name}}</span>
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.html"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{!-- Biography Tab --}}
|
||||
<div class="tab description" data-group="primary" data-tab="description">
|
||||
<div class="form-group editor">
|
||||
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
|
||||
{{editor description target="system.description" button=true owner=owner editable=true}}
|
||||
</div>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor-sheet-editor-notes-mj.html"}}
|
||||
</div>
|
||||
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/editor-notes-mj.html"}}
|
||||
|
||||
</div>
|
||||
|
||||
</section>
|
||||
|
@ -1,28 +0,0 @@
|
||||
<h3>Blessures:</h3>
|
||||
<table class="table-container" role="table">
|
||||
<thead>
|
||||
<tr class="competence-header competence-title competence-label" >
|
||||
<th></th>
|
||||
<th>Loc.</th>
|
||||
<th>Premiers soins</th>
|
||||
<th>P.S. OK?</th>
|
||||
<th>Soins complets</th>
|
||||
<th>S.C. OK?</th>
|
||||
<th>Age (jours)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="table-row alterne-row" ><td/><td colspan="4">Légères</td></tr>
|
||||
{{#each data.blessures.legeres.liste as |bless key|}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html" bless=bless key=key gravite="legere" title="Légère"}}
|
||||
{{/each}}
|
||||
<tr class="table-row alterne-row"><td/><td colspan="4">Graves</td></tr>
|
||||
{{#each data.blessures.graves.liste as |bless key|}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html" bless=bless key=key gravite="grave" title="Grave"}}
|
||||
{{/each}}
|
||||
<tr class="table-row alterne-row"><td/><td colspan="4">Critiques</td></tr>
|
||||
{{#each data.blessures.critiques.liste as |bless key|}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html" bless=bless key=key gravite="critique" title="Critique"}}
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
@ -1,27 +0,0 @@
|
||||
<header class="competence-header flexrow">
|
||||
<span class="competence-title">{{categorie}}</span>
|
||||
</header>
|
||||
<ul class="item-list alterne-list competence-list">
|
||||
{{#if @root.options.vueDetaillee}}
|
||||
<li class="item flexrow list-item ">
|
||||
|
||||
<span class="competence-label"></span>
|
||||
<span class="competence-value" >Niv.</span>
|
||||
<span class="competence-xp">xp</span>
|
||||
{{#if (eq categorie 'Draconic')}}
|
||||
<span class="competence-xp-sort">sort</span>
|
||||
{{/if}}
|
||||
<div class="item-controls">
|
||||
<i class="far fa-arrow-alt-circle-up"></i>
|
||||
<span class="competence-archetype">Arch</span>
|
||||
<i class="far fa-edit"></i>
|
||||
{{#if @root.options.isGM}}
|
||||
<i class="far fa-trash"></i>
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{#each competences as |comp key|}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-competence-partial.html" comp}}
|
||||
{{/each}}
|
||||
</ul>
|
@ -1,51 +0,0 @@
|
||||
{{#if visible}}
|
||||
<li class="item flexrow list-item {{#if data.isLevelUp}}xp-level-up tooltip{{/if}}" data-item-id="{{_id}}">
|
||||
<a class="competence-label" name="{{name}}">
|
||||
<img class="sheet-competence-img" src="{{img}}"/>
|
||||
<span class="competence-label">{{name}}</span>
|
||||
</a>
|
||||
|
||||
{{#if data.isLevelUp}}
|
||||
<span class="tooltiptext ttt-xp">Vous pouvez dépenser {{data.xpNext}} points d'Experience pour augmenter de 1 votre compétence {{name}}</span>
|
||||
<a class="item-control competence-xp-augmenter" compname="{{name}}" title="Augmenter">
|
||||
<i class="fas fa-arrow-alt-circle-up"></i>
|
||||
</a>
|
||||
{{/if}}
|
||||
|
||||
<input class="competence-value" type="text" compname="{{name}}" name="comp-value-{{name}}"
|
||||
value="{{numberFormat data.niveau decimals=0 sign=true}}" data-dtype="number"
|
||||
{{#unless @root.options.editCaracComp}}disabled{{/unless}} />
|
||||
|
||||
<span class="competence-xp tooltip">
|
||||
<input class="competence-xp " type="text" compname="{{name}}" name="comp-xp-{{name}}"
|
||||
value="{{numberFormat data.xp decimals=0 sign=false}}" data-dtype="number"
|
||||
{{#unless @root.options.editCaracComp}}disabled{{/unless}} />
|
||||
<span class="tooltiptext left-competence ttt-xp">Vous devez acquérir {{data.xpNext}} points d'Experience pour augmenter de 1 votre compétence {{name}}</span>
|
||||
</span>
|
||||
|
||||
{{#if (eq data.categorie 'draconic')}}
|
||||
<input class="competence-xp-sort" type="text" compname="{{name}}" name="comp-xp-sort-{{name}}"
|
||||
value="{{numberFormat data.xp_sort decimals=0 sign=false}}" data-dtype="number"
|
||||
{{#unless @root.options.editCaracComp}}disabled{{/unless}}/>
|
||||
{{/if}}
|
||||
{{#if @root.options.vueDetaillee}}
|
||||
<div class="item-controls">
|
||||
{{#if data.stressXpMax}}
|
||||
<a class="item-control competence-stress-augmenter" compname="{{name}}"
|
||||
title="Dépenser {{data.stressXpMax}} points de stress {{#if data.isStressLevelUp}} pour augmenter d'un niveau {{/if}}">
|
||||
<i class="fas fa-arrow-alt-circle-up allouer-stress{{#if data.isStressLevelUp}}-level-up{{/if}}"></i>
|
||||
</a>
|
||||
{{else}}
|
||||
<i class="far fa-circle"></i>
|
||||
{{/if}}
|
||||
<input class="competence-archetype niveau-archetype" type="text" compname="{{name}}" name="comp-archetype-{{name}}"
|
||||
value="{{numberFormat data.niveau_archetype decimals=0 sign=true}}" data-dtype="number"
|
||||
{{#unless @root.options.editCaracComp}}disabled{{/unless}} />
|
||||
<a class="item-control item-edit" title="Modifier"><i class="fas fa-edit"></i></a>
|
||||
{{#if @root.options.isGM}}
|
||||
<a class="item-control item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/if}}
|
@ -1,6 +0,0 @@
|
||||
{{#if options.isGM}}
|
||||
<h3>Notes du MJ : </h3>
|
||||
<div class="form-group editor">
|
||||
{{editor content=data.notesmj target="data.notesmj" button=true owner=owner editable=editable}}
|
||||
</div>
|
||||
{{/if}}
|
@ -1,13 +0,0 @@
|
||||
{{#if calc.surprise}}{{calc.surprise}}! {{/if}}
|
||||
{{#if effects}}
|
||||
{{#each effects as |effect key|}}
|
||||
<span class="active-effect" data-id="{{effect._id}}">
|
||||
<img class="button-effect-img delete-active-effect" src="{{effect.icon}}" alt="{{localize effect.label}}" width="24" height="24" />
|
||||
</span>
|
||||
{{/each}}
|
||||
{{#if options.isGM}}
|
||||
<span class="enlever-tous-effets"><a>(enlever tout)</a></span>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
Aucun effet actif
|
||||
{{/if}}
|
@ -1,32 +0,0 @@
|
||||
<li class="item flexrow list-item" data-item-id="{{item._id}}" draggable="true">
|
||||
<img class="sheet-competence-img" src="{{item.img}}" title="{{item.name}}"/>
|
||||
|
||||
{{#if (eq item.type 'conteneur')}}
|
||||
<span class="item-name conteneur-name flex-grow"><a data-item-id="{{item._id}}">+{{item.name}}</a></span>
|
||||
{{else}}
|
||||
<span class="item-name flex-grow">{{item.name}}</span>
|
||||
{{/if}}
|
||||
<span class="item-quantite">{{item.data.quantite}}
|
||||
{{#if (gt item.data.quantite 1)}}
|
||||
<a class="item-control item-split" title="Séparer"><i class="fas fa-unlink"></i></a>
|
||||
{{/if}}
|
||||
</span>
|
||||
<span class="item-quantite">{{numberFormat item.data.encTotal decimals=2}}</span>
|
||||
<div class="item-controls flex-grow">
|
||||
{{#unless item.estContenu}}
|
||||
{{#if (ne item.type 'conteneur')}}
|
||||
<a class="item-control item-equip" title="Equiper">{{#if item.data.equipe}}<i class="fas fa-hand-rock"></i>{{else}}<i class="far fa-hand-paper"></i>{{/if}}</a>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
<a class="item-control item-edit" title="Editer"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
|
||||
{{#if (or (eq item.type 'arme') (eq item.type 'conteneur') item.data.quantite)}}
|
||||
|
||||
<a class="item-control item-vendre" title="Vendre ou donner"><i class="fas fa-comments-dollar"></i></a>
|
||||
{{/if}}
|
||||
<a class="item-control item-montrer" title="Montrer"><i class="fas fa-comment"></i></a>
|
||||
{{#if item.data.actionPrincipale}}
|
||||
<a class="item-name item-action">{{item.data.actionPrincipale}}</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</li>
|
@ -1,18 +0,0 @@
|
||||
<span class="item-name"><h4>Argent et Monnaies</h4></span>
|
||||
<ul class="item-list alterne-list">
|
||||
{{#each monnaie as |piece id|}}
|
||||
<li class="item flexrow list-item" data-item-id="{{piece._id}}">
|
||||
<img class="sheet-competence-img" src="{{piece.img}}" title="{{piece.name}}"/>
|
||||
<span class="competence-title competence-label">{{piece.name}}</span>
|
||||
<span class="competence-title competence-label">{{piece.data.quantite}}</span>
|
||||
<span class="competence-title">
|
||||
<a class="monnaie-plus plus-moins">+</a>
|
||||
<a class="monnaie-moins plus-moins">-</a>
|
||||
</span>
|
||||
<div class="item-controls flex-shrink">
|
||||
<a class="item-control item-edit" title="Editer"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
@ -1,11 +0,0 @@
|
||||
<li class="item flexrow list-item" data-item-id="{{oeuvre._id}}">
|
||||
<span>{{upperFirst typeOeuvre}}</span>
|
||||
<span class="competence-title {{classOeuvre}}">
|
||||
<a>{{oeuvre.name}} (niveau {{oeuvre.data.niveau}})</a>
|
||||
</span>
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user