Compare commits
7 Commits
foundryvtt
...
v1.5
Author | SHA1 | Date | |
---|---|---|---|
773b3756a6 | |||
d57cdc2af4 | |||
f2d1879135 | |||
ea7132468d | |||
2391fbc4bc | |||
0d2bb2d9a3 | |||
7198eb621d |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,5 +1,5 @@
|
|||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
.idea
|
.idea
|
||||||
|
todo.txt
|
||||||
todo.md
|
todo.md
|
||||||
/.vscode
|
/.vscode
|
||||||
/ignored/
|
|
||||||
|
1
foundryvtt-reve-de-dragon
Symbolic link
1
foundryvtt-reve-de-dragon
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
foundryvtt-reve-de-dragon
|
@ -15,7 +15,7 @@
|
|||||||
"TypeNombreastral": "Nombre astral",
|
"TypeNombreastral": "Nombre astral",
|
||||||
"TypeTarot": "Carte de tarot",
|
"TypeTarot": "Carte de tarot",
|
||||||
"TypeCasetmr": "TMR spéciale",
|
"TypeCasetmr": "TMR spéciale",
|
||||||
"TypeRencontre": "Rencontre TMR",
|
"TypeRencontrestmr": "Rencontre TMR",
|
||||||
"TypeMunition": "Munition",
|
"TypeMunition": "Munition",
|
||||||
"TypeMonnaie": "Monnaie",
|
"TypeMonnaie": "Monnaie",
|
||||||
"TypeHerbe": "Herbe ou plante",
|
"TypeHerbe": "Herbe ou plante",
|
||||||
@ -41,9 +41,7 @@
|
|||||||
"TypeOmbre": "Ombre de Thanatos",
|
"TypeOmbre": "Ombre de Thanatos",
|
||||||
"TypeSouffle": "Souffle de Dragon",
|
"TypeSouffle": "Souffle de Dragon",
|
||||||
"TypeTete": "Tête de Dragon",
|
"TypeTete": "Tête de Dragon",
|
||||||
"TypePossession": "Possession",
|
"TypePossession": "Possession"
|
||||||
"TypeSortreserve": "Sort en réserve",
|
|
||||||
"TypeExtraitpoetique": "Extrait poetique"
|
|
||||||
},
|
},
|
||||||
"EFFECT": {
|
"EFFECT": {
|
||||||
"StatusStunned": "Sonné",
|
"StatusStunned": "Sonné",
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
* @extends {ActorSheet}
|
* @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";
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
export class RdDActorCreatureSheet extends RdDActorSheet {
|
export class RdDActorCreatureSheet extends RdDActorSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
@ -14,15 +20,38 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
|
|||||||
width: 640,
|
width: 640,
|
||||||
height: 720,
|
height: 720,
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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 */
|
/** @override */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
// Everything below here is only needed if the sheet is editable
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
/**
|
||||||
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
|
* @extends {ActorSheet}
|
||||||
|
*/
|
||||||
|
|
||||||
export class RdDActorEntiteSheet extends RdDActorSheet {
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
export class RdDActorEntiteSheet extends ActorSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
@ -10,18 +18,69 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
|
|||||||
width: 640,
|
width: 640,
|
||||||
height: 720,
|
height: 720,
|
||||||
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac"}],
|
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac"}],
|
||||||
dragDrop: [{dragSelector: ".item-list .item", dropSelector: undefined}]
|
dragDrop: [{dragSelector: ".item-list .item", dropSelector: null}]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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 */
|
/** @override */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
// Everything below here is only needed if the sheet is editable
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
// 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
|
// On competence change
|
||||||
html.find('.creature-carac').change(async event => {
|
html.find('.creature-carac').change(async event => {
|
||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
@ -35,6 +94,53 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
|
|||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
this.actor.updateCreatureCompetence( compName, "dommages", parseInt(event.target.value) );
|
this.actor.updateCreatureCompetence( compName, "dommages", parseInt(event.target.value) );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
|
/**
|
||||||
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
|
* @extends {ActorSheet}
|
||||||
|
*/
|
||||||
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
import { RdDItemArme } from "./item-arme.js";
|
import { RdDItemArme } from "./item-arme.js";
|
||||||
@ -7,16 +12,11 @@ import { Misc } from "./misc.js";
|
|||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
import { RdDCombatManager } from "./rdd-combat.js";
|
||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
import { DialogSplitItem } from "./dialog-split-item.js";
|
import { DialogSplitItem } from "./dialog-split-item.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||||
import { DialogRepos } from "./dialog-repos.js";
|
import { DialogRepos } from "./dialog-repos.js";
|
||||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/**
|
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
|
||||||
* @extends {ActorSheet}
|
|
||||||
*/
|
|
||||||
export class RdDActorSheet extends ActorSheet {
|
export class RdDActorSheet extends ActorSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
@ -25,9 +25,10 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
return mergeObject(super.defaultOptions, {
|
return mergeObject(super.defaultOptions, {
|
||||||
classes: ["rdd", "sheet", "actor"],
|
classes: ["rdd", "sheet", "actor"],
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html",
|
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html",
|
||||||
width: 550,
|
width: 640,
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
||||||
|
editCaracComp: false,
|
||||||
showCompNiveauBase: false,
|
showCompNiveauBase: false,
|
||||||
vueDetaillee: false
|
vueDetaillee: false
|
||||||
});
|
});
|
||||||
@ -35,85 +36,90 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getData() {
|
async getData() {
|
||||||
|
const objectData = Misc.data(this.object);
|
||||||
this.timerRecherche = undefined;
|
this.timerRecherche = undefined;
|
||||||
this.actor.computeEtatGeneral();
|
|
||||||
|
|
||||||
let formData = {
|
let formData = {
|
||||||
title: this.title,
|
title: this.title,
|
||||||
id: this.actor.id,
|
id: objectData.id,
|
||||||
type: this.actor.type,
|
type: objectData.type,
|
||||||
img: this.actor.img,
|
img: objectData.img,
|
||||||
name: this.actor.name,
|
name: objectData.name,
|
||||||
editable: this.isEditable,
|
editable: this.isEditable,
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
cssClass: this.isEditable ? "editable" : "locked",
|
||||||
system: foundry.utils.deepClone(this.actor.system),
|
data: foundry.utils.deepClone(Misc.templateData(this.object)),
|
||||||
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
|
effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)),
|
||||||
limited: this.actor.limited,
|
limited: this.object.limited,
|
||||||
options: this.options,
|
options: this.options,
|
||||||
owner: this.actor.isOwner,
|
owner: this.document.isOwner,
|
||||||
description: await TextEditor.enrichHTML(this.object.system.description, {async: true}),
|
itemsByType: Misc.classify(this.object.items.map(i => foundry.utils.deepClone(i.data))),
|
||||||
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}),
|
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||||
calc: {
|
|
||||||
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
formData.options.isGM = game.user.isGM;
|
||||||
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
|
||||||
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
|
if (formData.type == 'creature') return formData; // Shortcut
|
||||||
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
|
|
||||||
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
|
formData.competenceByCategory = Misc.classify(formData.competences, it => it.data.categorie);
|
||||||
surEncombrementMessage: this.actor.getMessageSurEncombrement(),
|
|
||||||
},
|
formData.calc = {
|
||||||
}
|
comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.competences),
|
||||||
formData.options.isGM = game.user.isGM;
|
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.recherche
|
||||||
|
? RdDItemCompetence.nomContientTexte(item, this.options.recherche.text)
|
||||||
|
: (!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.listActionsArmes(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()
|
||||||
|
}
|
||||||
|
|
||||||
RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
|
||||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||||
|
|
||||||
if (formData.type == 'personnage') {
|
formData.subacteurs = {
|
||||||
formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie)
|
vehicules: this.actor.listeVehicules(),
|
||||||
formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences);
|
montures: this.actor.listeMontures(),
|
||||||
formData.calc.competenceXPTotal= RdDItemCompetence.computeTotalXP(formData.competences);
|
suivants: this.actor.listeSuivants()
|
||||||
formData.calc.fatigue= RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max);
|
}
|
||||||
|
if (this.actor.getBestDraconic().data.niveau > -11 && !this.actor.isHautRevant()) {
|
||||||
formData.competences.forEach(item => {
|
ui.notifications.error(`${this.actor.name} a des compétences draconiques, mais pas le don de Haut-Rêve!
|
||||||
item.system.isVisible = this.options.recherche
|
<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`);
|
||||||
? 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),
|
|
||||||
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;
|
return formData;
|
||||||
}
|
}
|
||||||
@ -124,16 +130,16 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _onDropActor(event, dragData) {
|
async _onDropActor(event, dragData) {
|
||||||
const dropActor = fromUuidSync(dragData.uuid);
|
console.log("_onDropActor", this.actor.id, dragData);
|
||||||
this.actor.addSubActeur(dropActor);
|
this.actor.addSubActeur(dragData.id || dragData.data._id);
|
||||||
super._onDropActor(event, dragData);
|
super._onDropActor(event, dragData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _onDropItem(event, dragData) {
|
async _onDropItem(event, dragData) {
|
||||||
const destItemId = $(event.target)?.closest('.item').attr('data-item-id')
|
const destItemId = $(event.target)?.closest('.item').attr('data-item-id');
|
||||||
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor.id, dragData, this.objetVersConteneur)
|
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor.id, dragData, this.objetVersConteneur);
|
||||||
const callSuper = await this.actor.processDropItem(dropParams)
|
const callSuper = await this.actor.processDropItem(dropParams);
|
||||||
if (callSuper) {
|
if (callSuper) {
|
||||||
await super._onDropItem(event, dragData)
|
await super._onDropItem(event, dragData)
|
||||||
}
|
}
|
||||||
@ -153,6 +159,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
|
||||||
HtmlUtility._showControlWhen($(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
HtmlUtility._showControlWhen($(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
// Everything below here is only needed if the sheet is editable
|
||||||
@ -164,16 +171,19 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
});
|
});
|
||||||
html.find('.item-edit').click(async event => {
|
html.find('.item-edit').click(async event => {
|
||||||
const item = RdDSheetUtility.getItem(event, this.actor)
|
const item = RdDSheetUtility.getItem(event, this.actor)
|
||||||
|
console.log("ITEM :", item)
|
||||||
item.sheet.render(true)
|
item.sheet.render(true)
|
||||||
})
|
})
|
||||||
html.find('.display-label a').click(async event => {
|
html.find('.display-label a').click(async event => {
|
||||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||||
item.sheet.render(true);
|
item.sheet.render(true);
|
||||||
});
|
});
|
||||||
|
html.find('.rencontre-delete').click(async event => {
|
||||||
|
this.actor.deleteTMRRencontre(RdDSheetUtility.getItemId(event));
|
||||||
|
});
|
||||||
html.find('.item-delete').click(async event => {
|
html.find('.item-delete').click(async event => {
|
||||||
const li = RdDSheetUtility.getEventElement(event);
|
const li = RdDSheetUtility.getEventElement(event);
|
||||||
const item = this.actor.getObjet(li.data("item-id"));
|
RdDUtility.confirmerSuppression(this, li);
|
||||||
RdDUtility.confirmerSuppressionItem(this, item, li);
|
|
||||||
});
|
});
|
||||||
html.find('.item-vendre').click(async event => {
|
html.find('.item-vendre').click(async event => {
|
||||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||||
@ -183,28 +193,16 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||||
item?.postItem();
|
item?.postItem();
|
||||||
});
|
});
|
||||||
|
|
||||||
html.find('.item-action').click(async event => {
|
html.find('.item-action').click(async event => {
|
||||||
const item = RdDSheetUtility.getItem(event, this.actor)
|
const item = RdDSheetUtility.getItem(event, this.actor)
|
||||||
this.actor.actionItem(item);
|
this.actor.actionItem(item);
|
||||||
});
|
});
|
||||||
html.find('.subacteur-delete').click(async event => {
|
html.find('.subacteur-delete').click(async event => {
|
||||||
const li = RdDSheetUtility.getEventElement(event);
|
const li = RdDSheetUtility.getEventElement(event);
|
||||||
const actorId = li.data("actor-id");
|
RdDUtility.confirmerSuppressionSubacteur(this, li);
|
||||||
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 => {
|
html.find('.encaisser-direct').click(async event => {
|
||||||
this.actor.encaisser();
|
this.actor.encaisser();
|
||||||
})
|
})
|
||||||
@ -226,7 +224,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
html.find('.creer-une-oeuvre').click(async event => {
|
html.find('.creer-une-oeuvre').click(async event => {
|
||||||
RdDUtility.selectTypeOeuvre(this);
|
RdDUtility.selectTypeOeuvre(this);
|
||||||
});
|
});
|
||||||
html.find('.nettoyer-conteneurs').click(async event => {
|
html.find('#nettoyer-conteneurs').click(async event => {
|
||||||
this.actor.nettoyerConteneurs();
|
this.actor.nettoyerConteneurs();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -241,7 +239,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Blessure data
|
// Blessure data
|
||||||
html.find('.blessure-soins').change(async event => {
|
html.find('.blessures-soins').change(async event => {
|
||||||
const tr = $(event.currentTarget).parents(".item");
|
const tr = $(event.currentTarget).parents(".item");
|
||||||
let btype = tr.data('blessure-type');
|
let btype = tr.data('blessure-type');
|
||||||
let index = tr.data('blessure-index');
|
let index = tr.data('blessure-index');
|
||||||
@ -319,7 +317,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
this.actor.reinsertionAleatoire("Action MJ");
|
this.actor.reinsertionAleatoire("Action MJ");
|
||||||
});
|
});
|
||||||
html.find('.afficher-tmr').click(async event => {
|
html.find('.afficher-tmr').click(async event => {
|
||||||
this.actor.changeTMRVisible();
|
this.actor.afficheTMRetMessage();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Points de reve actuel
|
// Points de reve actuel
|
||||||
@ -334,7 +332,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
});
|
});
|
||||||
// Initiative pour l'arme
|
// Initiative pour l'arme
|
||||||
html.find('.arme-initiative a').click(async event => {
|
html.find('.arme-initiative a').click(async event => {
|
||||||
let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id);
|
let combatant = game.combat.data.combatants.find(c => c.actor.data._id == this.actor.data._id);
|
||||||
if (combatant) {
|
if (combatant) {
|
||||||
let action = this._getEventArmeCombat(event);
|
let action = this._getEventArmeCombat(event);
|
||||||
RdDCombatManager.rollInitiativeAction(combatant._id, action);
|
RdDCombatManager.rollInitiativeAction(combatant._id, action);
|
||||||
@ -361,15 +359,11 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
await DialogRepos.create(this.actor);
|
await DialogRepos.create(this.actor);
|
||||||
});
|
});
|
||||||
html.find('.delete-active-effect').click(async event => {
|
html.find('.delete-active-effect').click(async event => {
|
||||||
if (game.user.isGM) {
|
let id = $(event.currentTarget).parents(".active-effect").data('id');
|
||||||
let effect = $(event.currentTarget).parents(".active-effect").data('effect');
|
this.actor.enleverActiveEffectById(id);
|
||||||
this.actor.removeEffect(effect);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
html.find('.enlever-tous-effets').click(async event => {
|
html.find('.enlever-tous-effets').click(async event => {
|
||||||
if (game.user.isGM) {
|
this.actor.enleverTousLesEffets();
|
||||||
await this.actor.removeEffects();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
html.find('.conteneur-name a').click(async event => {
|
html.find('.conteneur-name a').click(async event => {
|
||||||
RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event));
|
RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event));
|
||||||
@ -386,14 +380,16 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event));
|
this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event));
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.options.vueDetaillee) {
|
if (this.options.editCaracComp) {
|
||||||
// On carac change
|
// On carac change
|
||||||
html.find('.carac-value').change(async event => {
|
html.find('.carac-value').change(async event => {
|
||||||
let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", "");
|
let caracName = event.currentTarget.name.replace(".value", "").replace("data.carac.", "");
|
||||||
|
//console.log("Value changed :", event, caracName);
|
||||||
this.actor.updateCarac(caracName, parseInt(event.target.value));
|
this.actor.updateCarac(caracName, parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
html.find('input.carac-xp').change(async event => {
|
html.find('.carac-xp').change(async event => {
|
||||||
let caracName = event.currentTarget.name.replace(".xp", "").replace("system.carac.", "");
|
let caracName = event.currentTarget.name.replace(".xp", "").replace("data.carac.", "");
|
||||||
|
//console.log("Value changed :", event, caracName);
|
||||||
this.actor.updateCaracXP(caracName, parseInt(event.target.value));
|
this.actor.updateCaracXP(caracName, parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
// On competence change
|
// On competence change
|
||||||
@ -403,12 +399,12 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
this.actor.updateCompetence(compName, parseInt(event.target.value));
|
this.actor.updateCompetence(compName, parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
// On competence xp change
|
// On competence xp change
|
||||||
html.find('input.competence-xp').change(async event => {
|
html.find('.competence-xp').change(async event => {
|
||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
this.actor.updateCompetenceXP(compName, parseInt(event.target.value));
|
this.actor.updateCompetenceXP(compName, parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
// On competence xp change
|
// On competence xp change
|
||||||
html.find('input.competence-xp-sort').change(async event => {
|
html.find('.competence-xp-sort').change(async event => {
|
||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value));
|
this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
@ -423,6 +419,10 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
this.options.showCompNiveauBase = !this.options.showCompNiveauBase;
|
this.options.showCompNiveauBase = !this.options.showCompNiveauBase;
|
||||||
this.render(true);
|
this.render(true);
|
||||||
});
|
});
|
||||||
|
html.find('.lock-unlock-sheet').click(async event => {
|
||||||
|
this.options.editCaracComp = !this.options.editCaracComp;
|
||||||
|
this.render(true);
|
||||||
|
});
|
||||||
|
|
||||||
html.find('.recherche')
|
html.find('.recherche')
|
||||||
.each((index, field) => {
|
.each((index, field) => {
|
||||||
@ -455,7 +455,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
// On pts de reve change
|
// On pts de reve change
|
||||||
html.find('.pointsreve-value').change(async event => {
|
html.find('.pointsreve-value').change(async event => {
|
||||||
let reveValue = event.currentTarget.value;
|
let reveValue = event.currentTarget.value;
|
||||||
this.actor.update({ "system.reve.reve.value": reveValue });
|
this.actor.update({ "data.reve.reve.value": reveValue });
|
||||||
});
|
});
|
||||||
|
|
||||||
// On seuil de reve change
|
// On seuil de reve change
|
||||||
@ -489,7 +489,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
html.find('.moral-heureux').click(async event => {
|
html.find('.moral-heureux').click(async event => {
|
||||||
this.actor.jetDeMoral('heureuse');
|
this.actor.jetDeMoral('heureuse');
|
||||||
});
|
});
|
||||||
html.find('.ethylisme-test').click(async event => {
|
html.find('#ethylisme-test').click(async event => {
|
||||||
this.actor.jetEthylisme();
|
this.actor.jetEthylisme();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -548,9 +548,9 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
const li = $(event.currentTarget)?.parents(".item");
|
const li = $(event.currentTarget)?.parents(".item");
|
||||||
let armeName = li.data("arme-name");
|
let armeName = li.data("arme-name");
|
||||||
let compName = li.data('competence-name');
|
let compName = li.data('competence-name');
|
||||||
const arme = this.armesList.find(a => a.name == armeName && a.system.competence == compName);
|
const arme = this.armesList.find(a => a.name == armeName && a.data.competence == compName);
|
||||||
if (!arme) {
|
if (!arme) {
|
||||||
return { name: armeName, system: { competence: compName } };
|
return { name: armeName, data: { competence: compName } };
|
||||||
}
|
}
|
||||||
return arme;
|
return arme;
|
||||||
}
|
}
|
||||||
@ -562,10 +562,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
const sheetHeader = this.element.find(".sheet-header");
|
const sheetHeader = this.element.find(".sheet-header");
|
||||||
const sheetTabs = this.element.find(".sheet-tabs");
|
const sheetTabs = this.element.find(".sheet-tabs");
|
||||||
const sheetBody = this.element.find(".sheet-body");
|
const sheetBody = this.element.find(".sheet-body");
|
||||||
let bodyHeight = position.height - sheetHeader[0].clientHeight;
|
const bodyHeight = position.height - sheetHeader[0].clientHeight - sheetTabs[0].clientHeight;
|
||||||
if (sheetTabs.length>0) {
|
|
||||||
bodyHeight -= sheetTabs[0].clientHeight;
|
|
||||||
}
|
|
||||||
sheetBody.css("height", bodyHeight);
|
sheetBody.css("height", bodyHeight);
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
@ -575,7 +572,7 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
/** @override */
|
/** @override */
|
||||||
_updateObject(event, formData) {
|
_updateObject(event, formData) {
|
||||||
// Update the Actor
|
// Update the Actor
|
||||||
return this.actor.update(formData);
|
return this.object.update(formData);
|
||||||
}
|
}
|
||||||
|
|
||||||
async splitItem(item) {
|
async splitItem(item) {
|
||||||
@ -584,11 +581,11 @@ export class RdDActorSheet extends ActorSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _onSplitItem(item, split) {
|
async _onSplitItem(item, split) {
|
||||||
if (split >= 1 && split < item.system.quantite) {
|
if (split >= 1 && split < Misc.data(item).data.quantite) {
|
||||||
await item.diminuerQuantite(split);
|
await item.diminuerQuantite(split);
|
||||||
const splitItem = duplicate(item);
|
const itemData = duplicate(Misc.data(item));
|
||||||
splitItem.system.quantite = split;
|
itemData.data.quantite = split;
|
||||||
await this.actor.createEmbeddedDocuments('Item', [splitItem])
|
await this.actor.createEmbeddedDocuments('Item', [itemData])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
|
* @extends {ActorSheet}
|
||||||
|
*/
|
||||||
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
|
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDActorVehiculeSheet extends RdDActorSheet {
|
export class RdDActorVehiculeSheet extends ActorSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
@ -14,26 +21,145 @@ export class RdDActorVehiculeSheet extends RdDActorSheet {
|
|||||||
width: 640,
|
width: 640,
|
||||||
height: 720,
|
height: 720,
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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) {
|
activateListeners(html) {
|
||||||
super.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;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
html.find('.resistance-moins').click(async event => {
|
// Update Inventory Item
|
||||||
this.actor.vehicleIncDec("resistance", -1);
|
html.find('.item-edit').click(async event => {
|
||||||
|
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||||
|
item.sheet.render(true);
|
||||||
});
|
});
|
||||||
html.find('.resistance-plus').click(async event => {
|
// Delete Inventory Item
|
||||||
this.actor.vehicleIncDec("resistance", 1);
|
html.find('.item-delete').click(async event => {
|
||||||
|
const li = RdDSheetUtility.getEventElement(event);
|
||||||
|
RdDUtility.confirmerSuppression(this, li);
|
||||||
});
|
});
|
||||||
html.find('.structure-moins').click(async event => {
|
html.find('.item-vendre').click(async event => {
|
||||||
this.actor.vehicleIncDec("structure", -1);
|
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||||
|
item?.proposerVente();
|
||||||
});
|
});
|
||||||
html.find('.structure-plus').click(async event => {
|
html.find('.item-montrer').click(async event => {
|
||||||
this.actor.vehicleIncDec("structure", 1);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
2004
module/actor.js
2004
module/actor.js
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,7 @@
|
|||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.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
|
* Class providing helper methods to get the list of users, and
|
||||||
@ -18,50 +19,61 @@ export class ChatUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static notifyUser(userId, level = 'info', message) {
|
static notifyUser(userId, level = 'info', message) {
|
||||||
const socketData = {
|
const data = {
|
||||||
userId: userId, level: level, message: message
|
userId: userId, level: level, message: message
|
||||||
};
|
};
|
||||||
if (game.user.id == userId) {
|
if (game.user.id == userId) {
|
||||||
ChatUtility.onNotifyUser(socketData);
|
ChatUtility.onNotifyUser(data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
msg: "msg_user_ui_notifications", data: socketData
|
msg: "msg_user_ui_notifications", data: data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static onNotifyUser(socketData) {
|
static onNotifyUser(data) {
|
||||||
if (game.user.id == socketData.userId) {
|
if (game.user.id == data.userId) {
|
||||||
switch (socketData.level) {
|
switch (data.level) {
|
||||||
case 'warn': ui.notifications.warn(socketData.message); break;
|
case 'warn': ui.notifications.warn(data.message); break;
|
||||||
case 'error': ui.notifications.error(socketData.message); break;
|
case 'error': ui.notifications.error(data.message); break;
|
||||||
default: ui.notifications.info(socketData.message); break;
|
default: ui.notifications.info(data.message); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static onRemoveMessages(socketData) {
|
static onRemoveMessages(data) {
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
if (socketData.part) {
|
if (data.part) {
|
||||||
const toDelete = game.messages.filter(it => it.content.includes(socketData.part));
|
const toDelete = game.messages.filter(it => it.data.content.includes(data.part));
|
||||||
toDelete.forEach(it => it.delete());
|
toDelete.forEach(it => it.delete());
|
||||||
}
|
}
|
||||||
if (socketData.messageId) {
|
if (data.messageId) {
|
||||||
game.messages.get(socketData.messageId)?.delete();
|
game.messages.get(data.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(socketData) {
|
static removeMessages(data) {
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
ChatUtility.onRemoveMessages(socketData);
|
ChatUtility.onRemoveMessages(data);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_delete_chat_message", data: socketData });
|
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_delete_chat_message", data: data });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,7 +141,7 @@ export class ChatUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getUsers(filter) {
|
static getUsers(filter) {
|
||||||
return game.users.filter(filter).map(user => user.id);
|
return Misc.getUsers().filter(filter).map(user => user.data._id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -142,17 +154,17 @@ export class ChatUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static handleGMChatMessage(socketData) {
|
static handleGMChatMessage(data) {
|
||||||
console.log("blindMessageToGM", socketData);
|
console.log("blindMessageToGM", data);
|
||||||
if (game.user.isGM) { // message privé pour GM only
|
if (game.user.isGM) { // message privé pour GM only
|
||||||
socketData.user = game.user.id;
|
data.user = game.user.id;
|
||||||
ChatMessage.create(socketData);
|
ChatMessage.create(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async setMessageData(chatMessage, key, flag) {
|
static async setMessageData(chatMessage, key, data) {
|
||||||
if (flag) {
|
if (data) {
|
||||||
await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(flag));
|
await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
export const SYSTEM_RDD = 'foundryvtt-reve-de-dragon';
|
export const SYSTEM_RDD = 'foundryvtt-reve-de-dragon';
|
||||||
export const SYSTEM_SOCKET_ID = 'system.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 HIDE_DICE = 'hide';
|
||||||
export const SHOW_DICE = 'show';
|
export const SHOW_DICE = 'show';
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
|
||||||
import { Grammar } from "./grammar.js";
|
|
||||||
|
|
||||||
|
|
||||||
const LATEST_USED_JOURNAL_ID = "chronologie-dernier-journal";
|
|
||||||
|
|
||||||
export class DialogChronologie extends Dialog {
|
|
||||||
|
|
||||||
static init() {
|
|
||||||
game.settings.register(SYSTEM_RDD, LATEST_USED_JOURNAL_ID, {
|
|
||||||
name: "Dernier article de journal utilisé pour enregistrer la chronologie",
|
|
||||||
scope: "client",
|
|
||||||
config: false,
|
|
||||||
default: "",
|
|
||||||
type: String
|
|
||||||
});
|
|
||||||
}
|
|
||||||
static async create() {
|
|
||||||
const dateRdD = game.system.rdd.calendrier.getCalendrier();
|
|
||||||
const dialogData = {
|
|
||||||
auteur: game.user.name,
|
|
||||||
isGM: game.user.isGM,
|
|
||||||
information: "",
|
|
||||||
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
|
|
||||||
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
|
|
||||||
dateRdD: dateRdD,
|
|
||||||
jourRdD: dateRdD.jour +1,
|
|
||||||
heureRdD: game.system.rdd.calendrier.getCurrentHeure(),
|
|
||||||
dateReel: DialogChronologie.getCurrentDateTime()
|
|
||||||
};
|
|
||||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.html", dialogData);
|
|
||||||
const dialog = new DialogChronologie(html);
|
|
||||||
dialog.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(html) {
|
|
||||||
const options = {
|
|
||||||
classes: ["DialogChronologie"],
|
|
||||||
width: 500,
|
|
||||||
height: 'fit-content',
|
|
||||||
'z-index': 99999
|
|
||||||
};
|
|
||||||
const conf = {
|
|
||||||
title: "Chronologie",
|
|
||||||
content: html,
|
|
||||||
buttons: {
|
|
||||||
ajout: { label: "Ajouter", callback: it => this.ajouter() },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
super(conf, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getCurrentDateTime() {
|
|
||||||
return new Date().toLocaleString("sv-SE", {
|
|
||||||
year: "numeric",
|
|
||||||
month: "2-digit",
|
|
||||||
day: "2-digit",
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit"
|
|
||||||
}).replace(" ", "T");
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
}
|
|
||||||
|
|
||||||
async ajouter() {
|
|
||||||
await this.forceValidation();
|
|
||||||
const { journalId, journalEntry } = this.findJournal();
|
|
||||||
// ajouter à la page ou créer une page
|
|
||||||
this.addContentToJournal(journalEntry, await this.prepareChronologieEntry());
|
|
||||||
|
|
||||||
this.storeLatestUsedJournalEntry(journalId);
|
|
||||||
}
|
|
||||||
|
|
||||||
async forceValidation() {
|
|
||||||
await $("form.rdddialogchrono :input").change();
|
|
||||||
}
|
|
||||||
|
|
||||||
findJournal() {
|
|
||||||
const journalId = $("form.rdddialogchrono :input[name='journalId']").val();
|
|
||||||
const journalEntry = game.journal.get(journalId);
|
|
||||||
return { journalId, journalEntry };
|
|
||||||
}
|
|
||||||
|
|
||||||
async prepareChronologieEntry() {
|
|
||||||
return await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chronologie-entry.html", this.extractJournalParameters());
|
|
||||||
}
|
|
||||||
|
|
||||||
extractJournalParameters() {
|
|
||||||
return {
|
|
||||||
auteur: $("form.rdddialogchrono :input[name='auteur']").val(),
|
|
||||||
information: $("form.rdddialogchrono :input[name='information']").val(),
|
|
||||||
dateRdD: {
|
|
||||||
jour: $("form.rdddialogchrono :input[name='jourRdD']").val(),
|
|
||||||
moisRdD: $("form.rdddialogchrono :input[name='dateRdD.moisRdD.key']").val(),
|
|
||||||
annee: $("form.rdddialogchrono :input[name='dateRdD.annee']").val()
|
|
||||||
},
|
|
||||||
heureRdD: $("form.rdddialogchrono :input[name='heureRdD']").val(),
|
|
||||||
dateReel: $("form.rdddialogchrono :input[name='dateReel']").val().replace('T', ' ')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addContentToJournal(journalEntry, content) {
|
|
||||||
let page = journalEntry.pages.find(p => p.type == 'text' && Grammar.equalsInsensitive(p.name, 'Chronologie'));
|
|
||||||
if (page) {
|
|
||||||
page.update({ 'text.content': content + '\n' + page.text.content });
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
journalEntry.createEmbeddedDocuments('JournalEntryPage', [this.newPageChronologie(content)]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newPageChronologie(content) {
|
|
||||||
return new JournalEntryPage({
|
|
||||||
name: 'Chronologie',
|
|
||||||
type: 'text',
|
|
||||||
title: { show: true, level: 1 },
|
|
||||||
text: { content: content, format: 1 }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
storeLatestUsedJournalEntry(journalId) {
|
|
||||||
game.settings.set(SYSTEM_RDD, LATEST_USED_JOURNAL_ID, journalId);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
|
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
export class DialogCreateSigneDraconique extends Dialog {
|
export class DialogCreateSigneDraconique extends Dialog {
|
||||||
@ -9,13 +10,12 @@ export class DialogCreateSigneDraconique extends Dialog {
|
|||||||
const signe = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
|
const signe = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
|
||||||
let dialogData = {
|
let dialogData = {
|
||||||
signe: signe,
|
signe: signe,
|
||||||
tmrs: TMRUtility.buildSelectionTypesTMR(signe.system.typesTMR),
|
tmrs: TMRUtility.listSelectedTMR(signe.data.typesTMR ?? []),
|
||||||
actors: game.actors.filter(actor => actor.isPersonnage() && actor.isHautRevant())
|
actors: game.actors.filter(actor => actor.isHautRevant()).map(actor => {
|
||||||
.map(actor => ({
|
let actorData = duplicate(Misc.data(actor));
|
||||||
id: actor.id,
|
actorData.selected = actor.hasPlayerOwner;
|
||||||
name: actor.name,
|
return actorData;
|
||||||
selected: true
|
})
|
||||||
}))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-create-signedraconique.html", dialogData);
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-create-signedraconique.html", dialogData);
|
||||||
@ -23,11 +23,12 @@ export class DialogCreateSigneDraconique extends Dialog {
|
|||||||
.render(true);
|
.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(dialogData, html) {
|
constructor(dialogData, html, callback) {
|
||||||
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 500, height: 650, 'z-index': 99999 };
|
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 500, height: 650, 'z-index': 99999 };
|
||||||
let conf = {
|
let conf = {
|
||||||
title: "Créer un signe",
|
title: "Créer un signe",
|
||||||
content: html,
|
content: html,
|
||||||
|
default: "Ajouter aux haut-rêvants",
|
||||||
buttons: {
|
buttons: {
|
||||||
"Ajouter aux haut-rêvants": { label: "Ajouter aux haut-rêvants", callback: it => { this._onCreerSigneActeurs(); } }
|
"Ajouter aux haut-rêvants": { label: "Ajouter aux haut-rêvants", callback: it => { this._onCreerSigneActeurs(); } }
|
||||||
}
|
}
|
||||||
@ -37,91 +38,81 @@ export class DialogCreateSigneDraconique extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _onCreerSigneActeurs() {
|
async _onCreerSigneActeurs() {
|
||||||
await $("[name='signe.system.ephemere']").change();
|
await $("[name='signe.data.ephemere']").change();
|
||||||
await $(".signe-xp-sort").change();
|
await $(".signe-xp-sort").change();
|
||||||
this.validerSigne();
|
this.validerSigne();
|
||||||
this.dialogData.actors.filter(it => it.selected)
|
this.dialogData.actors.filter(it => it.selected).map(it => game.actors.get(it._id))
|
||||||
.map(it => game.actors.get(it.id))
|
|
||||||
.forEach(actor => this._createSigneForActor(actor, this.dialogData.signe));
|
.forEach(actor => this._createSigneForActor(actor, this.dialogData.signe));
|
||||||
}
|
}
|
||||||
|
|
||||||
async _createSigneForActor(actor, signe) {
|
async _createSigneForActor(actor, signe) {
|
||||||
actor.createEmbeddedDocuments("Item", [signe]);
|
actor.createEmbeddedDocuments("Item", [signe]);
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(actor.name),
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(Misc.data(actor).name),
|
||||||
content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html", {
|
content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html", {
|
||||||
signe: signe,
|
signe: signe,
|
||||||
alias: actor.name
|
alias: Misc.data(actor).name
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
validerSigne() {
|
validerSigne() {
|
||||||
this.dialogData.signe.name = $("[name='signe.name']").val();
|
this.dialogData.signe.name = $("[name='signe.name']").val();
|
||||||
this.dialogData.signe.system.valeur.norm = $("[name='signe.system.valeur.norm']").val();
|
this.dialogData.signe.data.valeur.norm = $("[name='signe.data.valeur.norm']").val();
|
||||||
this.dialogData.signe.system.valeur.sign = $("[name='signe.system.valeur.sign']").val();
|
this.dialogData.signe.data.valeur.sign = $("[name='signe.data.valeur.sign']").val();
|
||||||
this.dialogData.signe.system.valeur.part = $("[name='signe.system.valeur.part']").val();
|
this.dialogData.signe.data.valeur.part = $("[name='signe.data.valeur.part']").val();
|
||||||
this.dialogData.signe.system.difficulte = $("[name='signe.system.difficulte']").val();
|
this.dialogData.signe.data.difficulte = $("[name='signe.data.difficulte']").val();
|
||||||
this.dialogData.signe.system.ephemere = $("[name='signe.system.ephemere']").prop("checked");
|
this.dialogData.signe.data.ephemere = $("[name='signe.data.ephemere']").prop("checked");
|
||||||
this.dialogData.signe.system.duree = $("[name='signe.system.duree']").val();
|
this.dialogData.signe.data.duree = $("[name='signe.data.duree']").val();
|
||||||
this.dialogData.signe.system.typesTMR = TMRUtility.buildListTypesTMRSelection(this.dialogData.tmrs);
|
this.dialogData.signe.data.typesTMR = $(".select-tmr").val();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
this.setEphemere(this.dialogData.signe.system.ephemere);
|
this.setEphemere(this.dialogData.signe.data.ephemere);
|
||||||
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
|
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
|
||||||
html.find("[name='signe.system.ephemere']").change((event) => this.setEphemere(event.currentTarget.checked));
|
html.find("[name='signe.data.ephemere']").change((event) => this.setEphemere(event.currentTarget.checked));
|
||||||
|
html.find(".select-actor").change((event) => this.onSelectActor(event));
|
||||||
html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event));
|
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() {
|
async setSigneAleatoire() {
|
||||||
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
|
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
|
||||||
|
|
||||||
$("[name='signe.name']").val(newSigne.name);
|
$("[name='signe.name']").val(newSigne.name);
|
||||||
$("[name='signe.system.valeur.norm']").val(newSigne.system.valeur.norm);
|
$("[name='signe.data.valeur.norm']").val(newSigne.data.valeur.norm);
|
||||||
$("[name='signe.system.valeur.sign']").val(newSigne.system.valeur.sign);
|
$("[name='signe.data.valeur.sign']").val(newSigne.data.valeur.sign);
|
||||||
$("[name='signe.system.valeur.part']").val(newSigne.system.valeur.part);
|
$("[name='signe.data.valeur.part']").val(newSigne.data.valeur.part);
|
||||||
$("[name='signe.system.difficulte']").val(newSigne.system.difficulte);
|
$("[name='signe.data.difficulte']").val(newSigne.data.difficulte);
|
||||||
$("[name='signe.system.duree']").val(newSigne.system.duree);
|
$("[name='signe.data.duree']").val(newSigne.data.duree);
|
||||||
$("[name='signe.system.ephemere']").prop("checked", newSigne.system.ephemere);
|
$("[name='signe.data.ephemere']").prop("checked", newSigne.data.ephemere);
|
||||||
this.dialogData.tmrs = TMRUtility.buildSelectionTypesTMR(newSigne.system.typesTMR);
|
$(".select-tmr").val(newSigne.data.typesTMR);
|
||||||
this.dialogData.tmrs.forEach(t => {
|
this.setEphemere(newSigne.data.ephemere);
|
||||||
$(`[data-tmr-name='${t.name}']`).prop( "checked", t.selected);
|
|
||||||
})
|
|
||||||
this.setEphemere(newSigne.system.ephemere);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async setEphemere(ephemere) {
|
async setEphemere(ephemere) {
|
||||||
this.dialogData.signe.system.ephemere = ephemere;
|
this.dialogData.signe.data.ephemere = ephemere;
|
||||||
HtmlUtility._showControlWhen($(".signe-system-duree"), ephemere);
|
HtmlUtility._showControlWhen($(".signe-data-duree"), ephemere);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSelectActor(event) {
|
async onSelectActor(event) {
|
||||||
const actorId = $(event.currentTarget)?.data("actor-id");
|
event.preventDefault();
|
||||||
const actor = this.dialogData.actors.find(it => it.id == actorId);
|
const options = event.currentTarget.options;
|
||||||
if (actor) {
|
for (var i = 0; i < options.length; i++) { // looping over the options
|
||||||
actor.selected = event.currentTarget.checked;
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
onValeurXpSort(event) {
|
||||||
const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0;
|
const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0;
|
||||||
const xp = Number(event.currentTarget.value);
|
const xp = Number(event.currentTarget.value);
|
||||||
const oldValeur = this.dialogData.signe.system.valeur;
|
const oldValeur = this.dialogData.signe.data.valeur;
|
||||||
this.dialogData.signe.system.valeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
|
this.dialogData.signe.data.valeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -6,15 +6,10 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async create(actor, item, dialogConfig) {
|
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 potionData = DialogFabriquerPotion.prepareData(actor, item);
|
||||||
|
|
||||||
let conf = {
|
let conf = {
|
||||||
title: `Fabriquer une potion de ${potionData.system.categorie}`,
|
title: `Fabriquer une potion de ${potionData.data.categorie}`,
|
||||||
content: await renderTemplate(dialogConfig.html, potionData),
|
content: await renderTemplate(dialogConfig.html, potionData),
|
||||||
default: potionData.buttonName,
|
default: potionData.buttonName,
|
||||||
};
|
};
|
||||||
@ -29,12 +24,9 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static prepareData(actor, item) {
|
static prepareData(actor, item) {
|
||||||
let potionData = duplicate(item)
|
let potionData = duplicate(Misc.data(item));
|
||||||
potionData.nbBrinsSelect = RdDUtility.buildListOptions(
|
potionData.nbBrinsSelect = RdDUtility.buildListOptions(1, potionData.data.quantite);
|
||||||
DialogFabriquerPotion.nombreBrinsMinimum(item),
|
potionData.nbBrins = Math.min(potionData.data.quantite, DialogFabriquerPotion.getNombreBrinOptimal(potionData));
|
||||||
DialogFabriquerPotion.nombreBrinsOptimal(item));
|
|
||||||
potionData.nbBrins = Math.min(potionData.system.quantite, DialogFabriquerPotion.nombreBrinsOptimal(potionData));
|
|
||||||
potionData.herbebonus = item.system.niveau;
|
|
||||||
potionData.buttonName = "Fabriquer";
|
potionData.buttonName = "Fabriquer";
|
||||||
return potionData;
|
return potionData;
|
||||||
}
|
}
|
||||||
@ -53,18 +45,10 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
this.potionData = potionData;
|
this.potionData = potionData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nombreBrinsMinimum(herbeData) {
|
static getNombreBrinOptimal(herbeData) {
|
||||||
switch (herbeData.system.categorie ?? '') {
|
switch (herbeData.data.categorie ?? '') {
|
||||||
case "Soin": return 1 + Math.max(0, 12 - 2 * herbeData.system.niveau);
|
case "Soin": return 12 - herbeData.data.niveau;
|
||||||
case "Repos": return 1 + Math.max(0, 7 - 2 * herbeData.system.niveau);
|
case "Repos": return 7 - herbeData.data.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;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -75,8 +59,6 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
|
|
||||||
html.find("#nbBrins").change(event => {
|
html.find("#nbBrins").change(event => {
|
||||||
this.potionData.nbBrins = Misc.toInt(event.currentTarget.value);
|
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,64 +1,45 @@
|
|||||||
|
|
||||||
import { Monnaie } from "./item-monnaie.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
|
||||||
export class DialogItemAchat extends Dialog {
|
export class DialogItemAchat extends Dialog {
|
||||||
|
|
||||||
static venteData(button) {
|
static async onButtonAcheter(event) {
|
||||||
const vendeurId = button.attributes['data-vendeurId']?.value;
|
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;
|
||||||
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
|
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
|
||||||
const acheteur = RdDUtility.getSelectedActor();
|
const acheteur = RdDUtility.getSelectedActor();
|
||||||
const json = button.attributes['data-jsondata']?.value;
|
|
||||||
if (!acheteur && !vendeur) {
|
if (!acheteur && !vendeur) {
|
||||||
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
|
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
|
||||||
return undefined;
|
return;
|
||||||
}
|
|
||||||
if (!json) {
|
|
||||||
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const prixLot = Number(button.attributes['data-prixLot']?.value ?? 0);
|
let venteData = DialogItemAchat.prepareVenteData(buttonAcheter, vendeurId, vendeur, acheteur);
|
||||||
return {
|
|
||||||
item: json ? JSON.parse(json) : undefined,
|
|
||||||
actingUserId: game.user.id,
|
|
||||||
vendeurId: vendeurId,
|
|
||||||
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,
|
|
||||||
supprimerSiZero: true
|
|
||||||
},
|
|
||||||
prixLot: prixLot,
|
|
||||||
prixTotal: prixLot,
|
|
||||||
isVente: prixLot > 0,
|
|
||||||
chatMessageIdVente: RdDUtility.findChatMessageId(button)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static async onAcheter(venteData) {
|
|
||||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
|
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
|
||||||
const dialog = new DialogItemAchat(html, venteData);
|
const dialog = new DialogItemAchat(html, vendeur, acheteur, venteData, chatMessageIdVente);
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(html, venteData) {
|
constructor(html, vendeur, acheteur, venteData, chatMessageIdVente) {
|
||||||
const isConsommable = venteData.item.type == 'nourritureboisson' && venteData.acheteur?.isPersonnage();
|
const isConsommable = venteData.item.type == 'nourritureboisson';
|
||||||
let options = { classes: ["dialogachat"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
let options = { classes: ["dialogachat"], width: 400, height: isConsommable ? 450 : 350, 'z-index': 99999 };
|
||||||
|
|
||||||
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
|
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
|
||||||
const buttons = {};
|
const buttons = {};
|
||||||
if (isConsommable) {
|
if (isConsommable) {
|
||||||
buttons["consommer"] = { label: venteData.item.system.boisson ? "Boire" : "Manger", callback: it => this.onAchatConsommer() }
|
buttons["consommer"] = { label: venteData.item.data.boisson ? "Boire" : "Manger", callback: it => { this.onAchatConsommer(); } }
|
||||||
}
|
}
|
||||||
buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
|
buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
|
||||||
buttons["decliner"] = { label: "Décliner", callback: it => { } };
|
buttons["decliner"] = { label: "Décliner", callback: it => { } };
|
||||||
let conf = {
|
let conf = {
|
||||||
title: venteData.acheteur ? venteData.acheteur.name + " - " + actionAchat : actionAchat,
|
title: venteData.acheteur? venteData.acheteur.name + " - " + actionAchat : actionAchat,
|
||||||
content: html,
|
content: html,
|
||||||
default: actionAchat,
|
default: actionAchat,
|
||||||
buttons: buttons
|
buttons: buttons
|
||||||
@ -66,22 +47,47 @@ export class DialogItemAchat extends Dialog {
|
|||||||
|
|
||||||
super(conf, options);
|
super(conf, options);
|
||||||
|
|
||||||
|
this.vendeur = vendeur;
|
||||||
|
this.acheteur = acheteur;
|
||||||
|
this.chatMessageIdVente = chatMessageIdVente;
|
||||||
this.venteData = venteData;
|
this.venteData = venteData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static prepareVenteData(buttonAcheter, vendeurId, vendeur, acheteur) {
|
||||||
|
const jsondata = buttonAcheter.attributes['data-jsondata']?.value;
|
||||||
|
const prixLot = parseInt(buttonAcheter.attributes['data-prixLot']?.value ?? 0);
|
||||||
|
let venteData = {
|
||||||
|
item: JSON.parse(jsondata),
|
||||||
|
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),
|
||||||
|
choix: {
|
||||||
|
nombreLots: 1,
|
||||||
|
seForcer: false,
|
||||||
|
supprimerSiZero: true
|
||||||
|
},
|
||||||
|
prixLot: prixLot,
|
||||||
|
prixTotal: prixLot,
|
||||||
|
isVente: prixLot > 0
|
||||||
|
};
|
||||||
|
return venteData;
|
||||||
|
}
|
||||||
|
|
||||||
async onAchat() {
|
async onAchat() {
|
||||||
await $(".nombreLots").change();
|
await $(".nombreLots").change();
|
||||||
(this.venteData.vendeur ?? this.venteData.acheteur).achatVente({
|
(this.vendeur ?? this.acheteur).achatVente({
|
||||||
userId: game.user.id,
|
userId: game.user.id,
|
||||||
vendeurId: this.venteData.vendeur?.id,
|
vendeurId: this.vendeur?.id,
|
||||||
acheteurId: this.venteData.acheteur?.id,
|
acheteurId: this.acheteur?.id,
|
||||||
prixTotal: this.venteData.prixTotal,
|
prixTotal: this.venteData.prixTotal,
|
||||||
chatMessageIdVente: this.venteData.chatMessageIdVente,
|
chatMessageIdVente: this.chatMessageIdVente,
|
||||||
choix: this.venteData.choix,
|
choix: this.venteData.choix
|
||||||
vente: this.venteData
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async onAchatConsommer() {
|
async onAchatConsommer() {
|
||||||
this.venteData.choix.consommer = true;
|
this.venteData.choix.consommer = true;
|
||||||
await this.onAchat();
|
await this.onAchat();
|
||||||
@ -100,12 +106,8 @@ export class DialogItemAchat extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setNombreLots(nombreLots) {
|
setNombreLots(nombreLots) {
|
||||||
if (nombreLots > this.venteData.quantiteNbLots) {
|
this.venteData.choix.nombreLots = nombreLots;
|
||||||
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);
|
this.venteData.prixTotal = (nombreLots * this.venteData.prixLot).toFixed(2);
|
||||||
$(".nombreLots").val(this.venteData.choix.nombreLots);
|
|
||||||
$(".prixTotal").text(this.venteData.prixTotal);
|
$(".prixTotal").text(this.venteData.prixTotal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ export class DialogConsommer extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(actor, item, consommerData, html, onActionItem = async ()=>{}) {
|
constructor(actor, item, consommerData, html, onActionItem = async ()=>{}) {
|
||||||
const options = { classes: ["dialogconsommer"], width: 350, height: 'fit-content', 'z-index': 99999 };
|
const options = { classes: ["dialogconsommer"], width: 350, height: 450, 'z-index': 99999 };
|
||||||
let conf = {
|
let conf = {
|
||||||
title: consommerData.title,
|
title: consommerData.title,
|
||||||
content: html,
|
content: html,
|
||||||
@ -38,22 +38,22 @@ export class DialogConsommer extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static prepareData(actor, item) {
|
static prepareData(actor, item) {
|
||||||
item = duplicate(item);
|
const itemData = duplicate(Misc.data(item));
|
||||||
let consommerData = {
|
let consommerData = {
|
||||||
item: item,
|
item: itemData,
|
||||||
cuisine: actor.getCompetence('cuisine'),
|
cuisine: Misc.data(actor.getCompetence('cuisine')),
|
||||||
choix: {
|
choix: {
|
||||||
doses: 1,
|
doses: 1,
|
||||||
seForcer: false,
|
seForcer: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (item.type) {
|
switch (itemData.type) {
|
||||||
case 'nourritureboisson':
|
case 'nourritureboisson':
|
||||||
consommerData.title = item.system.boisson ? `${item.name}: boire une dose` : `${item.name}: manger une portion`;
|
consommerData.title = itemData.data.boisson ? `${itemData.name}: boire une dose` : `${itemData.name}: manger une portion`;
|
||||||
consommerData.buttonName = item.system.boisson ? "Boire" : "Manger";
|
consommerData.buttonName = itemData.data.boisson ? "Boire" : "Manger";
|
||||||
break;
|
break;
|
||||||
case 'potion':
|
case 'potion':
|
||||||
consommerData.title = `${item.name}: boire la potion`;
|
consommerData.title = `${itemData.name}: boire la potion`;
|
||||||
consommerData.buttonName = "Boire";
|
consommerData.buttonName = "Boire";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -61,11 +61,11 @@ export class DialogConsommer extends Dialog {
|
|||||||
return consommerData;
|
return consommerData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static calculDoses(consommer) {
|
static calculDoses(consommerData) {
|
||||||
const doses = consommer.choix.doses;
|
const doses = consommerData.choix.doses;
|
||||||
consommer.totalSust = Misc.keepDecimals(doses * (consommer.item.system.sust ?? 0), 2);
|
consommerData.totalSust = Misc.keepDecimals(doses * (consommerData.item.data.sust ?? 0), 2);
|
||||||
consommer.totalDesaltere = consommer.item.system.boisson
|
consommerData.totalDesaltere = consommerData.item.data.boisson
|
||||||
? Misc.keepDecimals(doses * (consommer.item.system.desaltere ?? 0), 2)
|
? Misc.keepDecimals(doses * (consommerData.item.data.desaltere ?? 0), 2)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
|
|
||||||
export class DialogItemVente extends Dialog {
|
export class DialogItemVente extends Dialog {
|
||||||
|
|
||||||
static async display(item, callback) {
|
static async create(item, callback) {
|
||||||
const quantite = item.isConteneur() ? 1 : item.system.quantite;
|
const itemData = Misc.data(item);
|
||||||
|
const quantite = item.isConteneur() ? 1 : itemData.data.quantite;
|
||||||
const venteData = {
|
const venteData = {
|
||||||
item: item,
|
item: itemData,
|
||||||
alias: item.actor?.name ?? game.user.name,
|
alias: item.actor?.name ?? game.user.name,
|
||||||
vendeurId: item.actor?.id,
|
vendeurId: item.actor?.id,
|
||||||
prixOrigine: item.system.cout,
|
prixOrigine: itemData.data.cout,
|
||||||
prixUnitaire: item.system.cout,
|
prixUnitaire: itemData.data.cout,
|
||||||
prixLot: item.system.cout,
|
prixLot: itemData.data.cout,
|
||||||
tailleLot: 1,
|
tailleLot: 1,
|
||||||
quantiteNbLots: quantite,
|
quantiteNbLots: quantite,
|
||||||
quantiteMaxLots: quantite,
|
quantiteMaxLots: quantite,
|
||||||
@ -19,11 +21,11 @@ export class DialogItemVente extends Dialog {
|
|||||||
isOwned: item.isOwned,
|
isOwned: item.isOwned,
|
||||||
};
|
};
|
||||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
|
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
|
||||||
return new DialogItemVente(venteData, html, callback).render(true);
|
return new DialogItemVente(venteData, html, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(venteData, html, callback) {
|
constructor(venteData, html, callback) {
|
||||||
let options = { classes: ["dialogvente"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
let options = { classes: ["dialogvente"], width: 400, height: 300, 'z-index': 99999 };
|
||||||
|
|
||||||
let conf = {
|
let conf = {
|
||||||
title: "Proposer",
|
title: "Proposer",
|
||||||
|
@ -3,9 +3,9 @@ import { Misc } from "./misc.js";
|
|||||||
export class DialogRepos extends Dialog {
|
export class DialogRepos extends Dialog {
|
||||||
|
|
||||||
static async create(actor) {
|
static async create(actor) {
|
||||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-repos.html", actor);
|
let actorData = Misc.data(actor)
|
||||||
const dialog = new DialogRepos(html, actor);
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-repos.html", actorData);
|
||||||
dialog.render(true);
|
new DialogRepos(html, actor).render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(html, actor) {
|
constructor(html, actor) {
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
|
|
||||||
export class DialogSelectTarget extends Dialog {
|
|
||||||
constructor(html, onSelectTarget, targets) {
|
|
||||||
const options = {
|
|
||||||
classes: ["rdd-dialog-select-target"],
|
|
||||||
width: 'fit-content',
|
|
||||||
height: 'fit-content',
|
|
||||||
'max-height': 600,
|
|
||||||
'z-index': 99999
|
|
||||||
};
|
|
||||||
const conf = {
|
|
||||||
title: "Choisir une cible",
|
|
||||||
content: html,
|
|
||||||
buttons: {}
|
|
||||||
};
|
|
||||||
super(conf, options);
|
|
||||||
this.onSelectTarget = onSelectTarget;
|
|
||||||
this.targets = targets;
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
html.find("li.select-target").click((event) => {
|
|
||||||
this.targetSelected($(event.currentTarget)?.data("token-id"));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
targetSelected(tokenId) {
|
|
||||||
const target = this.targets.find(it => it.id == tokenId);
|
|
||||||
this.close();
|
|
||||||
if (target) {
|
|
||||||
this.onSelectTarget(target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,9 +3,10 @@ import { Misc } from "./misc.js";
|
|||||||
export class DialogSplitItem extends Dialog {
|
export class DialogSplitItem extends Dialog {
|
||||||
|
|
||||||
static async create(item, callback) {
|
static async create(item, callback) {
|
||||||
|
const itemData = Misc.data(item);
|
||||||
const splitData = {
|
const splitData = {
|
||||||
item: item,
|
item: itemData,
|
||||||
choix: { quantite: 1, max: item.system.quantite - 1 }
|
choix: { quantite: 1, max: itemData.data.quantite - 1 }
|
||||||
};
|
};
|
||||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-split.html`, splitData);
|
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-split.html`, splitData);
|
||||||
return new DialogSplitItem(item, splitData, html, callback)
|
return new DialogSplitItem(item, splitData, html, callback)
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
|
import { Misc } from "./misc.js";
|
||||||
|
|
||||||
export class DialogStress extends Dialog {
|
export class DialogStress extends Dialog {
|
||||||
|
|
||||||
static async distribuerStress() {
|
static async distribuerStress() {
|
||||||
const dialogData = {
|
let dialogData = {
|
||||||
motif: "Motif",
|
motif: "Motif",
|
||||||
stress: 10,
|
stress: 10,
|
||||||
immediat: false,
|
immediat: false,
|
||||||
actors: game.actors.filter(actor => actor.hasPlayerOwner && actor.isPersonnage())
|
actors: game.actors.filter(actor => actor.hasPlayerOwner && actor.isPersonnage())
|
||||||
.map(actor => ({
|
.map(actor => {
|
||||||
id: actor.id,
|
let actorData = duplicate(Misc.data(actor));
|
||||||
name: actor.name,
|
actorData.selected = actor.hasPlayerOwner;
|
||||||
selected: true
|
return actorData;
|
||||||
})
|
})
|
||||||
)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-stress.html", dialogData);
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-stress.html", dialogData);
|
||||||
@ -21,43 +21,52 @@ export class DialogStress extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
constructor(dialogData, html) {
|
constructor(dialogData, html) {
|
||||||
const options = { classes: ["DialogStress"],
|
let options = { classes: ["DialogStress"], width: 400, height: 320, 'z-index': 99999 };
|
||||||
width: 400,
|
let conf = {
|
||||||
height: 'fit-content',
|
|
||||||
'z-index': 99999
|
|
||||||
};
|
|
||||||
const conf = {
|
|
||||||
title: "Donner du stress",
|
title: "Donner du stress",
|
||||||
content: html,
|
content: html,
|
||||||
buttons: {
|
buttons: {
|
||||||
stress: { label: "Stress !", callback: it => { this.onStress(); } }
|
"Stress": { label: "Stress !", callback: it => { this._onStress(); } }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
super(conf, options);
|
super(conf, options);
|
||||||
this.dialogData = dialogData;
|
this.dialogData = dialogData;
|
||||||
}
|
}
|
||||||
|
|
||||||
async onStress() {
|
async _onStress() {
|
||||||
const motif = $("form.rdddialogstress input[name='motif']").val();
|
this.validerStress();
|
||||||
const stress = Number($("form.rdddialogstress input[name='stress']").val());
|
const compteur = this.dialogData.immediat ? 'experience' : 'stress';
|
||||||
const compteur = ($("form.rdddialogstress input[name='immediat']").prop("checked")) ? 'experience' : 'stress';
|
const stress = this.dialogData.stress;
|
||||||
|
const motif = this.dialogData.motif;
|
||||||
|
|
||||||
this.dialogData.actors.filter(it => it.selected)
|
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));
|
.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) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
html.find("input.select-actor").change((event) => this.onSelectActor(event));
|
html.find(".select-actor").change((event) => this.onSelectActor(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSelectActor(event) {
|
async onSelectActor(event) {
|
||||||
const actorId = $(event.currentTarget)?.data("actor-id");
|
event.preventDefault();
|
||||||
const actor = this.dialogData.actors.find(it => it.id == actorId);
|
const options = event.currentTarget.options;
|
||||||
if (actor) {
|
for (var i = 0; i < options.length; i++) { // looping over the options
|
||||||
actor.selected = event.currentTarget.checked;
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,70 +0,0 @@
|
|||||||
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,137 +0,0 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
|
||||||
import { Poetique } from "./poetique.js";
|
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
|
||||||
|
|
||||||
export class EffetsRencontre {
|
|
||||||
|
|
||||||
static messager = async (dialog, context) => {
|
|
||||||
dialog.setRencontreState('messager', TMRUtility.getTMRPortee(context.tmr.coord, context.rencontre.system.force));
|
|
||||||
}
|
|
||||||
|
|
||||||
static passeur = async (dialog, context) => {
|
|
||||||
dialog.setRencontreState('passeur', TMRUtility.getTMRPortee(context.tmr.coord, context.rencontre.system.force));
|
|
||||||
}
|
|
||||||
|
|
||||||
static teleportation_typecase = async (dialog, context) => {
|
|
||||||
dialog.setRencontreState('changeur', TMRUtility.getCasesType(context.tmr.type));
|
|
||||||
}
|
|
||||||
|
|
||||||
static rencontre_persistante = async (dialog, context) => {
|
|
||||||
dialog.setRencontreState('persistant', []);
|
|
||||||
}
|
|
||||||
|
|
||||||
static reve_plus_force = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, context.rencontre.system.force) }
|
|
||||||
static reve_plus_1 = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, 1) }
|
|
||||||
static reve_moins_force = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, -context.rencontre.system.force) }
|
|
||||||
static reve_moins_1 = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, -1) }
|
|
||||||
static $reve_plus = async (actor, valeur) => { await actor.reveActuelIncDec(valeur) }
|
|
||||||
|
|
||||||
static vie_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
|
|
||||||
static vie_moins_force = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -context.rencontre.system.force) }
|
|
||||||
static $vie_plus = async (actor, valeur) => { await actor.santeIncDec("vie", valeur) }
|
|
||||||
|
|
||||||
static moral_plus_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, 1) }
|
|
||||||
static moral_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
|
|
||||||
static $moral_plus = async (actor, valeur) => { await actor.moralIncDec(valeur) }
|
|
||||||
|
|
||||||
static end_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
|
|
||||||
static end_moins_force = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -context.rencontre.system.force) }
|
|
||||||
static $end_plus = async (actor, valeur) => { await actor.santeIncDec("endurance", valeur) }
|
|
||||||
|
|
||||||
static fatigue_plus_1 = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, 1) }
|
|
||||||
static fatigue_plus_force = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, context.rencontre.system.force) }
|
|
||||||
static fatigue_moins_1 = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, -1) }
|
|
||||||
static fatigue_moins_force = async (dialog, context) => { await EffetsRencontre.$fatigue_plus(context.actor, -context.rencontre.system.force) }
|
|
||||||
static $fatigue_plus = async (actor, valeur) => { await actor.santeIncDec("fatigue", valeur) }
|
|
||||||
|
|
||||||
static perte_chance = async (dialog, context) => {
|
|
||||||
const perte = context.rolled.isETotal ? context.rencontre.system.force : 1;
|
|
||||||
await context.actor.chanceActuelleIncDec("fatigue", -perte);
|
|
||||||
}
|
|
||||||
|
|
||||||
static xp_sort_force = async (dialog, context) => {
|
|
||||||
let competence = context.competence;
|
|
||||||
if (competence) {
|
|
||||||
const xpSort = Misc.toInt(competence.system.xp_sort) + context.rencontre.system.force;
|
|
||||||
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': xpSort }]);
|
|
||||||
await this.updateExperienceLog("XP Sort", xpSort, `Rencontre d'un ${context.rencontre.name} en TMR`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static stress_plus_1 = async (dialog, context) => {
|
|
||||||
await context.actor.addCompteurValue('stress', 1, `Rencontre d'un ${context.rencontre.name} en TMR`);
|
|
||||||
}
|
|
||||||
|
|
||||||
static reinsertion = async (dialog, context) => {
|
|
||||||
await EffetsRencontre.$reinsertion(dialog, context.actor, it => true)
|
|
||||||
}
|
|
||||||
|
|
||||||
static teleportation_aleatoire_typecase = async (dialog, context) => {
|
|
||||||
await EffetsRencontre.$reinsertion(dialog, context.actor, it => it.type == context.tmr.type && it.coord != context.tmr.coord)
|
|
||||||
}
|
|
||||||
|
|
||||||
static demireve_rompu = async (dialog, context) => {
|
|
||||||
dialog.close()
|
|
||||||
}
|
|
||||||
|
|
||||||
static sort_aleatoire = async (dialog, context) => {
|
|
||||||
context.sortReserve = await RdDDice.rollOneOf(context.actor.itemTypes['sortreserve']);
|
|
||||||
if (context.sortReserve) {
|
|
||||||
context.newTMR = TMRUtility.getTMR(context.sortReserve.system.coord);
|
|
||||||
await dialog.positionnerDemiReve(context.newTMR.coord);
|
|
||||||
await dialog.processSortReserve(context.sortReserve);
|
|
||||||
dialog.close();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
await EffetsRencontre.$reinsertion(dialog, context.actor, it => true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static deplacement_aleatoire = async (dialog, context) => {
|
|
||||||
const oldCoord = context.actor.system.reve.tmrpos.coord;
|
|
||||||
const newTmr = await TMRUtility.deplaceTMRAleatoire(context.actor, oldCoord);
|
|
||||||
await dialog.positionnerDemiReve(newTmr.coord)
|
|
||||||
}
|
|
||||||
|
|
||||||
static rdd_part_tete = async (dialog, context) => {
|
|
||||||
mergeObject(context, {
|
|
||||||
tete: context.rolled.isPart,
|
|
||||||
poesie: await Poetique.getExtrait()
|
|
||||||
})
|
|
||||||
ChatMessage.create({
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(context.actor.name),
|
|
||||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, context)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static rdd_echec_queue = async (dialog, context) => {
|
|
||||||
mergeObject(context, {
|
|
||||||
queues: [await context.actor.ajouterQueue()],
|
|
||||||
poesie: await Poetique.getExtrait()
|
|
||||||
})
|
|
||||||
if (context.rolled.isETotal) {
|
|
||||||
context.queues.push(await context.actor.ajouterQueue());
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatMessage.create({
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
|
||||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, context)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static experience_particuliere = async (dialog, context) => {
|
|
||||||
await context.actor.appliquerAjoutExperience(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
static regain_seuil = async (dialog, context) => {
|
|
||||||
await context.actor.regainPointDeSeuil()
|
|
||||||
}
|
|
||||||
|
|
||||||
static async $reinsertion(dialog, actor, filter) {
|
|
||||||
const newTMR = await TMRUtility.getTMRAleatoire(filter);
|
|
||||||
await actor.forcerPositionTMRInconnue(newTMR);
|
|
||||||
await dialog.positionnerDemiReve(newTMR.coord);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,222 +0,0 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
|
||||||
import { Grammar } from "./grammar.js";
|
|
||||||
import { Misc } from "./misc.js";
|
|
||||||
import { CompendiumTableHelpers, SystemCompendiums, CompendiumTable } from "./settings/system-compendiums.js";
|
|
||||||
|
|
||||||
const RARETES = [
|
|
||||||
{ name: 'Commune', frequence: 54, min: 27, max: 108 },
|
|
||||||
{ name: 'Frequente', frequence: 18, min: 9, max: 36 },
|
|
||||||
{ name: 'Rare', frequence: 6, min: 3, max: 12 },
|
|
||||||
{ name: 'Rarissime', frequence: 2, min: 1, max: 4 }]
|
|
||||||
|
|
||||||
const SETTINGS_LISTE_MILIEUX = "liste-milieux";
|
|
||||||
const MILIEUX = [
|
|
||||||
"Collines",
|
|
||||||
"Déserts",
|
|
||||||
"Désolations",
|
|
||||||
"Forêts",
|
|
||||||
"Forêts Tropicales",
|
|
||||||
"Marais",
|
|
||||||
"Milieux Aquatiques",
|
|
||||||
"Milieux Maritimes",
|
|
||||||
"Montagnes",
|
|
||||||
"Plaines",
|
|
||||||
"Sous-Sols",
|
|
||||||
]
|
|
||||||
const ITEM_ENVIRONNEMENT_TYPES = [
|
|
||||||
'herbe', 'ingredient'
|
|
||||||
]
|
|
||||||
|
|
||||||
export class Environnement {
|
|
||||||
|
|
||||||
static init() {
|
|
||||||
game.settings.register(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX, {
|
|
||||||
name: "Liste des milieux proposés",
|
|
||||||
hint: "Liste des milieux proposés pour la faune&flore, séparés par des virgules",
|
|
||||||
scope: "world",
|
|
||||||
config: true,
|
|
||||||
default: MILIEUX.reduce(Misc.joining(',')),
|
|
||||||
type: String
|
|
||||||
});
|
|
||||||
game.system.rdd.environnement = new Environnement();
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.table = new CompendiumTable('faune-flore-mineraux', 'Item', ITEM_ENVIRONNEMENT_TYPES)
|
|
||||||
}
|
|
||||||
|
|
||||||
static getRarete(name = undefined) {
|
|
||||||
return RARETES.find(it => it.name == name) ?? RARETES[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static getFrequenceRarete(rarete, field = undefined) {
|
|
||||||
const selected = this.getRarete(rarete);
|
|
||||||
return selected[field];
|
|
||||||
}
|
|
||||||
|
|
||||||
async milieux() {
|
|
||||||
const milieux = new Set(this.getMilieuxSettings());
|
|
||||||
const elements = await this.getElements(it => 1, it => ITEM_ENVIRONNEMENT_TYPES.includes(it.type));
|
|
||||||
elements.forEach(it => it.system.environnement.forEach(env => milieux.add(env.milieu)))
|
|
||||||
return [...milieux].filter(env => env);
|
|
||||||
}
|
|
||||||
|
|
||||||
getMilieuxSettings() {
|
|
||||||
return game.settings.get(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX).split(',');
|
|
||||||
}
|
|
||||||
|
|
||||||
async findEnvironnementsLike(search) {
|
|
||||||
const milieux = (await this.milieux()).filter(it => Grammar.includesLowerCaseNoAccent(it, search));
|
|
||||||
if (milieux.length > 1){
|
|
||||||
const milieuExact = milieux.find(it => Grammar.equalsInsensitive(it, search));
|
|
||||||
if (milieuExact) {
|
|
||||||
return [milieuExact];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return milieux;
|
|
||||||
}
|
|
||||||
|
|
||||||
async searchToChatMessage(milieux, typeName) {
|
|
||||||
const table = await this.buildEnvironnementTable(milieux);
|
|
||||||
await CompendiumTableHelpers.tableToChatMessage(table, 'Item', ITEM_ENVIRONNEMENT_TYPES, typeName);
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRandom(milieux, typeName) {
|
|
||||||
const table = await this.buildEnvironnementTable(milieux);
|
|
||||||
return await CompendiumTableHelpers.getRandom(table, 'Item', ITEM_ENVIRONNEMENT_TYPES, undefined, typeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
async buildEnvironnementTable(milieux) {
|
|
||||||
const filterMilieux = item => item.system?.environnement.filter(env => milieux.includes(env.milieu));
|
|
||||||
const itemRareteEnMilieu = item => {
|
|
||||||
const raretes = filterMilieux(item);
|
|
||||||
const frequenceMax = Math.max(raretes.map(env => env.frequence));
|
|
||||||
return raretes.find(env => env.frequence == frequenceMax);
|
|
||||||
}
|
|
||||||
const itemFrequenceEnMilieu = item => itemRareteEnMilieu(item)?.frequence ?? 0;
|
|
||||||
const isPresentEnMilieu = item => itemFrequenceEnMilieu(item) > 0;
|
|
||||||
return await this.table.buildTable(itemFrequenceEnMilieu, isPresentEnMilieu);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async getElements(itemFrequence, filter) {
|
|
||||||
return await this.table.getContent(itemFrequence, filter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class EnvironmentSheetHelper {
|
|
||||||
|
|
||||||
static defaultOptions(defaultOptions, type) {
|
|
||||||
return mergeObject(defaultOptions, {
|
|
||||||
classes: ["rdd", "sheet", "item"],
|
|
||||||
template: `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`,
|
|
||||||
width: 500,
|
|
||||||
height: 600,
|
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static getHeaderButtons(sheet, buttons) {
|
|
||||||
buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => sheet.item.postItem() });
|
|
||||||
return buttons;
|
|
||||||
}
|
|
||||||
|
|
||||||
static setPosition(sheet, superPosition) {
|
|
||||||
const position = superPosition;
|
|
||||||
const sheetHeader = sheet.element.find(".sheet-header");
|
|
||||||
const sheetBody = sheet.element.find(".sheet-body");
|
|
||||||
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async getData(sheet) {
|
|
||||||
const formData = duplicate(sheet.item);
|
|
||||||
const milieux = await game.system.rdd.environnement.milieux();
|
|
||||||
const milieuxDisponibles = milieux.filter(it => !sheet.item.system.environnement.find(e => e.milieu == it));
|
|
||||||
mergeObject(formData, {
|
|
||||||
title: formData.name,
|
|
||||||
isGM: game.user.isGM,
|
|
||||||
owner: sheet.actor?.isOwner,
|
|
||||||
isOwned: sheet.actor ? true : false,
|
|
||||||
actorId: sheet.actor?.id,
|
|
||||||
editable: sheet.isEditable,
|
|
||||||
cssClass: sheet.isEditable ? "editable" : "locked",
|
|
||||||
milieux: milieuxDisponibles
|
|
||||||
});
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
static activateListeners(sheet, html) {
|
|
||||||
if (!sheet.options.editable) return;
|
|
||||||
html.find("a.milieu-add").click(event => EnvironmentSheetHelper.onAddMilieu(html, sheet, event));
|
|
||||||
html.find("div.environnement-milieu a.milieu-delete").click(event => EnvironmentSheetHelper.onDeleteMilieu(sheet, event));
|
|
||||||
html.find("div.environnement-milieu select.environnement-rarete").change(event => EnvironmentSheetHelper.onChange(sheet, event,
|
|
||||||
(updated) => {
|
|
||||||
const name = $(event.currentTarget).val();
|
|
||||||
const rarete = Environnement.getRarete(name);
|
|
||||||
updated.rarete = rarete.name;
|
|
||||||
updated.frequence = Math.min(
|
|
||||||
Math.max(rarete.min, updated.frequence ?? rarete.frequence),
|
|
||||||
rarete.max);
|
|
||||||
}));
|
|
||||||
html.find("div.environnement-milieu input[name='environnement-frequence']").change(event => EnvironmentSheetHelper.onChange(sheet, event,
|
|
||||||
(updated) => {
|
|
||||||
updated.frequence = Number($(event.currentTarget).val())
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
static async onAddMilieu(html, sheet, event) {
|
|
||||||
const milieu = html.find('input.input-selection-milieu').val();
|
|
||||||
if (!milieu) {
|
|
||||||
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${sheet.item.name}`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const list = sheet.item.system.environnement;
|
|
||||||
const exists = list.find(it => it.milieu == milieu);
|
|
||||||
if (exists) {
|
|
||||||
ui.notifications.warn(`${sheet.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const rarete = Environnement.getRarete();
|
|
||||||
const newList = [...list, { milieu, rarete: rarete.name, frequence: rarete.frequence }].sort(Misc.ascending(it => it.milieu))
|
|
||||||
await sheet.item.update({ 'system.environnement': newList })
|
|
||||||
}
|
|
||||||
|
|
||||||
static async onDeleteMilieu(sheet, event) {
|
|
||||||
const milieu = EnvironmentSheetHelper.$getEventMilieu(event);
|
|
||||||
if (milieu) {
|
|
||||||
const newList = sheet.item.system.environnement.filter(it => it.milieu != milieu)
|
|
||||||
.sort(Misc.ascending(it => it.milieu));
|
|
||||||
await sheet.item.update({ 'system.environnement': newList });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async onChange(sheet, event, doMutation) {
|
|
||||||
const list = sheet.item.system.environnement;
|
|
||||||
const milieu = EnvironmentSheetHelper.$getEventMilieu(event);
|
|
||||||
const updated = list.find(it => it.milieu == milieu);
|
|
||||||
if (updated) {
|
|
||||||
doMutation(updated);
|
|
||||||
const newList = [...list.filter(it => it.milieu != milieu), updated]
|
|
||||||
.sort(Misc.ascending(it => it.milieu));
|
|
||||||
await sheet.item.update({ 'system.environnement': newList });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static $getEventMilieu(event) {
|
|
||||||
return $(event.currentTarget)?.parents("div.environnement-milieu").data("milieu");
|
|
||||||
}
|
|
||||||
|
|
||||||
static template(itemType) {
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
return `systems/foundryvtt-reve-de-dragon/templates/item-${itemType}-sheet.html`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static title(item) {
|
|
||||||
return Misc.typeName('Item', item.type) + ': ' + item.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -19,14 +19,10 @@ export class Grammar {
|
|||||||
return word.match(/^[aeiouy]/i)
|
return word.match(/^[aeiouy]/i)
|
||||||
}
|
}
|
||||||
|
|
||||||
static equalsInsensitive(a, b) {
|
|
||||||
return Grammar.toLowerCaseNoAccent(a) == Grammar.toLowerCaseNoAccent(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
static includesLowerCaseNoAccent(value, content) {
|
static includesLowerCaseNoAccent(value, content) {
|
||||||
return Grammar.toLowerCaseNoAccent(value).includes(Grammar.toLowerCaseNoAccent(content));
|
return Grammar.toLowerCaseNoAccent(value).includes(Grammar.toLowerCaseNoAccent(content));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static toLowerCaseNoAccent(words) {
|
static toLowerCaseNoAccent(words) {
|
||||||
return words?.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "") ?? words;
|
return words?.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "") ?? words;
|
||||||
|
9
module/hook-renderChatLog.js
Normal file
9
module/hook-renderChatLog.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
/* -------------------------------------------- */
|
||||||
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
// Activate chat listeners defined
|
||||||
|
// Hooks.on('renderChatLog', (log, html, data) => {
|
||||||
|
// RdDUtility.chatListeners(html);
|
||||||
|
// });
|
||||||
|
|
@ -19,34 +19,36 @@ const nomCategorieParade = {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDItemArme extends Item {
|
export class RdDItemArme extends Item {
|
||||||
|
|
||||||
static isArme(item) {
|
static isArme(itemData) {
|
||||||
return (item.type == 'competencecreature' && item.system.iscombat) || item.type == 'arme';
|
itemData = Misc.data(itemData);
|
||||||
|
return (itemData.type == 'competencecreature' && itemData.data.iscombat) || itemData.type == 'arme';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getArme(arme) {
|
static getArmeData(armeData) {
|
||||||
switch (arme ? arme.type : '') {
|
armeData = Misc.data(armeData);
|
||||||
case 'arme': return arme;
|
switch (armeData ? armeData.type : '') {
|
||||||
|
case 'arme': return armeData;
|
||||||
case 'competencecreature':
|
case 'competencecreature':
|
||||||
return RdDItemCompetenceCreature.armeNaturelle(arme);
|
return RdDItemCompetenceCreature.toActionArme(armeData);
|
||||||
}
|
}
|
||||||
return RdDItemArme.mainsNues();
|
return RdDItemArme.mainsNues();
|
||||||
}
|
}
|
||||||
|
|
||||||
static computeNiveauArmes(armes, competences) {
|
static computeNiveauArmes(armes, competences) {
|
||||||
for (const arme of armes) {
|
for (const arme of armes) {
|
||||||
arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
|
arme.data.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static niveauCompetenceArme(arme, competences) {
|
static niveauCompetenceArme(arme, competences) {
|
||||||
const compArme = competences.find(it => it.name == arme.system.competence);
|
const compArme = competences.find(it => it.name == arme.data.competence);
|
||||||
return compArme?.system.niveau ?? -8;
|
return compArme?.data.niveau ?? -8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getNomCategorieParade(arme) {
|
static getNomCategorieParade(arme) {
|
||||||
const categorie = arme?.system ? RdDItemArme.getCategorieParade(arme) : arme;
|
const categorie = arme?.data ? RdDItemArme.getCategorieParade(arme) : arme;
|
||||||
return nomCategorieParade[categorie];
|
return nomCategorieParade[categorie];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,20 +66,21 @@ export class RdDItemArme extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getCategorieParade(armeData) {
|
static getCategorieParade(armeData) {
|
||||||
if (armeData.system.categorie_parade) {
|
armeData = Misc.data(armeData);
|
||||||
return armeData.system.categorie_parade;
|
if (armeData.data.categorie_parade) {
|
||||||
|
return armeData.data.categorie_parade;
|
||||||
}
|
}
|
||||||
// pour compatibilité avec des personnages existants
|
// pour compatibilité avec des personnages existants
|
||||||
if (armeData.type == 'competencecreature' || armeData.system.categorie == 'creature') {
|
if (armeData.type == 'competencecreature' || armeData.data.categorie == 'creature') {
|
||||||
return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '');
|
return armeData.data.categorie_parade || (armeData.data.isparade ? 'armes-naturelles' : '');
|
||||||
}
|
}
|
||||||
if (!armeData.type.match(/arme|competencecreature/)) {
|
if (!armeData.type.match(/arme|competencecreature/)) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (armeData.system.competence == undefined) {
|
if (armeData.data.competence == undefined) {
|
||||||
return 'competencecreature';
|
return 'competencecreature';
|
||||||
}
|
}
|
||||||
let compname = armeData.system.competence.toLowerCase();
|
let compname = armeData.data.competence.toLowerCase();
|
||||||
if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return '';
|
if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return '';
|
||||||
|
|
||||||
if (compname.match('hache')) return 'haches';
|
if (compname.match('hache')) return 'haches';
|
||||||
@ -134,21 +137,22 @@ export class RdDItemArme extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static armeUneOuDeuxMains(armeData, aUneMain) {
|
static armeUneOuDeuxMains(armeData, aUneMain) {
|
||||||
if (armeData && !armeData.system.cac) {
|
armeData = Misc.data(armeData);
|
||||||
armeData.system.unemain = armeData.system.unemain || !armeData.system.deuxmains;
|
if (armeData && !armeData.data.cac) {
|
||||||
const uneOuDeuxMains = armeData.system.unemain && armeData.system.deuxmains;
|
armeData.data.unemain = armeData.data.unemain || !armeData.data.deuxmains;
|
||||||
const containsSlash = !Number.isInteger(armeData.system.dommages) && armeData.system.dommages.includes("/");
|
const uneOuDeuxMains = armeData.data.unemain && armeData.data.deuxmains;
|
||||||
|
const containsSlash = !Number.isInteger(armeData.data.dommages) && armeData.data.dommages.includes("/");
|
||||||
if (containsSlash) { // Sanity check
|
if (containsSlash) { // Sanity check
|
||||||
armeData = duplicate(armeData);
|
armeData = duplicate(armeData);
|
||||||
|
|
||||||
const tableauDegats = armeData.system.dommages.split("/");
|
const tableauDegats = armeData.data.dommages.split("/");
|
||||||
if (aUneMain)
|
if (aUneMain)
|
||||||
armeData.system.dommagesReels = Number(tableauDegats[0]);
|
armeData.data.dommagesReels = Number(tableauDegats[0]);
|
||||||
else // 2 mains
|
else // 2 mains
|
||||||
armeData.system.dommagesReels = Number(tableauDegats[1]);
|
armeData.data.dommagesReels = Number(tableauDegats[1]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
armeData.system.dommagesReels = Number(armeData.system.dommages);
|
armeData.data.dommagesReels = Number(armeData.data.dommages);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uneOuDeuxMains != containsSlash) {
|
if (uneOuDeuxMains != containsSlash) {
|
||||||
@ -158,50 +162,51 @@ export class RdDItemArme extends Item {
|
|||||||
return armeData;
|
return armeData;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isArmeUtilisable(arme) {
|
static isArmeUtilisable(itemData) {
|
||||||
return arme.type == 'arme' && arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0);
|
itemData = Misc.data(itemData);
|
||||||
|
return itemData.type == 'arme' && itemData.data.equipe && (itemData.data.resistance > 0 || itemData.data.portee_courte > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ajoutCorpsACorps(armes, competences, carac) {
|
static ajoutCorpsACorps(armes, competences, carac) {
|
||||||
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { system: { niveau: -6 } };
|
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { data: { niveau: -6 } };
|
||||||
let init = RdDCombatManager.calculInitiative(corpsACorps.system.niveau, carac['melee'].value);
|
let init = RdDCombatManager.calculInitiative(corpsACorps.data.niveau, carac['melee'].value);
|
||||||
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.system.niveau, initiative: init }));
|
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.data.niveau, initiative: init }));
|
||||||
//armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
|
//armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.data.niveau, initiative: init }));
|
||||||
}
|
}
|
||||||
|
|
||||||
static corpsACorps(mainsNuesActor) {
|
static corpsACorps(actorData) {
|
||||||
const corpsACorps = {
|
const corpsACorps = {
|
||||||
name: 'Corps à corps',
|
name: 'Corps à corps',
|
||||||
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
|
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
|
||||||
system: {
|
data: {
|
||||||
equipe: true,
|
equipe: true,
|
||||||
rapide: true,
|
rapide: true,
|
||||||
force: 0,
|
force: 0,
|
||||||
dommages: "0",
|
dommages: 0,
|
||||||
dommagesReels: 0,
|
dommagesReels: 0,
|
||||||
mortalite: 'non-mortel',
|
mortalite: 'non-mortel',
|
||||||
competence: 'Corps à corps',
|
competence: 'Corps à corps',
|
||||||
categorie_parade: 'sans-armes'
|
categorie_parade: 'sans-armes'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mergeObject(corpsACorps.system, mainsNuesActor ?? {}, { overwrite: false });
|
mergeObject(corpsACorps.data, actorData ?? {}, { overwrite: false });
|
||||||
return corpsACorps;
|
return corpsACorps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mainsNues(mainsNuesActor) {
|
static mainsNues(actorData) {
|
||||||
const mainsNues = RdDItemArme.corpsACorps(mainsNuesActor)
|
const mainsNues = RdDItemArme.corpsACorps(actorData);
|
||||||
mainsNues.name = 'Mains nues'
|
mainsNues.name = 'Mains nues';
|
||||||
mainsNues.system.cac = 'pugilat'
|
mainsNues.data.cac = 'pugilat';
|
||||||
mainsNues.system.baseInit = 4
|
mainsNues.data.baseInit = 4;
|
||||||
return mainsNues;
|
return mainsNues;
|
||||||
}
|
}
|
||||||
|
|
||||||
static empoignade(mainsNuesActor) {
|
static empoignade(actorData) {
|
||||||
const empoignade = RdDItemArme.corpsACorps(mainsNuesActor)
|
const empoignade = RdDItemArme.corpsACorps(actorData);
|
||||||
empoignade.name = 'Empoignade'
|
empoignade.name = 'Empoignade';
|
||||||
empoignade.system.cac = 'empoignade'
|
empoignade.data.cac = 'empoignade';
|
||||||
empoignade.system.baseInit = 3
|
empoignade.data.baseInit = 3;
|
||||||
empoignade.system.mortalite = 'empoignade'
|
empoignade.data.mortalite = 'empoignade';
|
||||||
return empoignade
|
return empoignade;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,13 @@ const categorieCompetences = {
|
|||||||
"lancer": { base: -8, label: "Lancer" }
|
"lancer": { base: -8, label: "Lancer" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const compendiumCompetences = {
|
||||||
|
"personnage": "foundryvtt-reve-de-dragon.competences",
|
||||||
|
"creature": "foundryvtt-reve-de-dragon.competences-creatures",
|
||||||
|
"entite": "foundryvtt-reve-de-dragon.competences-entites"
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
function _buildCumulXP() {
|
function _buildCumulXP() {
|
||||||
let cumulXP = { "-11": 0 };
|
let cumulXP = { "-11": 0 };
|
||||||
let cumul = 0;
|
let cumul = 0;
|
||||||
@ -48,6 +55,12 @@ function _buildCumulXP() {
|
|||||||
const competence_xp_cumul = _buildCumulXP();
|
const competence_xp_cumul = _buildCumulXP();
|
||||||
|
|
||||||
export class RdDItemCompetence extends Item {
|
export class RdDItemCompetence extends Item {
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static actorCompendium(actorType) {
|
||||||
|
return compendiumCompetences[actorType];
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getCategorieCompetences() {
|
static getCategorieCompetences() {
|
||||||
return categorieCompetences;
|
return categorieCompetences;
|
||||||
@ -63,49 +76,40 @@ export class RdDItemCompetence extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getCategorie(competence) {
|
static getCategorie(competence) {
|
||||||
return competence?.system.categorie;
|
return Misc.data(competence)?.data.categorie;
|
||||||
}
|
}
|
||||||
static isDraconic(competence) {
|
static isDraconic(competence) {
|
||||||
return competence?.system.categorie == 'draconic';
|
return Misc.data(competence)?.data.categorie == 'draconic';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getVoieDraconic(competences, voie) {
|
static getVoieDraconic(competences, voie) {
|
||||||
return RdDItemCompetence.findFirstItem(competences, voie, {
|
return RdDItemCompetence.findCompetence(competences.filter(it => RdDItemCompetence.isDraconic(it)), voie);
|
||||||
preFilter: it => it.isCompetence() && RdDItemCompetence.isDraconic(it),
|
|
||||||
description: 'Draconic',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isCompetenceArme(competence) {
|
static isCompetenceArme(competence) {
|
||||||
if (competence.isCompetence()) {
|
switch (Misc.templateData(competence).categorie) {
|
||||||
switch (competence.system.categorie) {
|
case 'melee':
|
||||||
case 'melee':
|
return Misc.data(competence).name != 'Esquive';
|
||||||
return !Grammar.toLowerCaseNoAccent(competence.name).includes('esquive');
|
case 'tir':
|
||||||
case 'tir':
|
case 'lancer':
|
||||||
case 'lancer':
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isArmeUneMain(competence) {
|
static isArmeUneMain(competence) {
|
||||||
return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("1 main");
|
return Misc.data(competence)?.name.toLowerCase().includes("1 main");
|
||||||
}
|
}
|
||||||
static isArme2Main(competence) {
|
static isArme2Main(competence) {
|
||||||
return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("2 main");
|
return Misc.data(competence)?.name.toLowerCase().includes("2 main");
|
||||||
}
|
|
||||||
|
|
||||||
static isThanatos(competence) {
|
|
||||||
return competence.isCompetencePersonnage() && Grammar.toLowerCaseNoAccent(competence.name).includes('thanatos');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isMalusEncombrementTotal(competence) {
|
static isMalusEncombrementTotal(competence) {
|
||||||
return competence?.name.toLowerCase().match(/(natation|acrobatie)/) || 0;
|
return Misc.data(competence)?.name.toLowerCase().match(/(natation|acrobatie)/);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -129,10 +133,11 @@ export class RdDItemCompetence extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static computeXP(competence) {
|
static computeXP(competence) {
|
||||||
const factor = RdDItemCompetence.isThanatos(competence) ? 2 : 1; // Thanatos compte double !
|
const itemData = Misc.data(competence);
|
||||||
const xpNiveau = RdDItemCompetence.computeDeltaXP(competence.system.base, competence.system.niveau ?? competence.system.base);
|
const factor = itemData.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double !
|
||||||
const xp = competence.system.xp ?? 0;
|
const xpNiveau = RdDItemCompetence.computeDeltaXP(itemData.data.base, itemData.data.niveau ?? itemData.data.base);
|
||||||
const xpSort = competence.system.xp_sort ?? 0;
|
const xp = itemData.data.xp ?? 0;
|
||||||
|
const xpSort = itemData.data.xp_sort ?? 0;
|
||||||
return factor * (xpNiveau + xp) + xpSort;
|
return factor * (xpNiveau + xp) + xpSort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +146,7 @@ export class RdDItemCompetence extends Item {
|
|||||||
return competenceTroncs.map(
|
return competenceTroncs.map(
|
||||||
list => list.map(name => RdDItemCompetence.findCompetence(competences, name))
|
list => list.map(name => RdDItemCompetence.findCompetence(competences, name))
|
||||||
// calcul du coût xp jusqu'au niveau 0 maximum
|
// calcul du coût xp jusqu'au niveau 0 maximum
|
||||||
.map(it => RdDItemCompetence.computeDeltaXP(it?.system.base ?? -11, Math.min(it?.system.niveau ?? -11, 0)))
|
.map(it => RdDItemCompetence.computeDeltaXP(it?.data.base ?? -11, Math.min(it?.data.niveau ?? -11, 0)))
|
||||||
.sort(Misc.ascending())
|
.sort(Misc.ascending())
|
||||||
.splice(0, list.length - 1) // prendre toutes les valeurs sauf l'une des plus élevées
|
.splice(0, list.length - 1) // prendre toutes les valeurs sauf l'une des plus élevées
|
||||||
.reduce(Misc.sum(), 0)
|
.reduce(Misc.sum(), 0)
|
||||||
@ -157,10 +162,11 @@ export class RdDItemCompetence extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static computeCompetenceXPCost(competence) {
|
static computeCompetenceXPCost(competence) {
|
||||||
let xp = RdDItemCompetence.getDeltaXp(competence.system.base, competence.system.niveau ?? competence.system.base);
|
const compData = Misc.data(competence);
|
||||||
xp += competence.system.xp ?? 0;
|
let xp = RdDItemCompetence.getDeltaXp(compData.data.base, compData.data.niveau ?? compData.data.base);
|
||||||
|
xp += compData.data.xp ?? 0;
|
||||||
if (compData.name.includes('Thanatos')) xp *= 2; /// Thanatos compte double !
|
if (compData.name.includes('Thanatos')) xp *= 2; /// Thanatos compte double !
|
||||||
xp += competence.system.xp_sort ?? 0;
|
xp += compData.data.xp_sort ?? 0;
|
||||||
return xp;
|
return xp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,75 +175,61 @@ export class RdDItemCompetence extends Item {
|
|||||||
let economie = 0;
|
let economie = 0;
|
||||||
for (let troncList of competenceTroncs) {
|
for (let troncList of competenceTroncs) {
|
||||||
let list = troncList.map(name => RdDItemCompetence.findCompetence(competences, name))
|
let list = troncList.map(name => RdDItemCompetence.findCompetence(competences, name))
|
||||||
.sort(Misc.descending(c => this.system.niveau)); // tri du plus haut au plus bas
|
.sort(Misc.descending(c => Misc.templateData(c).niveau)); // tri du plus haut au plus bas
|
||||||
list.splice(0, 1); // ignorer la plus élevée
|
list.splice(0, 1); // ignorer la plus élevée
|
||||||
list.map(c => c).forEach(c => {
|
list.map(c => Misc.templateData(c)).forEach(tplData => {
|
||||||
economie += RdDItemCompetence.getDeltaXp(c.system.base, Math.min(c.system.niveau, 0))
|
economie += RdDItemCompetence.getDeltaXp(tplData.base, Math.min(tplData.niveau, 0));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return economie;
|
return economie;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static levelUp(item, stressTransforme) {
|
static levelUp(itemData, stressTransforme) {
|
||||||
item.system.xpNext = RdDItemCompetence.getCompetenceNextXp(item.system.niveau);
|
itemData.data.xpNext = RdDItemCompetence.getCompetenceNextXp(itemData.data.niveau);
|
||||||
const xpManquant = item.system.xpNext - item.system.xp;
|
const xpManquant = itemData.data.xpNext - itemData.data.xp;
|
||||||
item.system.isLevelUp = xpManquant <= 0;
|
itemData.data.isLevelUp = xpManquant <= 0;
|
||||||
item.system.isStressLevelUp = (xpManquant > 0 && stressTransforme >= xpManquant && item.system.niveau < item.system.niveau_archetype);
|
itemData.data.isStressLevelUp = (xpManquant > 0 && stressTransforme >= xpManquant && itemData.data.niveau < itemData.data.niveau_archetype);
|
||||||
item.system.stressXpMax = 0;
|
itemData.data.stressXpMax = 0;
|
||||||
if (xpManquant > 0 && stressTransforme > 0 && item.system.niveau < item.system.niveau_archetype) {
|
if (xpManquant > 0 && stressTransforme > 0 && itemData.data.niveau < itemData.data.niveau_archetype) {
|
||||||
item.system.stressXpMax = Math.min(xpManquant, stressTransforme);
|
itemData.data.stressXpMax = Math.min(xpManquant , stressTransforme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isVisible(item) {
|
static isVisible(itemData) {
|
||||||
return Number(item.system.niveau) != RdDItemCompetence.getNiveauBase(item.system.categorie);
|
return Number(itemData.data.niveau) != RdDItemCompetence.getNiveauBase(itemData.data.categorie);
|
||||||
}
|
}
|
||||||
|
|
||||||
static nomContientTexte(item, texte) {
|
static nomContientTexte(itemData, texte) {
|
||||||
return Grammar.toLowerCaseNoAccent(item.name).includes(Grammar.toLowerCaseNoAccent(texte))
|
return Grammar.toLowerCaseNoAccent(itemData.name).includes(Grammar.toLowerCaseNoAccent(texte))
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isNiveauBase(item) {
|
static isNiveauBase(itemData) {
|
||||||
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie);
|
return Number(itemData.data.niveau) == RdDItemCompetence.getNiveauBase(itemData.data.categorie);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static findCompetence(list, idOrName, options = {}) {
|
static findCompetence(list, idOrName, options = {}) {
|
||||||
if (idOrName == undefined || idOrName == "") {
|
if (idOrName == undefined) {
|
||||||
return RdDItemCompetence.sansCompetence();
|
return undefined;
|
||||||
}
|
}
|
||||||
options = mergeObject(options, { preFilter: it => it.isCompetence(), description: 'compétence' }, { overwrite: false });
|
options = mergeObject(options, {
|
||||||
return RdDItemCompetence.findFirstItem(list, idOrName, options);
|
preFilter: it => RdDItemCompetence.isCompetence(it),
|
||||||
|
description: 'compétence',
|
||||||
|
});
|
||||||
|
return list.find(it => it.id == idOrName && RdDItemCompetence.isCompetence(it))
|
||||||
|
?? Misc.findFirstLike(idOrName, list, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static findCompetences(list, name) {
|
static findCompetences(list, name) {
|
||||||
return Misc.findAllLike(name, list, { filter: it => it.isCompetence(), description: 'compétence' });
|
return Misc.findAllLike(name, list, { filter: it => RdDItemCompetence.isCompetence(it), description: 'compétence' });
|
||||||
}
|
}
|
||||||
|
|
||||||
static sansCompetence() {
|
static isCompetence(item) {
|
||||||
return {
|
return item.type == 'competence' || item.type == 'competencecreature';
|
||||||
name: "Sans compétence",
|
|
||||||
type: "competence",
|
|
||||||
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp",
|
|
||||||
system: {
|
|
||||||
niveau: 0,
|
|
||||||
default_diffLibre: 0,
|
|
||||||
base: 0,
|
|
||||||
categorie: "Aucune",
|
|
||||||
description: "",
|
|
||||||
descriptionmj: "",
|
|
||||||
defaut_carac: "",
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static findFirstItem(list, idOrName, options) {
|
|
||||||
return list.find(it => it.id == idOrName && options.preFilter(it))
|
|
||||||
?? Misc.findFirstLike(idOrName, list, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -268,7 +260,7 @@ export class RdDItemCompetence extends Item {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static computeResumeArchetype(competences) {
|
static computeResumeArchetype(competences) {
|
||||||
const archetype = RdDItemCompetence.getLimitesArchetypes();
|
const archetype = RdDItemCompetence.getLimitesArchetypes();
|
||||||
competences.map(it => Math.max(0, it.system.niveau_archetype))
|
competences.map(it => Math.max(0, Misc.templateData(it).niveau_archetype))
|
||||||
.forEach(niveau => {
|
.forEach(niveau => {
|
||||||
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
|
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
|
||||||
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;
|
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;
|
||||||
|
@ -1,53 +1,51 @@
|
|||||||
|
import { Misc } from "./misc.js";
|
||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDItemCompetenceCreature extends Item {
|
export class RdDItemCompetenceCreature extends Item {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static setRollDataCreature(rollData) {
|
static setRollDataCreature(rollData) {
|
||||||
rollData.competence = rollData.competence
|
rollData.competence = Misc.data(rollData.competence);
|
||||||
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
|
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.data.carac_value } };
|
||||||
rollData.competence.system.defaut_carac = "carac_creature"
|
rollData.competence.data.defaut_carac = "carac_creature"
|
||||||
rollData.competence.system.categorie = "creature"
|
rollData.competence.data.categorie = "creature"
|
||||||
rollData.selectedCarac = rollData.carac.carac_creature
|
rollData.selectedCarac = rollData.carac.carac_creature
|
||||||
if (rollData.competence.system.iscombat) {
|
if (rollData.competence.data.iscombat) {
|
||||||
rollData.arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence);
|
rollData.arme = RdDItemCompetenceCreature.toActionArme(rollData.competence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static armeNaturelle(competencecreature) {
|
static toActionArme(item) {
|
||||||
if (RdDItemCompetenceCreature.isCompetenceAttaque(competencecreature)) {
|
if (RdDItemCompetenceCreature.isCompetenceAttaque(item)) {
|
||||||
// si c'est un Item compétence: cloner pour ne pas modifier lma compétence
|
// si c'est un Item compétence: cloner pour ne pas modifier la compétence
|
||||||
let arme = (competencecreature instanceof Item) ? competencecreature.clone(): competencecreature;
|
let arme = Misc.data( (item instanceof Item) ? item.clone(): item);
|
||||||
mergeObject(arme.system,
|
mergeObject(arme.data,
|
||||||
{
|
{
|
||||||
competence: arme.name,
|
competence: arme.name,
|
||||||
initiative: RdDCombatManager.calculInitiative(competencecreature.system.niveau, competencecreature.system.carac_value),
|
|
||||||
niveau: competencecreature.system.niveau,
|
|
||||||
equipe: true,
|
|
||||||
resistance: 100,
|
resistance: 100,
|
||||||
dommagesReels: arme.system.dommages,
|
equipe: true,
|
||||||
|
dommagesReels: arme.data.dommages,
|
||||||
penetration: 0,
|
penetration: 0,
|
||||||
force: 0,
|
force: 0,
|
||||||
rapide: true,
|
rapide: true,
|
||||||
cac: competencecreature.system.isnaturelle ? "naturelle" : "",
|
|
||||||
action: 'attaque'
|
action: 'attaque'
|
||||||
});
|
});
|
||||||
return arme;
|
return arme;
|
||||||
}
|
}
|
||||||
console.error("RdDItemCompetenceCreature.toActionArme(", competencecreature, ") : impossible de transformer l'Item en arme");
|
console.error("RdDItemCompetenceCreature.toActionArme(", item, ") : impossible de transformer l'Item en arme");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isCompetenceAttaque(item) {
|
static isCompetenceAttaque(itemData) {
|
||||||
return item.type == 'competencecreature' && item.system.iscombat;
|
itemData = Misc.data(itemData);
|
||||||
|
return itemData.type == 'competencecreature' && itemData.data.iscombat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isCompetenceParade(item) {
|
static isCompetenceParade(itemData) {
|
||||||
return item.type == 'competencecreature' && item.system.categorie_parade !== "";
|
itemData = Misc.data(itemData);
|
||||||
|
return itemData.type == 'competencecreature' && itemData.data.isparade;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
|
||||||
import { EnvironmentSheetHelper as EnvironmentItemSheet } from "./environnement.js";
|
|
||||||
import { Misc } from "./misc.js";
|
|
||||||
|
|
||||||
const ITEM_TYPE = 'herbe';
|
|
||||||
|
|
||||||
export class RdDHerbeItemSheet extends ItemSheet {
|
|
||||||
|
|
||||||
static register() {
|
|
||||||
Items.registerSheet(SYSTEM_RDD, RdDHerbeItemSheet, {
|
|
||||||
label: Misc.typeName('Item', ITEM_TYPE),
|
|
||||||
types: [ITEM_TYPE],
|
|
||||||
makeDefault: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
return EnvironmentItemSheet.defaultOptions(super.defaultOptions, ITEM_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getHeaderButtons() {
|
|
||||||
return EnvironmentItemSheet.getHeaderButtons(this, super._getHeaderButtons());
|
|
||||||
}
|
|
||||||
|
|
||||||
setPosition(options = {}) {
|
|
||||||
return EnvironmentItemSheet.setPosition(this, super.setPosition(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
async getData() {
|
|
||||||
return await EnvironmentItemSheet.getData(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
EnvironmentItemSheet.activateListeners(this, html);
|
|
||||||
}
|
|
||||||
|
|
||||||
get template() {
|
|
||||||
return EnvironmentItemSheet.template(this.item.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
get title() {
|
|
||||||
return EnvironmentItemSheet.title(this.item);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,44 +0,0 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
|
||||||
import { EnvironmentSheetHelper } from "./environnement.js";
|
|
||||||
import { Misc } from "./misc.js";
|
|
||||||
|
|
||||||
const ITEM_TYPE = 'ingredient';
|
|
||||||
export class RdDIngredientItemSheet extends ItemSheet {
|
|
||||||
|
|
||||||
static register() {
|
|
||||||
Items.registerSheet(SYSTEM_RDD, RdDIngredientItemSheet, {
|
|
||||||
label: Misc.typeName('Item', ITEM_TYPE),
|
|
||||||
types: [ITEM_TYPE],
|
|
||||||
makeDefault: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions, ITEM_TYPE);
|
|
||||||
}
|
|
||||||
|
|
||||||
_getHeaderButtons() {
|
|
||||||
return EnvironmentSheetHelper.getHeaderButtons(this, super._getHeaderButtons());
|
|
||||||
}
|
|
||||||
|
|
||||||
setPosition(options = {}) {
|
|
||||||
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
async getData() {
|
|
||||||
return await EnvironmentSheetHelper.getData(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
EnvironmentSheetHelper.activateListeners(this, html);
|
|
||||||
}
|
|
||||||
|
|
||||||
get template() {
|
|
||||||
return EnvironmentSheetHelper.template(this.item.type);
|
|
||||||
}
|
|
||||||
|
|
||||||
get title() {
|
|
||||||
return EnvironmentSheetHelper.title(this.item);
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ export class RdDItemMeditation {
|
|||||||
static calculDifficulte(rollData) {
|
static calculDifficulte(rollData) {
|
||||||
if (rollData.meditation) {
|
if (rollData.meditation) {
|
||||||
// Malus permanent éventuel
|
// Malus permanent éventuel
|
||||||
let diff = rollData.meditation.system.malus ?? 0;
|
let diff = rollData.meditation.data.malus ?? 0;
|
||||||
if (!rollData.conditionMeditation.isHeure) diff -= 2;
|
if (!rollData.conditionMeditation.isHeure) diff -= 2;
|
||||||
if (!rollData.conditionMeditation.isVeture) diff -= 2;
|
if (!rollData.conditionMeditation.isVeture) diff -= 2;
|
||||||
if (!rollData.conditionMeditation.isComportement) diff -= 2;
|
if (!rollData.conditionMeditation.isComportement) diff -= 2;
|
||||||
|
@ -1,93 +1,61 @@
|
|||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { LOG_HEAD } from "./constants.js";
|
|
||||||
|
|
||||||
const MONNAIE_ETAIN = {
|
const monnaiesData = [
|
||||||
name: "Etain (1 denier)", type: 'monnaie',
|
{
|
||||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
|
name: "Etain (1 denier)", type: 'monnaie',
|
||||||
system: { quantite: 0, cout: 0.01, encombrement: 0.001, description: "" }
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
|
||||||
};
|
data: { 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",
|
name: "Bronze (10 deniers)", type: 'monnaie',
|
||||||
system: { quantite: 0, cout: 0.10, encombrement: 0.002, description: "" }
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp",
|
||||||
};
|
data: { 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",
|
name: "Argent (1 sol)", type: 'monnaie',
|
||||||
system: { quantite: 0, cout: 1, encombrement: 0.003, description: "" }
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp",
|
||||||
};
|
data: { 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",
|
name: "Or (10 sols)", type: 'monnaie',
|
||||||
system: { quantite: 0, cout: 10, encombrement: 0.004, description: "" }
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
|
||||||
};
|
data: { quantite: 0, valeur_deniers: 1000, encombrement: 0.004, description: "" }
|
||||||
|
}
|
||||||
const MONNAIES_STANDARD = [MONNAIE_ETAIN, MONNAIE_BRONZE, MONNAIE_ARGENT, MONNAIE_OR];
|
]
|
||||||
|
|
||||||
export class Monnaie {
|
export class Monnaie {
|
||||||
|
|
||||||
static monnaiesStandard() {
|
static isSystemMonnaie(item) {
|
||||||
return MONNAIES_STANDARD;
|
let present = monnaiesData.find(monnaie => monnaie.data.valeur_deniers == Misc.data(item)?.data?.valeur_deniers);
|
||||||
|
return present;
|
||||||
}
|
}
|
||||||
|
|
||||||
static monnaiesManquantes(actor) {
|
static monnaiesData() {
|
||||||
const disponibles = actor.itemTypes['monnaie'];
|
return monnaiesData;
|
||||||
const manquantes = MONNAIES_STANDARD.filter(standard => !disponibles.find(disponible => Monnaie.deValeur(disponible, standard.system?.cout)));
|
|
||||||
if (manquantes.length > 0) {
|
|
||||||
console.error(`${LOG_HEAD} monnaiesManquantes pour ${actor.name}`, manquantes, ' avec monnaies', disponibles, MONNAIES_STANDARD);
|
|
||||||
}
|
|
||||||
return manquantes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static deValeur(monnaie, valeur) {
|
static filtrerMonnaies(items) {
|
||||||
return Monnaie.valEntiere(valeur) == Monnaie.valEntiere(monnaie.system.cout)
|
return items.filter(it => Misc.data(it).type == 'monnaie');
|
||||||
}
|
}
|
||||||
|
|
||||||
static valEntiere(sols) {
|
static monnaiesManquantes(items) {
|
||||||
return Math.max(Math.floor((sols??0)*100), 0);
|
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 triValeurEntiere() {
|
static deValeur(monnaie, v) {
|
||||||
return Misc.ascending(item => Monnaie.valEntiere(item.system.cout))
|
return v != monnaie.data.valeur_deniers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async creerMonnaiesStandard(actor) {
|
static arrondiDeniers(sols) {
|
||||||
await actor.createEmbeddedDocuments('Item', MONNAIES_STANDARD, { renderSheet: false });
|
return sols.toFixed(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static async creerMonnaiesDeniers(actor, fortune) {
|
static triValeurDenier() {
|
||||||
await actor.createEmbeddedDocuments('Item', [Monnaie.creerDeniers(fortune)], { renderSheet: false });
|
return Misc.ascending(item => Misc.data(item).data.valeur_deniers);
|
||||||
}
|
}
|
||||||
|
|
||||||
static creerDeniers(fortune) {
|
|
||||||
const deniers = duplicate(MONNAIE_ETAIN);
|
|
||||||
deniers.system.quantite = fortune;
|
|
||||||
return deniers;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async optimiserFortune(actor, fortune) {
|
|
||||||
let resteEnDeniers = Math.round(fortune*100);
|
|
||||||
let monnaies = actor.itemTypes['monnaie'];
|
|
||||||
let updates = [];
|
|
||||||
let parValeur = Misc.classifyFirst(monnaies, it => Monnaie.valEntiere(it.system.cout));
|
|
||||||
for (let valeurDeniers of [1000, 100, 10, 1]) {
|
|
||||||
const itemPiece = parValeur[valeurDeniers];
|
|
||||||
if (itemPiece) {
|
|
||||||
const quantite = Math.floor(resteEnDeniers / valeurDeniers);
|
|
||||||
if (quantite != itemPiece.system.quantite) {
|
|
||||||
updates.push({ _id: parValeur[valeurDeniers].id, 'system.quantite': quantite });
|
|
||||||
}
|
|
||||||
resteEnDeniers -= quantite*valeurDeniers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
console.log('Monnaie.optimiserFortune', actor.name, 'total', fortune, 'parValeur', parValeur, 'updates', updates, 'reste', resteEnDeniers);
|
|
||||||
if (updates.length > 0) {
|
|
||||||
await actor.updateEmbeddedDocuments('Item', updates);
|
|
||||||
}
|
|
||||||
if (resteEnDeniers > 0){
|
|
||||||
// créer le reste en deniers fortune en deniers
|
|
||||||
await Monnaie.creerMonnaiesDeniers(actor, resteEnDeniers);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
import { RdDRencontre } from "./item-rencontre.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Item sheet pour configurer les rencontres
|
|
||||||
* @extends {ItemSheet}
|
|
||||||
*/
|
|
||||||
export class RdDRencontreItemSheet extends ItemSheet {
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
static get defaultOptions() {
|
|
||||||
return mergeObject(super.defaultOptions, {
|
|
||||||
classes: ["rdd", "sheet", "item"],
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html",
|
|
||||||
width: 500,
|
|
||||||
height: 500,
|
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
_getHeaderButtons() {
|
|
||||||
let buttons = super._getHeaderButtons();
|
|
||||||
buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => this.item.postItem() });
|
|
||||||
return buttons;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** @override */
|
|
||||||
setPosition(options = {}) {
|
|
||||||
const position = super.setPosition(options);
|
|
||||||
const sheetHeader = this.element.find(".sheet-header");
|
|
||||||
const sheetBody = this.element.find(".sheet-body");
|
|
||||||
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async getData() {
|
|
||||||
const formData = duplicate(this.item);
|
|
||||||
mergeObject(formData, {
|
|
||||||
title: formData.name,
|
|
||||||
isGM: game.user.isGM,
|
|
||||||
owner: this.actor?.isOwner,
|
|
||||||
isOwned: this.actor ? true : false,
|
|
||||||
actorId: this.actor?.id,
|
|
||||||
editable: this.isEditable,
|
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
|
||||||
effets: {
|
|
||||||
succes: {
|
|
||||||
liste: RdDRencontre.getEffetsSucces(),
|
|
||||||
select: RdDRencontre.mapEffets(this.item.system.succes.effets)
|
|
||||||
},
|
|
||||||
echec: {
|
|
||||||
liste: RdDRencontre.getEffetsEchec(),
|
|
||||||
select: RdDRencontre.mapEffets(this.item.system.echec.effets)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** @override */
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
if (!this.options.editable) return;
|
|
||||||
html.find("a.effet-add").click(event => this.onAddEffet(event));
|
|
||||||
html.find("a.effet-delete").click(event => this.onDeleteEffet(event));
|
|
||||||
}
|
|
||||||
|
|
||||||
async onAddEffet(event) {
|
|
||||||
const resultat = $(event.currentTarget)?.data("effet-resultat");
|
|
||||||
const keyEffets = `system.${resultat}.effets`;
|
|
||||||
|
|
||||||
const code = $(event.currentTarget)?.data("effet-code");
|
|
||||||
const liste = RdDRencontre.getListeEffets(this.item, resultat);
|
|
||||||
liste.push(code);
|
|
||||||
|
|
||||||
await this._updateEffetsRencontre(keyEffets, liste);
|
|
||||||
}
|
|
||||||
|
|
||||||
async onDeleteEffet(event) {
|
|
||||||
const resultat = $(event.currentTarget)?.data("effet-resultat");
|
|
||||||
const keyEffets = `system.${resultat}.effets`;
|
|
||||||
|
|
||||||
const pos = $(event.currentTarget)?.data("effet-pos");
|
|
||||||
const liste = RdDRencontre.getListeEffets(this.item, resultat);
|
|
||||||
liste.splice(pos, 1);
|
|
||||||
|
|
||||||
await this._updateEffetsRencontre(keyEffets, liste);
|
|
||||||
}
|
|
||||||
|
|
||||||
async _updateEffetsRencontre(key, liste) {
|
|
||||||
const updates = {};
|
|
||||||
updates[key] = liste;
|
|
||||||
this.item.update(updates);
|
|
||||||
}
|
|
||||||
|
|
||||||
get template() {
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
return `systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html`;
|
|
||||||
}
|
|
||||||
|
|
||||||
get title() {
|
|
||||||
return `Rencontre: ${this.object.name}`;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
import { EffetsRencontre } from "./effets-rencontres.js";
|
|
||||||
|
|
||||||
const tableEffets = [
|
|
||||||
{ code: "messager", resultat: "succes", description: "Envoie un message à (force) cases", method: EffetsRencontre.messager },
|
|
||||||
{ code: "passeur", resultat: "succes", description: "Déplacer le demi-rêve à (force) cases", method: EffetsRencontre.passeur},
|
|
||||||
{ code: "reve+f", resultat: "succes", description: "Gain de (force) points de rêve" , method: EffetsRencontre.reve_plus_force},
|
|
||||||
{ code: "teleport", resultat: "succes", description: "Déplacer le demi-rêve (même type)", method: EffetsRencontre.teleportation_typecase },
|
|
||||||
{ code: "part+tete", resultat: "succes", description: "Tête de dragon sur réussite particulière", method: EffetsRencontre.rdd_part_tete },
|
|
||||||
{ code: "part+xp", resultat: "succes", description: "Expérience sur réussite particulière", method: EffetsRencontre.experience_particuliere },
|
|
||||||
{ code: "seuil", resultat: "succes", description: "Récupération de seuil de rêve", method: EffetsRencontre.regain_seuil },
|
|
||||||
|
|
||||||
{ code: "reve-1", resultat: "echec", description: "Perte de 1 point de rêve", method: EffetsRencontre.reve_moins_1 },
|
|
||||||
{ code: "reve-f", resultat: "echec", description: "Perte de (force) points de rêve", method: EffetsRencontre.reve_moins_force },
|
|
||||||
{ code: "vie-1", resultat: "echec", description: "Perte de 1 point de vie", method: EffetsRencontre.vie_moins_1 },
|
|
||||||
{ code: "reinsere", resultat: "echec", description: "Réinsertion aléatoire", method: EffetsRencontre.reinsertion },
|
|
||||||
{ code: "persistant", resultat: "echec", description: "Bloque le demi-rêve", method: EffetsRencontre.rencontre_persistante },
|
|
||||||
{ code: "teleport-aleatoire", resultat: "echec", description: "Déplacement aléatoire (même type)", method: EffetsRencontre.teleportation_aleatoire_typecase },
|
|
||||||
{ code: "aleatoire", resultat: "echec", description: "Déplacement aléatoire", method: EffetsRencontre.deplacement_aleatoire },
|
|
||||||
{ code: "sort-aleatoire", resultat: "echec", description: "Déclenche un sort en réserve aléatoire", method: EffetsRencontre.sort_aleatoire },
|
|
||||||
{ code: "rompu", resultat: "echec", description: "Demi-rêve interrompu", method: EffetsRencontre.demireve_rompu },
|
|
||||||
{ code: "echec-queue", resultat: "echec", description: "Queue(s) de dragon sur échec", method: EffetsRencontre.rdd_echec_queue },
|
|
||||||
|
|
||||||
{ code: "reve+1", resultat: "succes", description: "Gain de 1 point de rêve", method: EffetsRencontre.reve_plus_1 },
|
|
||||||
{ code: "vie-f", resultat: "echec", description: "Perte de (force) points de vie", method: EffetsRencontre.vie_moins_force },
|
|
||||||
{ code: "moral+1", resultat: "succes", description: "Gain de 1 point de moral", method: EffetsRencontre.moral_plus_1 },
|
|
||||||
{ code: "moral-1", resultat: "echec", description: "Perte de 1 point de moral", method: EffetsRencontre.moral_moins_1 },
|
|
||||||
{ code: "xpsort+f", resultat: "succes", description: "Gain de (force) xp sort", method: EffetsRencontre.xp_sort_force },
|
|
||||||
{ code: "endurance-1", resultat: "echec", description: "Perte de 1 point d'endurance", method: EffetsRencontre.end_moins_1 },
|
|
||||||
{ code: "endurance-f", resultat: "echec", description: "Perte de (force) points d'endurance", method: EffetsRencontre.end_moins_force },
|
|
||||||
{ code: "fatigue+1", resultat: "echec", description: "Coup de fatigue de 1 point", method: EffetsRencontre.fatigue_plus_1},
|
|
||||||
{ code: "fatigue+f", resultat: "echec", description: "Coup de fatigue de 1 (force) points", method: EffetsRencontre.fatigue_plus_force },
|
|
||||||
{ code: "fatigue-1", resultat: "succes", description: "Récupération de 1 point de fatigue", method: EffetsRencontre.fatigue_moins_1},
|
|
||||||
{ code: "fatigue-f", resultat: "succes", description: "Récupération de 1 (force) points de fatigue", method: EffetsRencontre.fatigue_moins_force },
|
|
||||||
{ code: "perte-chance", resultat: "echec", description: "Perte de chance actuelle", method: EffetsRencontre.perte_chance },
|
|
||||||
{ code: "stress+1", resultat: "succes", description: "Gain de 1 point de stress", method: EffetsRencontre.stress_plus_1 },
|
|
||||||
// { code: "epart-souffle", resultat: "echec", description: "Souffle de dragon sur échec particulier" },
|
|
||||||
];
|
|
||||||
|
|
||||||
export class RdDRencontre {
|
|
||||||
|
|
||||||
static getEffetsSucces() { return RdDRencontre.getEffets("succes"); }
|
|
||||||
static getEffetsEchec() { return RdDRencontre.getEffets("echec"); }
|
|
||||||
static getEffets(resultat) {
|
|
||||||
return tableEffets.filter(e => resultat == e.resultat);
|
|
||||||
}
|
|
||||||
|
|
||||||
static mapEffets(liste) {
|
|
||||||
return liste.map(it => RdDRencontre.getEffet(it));
|
|
||||||
}
|
|
||||||
|
|
||||||
static getListeEffets(item, reussite) {
|
|
||||||
if (reussite == 'echec') {
|
|
||||||
return [...item.system.echec.effets];
|
|
||||||
}
|
|
||||||
if (reussite == 'succes') {
|
|
||||||
return [...item.system.succes.effets];
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
static getEffet(code) {
|
|
||||||
return tableEffets.find(it => code == it.code)
|
|
||||||
}
|
|
||||||
|
|
||||||
static async appliquer(codes, tmrDialog, rencData) {
|
|
||||||
for(const effet of RdDRencontre.mapEffets(codes)){
|
|
||||||
await effet.method(tmrDialog, rencData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -4,11 +4,11 @@ import { RdDAlchimie } from "./rdd-alchimie.js";
|
|||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
import { RdDHerbes } from "./rdd-herbes.js";
|
import { RdDHerbes } from "./rdd-herbes.js";
|
||||||
import { RdDGemme } from "./rdd-gemme.js";
|
import { RdDGemme } from "./rdd-gemme.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||||
import { SYSTEM_RDD } from "./constants.js";
|
import { SYSTEM_RDD } from "./constants.js";
|
||||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the basic ItemSheet with some very simple modifications
|
* Extend the basic ItemSheet with some very simple modifications
|
||||||
@ -32,7 +32,7 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
let buttons = super._getHeaderButtons();
|
let buttons = super._getHeaderButtons();
|
||||||
// Add "Post to chat" button
|
// 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!
|
// 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 this.item.system && this.item.isVideOuNonConteneur()) {
|
if ("cout" in Misc.templateData(this.object) && this.object.isVideOuNonConteneur()) {
|
||||||
buttons.unshift({
|
buttons.unshift({
|
||||||
class: "vendre",
|
class: "vendre",
|
||||||
icon: "fas fa-comments-dollar",
|
icon: "fas fa-comments-dollar",
|
||||||
@ -60,75 +60,55 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getData() {
|
async getData() {
|
||||||
|
const objectData = Misc.data(this.object)
|
||||||
let formData = {
|
let formData = {
|
||||||
id: this.item.id,
|
id: this.object.id,
|
||||||
title: this.item.name,
|
title: objectData.name,
|
||||||
type: this.item.type,
|
type: objectData.type,
|
||||||
img: this.item.img,
|
img: objectData.img,
|
||||||
name: this.item.name,
|
name: objectData.name,
|
||||||
system: this.item.system,
|
data: objectData.data,
|
||||||
isGM: game.user.isGM,
|
isGM: game.user.isGM,
|
||||||
actorId: this.actor?.id,
|
actorId: this.actor?.id,
|
||||||
owner: this.item.isOwner,
|
owner: this.document.isOwner,
|
||||||
editable: this.isEditable,
|
editable: this.isEditable,
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
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) {
|
if (this.actor) {
|
||||||
formData.isOwned = true;
|
formData.isOwned = true;
|
||||||
if (this.item.type == 'conteneur') {
|
if (objectData.type == 'conteneur') {
|
||||||
this.prepareConteneurData(formData);
|
this.prepareConteneurData(formData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const competences = await SystemCompendiums.getCompetences(this.actor?.type);
|
|
||||||
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences()
|
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences()
|
||||||
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
|
if (formData.type == 'tache' || formData.type == 'livre' || formData.type == 'meditation' || formData.type == 'oeuvre') {
|
||||||
formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
|
formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
|
||||||
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve)
|
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve)
|
||||||
formData.competences = competences;
|
formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences')
|
||||||
}
|
}
|
||||||
if (this.item.type == 'arme') {
|
if (formData.type == 'arme') {
|
||||||
formData.competences = competences.filter(it => RdDItemCompetence.isCompetenceArme(it));
|
formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it));
|
||||||
|
console.log(formData.competences)
|
||||||
}
|
}
|
||||||
if (['sort', 'sortreserve'].includes(this.item.type)) {
|
if (formData.type == 'recettealchimique') {
|
||||||
formData.competences = competences.filter(it => RdDItemCompetence.isDraconic(it));
|
RdDAlchimie.processManipulation(objectData, this.actor && this.actor.id);
|
||||||
}
|
}
|
||||||
if (this.item.type == 'recettecuisine') {
|
if (formData.type == 'gemme') {
|
||||||
formData.ingredients = await TextEditor.enrichHTML(this.object.system.ingredients, {async: true})
|
|
||||||
}
|
|
||||||
if (this.item.type == 'extraitpoetique') {
|
|
||||||
formData.extrait = await TextEditor.enrichHTML(this.object.system.extrait, {async: true})
|
|
||||||
formData.texte = await TextEditor.enrichHTML(this.object.system.texte, {async: true})
|
|
||||||
}
|
|
||||||
if (this.item.type == 'recettealchimique') {
|
|
||||||
RdDAlchimie.processManipulation(this.item, this.actor && this.actor.id);
|
|
||||||
formData.manipulation_update = await TextEditor.enrichHTML(this.object.system.manipulation_update, {async: true})
|
|
||||||
formData.utilisation = await TextEditor.enrichHTML(this.object.system.utilisation, {async: true})
|
|
||||||
formData.enchantement = await TextEditor.enrichHTML(this.object.system.enchantement, {async: true})
|
|
||||||
formData.sureffet = await TextEditor.enrichHTML(this.object.system.sureffet, {async: true})
|
|
||||||
}
|
|
||||||
if (this.item.type == 'gemme') {
|
|
||||||
formData.gemmeTypeList = RdDGemme.getGemmeTypeOptionList();
|
formData.gemmeTypeList = RdDGemme.getGemmeTypeOptionList();
|
||||||
RdDGemme.calculDataDerivees(this.item);
|
RdDGemme.calculDataDerivees(formData.data);
|
||||||
}
|
}
|
||||||
if (this.item.type == 'potion') {
|
if (formData.type == 'potion') {
|
||||||
if (this.dateUpdated) {
|
if (this.dateUpdated) {
|
||||||
formData.system.prdate = this.dateUpdated;
|
formData.data.prdate = this.dateUpdated;
|
||||||
this.dateUpdated = undefined;
|
this.dateUpdated = undefined;
|
||||||
}
|
}
|
||||||
await RdDHerbes.updatePotionData(formData);
|
RdDHerbes.updatePotionData(formData);
|
||||||
}
|
}
|
||||||
if (formData.isOwned && this.item.type == 'herbe' && (formData.system.categorie == 'Soin' || formData.system.categorie == 'Repos')) {
|
if (formData.isOwned && formData.type == 'herbe' && (formData.data.categorie == 'Soin' || formData.data.categorie == 'Repos')) {
|
||||||
formData.isIngredientPotionBase = true;
|
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);
|
formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
|
||||||
|
|
||||||
return formData;
|
return formData;
|
||||||
@ -136,10 +116,11 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
prepareConteneurData(formData) {
|
prepareConteneurData(formData) {
|
||||||
RdDUtility.filterEquipementParType(formData, this.actor.itemTypes);
|
formData.itemsByType = Misc.classify(this.actor.items.map(i => foundry.utils.deepClone(i.data)));
|
||||||
|
RdDUtility.filterEquipementParType(formData);
|
||||||
|
|
||||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||||
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
|
formData.subItems = formData.conteneurs.find(it => it._id == this.object.id)?.subItems;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,15 +129,15 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
if (this.item.type == 'conteneur') {
|
if (this.object.type == 'conteneur') {
|
||||||
this.form.ondragstart = (event) => this._onDragStart(event);
|
this.form.ondragstart = (event) => this._onDragStart(event);
|
||||||
this.form.ondrop = (event) => this._onDrop(event);
|
this.form.ondrop = (event) => this._onDrop(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
let itemSheetDialog = this;
|
let itemSheetDialog = this;
|
||||||
|
|
||||||
HtmlUtility._showControlWhen($(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.item.isOwned);
|
HtmlUtility._showControlWhen($(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.object.isOwned);
|
||||||
HtmlUtility._showControlWhen($(".item-magique"), this.item.isMagique());
|
HtmlUtility._showControlWhen($(".item-magique"), this.object.isMagique());
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
// Everything below here is only needed if the sheet is editable
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
@ -165,8 +146,8 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
html.find(".categorie").change(event => this._onSelectCategorie(event));
|
html.find(".categorie").change(event => this._onSelectCategorie(event));
|
||||||
|
|
||||||
html.find('.sheet-competence-xp').change((event) => {
|
html.find('.sheet-competence-xp').change((event) => {
|
||||||
if (this.item.isCompetencePersonnage()) {
|
if (this.object.data.type == 'competence') {
|
||||||
RdDUtility.checkThanatosXP(this.item.name);
|
RdDUtility.checkThanatosXP(this.object.data.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -201,7 +182,7 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
if (actor) {
|
if (actor) {
|
||||||
actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData);
|
actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData);
|
||||||
} else {
|
} else {
|
||||||
ui.notifications.info("Impossible trouver un acteur pour réaliser cette tache Alchimique.");
|
ui.notifications.info("Impossible trouver un actur pour réaliser cette tache Alchimique.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -215,8 +196,7 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
});
|
});
|
||||||
html.find('.item-delete').click(async event => {
|
html.find('.item-delete').click(async event => {
|
||||||
const li = RdDSheetUtility.getEventElement(event);
|
const li = RdDSheetUtility.getEventElement(event);
|
||||||
const item = this.actor.getObjet(li.data("item-id"));
|
RdDUtility.confirmerSuppression(this, li);
|
||||||
RdDUtility.confirmerSuppressionItem(this, item, li);
|
|
||||||
});
|
});
|
||||||
html.find('.item-vendre').click(async event => {
|
html.find('.item-vendre').click(async event => {
|
||||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||||
@ -240,27 +220,27 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
async _onSelectCategorie(event) {
|
async _onSelectCategorie(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if (this.item.isCompetence()) {
|
if (this.object.isCompetence()) {
|
||||||
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
|
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
|
||||||
this.item.system.base = level;
|
Misc.templateData(this.object).base = level;
|
||||||
$("#base").val(level);
|
$("#base").val(level);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
get template() {
|
get template() {
|
||||||
let type = this.item.type
|
let type = this.object.data.type;
|
||||||
return `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`;
|
return `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
_updateObject(event, formData) {
|
_updateObject(event, formData) { // Deprecated en v0.8 à clarifier
|
||||||
// Données de bonus de cases ?
|
// Données de bonus de cases ?
|
||||||
formData['system.bonuscase'] = RdDItemSort.buildBonusCaseStringFromFormData(formData.bonusValue, formData.caseValue);
|
formData = RdDItemSort.buildBonusCaseStringFromFormData(formData);
|
||||||
|
|
||||||
return this.item.update(formData);
|
return this.object.update(formData);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDragStart(event) {
|
async _onDragStart(event) {
|
||||||
@ -273,28 +253,28 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
const dragData = {
|
const dragData = {
|
||||||
actorId: this.actor.id,
|
actorId: this.actor.id,
|
||||||
type: "Item",
|
type: "Item",
|
||||||
data: item.system
|
data: item.data
|
||||||
};
|
};
|
||||||
|
|
||||||
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
|
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDrop(event) {
|
async _onDrop(event) {
|
||||||
// Try to extract the dragData
|
// Try to extract the data
|
||||||
let dragData;
|
let data;
|
||||||
try {
|
try {
|
||||||
dragData = JSON.parse(event.dataTransfer.getData('text/plain'));
|
data = JSON.parse(event.dataTransfer.getData('text/plain'));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const allowed = Hooks.call("dropActorSheetData", this.actor, this, dragData);
|
const allowed = Hooks.call("dropActorSheetData", this.actor, this, data);
|
||||||
if (allowed === false) return;
|
if (allowed === false) return;
|
||||||
|
|
||||||
// Handle different dragData types
|
// Handle different data types
|
||||||
switch (dragData.type) {
|
switch (data.type) {
|
||||||
case "Item":
|
case "Item":
|
||||||
return this._onDropItem(event, dragData);
|
return this._onDropItem(event, data);
|
||||||
}
|
}
|
||||||
return super._onDrop(event);
|
return super._onDrop(event);
|
||||||
}
|
}
|
||||||
@ -302,7 +282,7 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _onDropItem(event, dragData) {
|
async _onDropItem(event, dragData) {
|
||||||
if (this.actor) {
|
if (this.actor) {
|
||||||
const dropParams = RdDSheetUtility.prepareItemDropParameters(this.item.id, this.actor.id, dragData, this.objetVersConteneur);
|
const dropParams = RdDSheetUtility.prepareItemDropParameters(this.object.id, this.actor.id, dragData, this.objetVersConteneur);
|
||||||
await this.actor.processDropItem(dropParams);
|
await this.actor.processDropItem(dropParams);
|
||||||
await this.render(true);
|
await this.render(true);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
import { SYSTEM_RDD } from "./constants.js";
|
||||||
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
|
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { Misc } from "./misc.js";
|
||||||
|
import { TMRType, TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item sheet pour signes draconiques
|
* Item sheet pour signes draconiques
|
||||||
@ -31,25 +32,25 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet {
|
|||||||
const position = super.setPosition(options);
|
const position = super.setPosition(options);
|
||||||
const sheetHeader = this.element.find(".sheet-header");
|
const sheetHeader = this.element.find(".sheet-header");
|
||||||
const sheetBody = this.element.find(".sheet-body");
|
const sheetBody = this.element.find(".sheet-body");
|
||||||
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
|
const bodyHeight = position.height - sheetHeader[0].clientHeight;
|
||||||
|
sheetBody.css("height", bodyHeight);
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getData() {
|
async getData() {
|
||||||
const formData = duplicate(this.item);
|
const formData = duplicate(Misc.data(this.object));
|
||||||
this.tmrs = TMRUtility.buildSelectionTypesTMR(this.item.system.typesTMR);
|
|
||||||
mergeObject(formData, {
|
mergeObject(formData, {
|
||||||
tmrs: this.tmrs,
|
|
||||||
title: formData.name,
|
title: formData.name,
|
||||||
isGM: game.user.isGM,
|
isGM: game.user.isGM,
|
||||||
owner: this.actor?.isOwner,
|
owner: this.document.isOwner,
|
||||||
isOwned: this.actor ? true : false,
|
isOwned: this.actor ? true : false,
|
||||||
actorId: this.actor?.id,
|
actorId: this.actor?.id,
|
||||||
editable: this.isEditable,
|
editable: this.isEditable,
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
cssClass: this.isEditable ? "editable" : "locked",
|
||||||
});
|
});
|
||||||
|
formData.tmrs = TMRUtility.listSelectedTMR(formData.data.typesTMR ?? []);
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,31 +62,27 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet {
|
|||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
|
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
|
||||||
html.find("input.select-tmr").change((event) => this.onSelectTmr(event));
|
html.find(".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)));
|
html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event.currentTarget.attributes['data-typereussite']?.value, Number(event.currentTarget.value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async setSigneAleatoire() {
|
async setSigneAleatoire() {
|
||||||
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique();
|
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique();
|
||||||
this.item.update(newSigne);
|
this.object.update(newSigne);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSelectTmr(event) {
|
async onSelectTmr(event) {
|
||||||
const tmrName = $(event.currentTarget)?.data("tmr-name");
|
event.preventDefault();
|
||||||
const onTmr = this.tmrs.find(it => it.name == tmrName);
|
const selectedTMR = $(".select-tmr").val();
|
||||||
if (onTmr){
|
this.object.update({ 'data.typesTMR': selectedTMR });
|
||||||
onTmr.selected = event.currentTarget.checked;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.item.update({ 'system.typesTMR': TMRUtility.buildListTypesTMRSelection(this.tmrs) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onValeurXpSort(event) {
|
async onValeurXpSort(event) {
|
||||||
const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0;
|
const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0;
|
||||||
const xp = Number(event.currentTarget.value);
|
const xp = Number(event.currentTarget.value);
|
||||||
const oldValeur = this.item.system.valeur;
|
const oldValeur = Misc.templateData(this.object).valeur;
|
||||||
const newValeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
|
const newValeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
|
||||||
await this.item.update({ 'system.valeur': newValeur });
|
await this.object.update({ 'data.valeur': newValeur });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@ -18,12 +18,13 @@ const DIFFICULTE_LECTURE_SIGNE_MANQUE = +11;
|
|||||||
export class RdDItemSigneDraconique {
|
export class RdDItemSigneDraconique {
|
||||||
|
|
||||||
static prepareSigneDraconiqueMeditation(meditation, rolled) {
|
static prepareSigneDraconiqueMeditation(meditation, rolled) {
|
||||||
|
meditation = Misc.data(meditation);
|
||||||
return {
|
return {
|
||||||
name: "de la " + meditation.name,
|
name: "de la " + meditation.name,
|
||||||
type: "signedraconique",
|
type: "signedraconique",
|
||||||
img: meditation.img,
|
img: meditation.img,
|
||||||
system: {
|
data: {
|
||||||
typesTMR: [TMRUtility.typeTmrName(meditation.system.tmr)],
|
typesTMR: [TMRUtility.typeTmrName(meditation.data.tmr)],
|
||||||
difficulte: rolled.isSuccess ? RdDItemSigneDraconique.getDiffSigneMeditation(rolled.code) : DIFFICULTE_LECTURE_SIGNE_MANQUE,
|
difficulte: rolled.isSuccess ? RdDItemSigneDraconique.getDiffSigneMeditation(rolled.code) : DIFFICULTE_LECTURE_SIGNE_MANQUE,
|
||||||
ephemere: true,
|
ephemere: true,
|
||||||
duree: "1 round",
|
duree: "1 round",
|
||||||
@ -42,7 +43,7 @@ export class RdDItemSigneDraconique {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static getXpSortSigneDraconique(code, signe) {
|
static getXpSortSigneDraconique(code, signe) {
|
||||||
return Misc.toInt(signe.system.valeur[code] ?? 0);
|
return Misc.toInt(Misc.data(signe).data.valeur[code] ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static calculValeursXpSort(qualite, valeur, avant) {
|
static calculValeursXpSort(qualite, valeur, avant) {
|
||||||
@ -74,7 +75,7 @@ export class RdDItemSigneDraconique {
|
|||||||
name: await RdDItemSigneDraconique.randomSigneDescription(),
|
name: await RdDItemSigneDraconique.randomSigneDescription(),
|
||||||
type: "signedraconique",
|
type: "signedraconique",
|
||||||
img: defaultItemImg.signedraconique,
|
img: defaultItemImg.signedraconique,
|
||||||
system: {
|
data: {
|
||||||
typesTMR: await RdDItemSigneDraconique.randomTmrs(modele.nbCases),
|
typesTMR: await RdDItemSigneDraconique.randomTmrs(modele.nbCases),
|
||||||
ephemere: options?.ephemere == undefined ? RdDDice.rollTotal("1d2") == 2 : options.ephemere,
|
ephemere: options?.ephemere == undefined ? RdDDice.rollTotal("1d2") == 2 : options.ephemere,
|
||||||
duree: "1 round",
|
duree: "1 round",
|
||||||
|
@ -7,25 +7,25 @@ export class RdDItemSort extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isDifficulteVariable(sort) {
|
static isDifficulteVariable(sort) {
|
||||||
return sort && (sort.system.difficulte.toLowerCase() == "variable");
|
return sort && (sort.data.difficulte.toLowerCase() == "variable");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isCoutVariable(sort) {
|
static isCoutVariable(sort) {
|
||||||
return sort && (sort.system.ptreve.toLowerCase() == "variable" || sort.system.ptreve.indexOf("+") >= 0);
|
return sort && (sort.data.ptreve.toLowerCase() == "variable" || sort.data.ptreve.indexOf("+") >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static setCoutReveReel(sort){
|
static setCoutReveReel(sort){
|
||||||
if (sort) {
|
if (sort) {
|
||||||
sort.system.ptreve_reel = this.isCoutVariable(sort) ? 1 : sort.system.ptreve;
|
sort.data.ptreve_reel = this.isCoutVariable(sort) ? 1 : sort.data.ptreve;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getDifficulte(sort, variable) {
|
static getDifficulte(sort, variable) {
|
||||||
if (sort && !RdDItemSort.isDifficulteVariable(sort)) {
|
if (sort && !RdDItemSort.isDifficulteVariable(sort)) {
|
||||||
return Misc.toInt(sort.system.difficulte);
|
return Misc.toInt(sort.data.difficulte);
|
||||||
}
|
}
|
||||||
return variable;
|
return variable;
|
||||||
}
|
}
|
||||||
@ -54,35 +54,40 @@ export class RdDItemSort extends Item {
|
|||||||
static getBonusCaseList( item, newCase = false ) {
|
static getBonusCaseList( item, newCase = false ) {
|
||||||
// Gestion spéciale case bonus
|
// Gestion spéciale case bonus
|
||||||
if ( item.type == 'sort') {
|
if ( item.type == 'sort') {
|
||||||
return this.buildBonusCaseList(item.system.bonuscase, newCase );
|
return this.buildBonusCaseList(item.data.bonuscase, newCase );
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/** Met à jour les données de formulaire
|
/** Met à jour les données de formulaire
|
||||||
* si static des bonus de cases sont présents
|
* si static des bonus de cases sont présents
|
||||||
* */
|
* */
|
||||||
static buildBonusCaseStringFromFormData( bonuses, cases ) {
|
static buildBonusCaseStringFromFormData( formData ) {
|
||||||
if ( bonuses ) {
|
if ( formData.bonusValue ) {
|
||||||
let list = [];
|
let list = [];
|
||||||
let caseCheck = {};
|
let caseCheck = {};
|
||||||
for (let i=0; i<bonuses.length; i++) {
|
for(let i=0; i<formData.bonusValue.length; i++) {
|
||||||
let coord = cases[i]?.toUpperCase() || 'A1';
|
let coord = formData.caseValue[i] || 'A1';
|
||||||
let bonus = bonuses[i] || 0;
|
coord = coord.toUpperCase();
|
||||||
if ( TMRUtility.verifyTMRCoord( coord ) && bonus > 0 && caseCheck[coord] == undefined ) {
|
if ( TMRUtility.verifyTMRCoord( coord ) ) { // Sanity check
|
||||||
caseCheck[coord] = bonus;
|
let bonus = formData.bonusValue[i] || 0;
|
||||||
list.push( coord+":"+bonus );
|
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 list.toString();
|
return formData;
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static incrementBonusCase( actor, sort, coord ) {
|
static incrementBonusCase( actor, sort, coord ) {
|
||||||
let bonusCaseList = this.buildBonusCaseList(sort.system.bonuscase, false);
|
let bonusCaseList = this.buildBonusCaseList(sort.data.bonuscase, false);
|
||||||
//console.log("ITEMSORT", sort, bonusCaseList);
|
//console.log("ITEMSORT", sort, bonusCaseList);
|
||||||
|
|
||||||
let found = false;
|
let found = false;
|
||||||
@ -101,12 +106,12 @@ export class RdDItemSort extends Item {
|
|||||||
// Sauvegarde/update
|
// Sauvegarde/update
|
||||||
let bonuscase = StringList.toString();
|
let bonuscase = StringList.toString();
|
||||||
//console.log("Bonus cae :", bonuscase);
|
//console.log("Bonus cae :", bonuscase);
|
||||||
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }] );
|
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'data.bonuscase': bonuscase }] );
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getCaseBonus( sort, coord) {
|
static getCaseBonus( sort, coord) {
|
||||||
let bonusCaseList = this.buildBonusCaseList(sort.system.bonuscase, false);
|
let bonusCaseList = this.buildBonusCaseList(sort.data.bonuscase, false);
|
||||||
for( let bc of bonusCaseList) {
|
for( let bc of bonusCaseList) {
|
||||||
if (bc.case == coord) { // Case existante
|
if (bc.case == coord) { // Case existante
|
||||||
return Number(bc.bonus);
|
return Number(bc.bonus);
|
||||||
|
594
module/item.js
594
module/item.js
@ -1,36 +1,15 @@
|
|||||||
import { DialogItemVente } from "./dialog-item-vente.js";
|
import { DialogItemVente } from "./dialog-item-vente.js";
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { Monnaie } from "./item-monnaie.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDHerbes } from "./rdd-herbes.js";
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
|
||||||
const typesObjetsEquipement = [
|
const typesObjetsEquipement = ["objet", "arme", "armure", "gemme", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "nourritureboisson", "monnaie"]
|
||||||
"arme",
|
|
||||||
"armure",
|
|
||||||
"conteneur",
|
|
||||||
"gemme",
|
|
||||||
"herbe",
|
|
||||||
"ingredient",
|
|
||||||
"livre",
|
|
||||||
"monnaie",
|
|
||||||
"munition",
|
|
||||||
"nourritureboisson",
|
|
||||||
"objet",
|
|
||||||
"potion",
|
|
||||||
]
|
|
||||||
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
|
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
|
||||||
const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"]
|
const encBrin = 0.00005;// un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
|
||||||
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 = {
|
export const defaultItemImg = {
|
||||||
competence: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
|
competence: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
|
||||||
competencecreature: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
|
compcreature: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
|
||||||
arme: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.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",
|
armure: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp",
|
||||||
conteneur: "systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp",
|
conteneur: "systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp",
|
||||||
@ -39,7 +18,6 @@ export const defaultItemImg = {
|
|||||||
ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp",
|
ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp",
|
||||||
livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp",
|
livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp",
|
||||||
potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp",
|
potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp",
|
||||||
rencontre: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp",
|
|
||||||
queue: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
|
queue: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
|
||||||
ombre: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
|
ombre: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
|
||||||
souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp",
|
souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp",
|
||||||
@ -57,52 +35,20 @@ export const defaultItemImg = {
|
|||||||
nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
|
nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
|
||||||
signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
|
signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
|
||||||
gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp",
|
gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp",
|
||||||
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp"
|
||||||
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
|
|
||||||
extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
|
|
||||||
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDItem extends Item {
|
export class RdDItem extends Item {
|
||||||
|
|
||||||
static getDefaultImg(itemType) {
|
constructor(data, context) {
|
||||||
return defaultItemImg[itemType];
|
if (!data.img) {
|
||||||
}
|
data.img = defaultItemImg[data.type];
|
||||||
|
|
||||||
static isEquipementFieldEditable(type, field) {
|
|
||||||
switch (field) {
|
|
||||||
case 'quantite':
|
|
||||||
if (['conteneur'].includes(type)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'cout':
|
|
||||||
if(['monnaie'].includes(type)){
|
|
||||||
return game.user.isGM;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return true;
|
super(data, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getUniteQuantite(type) {
|
static getTypeObjetsEquipement() {
|
||||||
switch (type) {
|
|
||||||
case "monnaie": return "(Pièces)"
|
|
||||||
case "herbe": return "(Brins)"
|
|
||||||
case "ingredient": return "(Pépins ou Brins)"
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(itemData, context) {
|
|
||||||
if (!itemData.img) {
|
|
||||||
itemData.img = RdDItem.getDefaultImg(itemData.type);
|
|
||||||
}
|
|
||||||
super(itemData, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTypesObjetsEquipement() {
|
|
||||||
return typesObjetsEquipement
|
return typesObjetsEquipement
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,141 +56,120 @@ export class RdDItem extends Item {
|
|||||||
return typesObjetsOeuvres
|
return typesObjetsOeuvres
|
||||||
}
|
}
|
||||||
|
|
||||||
isCompetencePersonnage() {
|
|
||||||
return this.type == 'competence'
|
|
||||||
}
|
|
||||||
isCompetence() {
|
isCompetence() {
|
||||||
return typesObjetsCompetence.includes(this.type)
|
return Misc.data(this).type == 'competence';
|
||||||
}
|
|
||||||
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';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getItemGroup() {
|
isConteneur() {
|
||||||
if (this.isEquipement()) return "equipement";
|
return Misc.data(this).type == 'conteneur';
|
||||||
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() {
|
isConteneurNonVide() {
|
||||||
return this.isConteneur() && (this.system.contenu?.length ?? 0) > 0;
|
return this.isConteneur() && (Misc.templateData(this).contenu?.length ?? 0) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isConteneurVide() {
|
isConteneurVide() {
|
||||||
return this.isConteneur() && (this.system.contenu?.length ?? 0) == 0;
|
return this.isConteneur() && (Misc.templateData(this).contenu?.length ?? 0) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isVideOuNonConteneur() {
|
isVideOuNonConteneur() {
|
||||||
return !this.isConteneur() || (this.system.contenu?.length ?? 0) == 0;
|
return !this.isConteneur() || (Misc.templateData(this).contenu?.length ?? 0) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isAlcool() {
|
isAlcool() {
|
||||||
return this.type == 'nourritureboisson' && this.system.boisson && this.system.alcoolise;
|
const itemData = Misc.data(this);
|
||||||
|
return itemData.type == 'nourritureboisson' && itemData.data.boisson && itemData.data.alcoolise;
|
||||||
}
|
}
|
||||||
isHerbeAPotion() {
|
isHerbeAPotion() {
|
||||||
return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos');
|
const itemData = Misc.data(this);
|
||||||
|
return itemData.type == 'herbe' && (itemData.data.categorie == 'Soin' || itemData.data.categorie == 'Repos');
|
||||||
}
|
}
|
||||||
isPotion() {
|
isPotion() {
|
||||||
return this.type == 'potion';
|
return Misc.data(this).type == 'potion';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isEquipement() {
|
||||||
|
return RdDItem.getTypeObjetsEquipement().includes(Misc.data(this).type);
|
||||||
|
}
|
||||||
|
|
||||||
isCristalAlchimique() {
|
isCristalAlchimique() {
|
||||||
return this.type == 'objet' && Grammar.toLowerCaseNoAccent(this.name) == 'cristal alchimique' && this.system.quantite > 0;
|
const itemData = Misc.data(this);
|
||||||
|
return itemData.type == 'objet' && Grammar.toLowerCaseNoAccent(itemData.name) == 'cristal alchimique' && itemData.data.quantite > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isMagique() {
|
isMagique() {
|
||||||
return this.system.magique
|
return Misc.templateData(this).magique;
|
||||||
}
|
|
||||||
|
|
||||||
getQuantite() {
|
|
||||||
return Math.round(this.isConteneur() ? 1 : (this.system.quantite ?? 0))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getEncTotal() {
|
getEncTotal() {
|
||||||
return this.getEnc() * this.getQuantite();
|
const itemData = Misc.data(this);
|
||||||
}
|
return Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
|
||||||
|
}
|
||||||
getEnc() {
|
getEnc() {
|
||||||
switch (this.type) {
|
const itemData = Misc.data(this);
|
||||||
|
switch (itemData.type) {
|
||||||
case 'herbe':
|
case 'herbe':
|
||||||
return encBrin;
|
return encBrin;
|
||||||
case 'gemme':
|
|
||||||
return encPepin * this.system.taille;
|
|
||||||
}
|
}
|
||||||
return Math.max(this.system.encombrement ?? 0, 0);
|
return itemData.data.encombrement ?? 0;
|
||||||
}
|
|
||||||
|
|
||||||
valeurTotale() {
|
|
||||||
return this.getQuantite() * this.valeur()
|
|
||||||
}
|
|
||||||
|
|
||||||
valeur() {
|
|
||||||
return this.system.cout ?? 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
super.prepareDerivedData();
|
super.prepareDerivedData();
|
||||||
if (this.isEquipement()) {
|
if (this.isEquipement()) {
|
||||||
this.system.encTotal = this.getEncTotal();
|
this._calculsEquipement();
|
||||||
|
|
||||||
if (this.isPotion()) {
|
if (this.isPotion()) {
|
||||||
this.prepareDataPotion()
|
this.prepareDataPotion()
|
||||||
}
|
}
|
||||||
this.system.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
|
const itemData = Misc.data(this);
|
||||||
|
itemData.data.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareDataPotion() {
|
prepareDataPotion() {
|
||||||
const categorie = Grammar.toLowerCaseNoAccent(this.system.categorie);
|
const tplData = Misc.templateData(this);
|
||||||
this.system.magique = categorie.includes('enchante');
|
const categorie = Grammar.toLowerCaseNoAccent(tplData.categorie);
|
||||||
if (this.system.magique) {
|
tplData.magique = categorie.includes('enchante');
|
||||||
|
if (tplData.magique) {
|
||||||
if (categorie.includes('soin') || categorie.includes('repos')) {
|
if (categorie.includes('soin') || categorie.includes('repos')) {
|
||||||
// TODO: utiliser calculPointsRepos / calculPointsGuerison
|
tplData.puissance = tplData.herbebonus * tplData.pr;
|
||||||
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 }) {
|
getActionPrincipale(options = { warnIfNot: true }) {
|
||||||
const warn = options.warnIfNot;
|
const itemData = Misc.data(this);
|
||||||
switch (this.type) {
|
if (!this.isConteneur() && (itemData.data.quantite ?? 0) <= 0) {
|
||||||
case 'nourritureboisson': return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
|
if (options.warnIfNot) {
|
||||||
case 'potion': return this._actionOrWarnQuantiteZero('Boire', warn);
|
ui.notifications.warn(`Vous n'avez plus de ${itemData.name}.`);
|
||||||
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;
|
return undefined;
|
||||||
}
|
}
|
||||||
else {
|
switch (itemData.type) {
|
||||||
return actionName;
|
case 'nourritureboisson': return itemData.data.boisson ? 'Boire' : 'Manger';
|
||||||
|
case 'potion': return 'Boire';
|
||||||
|
case 'livre': return 'Lire';
|
||||||
|
case 'conteneur': return 'Ouvrir';
|
||||||
}
|
}
|
||||||
|
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 }) {
|
async diminuerQuantite(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
|
||||||
@ -253,88 +178,88 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
|
async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
|
||||||
const quantite = Number(this.system.quantite ?? -1);
|
const itemData = Misc.data(this);
|
||||||
|
const quantite = Number(itemData.data.quantite ?? -1);
|
||||||
if (quantite >= 0) {
|
if (quantite >= 0) {
|
||||||
const reste = Math.max(quantite + Number(nombre), 0);
|
const reste = Math.max(quantite + Number(nombre), 0);
|
||||||
|
|
||||||
if (reste == 0) {
|
if (reste == 0) {
|
||||||
if (options.supprimerSiZero) {
|
if (options.supprimerSiZero) {
|
||||||
ui.notifications.notify(`${this.name} supprimé de votre équipement`);
|
ui.notifications.notify(`${itemData.name} supprimé de votre équipement`);
|
||||||
await this.delete();
|
await this.delete();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
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.`);
|
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({ "system.quantite": 0 });
|
await this.update({ "data.quantite": 0 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await this.update({ "system.quantite": reste });
|
await this.update({ "data.quantite": reste });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// détermine si deux équipements sont similaires: de même type, et avec les même champs hormis la quantité
|
// détermine si deux équipements sont similaires: de même type, et avec les même champs hormis la quantité
|
||||||
isEquipementEmpilable(other) {
|
isEquipementSimilaire(other) {
|
||||||
if (!other || !this.isEquipement()) {
|
const itemData = Misc.data(this);
|
||||||
return [false, undefined];
|
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;
|
||||||
|
|
||||||
if (this.system.quantite == undefined) {
|
const differences = Object.entries(tplData).filter(([key, value]) => !['quantite', 'encTotal', 'prixTotal', 'cout'].includes(key))
|
||||||
return [false, `Impossible de regrouper des ${this.type}, ils ne sont pas empilables`];
|
.filter(([key, value]) => value != otherTplData[key]);
|
||||||
}
|
if (differences.length > 0) {
|
||||||
else if (this.type != other.type) {
|
let message = `Impossible de regrouper les ${itemData.type} ${itemData.name}: `;
|
||||||
return [false, `Impossible de regrouper des ${this.type} avec des ${other.type}`];
|
for (const [key, value] of differences) {
|
||||||
}
|
message += `<br>${key}: ${value} vs ${otherTplData[key]}`;
|
||||||
else if (this.name != other.name) {
|
|
||||||
return [false, `Impossible de regrouper ${this.name} avec ${other.name}`];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const differences = Object.entries(this.system)
|
|
||||||
.filter(([key, value]) => !['quantite', 'cout', 'encTotal'].includes(key) && value != other.system[key]);
|
|
||||||
if (differences.length > 0) {
|
|
||||||
let message = `Impossible de regrouper les ${this.type} ${this.name}: `;
|
|
||||||
for (const [key, value] of differences) {
|
|
||||||
message += `<br>${key}: ${value} vs ${other.system[key]}`;
|
|
||||||
}
|
|
||||||
return [false, message];
|
|
||||||
}
|
}
|
||||||
|
ui.notifications.info(message)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return [true, undefined];
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async proposerVente() {
|
async proposerVente() {
|
||||||
console.log(this);
|
console.log(this);
|
||||||
if (this.isConteneurNonVide()) {
|
if (this.isConteneurNonVide()) {
|
||||||
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`);
|
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le donner ou le vendre`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await DialogItemVente.display(this, async (vente) => {
|
const dialog = await DialogItemVente.create(this, (vente) => this._onProposerVente(vente))
|
||||||
vente["properties"] = this.getProprietes();
|
dialog.render(true);
|
||||||
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}`)
|
async _onProposerVente(venteData) {
|
||||||
return;
|
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;
|
||||||
}
|
}
|
||||||
vente.jsondata = JSON.stringify(vente.item);
|
}
|
||||||
|
venteData.jsondata = JSON.stringify(venteData.item);
|
||||||
console.log(vente);
|
|
||||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
|
console.log(venteData);
|
||||||
ChatMessage.create(RdDUtility.chatDataSetup(html));
|
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', venteData);
|
||||||
});
|
ChatMessage.create(RdDUtility.chatDataSetup(html));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getProprietes() {
|
getProprietes() {
|
||||||
return this[`_${this.type}ChatData`]();
|
return this[`_${Misc.data(this).type}ChatData`]();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async postItem(modeOverride) {
|
async postItem(modeOverride) {
|
||||||
console.log(this);
|
console.log(this);
|
||||||
let chatData = duplicate(this);
|
let chatData = duplicate(Misc.data(this));
|
||||||
chatData["properties"] = this.getProprietes();
|
const properties = this.getProprietes();
|
||||||
|
chatData["properties"] = properties
|
||||||
if (this.actor) {
|
if (this.actor) {
|
||||||
chatData.actor = { id: this.actor.id };
|
chatData.actor = { id: this.actor.id };
|
||||||
}
|
}
|
||||||
@ -357,218 +282,254 @@ export class RdDItem extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_objetChatData() {
|
_objetChatData() {
|
||||||
return [].concat(
|
const tplData = Misc.templateData(this);
|
||||||
RdDItem.propertyIfDefined('Résistance', this.system.resistance, this.system.resistance),
|
let properties = [].concat(
|
||||||
RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite),
|
RdDItem.propertyIfDefined('Résistance', tplData.resistance, tplData.resistance),
|
||||||
RdDItem.propertyIfDefined('Encombrement', this.system.encombrement),
|
RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
|
||||||
|
RdDItem.propertyIfDefined('Encombrement', tplData.encombrement),
|
||||||
);
|
);
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_nourritureboissonChatData() {
|
_nourritureboissonChatData() {
|
||||||
return [].concat(
|
const tplData = Misc.templateData(this);
|
||||||
RdDItem.propertyIfDefined('Sustentation', this.system.sust, this.system.sust > 0),
|
let properties = [].concat(
|
||||||
RdDItem.propertyIfDefined('Désaltère', this.system.desaltere, this.system.boisson),
|
RdDItem.propertyIfDefined('Sustentation', tplData.sust, tplData.sust > 0),
|
||||||
RdDItem.propertyIfDefined('Force alcool', this.system.force, this.system.boisson && this.system.alcoolise),
|
RdDItem.propertyIfDefined('Désaltère', tplData.desaltere, tplData.boisson),
|
||||||
RdDItem.propertyIfDefined('Exotisme', this.system.exotisme, this.system.exotisme < 0),
|
RdDItem.propertyIfDefined('Force alcool', tplData.force, tplData.boisson && tplData.alcoolise),
|
||||||
RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite),
|
RdDItem.propertyIfDefined('Exotisme', tplData.exotisme, tplData.exotisme < 0),
|
||||||
RdDItem.propertyIfDefined('Encombrement', this.system.encombrement),
|
RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
|
||||||
|
RdDItem.propertyIfDefined('Encombrement', tplData.encombrement),
|
||||||
);
|
);
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_armeChatData() {
|
_armeChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Compétence</b>: ${this.system.competence}`,
|
let properties = [
|
||||||
`<b>Dommages</b>: ${this.system.dommages}`,
|
`<b>Compétence</b>: ${tplData.competence}`,
|
||||||
`<b>Force minimum</b>: ${this.system.force}`,
|
`<b>Dommages</b>: ${tplData.dommages}`,
|
||||||
`<b>Resistance</b>: ${this.system.resistance}`,
|
`<b>Force minimum</b>: ${tplData.force}`,
|
||||||
`<b>Encombrement</b>: ${this.system.encombrement}`
|
`<b>Resistance</b>: ${tplData.resistance}`,
|
||||||
|
`<b>Encombrement</b>: ${tplData.encombrement}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_conteneurChatData() {
|
_conteneurChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Capacité</b>: ${this.system.capacite} Enc.`,
|
let properties = [
|
||||||
`<b>Encombrement</b>: ${this.system.encombrement}`
|
`<b>Capacité</b>: ${tplData.capacite} Enc.`,
|
||||||
|
`<b>Encombrement</b>: ${tplData.encombrement}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_munitionChatData() {
|
_munitionChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Encombrement</b>: ${this.system.encombrement}`
|
let properties = [
|
||||||
|
`<b>Encombrement</b>: ${tplData.encombrement}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_armureChatData() {
|
_armureChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Protection</b>: ${this.system.protection}`,
|
let properties = [
|
||||||
`<b>Détérioration</b>: ${this.system.deterioration}`,
|
`<b>Protection</b>: ${tplData.protection}`,
|
||||||
`<b>Malus armure</b>: ${this.system.malus}`,
|
`<b>Détérioration</b>: ${tplData.deterioration}`,
|
||||||
`<b>Encombrement</b>: ${this.system.encombrement}`
|
`<b>Malus armure</b>: ${tplData.malus}`,
|
||||||
|
`<b>Encombrement</b>: ${tplData.encombrement}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_competenceChatData() {
|
_competenceChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Catégorie</b>: ${this.system.categorie}`,
|
let properties = [
|
||||||
`<b>Niveau</b>: ${this.system.niveau}`,
|
`<b>Catégorie</b>: ${tplData.categorie}`,
|
||||||
`<b>Caractéristique par défaut</b>: ${this.system.carac_defaut}`,
|
`<b>Niveau</b>: ${tplData.niveau}`,
|
||||||
`<b>XP</b>: ${this.system.xp}`
|
`<b>Caractéristique par défaut</b>: ${tplData.carac_defaut}`,
|
||||||
|
`<b>XP</b>: ${tplData.xp}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_competencecreatureChatData() {
|
_competencecreatureChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Catégorie</b>: ${this.system.categorie}`,
|
let properties = [
|
||||||
`<b>Niveau</b>: ${this.system.niveau}`,
|
`<b>Catégorie</b>: ${tplData.categorie}`,
|
||||||
`<b>Caractéristique</b>: ${this.system.carac_value}`,
|
`<b>Niveau</b>: ${tplData.niveau}`,
|
||||||
`<b>XP</b>: ${this.system.xp}`
|
`<b>Caractéristique</b>: ${tplData.carac_value}`,
|
||||||
|
`<b>XP</b>: ${tplData.xp}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_sortChatData() {
|
_sortChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Draconic</b>: ${this.system.draconic}`,
|
let properties = [
|
||||||
`<b>Difficulté</b>: ${this.system.difficulte}`,
|
`<b>Draconic</b>: ${tplData.draconic}`,
|
||||||
`<b>Case TMR</b>: ${this.system.caseTMR}`,
|
`<b>Difficulté</b>: ${tplData.difficulte}`,
|
||||||
`<b>Points de Rêve</b>: ${this.system.ptreve}`
|
`<b>Case TMR</b>: ${tplData.caseTMR}`,
|
||||||
|
`<b>Points de Rêve</b>: ${tplData.ptreve}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_herbeChatData() {
|
_herbeChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Milieu</b>: ${this.system.milieu}`,
|
let properties = [
|
||||||
`<b>Rareté</b>: ${this.system.rarete}`,
|
`<b>Milieu</b>: ${tplData.milieu}`,
|
||||||
`<b>Catégorie</b>: ${this.system.categorie}`,
|
`<b>Rareté</b>: ${tplData.rarete}`,
|
||||||
|
`<b>Catégorie</b>: ${tplData.categorie}`,
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_ingredientChatData() {
|
_ingredientChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Milieu</b>: ${this.system.milieu}`,
|
let properties = [
|
||||||
`<b>Rareté</b>: ${this.system.rarete}`,
|
`<b>Milieu</b>: ${tplData.milieu}`,
|
||||||
`<b>Catégorie</b>: ${this.system.categorie}`,
|
`<b>Rareté</b>: ${tplData.rarete}`,
|
||||||
|
`<b>Catégorie</b>: ${tplData.categorie}`,
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_tacheChatData() {
|
_tacheChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Caractéristique</b>: ${this.system.carac}`,
|
let properties = [
|
||||||
`<b>Compétence</b>: ${this.system.competence}`,
|
`<b>Caractéristique</b>: ${tplData.carac}`,
|
||||||
`<b>Périodicité</b>: ${this.system.periodicite}`,
|
`<b>Compétence</b>: ${tplData.competence}`,
|
||||||
`<b>Fatigue</b>: ${this.system.fatigue}`,
|
`<b>Périodicité</b>: ${tplData.periodicite}`,
|
||||||
`<b>Difficulté</b>: ${this.system.difficulte}`
|
`<b>Fatigue</b>: ${tplData.fatigue}`,
|
||||||
|
`<b>Difficulté</b>: ${tplData.difficulte}`
|
||||||
].concat([
|
].concat([
|
||||||
this.system.cacher_points_de_tache ? [] :`<b>Points de Tâche</b>: ${this.system.points_de_tache}`
|
tplData.cacher_points_de_tache ? [] :`<b>Points de Tâche</b>: ${tplData.points_de_tache}`
|
||||||
]).concat([
|
]).concat([
|
||||||
`<b>Points de Tâche atteints</b>: ${this.system.points_de_tache_courant}`]
|
`<b>Points de Tâche atteints</b>: ${tplData.points_de_tache_courant}`]
|
||||||
);
|
);
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_livreChatData() {
|
_livreChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Compétence</b>: ${this.system.competence}`,
|
let properties = [
|
||||||
`<b>Auteur</b>: ${this.system.auteur}`,
|
`<b>Compétence</b>: ${tplData.competence}`,
|
||||||
`<b>Difficulté</b>: ${this.system.difficulte}`,
|
`<b>Auteur</b>: ${tplData.auteur}`,
|
||||||
`<b>Points de Tâche</b>: ${this.system.points_de_tache}`,
|
`<b>Difficulté</b>: ${tplData.difficulte}`,
|
||||||
`<b>Encombrement</b>: ${this.system.encombrement}`
|
`<b>Points de Tâche</b>: ${tplData.points_de_tache}`,
|
||||||
|
`<b>Encombrement</b>: ${tplData.encombrement}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_potionChatData() {
|
_potionChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Rareté</b>: ${this.system.rarete}`,
|
let properties = [
|
||||||
`<b>Catégorie</b>: ${this.system.categorie}`,
|
`<b>Rareté</b>: ${tplData.rarete}`,
|
||||||
`<b>Encombrement</b>: ${this.system.encombrement}`,
|
`<b>Catégorie</b>: ${tplData.categorie}`,
|
||||||
|
`<b>Encombrement</b>: ${tplData.encombrement}`,
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_queueChatData() {
|
_queueChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Refoulement</b>: ${this.system.refoulement}`
|
let properties = [
|
||||||
|
`<b>Refoulement</b>: ${tplData.refoulement}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_ombreChatData() {
|
_ombreChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Refoulement</b>: ${this.system.refoulement}`
|
let properties = [
|
||||||
|
`<b>Refoulement</b>: ${tplData.refoulement}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_souffleChatData() {
|
_souffleChatData() {
|
||||||
return [];
|
const tplData = Misc.templateData(this);
|
||||||
|
let properties = [];
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_teteChatData() {
|
_teteChatData() {
|
||||||
return [];
|
const tplData = Misc.templateData(this);
|
||||||
|
let properties = [];
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_tarotChatData() {
|
_tarotChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Concept</b>: ${this.system.concept}`,
|
let properties = [
|
||||||
`<b>Aspect</b>: ${this.system.aspect}`,
|
`<b>Concept</b>: ${tplData.concept}`,
|
||||||
|
`<b>Aspect</b>: ${tplData.aspect}`,
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_nombreastralChatData() {
|
_nombreastralChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Valeur</b>: ${this.system.value}`,
|
let properties = [
|
||||||
`<b>Jour</b>: ${this.system.jourlabel}`,
|
`<b>Valeur</b>: ${tplData.value}`,
|
||||||
|
`<b>Jour</b>: ${tplData.jourlabel}`,
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_monnaieChatData() {
|
_monnaieChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Valeur en Sols</b>: ${this.system.cout}`,
|
let properties = [
|
||||||
`<b>Encombrement</b>: ${this.system.encombrement}`
|
`<b>Valeur en Deniers</b>: ${tplData.valeur_deniers}`,
|
||||||
|
`<b>Encombrement</b>: ${tplData.encombrement}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_meditationChatData() {
|
_meditationChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Thème</b>: ${this.system.theme}`,
|
let properties = [
|
||||||
`<b>Compétence</b>: ${this.system.competence}`,
|
`<b>Thème</b>: ${tplData.theme}`,
|
||||||
`<b>Support</b>: ${this.system.support}`,
|
`<b>Compétence</b>: ${tplData.competence}`,
|
||||||
`<b>Heure</b>: ${this.system.heure}`,
|
`<b>Support</b>: ${tplData.support}`,
|
||||||
`<b>Purification</b>: ${this.system.purification}`,
|
`<b>Heure</b>: ${tplData.heure}`,
|
||||||
`<b>Vêture</b>: ${this.system.veture}`,
|
`<b>Purification</b>: ${tplData.purification}`,
|
||||||
`<b>Comportement</b>: ${this.system.comportement}`,
|
`<b>Vêture</b>: ${tplData.veture}`,
|
||||||
`<b>Case TMR</b>: ${this.system.tmr}`
|
`<b>Comportement</b>: ${tplData.comportement}`,
|
||||||
]
|
`<b>Case TMR</b>: ${tplData.tmr}`
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
_rencontreChatData() {
|
|
||||||
if (this.system.coord) {
|
|
||||||
return [
|
|
||||||
`<b>Force</b>: ${this.system.force}`,
|
|
||||||
`<b>Coordonnées</b>: ${this.system.coord}`,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
return [
|
|
||||||
`<b>Force</b>: ${this.system.force}`,
|
|
||||||
`<b>Refoulement</b>: ${this.system.refoulement}`,
|
|
||||||
`<b>Présent de cités</b>: ${this.system.presentCite}`,
|
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_casetmrChatData() {
|
_casetmrChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Coordonnée</b>: ${this.system.coord}`,
|
let properties = [
|
||||||
`<b>Spécificité</b>: ${this.system.specific}`
|
`<b>Coordonnée</b>: ${tplData.coord}`,
|
||||||
|
`<b>Spécificité</b>: ${tplData.specific}`
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_maladieChatData() {
|
_maladieChatData() {
|
||||||
if (!this.system.identifie) {
|
const tplData = Misc.templateData(this);
|
||||||
return [`<b>Inconnue</b>`]
|
let properties
|
||||||
}
|
if (tplData.identifie) {
|
||||||
let properties = [
|
properties = [
|
||||||
`<b>Malignité</b>: ${this.system.malignite}`,
|
`<b>Malignité</b>: ${tplData.malignite}`,
|
||||||
`<b>Périodicité</b>: ${this.system.periodicite}`,
|
`<b>Périodicité</b>: ${tplData.periodicite}`,
|
||||||
`<b>Dommages</b>: ${this.system.dommages}`
|
`<b>Dommages</b>: ${tplData.dommages}`
|
||||||
]
|
]
|
||||||
if (this.system.remedesconnus) {
|
if (tplData.remedesconnus) {
|
||||||
properties.push(`<b>Remedes</b>: ${this.system.remedes}`)
|
properties.push(`<b>Remedes</b>: ${tplData.remedes}`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
properties = [
|
||||||
|
`<b>Inconnue</b>`]
|
||||||
}
|
}
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
@ -580,13 +541,16 @@ export class RdDItem extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_gemmeChatData() {
|
_gemmeChatData() {
|
||||||
return [
|
const tplData = Misc.templateData(this);
|
||||||
`<b>Pureté</b>: ${this.system.purete}`,
|
let properties = [
|
||||||
`<b>Taille</b>: ${this.system.taille}`,
|
`<b>Pureté</b>: ${tplData.purete}`,
|
||||||
`<b>Inertie</b>: ${this.system.inertie}`,
|
`<b>Taille</b>: ${tplData.taille}`,
|
||||||
`<b>Enchantabilité</b>: ${this.system.enchantabilite}`,
|
`<b>Inertie</b>: ${tplData.inertie}`,
|
||||||
`<b>Prix</b>: ${this.system.cout}`,
|
`<b>Enchantabilité</b>: ${tplData.enchantabilite}`,
|
||||||
|
`<b>Prix</b>: ${tplData.cout}`,
|
||||||
]
|
]
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,324 +0,0 @@
|
|||||||
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
|
||||||
import { Environnement } from "./environnement.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': undefined })
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _10_0_33_MigrationNomsDraconic extends Migration {
|
|
||||||
get code() { return "competences-creature-parade"; }
|
|
||||||
get version() { return "10.0.33"; }
|
|
||||||
|
|
||||||
migrationNomDraconic(ancien) {
|
|
||||||
if (typeof ancien == 'string') {
|
|
||||||
switch (ancien) {
|
|
||||||
case 'oniros': case "Voie d'Oniros": return "Voie d'Oniros";
|
|
||||||
case 'hypnos': case "Voie d'Hypnos": return "Voie d'Hypnos";
|
|
||||||
case 'narcos': case "Voie de Narcos": return "Voie de Narcos";
|
|
||||||
case 'thanatos': case "Voie de Thanatos": return "Voie de Thanatos";
|
|
||||||
}
|
|
||||||
return ancien;
|
|
||||||
}
|
|
||||||
else if (typeof ancien.name == 'string') {
|
|
||||||
return this.migrationNomDraconic(ancien.name)
|
|
||||||
}
|
|
||||||
return ancien;
|
|
||||||
}
|
|
||||||
async migrate() {
|
|
||||||
|
|
||||||
await this.applyItemsUpdates(items => items
|
|
||||||
.filter(it => ["sort", "sortreserve"].includes(it.type)
|
|
||||||
&& (typeof it.system.draconic == 'string') || (typeof it.system.draconic?.name == 'string'))
|
|
||||||
.map(it => { return { _id: it.id, "system.draconic": this.migrationNomDraconic(it.system.draconic) } }));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _10_2_5_ArmesTirLancer extends Migration {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
this.dagues = { "system.competence": 'Dague', "system.lancer": 'Dague de jet', "system.portee_courte": 3, "system.portee_moyenne": 8, "system.portee_extreme": 15 }
|
|
||||||
this.javelot = { "system.competence": 'Lance', "system.lancer": 'Javelot', "system.portee_courte": 6, "system.portee_moyenne": 12, "system.portee_extreme": 20 }
|
|
||||||
this.fouet = { "system.competence": '', "system.lancer": 'Fouet', "system.portee_courte": 2, "system.portee_moyenne": 2, "system.portee_extreme": 3, "system.penetration": -1 }
|
|
||||||
this.arc = { "system.competence": '', "system.tir": 'Arc' }
|
|
||||||
this.arbalete = { "system.competence": '', "system.tir": 'Arbalète' }
|
|
||||||
this.fronde = { "system.competence": '', "system.tir": 'Fronde' }
|
|
||||||
|
|
||||||
this.mappings = {
|
|
||||||
'dague': { filter: it => true, updates: this.dagues },
|
|
||||||
'dague de jet': { filter: it => true, updates: this.dagues },
|
|
||||||
'javelot': { filter: it => true, updates: this.javelot },
|
|
||||||
'lance': { filter: it => it.name == 'Javeline', updates: this.javelot },
|
|
||||||
'fouet': { filter: it => true, updates: this.fouet },
|
|
||||||
'arc': { filter: it => true, updates: this.arc },
|
|
||||||
'arbalete': { filter: it => true, updates: this.arbalete },
|
|
||||||
'fronde': { filter: it => true, updates: this.fronde },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get code() { return "separation-competences-tir-lancer"; }
|
|
||||||
get version() { return "10.2.5"; }
|
|
||||||
|
|
||||||
migrateArmeTirLancer(it) {
|
|
||||||
let updates = mergeObject({ _id: it.id }, this.getMapping(it).updates);
|
|
||||||
console.log(it.name, updates);
|
|
||||||
return updates;
|
|
||||||
}
|
|
||||||
|
|
||||||
async migrate() {
|
|
||||||
await this.applyItemsUpdates(items => items
|
|
||||||
.filter(it => "arme" == it.type)
|
|
||||||
.filter(it => this.isTirLancer(it))
|
|
||||||
.filter(it => this.getMapping(it).filter(it))
|
|
||||||
.map(it => this.migrateArmeTirLancer(it)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
isTirLancer(it) {
|
|
||||||
return Object.keys(this.mappings).includes(this.getCompKey(it));
|
|
||||||
}
|
|
||||||
|
|
||||||
getMapping(it) {
|
|
||||||
return this.mappings[this.getCompKey(it)];
|
|
||||||
}
|
|
||||||
|
|
||||||
getCompKey(it) {
|
|
||||||
return Grammar.toLowerCaseNoAccent(it.system.competence);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _10_2_10_DesirLancinant_IdeeFixe extends Migration {
|
|
||||||
get code() { return "desir-lancinat-idee-fixe"; }
|
|
||||||
get version() { return "10.2.10"; }
|
|
||||||
|
|
||||||
migrateQueue(it) {
|
|
||||||
let categorie = undefined
|
|
||||||
let name = it.name
|
|
||||||
if (Grammar.toLowerCaseNoAccent(name).includes('desir')) {
|
|
||||||
categorie = 'lancinant';
|
|
||||||
name = it.name.replace('Désir lancinant : ', '');
|
|
||||||
|
|
||||||
}
|
|
||||||
if (Grammar.toLowerCaseNoAccent(name).includes('idee fixe')) {
|
|
||||||
categorie = 'ideefixe';
|
|
||||||
name = it.name.replace('Idée fixe : ', '')
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
_id: it.id, name: name,
|
|
||||||
'system.ideefixe': undefined,
|
|
||||||
'system.lancinant': undefined,
|
|
||||||
'system.categorie': categorie
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async migrate() {
|
|
||||||
await this.applyItemsUpdates(items => items
|
|
||||||
.filter(it => ['queue', 'ombre'].includes(it.type))
|
|
||||||
.map(it => this.migrateQueue(it))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _10_3_0_Inventaire extends Migration {
|
|
||||||
get code() { return "migration-equipement-inventaire"; }
|
|
||||||
get version() { return "10.3.0"; }
|
|
||||||
|
|
||||||
async migrate() {
|
|
||||||
await this.applyItemsUpdates(items => {
|
|
||||||
return this._updatesMonnaies(items)
|
|
||||||
.concat(this._updatesNonEquipe(items))
|
|
||||||
.concat(this._updatesObjets(items))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_updatesNonEquipe(items) {
|
|
||||||
return items
|
|
||||||
.filter(it => ['munition'].includes(it.type))
|
|
||||||
.map(it => { return { _id: it.id, 'system.equipe': undefined } });
|
|
||||||
}
|
|
||||||
_updatesObjets(items) {
|
|
||||||
return items
|
|
||||||
.filter(it => ['objet'].includes(it.type))
|
|
||||||
.map(it => { return { _id: it.id, 'system.resistance': undefined, 'system.equipe': undefined } });
|
|
||||||
}
|
|
||||||
_updatesMonnaies(items) {
|
|
||||||
return items
|
|
||||||
.filter(it => ['monnaie'].includes(it.type) && it.system.cout == undefined)
|
|
||||||
.map(it => { return { _id: it.id, 'system.cout': it.system.valeur_deniers / 100, 'system.valeur_deniers': undefined } });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _10_3_0_FrequenceEnvironnement extends Migration {
|
|
||||||
get code() { return "migration-frequence-resources"; }
|
|
||||||
get version() { return "10.3.0"; }
|
|
||||||
|
|
||||||
async migrate() {
|
|
||||||
await this.applyItemsUpdates(items => items.filter(it => ['herbe', 'ingredient'].includes(it.type))
|
|
||||||
.map(it => this._updatesFrequences(it)));
|
|
||||||
}
|
|
||||||
|
|
||||||
_updatesFrequences(it) {
|
|
||||||
return {
|
|
||||||
_id: it.id,
|
|
||||||
'system.rarete': undefined,
|
|
||||||
'system.environnement': [{ milieu: it.system.milieu, rarete: it.system.rarete, frequence: Environnement.getFrequenceRarete(it.system.rarete, 'frequence') }]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Migrations {
|
|
||||||
static getMigrations() {
|
|
||||||
return [
|
|
||||||
new _10_0_16_MigrationSortsReserve(),
|
|
||||||
new _10_0_17_MigrationCompetenceCreature(),
|
|
||||||
new _10_0_21_VehiculeStructureResistanceMax(),
|
|
||||||
new _10_0_33_MigrationNomsDraconic(),
|
|
||||||
new _10_2_5_ArmesTirLancer(),
|
|
||||||
new _10_2_10_DesirLancinant_IdeeFixe(),
|
|
||||||
new _10_3_0_Inventaire(),
|
|
||||||
new _10_3_0_FrequenceEnvironnement()
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
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)) {
|
|
||||||
if (true) { /* comment previous and uncomment here to test before upgrade */
|
|
||||||
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`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -24,7 +24,7 @@ export class Misc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static sum() {
|
static sum() {
|
||||||
return (a, b) => Number(a) + Number(b);
|
return (a, b) => a + b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ascending(orderFunction = x => x) {
|
static ascending(orderFunction = x => x) {
|
||||||
@ -41,10 +41,6 @@ export class Misc {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static typeName(type, subType) {
|
|
||||||
return game.i18n.localize(`${type.toUpperCase()}.Type${Misc.upperFirst(subType)}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the value to an integer, or to 0 if undefined/null/not representing integer
|
* Converts the value to an integer, or to 0 if undefined/null/not representing integer
|
||||||
* @param {*} value value to convert to an integer using parseInt
|
* @param {*} value value to convert to an integer using parseInt
|
||||||
@ -73,9 +69,9 @@ export class Misc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static classify(items, classifier = it => it.type) {
|
static classify(items, classifier = it => it.type) {
|
||||||
let itemsBy = {}
|
let itemsBy = {};
|
||||||
Misc.classifyInto(itemsBy, items, classifier)
|
Misc.classifyInto(itemsBy, items, classifier);
|
||||||
return itemsBy
|
return itemsBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
static classifyFirst(items, classifier) {
|
static classifyFirst(items, classifier) {
|
||||||
@ -91,13 +87,13 @@ export class Misc {
|
|||||||
|
|
||||||
static classifyInto(itemsBy, items, classifier = it => it.type) {
|
static classifyInto(itemsBy, items, classifier = it => it.type) {
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const classification = classifier(item)
|
const classification = classifier(item);
|
||||||
let list = itemsBy[classification];
|
let list = itemsBy[classification];
|
||||||
if (!list) {
|
if (!list) {
|
||||||
list = []
|
list = [];
|
||||||
itemsBy[classification] = list
|
itemsBy[classification] = list;
|
||||||
}
|
}
|
||||||
list.push(item)
|
list.push(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,11 +102,29 @@ export class Misc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static join(params, separator = '') {
|
static join(params, separator = '') {
|
||||||
return params?.reduce(Misc.joining(separator)) ?? '';
|
return params.reduce((a, b) => a + separator + b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static joining(separator = '') {
|
|
||||||
return (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) {
|
static connectedGMOrUser(ownerId = undefined) {
|
||||||
@ -120,20 +134,17 @@ export class Misc {
|
|||||||
return Misc.firstConnectedGM()?.id ?? game.user.id;
|
return Misc.firstConnectedGM()?.id ?? game.user.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isRollModeHiddenToPlayer() {
|
static getUsers() {
|
||||||
switch (game.settings.get("core", "rollMode")) {
|
return game.version ? game.users : game.users.entities;
|
||||||
case CONST.DICE_ROLL_MODES.BLIND:
|
|
||||||
case CONST.DICE_ROLL_MODES.SELF: return true;
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static getActiveUser(id) {
|
static getActiveUser(id) {
|
||||||
return game.users.find(u => u.id == id && u.active);
|
return Misc.getUsers().find(u => u.id == id && u.active);
|
||||||
}
|
}
|
||||||
|
|
||||||
static firstConnectedGM() {
|
static firstConnectedGM() {
|
||||||
return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
|
return Misc.getUsers().filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static isOwnerPlayer(actor, user=undefined) {
|
static isOwnerPlayer(actor, user=undefined) {
|
||||||
@ -148,16 +159,12 @@ export class Misc {
|
|||||||
* @returns true pour un seul utilisateur: le premier GM connecté par ordre d'id
|
* @returns true pour un seul utilisateur: le premier GM connecté par ordre d'id
|
||||||
*/
|
*/
|
||||||
static isUniqueConnectedGM() {
|
static isUniqueConnectedGM() {
|
||||||
return game.user.id == Misc.firstConnectedGMId();
|
return game.user.id == Misc.firstConnectedGM()?.id;
|
||||||
}
|
|
||||||
|
|
||||||
static firstConnectedGMId() {
|
|
||||||
return Misc.firstConnectedGM()?.id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static findPlayer(name) {
|
static findPlayer(name) {
|
||||||
return Misc.findFirstLike(name, game.users, { description: 'joueur' });
|
return Misc.findFirstLike(name, Misc.getUsers(), { description: 'joueur' });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -210,4 +217,4 @@ export class Misc {
|
|||||||
}
|
}
|
||||||
return subset;
|
return subset;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,72 @@
|
|||||||
|
import { Misc } from "./misc.js"
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
|
||||||
|
const poesieHautReve = [
|
||||||
|
{
|
||||||
|
reference: 'Le Ratier Bretonien',
|
||||||
|
extrait: `Le courant du Fleuve
|
||||||
|
<br>Te domine et te Porte
|
||||||
|
<br>Avant que tu te moeuves
|
||||||
|
<br>Combat le, ou il t'emporte`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reference: 'Incompatibilité, Charles Beaudelaire',
|
||||||
|
extrait: `Et lorsque par hasard une nuée errante
|
||||||
|
<br>Assombrit dans son vol le lac silencieux,
|
||||||
|
<br>On croirait voir la robe ou l'ombre transparente
|
||||||
|
<br>D'un esprit qui voyage et passe dans les cieux.`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reference: 'Au fleuve de Loire, Joachim du Bellay',
|
||||||
|
extrait: `Ô de qui la vive course
|
||||||
|
<br>Prend sa bienheureuse source,
|
||||||
|
<br>D’une argentine fontaine,
|
||||||
|
<br>Qui d’une fuite lointaine,
|
||||||
|
<br>Te rends au sein fluctueux
|
||||||
|
<br>De l’Océan monstrueux`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reference: 'Denis Gerfaud',
|
||||||
|
extrait: `Et l'on peut savoir qui est le maître d'Oniros, c'est le Fleuve de l'Oubli.
|
||||||
|
Et l'on sait qui est le créateur du Fleuve de l'Oubli, c'est Hypnos et Narcos.
|
||||||
|
Mais l'on ne sait pas qui est le maître du Fleuve de l'Oubli,
|
||||||
|
sinon peut-être lui-même, ou peut-être Thanatos` },
|
||||||
|
{
|
||||||
|
reference: 'Denis Gerfaud',
|
||||||
|
extrait: `Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure
|
||||||
|
Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir.
|
||||||
|
Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reference: 'Denis Gerfaud',
|
||||||
|
extrait: `Narcos engendre le fils dont il est la mère à l'heure du Vaisseau,
|
||||||
|
car Oniros s'embarque pour redescendre le Fleuve
|
||||||
|
vers son père Hypnos sur la Voie de l'Oubli`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reference: 'Denis Gerfaud',
|
||||||
|
extrait: `Hypnos engendre le fils dont il est la mère à l'heure du Serpent, car
|
||||||
|
tel les serpents, Oniros commence à remonter le Fleuve
|
||||||
|
sur le Voie du Souvenir vers son père Narcos`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reference: 'Denis Gerfaud',
|
||||||
|
extrait: `Ainsi se succèdent les Jours et les Ages.
|
||||||
|
<br>Les jours des Dragons sont les Ages des Hommes.`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
reference: 'Denis Gerfaud',
|
||||||
|
extrait: `Ainsi parlent les sages:
|
||||||
|
«Les Dragons sont créateurs de leurs rêves, mais ils ne sont pas créateurs d'Oniros
|
||||||
|
Les Dragons ne sont pas les maîtres de leurs rêvezs, car ils ne sont pas maîtres d'Oniros.
|
||||||
|
Nul ne sait qui est le créateur des Dragons, ni qui est leur maître.
|
||||||
|
Mais l'on peut supposer qui est le maître du Rêve des Dragons, c'est Oniros»`
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
export class Poetique {
|
export class Poetique {
|
||||||
static async getExtrait() {
|
static async getExtrait(){
|
||||||
const items = await SystemCompendiums.getItems('extrait-poetique', 'extraitpoetique')
|
return await RdDDice.rollOneOf(poesieHautReve);
|
||||||
const selected = await RdDDice.rollOneOf(items);
|
|
||||||
return {
|
|
||||||
reference: selected?.name,
|
|
||||||
extrait: selected?.system.extrait
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
44
module/poetique.txt
Normal file
44
module/poetique.txt
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
Le courant du Fleuve
|
||||||
|
Te domine et te Porte
|
||||||
|
Avant que tu te moeuves
|
||||||
|
Combat le, ou il t'emporte
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
A vous qui faites ripaille
|
||||||
|
sourds aux damnés de la faim
|
||||||
|
à vous qui livrez
|
||||||
|
une inégale bataille
|
||||||
|
à ceux qui vous tendent la main
|
||||||
|
|
||||||
|
Ils sont tout près ! - Tenons fermée
|
||||||
|
<br>Cette salle, où nous les narguons.
|
||||||
|
<br>Quel bruit dehors ! Hideuse armée
|
||||||
|
<br>De vampires et de dragons !
|
||||||
|
<br>La poutre du toit descellée
|
||||||
|
<br>Ploie ainsi qu'une herbe mouillée,
|
||||||
|
<br>Et la vieille porte rouillée
|
||||||
|
<br>Tremble, à déraciner ses gonds !`),
|
||||||
|
|
||||||
|
https://www.poetica.fr/poeme-1423/guy-de-maupassant-le-sommeil-du-mandarin/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Le monde est un rêve de Dragons. Nous
|
||||||
|
ne savons pas qui sont les Dragons ni à quoi
|
||||||
|
ils ressemblent, en dépit de l’antique iconographie qui les dépeint comme de gigantesques créatures ailées capables de cracher
|
||||||
|
feu et flammes.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Car parmi les humains, autre nom lui est donné,
|
||||||
|
Nom sinistre parmi tous, nom funèbre, c'est la mort!
|
||||||
|
Un ami disparu... Thanatos est passé...
|
||||||
|
|
||||||
|
|
||||||
|
Messieurs, ne crachez pas de jurons ni d'ordure
|
||||||
|
Au visage fardé de cette pauvre impure
|
||||||
|
Que déesse Famine a par un soir d'hiver,
|
||||||
|
Contrainte à relever ses jupons en plein air.
|
||||||
|
|
@ -7,9 +7,9 @@ const matchOperationTerms = new RegExp(/@(\w*){([\w\-]+)}/i);
|
|||||||
export class RdDAlchimie {
|
export class RdDAlchimie {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static processManipulation(recette, actorId = undefined) {
|
static processManipulation(recetteData, actorId = undefined) {
|
||||||
//console.log("CALLED", recette, recette.isOwned, actorId );
|
//console.log("CALLED", recette, recette.isOwned, actorId );
|
||||||
let manip = recette.system.manipulation;
|
let manip = recetteData.data.manipulation;
|
||||||
let matchArray = manip.match(matchOperations);
|
let matchArray = manip.match(matchOperations);
|
||||||
if (matchArray) {
|
if (matchArray) {
|
||||||
for (let matchStr of matchArray) {
|
for (let matchStr of matchArray) {
|
||||||
@ -17,12 +17,12 @@ export class RdDAlchimie {
|
|||||||
//console.log("RESULT ", result);
|
//console.log("RESULT ", result);
|
||||||
if (result[1] && result[2]) {
|
if (result[1] && result[2]) {
|
||||||
let commande = Misc.upperFirst(result[1]);
|
let commande = Misc.upperFirst(result[1]);
|
||||||
let replacement = this[`_alchimie${commande}`](recette, result[2], actorId);
|
let replacement = this[`_alchimie${commande}`](recetteData, result[2], actorId);
|
||||||
manip = manip.replace(result[0], replacement);
|
manip = manip.replace(result[0], replacement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
recette.system.manipulation_update = manip;
|
recetteData.data.manipulation_update = manip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@ -12,23 +12,23 @@ export class RdDAstrologieJoueur extends Dialog {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async create(actor, dialogConfig) {
|
static async create(actor, dialogConfig) {
|
||||||
|
|
||||||
let dialogData = {
|
let data = {
|
||||||
nombres: this.organizeNombres(actor),
|
nombres: this.organizeNombres(actor),
|
||||||
dates: game.system.rdd.calendrier.getJoursSuivants(10),
|
dates: game.system.rdd.calendrier.getJoursSuivants(10),
|
||||||
etat: actor.getEtatGeneral(),
|
etat: actor.getEtatGeneral(),
|
||||||
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
|
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
|
||||||
astrologie: RdDItemCompetence.findCompetence(actor.items, 'Astrologie')
|
astrologie: RdDItemCompetence.findCompetence(actor.data.items, 'Astrologie')
|
||||||
}
|
}
|
||||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', dialogData);
|
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', data);
|
||||||
let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 };
|
let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 };
|
||||||
if (dialogConfig.options) {
|
if (dialogConfig.options) {
|
||||||
mergeObject(options, dialogConfig.options, { overwrite: true });
|
mergeObject(options, dialogConfig.options, { overwrite: true });
|
||||||
}
|
}
|
||||||
return new RdDAstrologieJoueur(html, actor, dialogData);
|
return new RdDAstrologieJoueur(html, actor, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(html, actor, dialogData) {
|
constructor(html, actor, data) {
|
||||||
|
|
||||||
let myButtons = {
|
let myButtons = {
|
||||||
saveButton: { label: "Fermer", callback: html => this.quitDialog() }
|
saveButton: { label: "Fermer", callback: html => this.quitDialog() }
|
||||||
@ -41,7 +41,7 @@ export class RdDAstrologieJoueur extends Dialog {
|
|||||||
super(dialogConf, dialogOptions);
|
super(dialogConf, dialogOptions);
|
||||||
|
|
||||||
this.actor = actor;
|
this.actor = actor;
|
||||||
this.dataNombreAstral = duplicate(dialogData);
|
this.dataNombreAstral = duplicate(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -49,12 +49,12 @@ export class RdDAstrologieJoueur extends Dialog {
|
|||||||
let itemNombres = actor.listItemsData('nombreastral');
|
let itemNombres = actor.listItemsData('nombreastral');
|
||||||
let itemFiltered = {};
|
let itemFiltered = {};
|
||||||
for (let item of itemNombres) {
|
for (let item of itemNombres) {
|
||||||
if (itemFiltered[item.system.jourindex]) {
|
if (itemFiltered[item.data.jourindex]) {
|
||||||
itemFiltered[item.system.jourindex].listValues.push(item.system.value);
|
itemFiltered[item.data.jourindex].listValues.push(item.data.value);
|
||||||
} else {
|
} else {
|
||||||
itemFiltered[item.system.jourindex] = {
|
itemFiltered[item.data.jourindex] = {
|
||||||
listValues: [item.system.value],
|
listValues: [item.data.value],
|
||||||
jourlabel: item.system.jourlabel
|
jourlabel: item.data.jourlabel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,9 +63,9 @@ export class RdDAstrologieJoueur extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
requestJetAstrologie() {
|
requestJetAstrologie() {
|
||||||
let socketData = {
|
let data = {
|
||||||
id: this.actor.id,
|
id: this.actor.data._id,
|
||||||
carac_vue: this.actor.system.carac['vue'].value,
|
carac_vue: Misc.data(this.actor).data.carac['vue'].value,
|
||||||
etat: this.dataNombreAstral.etat,
|
etat: this.dataNombreAstral.etat,
|
||||||
astrologie: this.dataNombreAstral.astrologie,
|
astrologie: this.dataNombreAstral.astrologie,
|
||||||
conditions: $("#diffConditions").val(),
|
conditions: $("#diffConditions").val(),
|
||||||
@ -73,11 +73,11 @@ export class RdDAstrologieJoueur extends Dialog {
|
|||||||
userId: game.user.id
|
userId: game.user.id
|
||||||
}
|
}
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
game.system.rdd.calendrier.requestNombreAstral(socketData);
|
game.system.rdd.calendrier.requestNombreAstral(data);
|
||||||
} else {
|
} else {
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
msg: "msg_request_nombre_astral",
|
msg: "msg_request_nombre_astral",
|
||||||
data: socketData
|
data: data
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.close();
|
this.close();
|
||||||
|
@ -20,7 +20,7 @@ export class RdDBonus {
|
|||||||
|
|
||||||
static isAjustementAstrologique(rollData) {
|
static isAjustementAstrologique(rollData) {
|
||||||
return RdDCarac.isChance(rollData.selectedCarac) ||
|
return RdDCarac.isChance(rollData.selectedCarac) ||
|
||||||
rollData.selectedSort?.system.isrituel;
|
rollData.selectedSort?.data.isrituel;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isDefenseAttaqueFinesse(rollData) {
|
static isDefenseAttaqueFinesse(rollData) {
|
||||||
@ -68,23 +68,23 @@ export class RdDBonus {
|
|||||||
}
|
}
|
||||||
return isCauchemar ? "cauchemar"
|
return isCauchemar ? "cauchemar"
|
||||||
: rollData.dmg?.mortalite
|
: rollData.dmg?.mortalite
|
||||||
?? rollData.arme?.system.mortalite
|
?? rollData.arme?.data.mortalite
|
||||||
?? "mortel";
|
?? "mortel";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _dmgArme(rollData) {
|
static _dmgArme(rollData) {
|
||||||
if ( rollData.arme) {
|
if ( rollData.arme) {
|
||||||
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0);
|
let dmgBase = rollData.arme.data.dommagesReels ?? Number(rollData.arme.data.dommages ?? 0);
|
||||||
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
|
//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.system.magique ? rollData.arme.system.ecaille_efficacite : 0);
|
return dmgBase + Math.min(dmgBase, rollData.arme.data.magique ? rollData.arme.data.ecaille_efficacite : 0);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _peneration(rollData) {
|
static _peneration(rollData) {
|
||||||
return parseInt(rollData.arme?.system.penetration ?? 0);
|
return parseInt(rollData.arme?.data.penetration ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@ -8,51 +8,48 @@ export class RdDCalendrierEditeur extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(html, calendrier, calendrierData) {
|
constructor(html, calendrier, calendrierData) {
|
||||||
let dialogConf = {
|
|
||||||
content: html,
|
let myButtons = {
|
||||||
title: "Editeur de date/heure",
|
saveButton: { label: "Enregistrer", callback: html => this.fillData() }
|
||||||
buttons: {
|
};
|
||||||
save: { label: "Enregistrer", callback: html => this.fillData() }
|
|
||||||
},
|
// Common conf
|
||||||
default: "save"
|
let dialogConf = { content: html, title: "Editeur de date/heure", buttons: myButtons, default: "saveButton" };
|
||||||
};
|
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 300, 'z-index': 99999 }
|
||||||
let dialogOptions = { classes: ["rdd-dialog-calendar-editor"], width: 400, height: 'fit-content', 'z-index': 99999 }
|
|
||||||
super(dialogConf, dialogOptions)
|
super(dialogConf, dialogOptions)
|
||||||
|
|
||||||
this.calendrier = calendrier;
|
this.calendrier = calendrier;
|
||||||
this.calendrierData = calendrierData;
|
this.calendrierData = calendrierData; //duplicate(calendrierData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
fillData() {
|
fillData( ) {
|
||||||
this.calendrierData.annee = $("input[name='annee']").val();
|
this.calendrierData.moisKey = $("#nomMois").val();
|
||||||
this.calendrierData.moisKey = $("select[name='nomMois']").val();
|
this.calendrierData.heureKey = $("#nomHeure").val();
|
||||||
this.calendrierData.heureKey = $("select[name='nomHeure']").val();
|
this.calendrierData.jourMois = $("#jourMois").val();
|
||||||
this.calendrierData.jourMois = $("select[name='jourMois']").val();
|
this.calendrierData.minutesRelative = $("#minutesRelative").val();
|
||||||
this.calendrierData.minutesRelative = $("select[name='minutesRelative']").val();
|
|
||||||
|
|
||||||
console.log("UPDATE ", this.calendrierData);
|
console.log("UPDATE ", this.calendrierData);
|
||||||
this.calendrier.saveEditeur(this.calendrierData)
|
this.calendrier.saveEditeur( this.calendrierData )
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
updateData(calendrierData) {
|
updateData( calendrierData ) {
|
||||||
this.calendrierData = duplicate(calendrierData);
|
this.calendrierData = duplicate(calendrierData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
let calendrierData = this.calendrierData;
|
let calendrierData = this.calendrierData;
|
||||||
|
|
||||||
$(function () {
|
$(function () {
|
||||||
console.log(calendrierData);
|
console.log(calendrierData);
|
||||||
$("input[name='nomMois']").val(calendrierData.moisKey);
|
$("#nomMois").val(calendrierData.moisKey);
|
||||||
$("select[name='nomHeure']").val(calendrierData.heureKey);
|
$("#nomHeure").val(calendrierData.heureKey);
|
||||||
$("select[name='jourMois']").val(calendrierData.jourMois);
|
$("#jourMois").val(calendrierData.jourMois);
|
||||||
$("select[name='minutesRelative']").val(calendrierData.minutesRelative);
|
$("#minutesRelative").val(calendrierData.minutesRelative);
|
||||||
$("select[name='annee']").val(calendrierData.annee);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,24 +8,23 @@ import { Grammar } from "./grammar.js";
|
|||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
import { DialogChronologie } from "./dialog-chronologie.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const dossierIconesHeures = 'systems/foundryvtt-reve-de-dragon/icons/heures/'
|
const dossierIconesHeures = 'systems/foundryvtt-reve-de-dragon/icons/heures/'
|
||||||
const heuresList = ["vaisseau", "sirene", "faucon", "couronne", "dragon", "epees", "lyre", "serpent", "poissonacrobate", "araignee", "roseau", "chateaudormant"];
|
const heuresList = ["vaisseau", "sirene", "faucon", "couronne", "dragon", "epees", "lyre", "serpent", "poissonacrobate", "araignee", "roseau", "chateaudormant"];
|
||||||
const heuresDef = {
|
const heuresDef = {
|
||||||
"vaisseau": {key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "printemps", heure: 0, icon: 'hd01.svg' },
|
"vaisseau": { label: "Vaisseau", lettreFont: 'v', saison: "printemps", heure: 0, icon: 'hd01.svg' },
|
||||||
"sirene": { key: "sirene", label: "Sirène", lettreFont: 'i', saison: "printemps", heure: 1, icon: 'hd02.svg' },
|
"sirene": { label: "Sirène", lettreFont: 'i', saison: "printemps", heure: 1, icon: 'hd02.svg' },
|
||||||
"faucon": { key: "faucon", label: "Faucon", lettreFont: 'f', saison: "printemps", heure: 2, icon: 'hd03.svg' },
|
"faucon": { label: "Faucon", lettreFont: 'f', saison: "printemps", heure: 2, icon: 'hd03.svg' },
|
||||||
"couronne": { key: "couronne", label: "Couronne", lettreFont: '', saison: "ete", heure: 3, icon: 'hd04.svg' },
|
"couronne": { label: "Couronne", lettreFont: '', saison: "ete", heure: 3, icon: 'hd04.svg' },
|
||||||
"dragon": { key: "dragon", label: "Dragon", lettreFont: 'd', saison: "ete", heure: 4, icon: 'hd05.svg' },
|
"dragon": { label: "Dragon", lettreFont: 'd', saison: "ete", heure: 4, icon: 'hd05.svg' },
|
||||||
"epees": { key: "epees", label: "Epées", lettreFont: 'e', saison: "ete", heure: 5, icon: 'hd06.svg' },
|
"epees": { label: "Epées", lettreFont: 'e', saison: "ete", heure: 5, icon: 'hd06.svg' },
|
||||||
"lyre": { key: "lyre", label: "Lyre", lettreFont: 'l', saison: "automne", heure: 6, icon: 'hd07.svg' },
|
"lyre": { label: "Lyre", lettreFont: 'l', saison: "automne", heure: 6, icon: 'hd07.svg' },
|
||||||
"serpent": { key: "serpent", label: "Serpent", lettreFont: 's', saison: "automne", heure: 7, icon: 'hd08.svg' },
|
"serpent": { label: "Serpent", lettreFont: 's', saison: "automne", heure: 7, icon: 'hd08.svg' },
|
||||||
"poissonacrobate": { key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "automne", heure: 8, icon: 'hd09.svg' },
|
"poissonacrobate": { label: "Poisson Acrobate", lettreFont: 'p', saison: "automne", heure: 8, icon: 'hd09.svg' },
|
||||||
"araignee": { key: "araignee", label: "Araignée", lettreFont: 'a', saison: "hiver", heure: 9, icon: 'hd10.svg' },
|
"araignee": { label: "Araignée", lettreFont: 'a', saison: "hiver", heure: 9, icon: 'hd10.svg' },
|
||||||
"roseau": { key: "roseau", label: "Roseau", lettreFont: 'r', saison: "hiver", heure: 10, icon: 'hd11.svg' },
|
"roseau": { label: "Roseau", lettreFont: 'r', saison: "hiver", heure: 10, icon: 'hd11.svg' },
|
||||||
"chateaudormant": { key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "hiver", heure: 11, icon: 'hd12.svg' }
|
"chateaudormant": { label: "Château Dormant", lettreFont: 'c', saison: "hiver", heure: 11, icon: 'hd12.svg' }
|
||||||
};
|
};
|
||||||
const saisonsDef = {
|
const saisonsDef = {
|
||||||
"printemps": { label: "Printemps" },
|
"printemps": { label: "Printemps" },
|
||||||
@ -52,50 +51,21 @@ export class RdDCalendrier extends Application {
|
|||||||
return Object.values(heuresDef).find(h => h.heure == chiffre);
|
return Object.values(heuresDef).find(h => h.heure == chiffre);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getSigneAs(key, value) {
|
|
||||||
const heure = (typeof value == 'string' || typeof value == 'number') && Number.isInteger(Number(value))
|
|
||||||
? Number(value)
|
|
||||||
: (typeof value == 'string') ? RdDCalendrier.getChiffreFromSigne(value)
|
|
||||||
: undefined
|
|
||||||
|
|
||||||
if (heure != undefined && ['key', 'label', 'lettreFont', 'saison', 'heure', 'icon'].includes(key)) {
|
|
||||||
return RdDCalendrier.getDefSigne(heure)[key]
|
|
||||||
}
|
|
||||||
if (heure != undefined && ['webp'].includes(key)) {
|
|
||||||
return RdDCalendrier.getDefSigne(heure)['icon'].replace('svg', 'webp');
|
|
||||||
}
|
|
||||||
console.error(`Appel à getSigneAs('${key}', ${value}) avec une clé/heure incorrects`);
|
|
||||||
return value;
|
|
||||||
|
|
||||||
}
|
|
||||||
static getChiffreFromSigne(signe) {
|
static getChiffreFromSigne(signe) {
|
||||||
return heuresList.indexOf(signe);
|
return heuresList.indexOf(signe);
|
||||||
}
|
}
|
||||||
|
|
||||||
static createCalendrierInitial() {
|
static getCalendrier(index) {
|
||||||
return {
|
let calendrier = {
|
||||||
heureRdD: 0,
|
|
||||||
minutesRelative: 0,
|
|
||||||
indexJour: 0,
|
|
||||||
annee: 0,
|
|
||||||
moisRdD: 0,
|
|
||||||
moisLabel: heuresDef["vaisseau"].label,
|
|
||||||
jour: 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
getCalendrier(index) {
|
|
||||||
index = index ?? this.getCurrentDayIndex();
|
|
||||||
const mois = Math.floor(index / RDD_JOUR_PAR_MOIS) % RDD_MOIS_PAR_AN;
|
|
||||||
return {
|
|
||||||
heureRdD: 0, // Index dans heuresList / heuresDef[x].heure
|
heureRdD: 0, // Index dans heuresList / heuresDef[x].heure
|
||||||
minutesRelative: 0,
|
minutesRelative: 0,
|
||||||
indexJour: index,
|
indexJour: index,
|
||||||
annee: Math.floor(index / (RDD_JOUR_PAR_MOIS * RDD_MOIS_PAR_AN)),
|
annee: Math.floor(index / (RDD_JOUR_PAR_MOIS * RDD_MOIS_PAR_AN)),
|
||||||
moisRdD: RdDCalendrier.getDefSigne(mois).heure,
|
moisRdD: Math.floor(index / RDD_JOUR_PAR_MOIS) % RDD_MOIS_PAR_AN,
|
||||||
moisLabel: RdDCalendrier.getDefSigne(mois).label,
|
|
||||||
jour: (index % RDD_JOUR_PAR_MOIS) // Le calendrier stocke le jour en 0-27, mais en 1-28 à l'affichage
|
jour: (index % RDD_JOUR_PAR_MOIS) // Le calendrier stocke le jour en 0-27, mais en 1-28 à l'affichage
|
||||||
}
|
}
|
||||||
|
calendrier.moisLabel = RdDCalendrier.getDefSigne(calendrier.moisRdD).label;
|
||||||
|
return calendrier;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -108,7 +78,7 @@ export class RdDCalendrier extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calendrier
|
// Calendrier
|
||||||
this.calendrier = duplicate(game.settings.get(SYSTEM_RDD, "calendrier") ?? RdDCalendrier.createCalendrierInitial());
|
this.calendrier = duplicate(game.settings.get(SYSTEM_RDD, "calendrier") ?? RdDCalendrier.getCalendrier(0));
|
||||||
this.calendrier.annee = this.calendrier.annee ?? Math.floor((this.calendrier.moisRdD ?? 0) / RDD_MOIS_PAR_AN);
|
this.calendrier.annee = this.calendrier.annee ?? Math.floor((this.calendrier.moisRdD ?? 0) / RDD_MOIS_PAR_AN);
|
||||||
this.calendrier.moisRdD = (this.calendrier.moisRdD ?? 0) % RDD_MOIS_PAR_AN;
|
this.calendrier.moisRdD = (this.calendrier.moisRdD ?? 0) % RDD_MOIS_PAR_AN;
|
||||||
|
|
||||||
@ -116,9 +86,9 @@ export class RdDCalendrier extends Application {
|
|||||||
game.settings.set(SYSTEM_RDD, "calendrier", this.calendrier);
|
game.settings.set(SYSTEM_RDD, "calendrier", this.calendrier);
|
||||||
|
|
||||||
this.listeNombreAstral = this.getListeNombreAstral();
|
this.listeNombreAstral = this.getListeNombreAstral();
|
||||||
this.rebuildListeNombreAstral(HIDE_DICE); // Ensure always up-to-date
|
this.rebuildListeNombreAstral(false); // Ensure always up-to-date
|
||||||
}
|
}
|
||||||
console.log('RdDCalendrier.constructor()', this.calendrier, this.calendrierPos, this.listeNombreAstral);
|
console.log(this.calendrier, this.calendrierPos, this.listeNombreAstral);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -137,13 +107,13 @@ export class RdDCalendrier extends Application {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getDateFromIndex(index) {
|
getDateFromIndex(index) {
|
||||||
const dateRdD = this.getCalendrier(index);
|
const date = RdDCalendrier.getCalendrier(index ?? this.getCurrentDayIndex());
|
||||||
return (dateRdD.jour + 1) + ' ' + dateRdD.moisLabel;
|
return (date.jour + 1) + ' ' + RdDCalendrier.getDefSigne(date.moisRdD).label;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getDayMonthFromIndex(index = undefined) {
|
getNumericDateFromIndex(index = undefined) {
|
||||||
const dateRdD = this.getCalendrier(index);
|
const dateRdD = RdDCalendrier.getCalendrier(index ?? this.getCurrentDayIndex());
|
||||||
return {
|
return {
|
||||||
day: dateRdD.jour + 1,
|
day: dateRdD.jour + 1,
|
||||||
month: heuresList[dateRdD.moisRdD]
|
month: heuresList[dateRdD.moisRdD]
|
||||||
@ -210,14 +180,14 @@ export class RdDCalendrier extends Application {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getNombreAstral(indexDate) {
|
getNombreAstral(indexDate) {
|
||||||
const listNombreAstral = this.getListeNombreAstral();
|
let astralData = this.getListeNombreAstral().find((nombreAstral, i) => nombreAstral.index == indexDate);
|
||||||
let astralData = listNombreAstral.find((nombreAstral, i) => nombreAstral.index == indexDate);
|
|
||||||
return astralData?.nombreAstral;
|
return astralData?.nombreAstral;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async rebuildListeNombreAstral(showDice = HIDE_DICE) {
|
async rebuildListeNombreAstral(showDice = SHOW_DICE) {
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
|
console.log("rebuildListeNombreAstral", showDice);
|
||||||
let jourCourant = this.getCurrentDayIndex();
|
let jourCourant = this.getCurrentDayIndex();
|
||||||
let newList = [];
|
let newList = [];
|
||||||
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
||||||
@ -229,8 +199,9 @@ export class RdDCalendrier extends Application {
|
|||||||
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice);
|
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", newList);
|
//console.log("SAVE list", newList, jourCourant);
|
||||||
this.listeNombreAstral = newList;
|
this.listeNombreAstral = newList;
|
||||||
|
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,9 +223,9 @@ export class RdDCalendrier extends Application {
|
|||||||
checkMaladie( periode) {
|
checkMaladie( periode) {
|
||||||
for (let actor of game.actors) {
|
for (let actor of game.actors) {
|
||||||
if (actor.type == 'personnage') {
|
if (actor.type == 'personnage') {
|
||||||
let maladies = actor.items.filter( item => (item.type == 'maladie' || (item.type == 'poison' && item.system.active) ) && item.system.periodicite.toLowerCase().includes(periode) );
|
let maladies = actor.filterItems( item => (item.type == 'maladie' || (item.type == 'poison' && item.data.active) ) && item.data.periodicite.toLowerCase().includes(periode) );
|
||||||
for (let maladie of maladies) {
|
for (let maladie of maladies) {
|
||||||
if ( maladie.system.identifie) {
|
if ( maladie.data.identifie) {
|
||||||
ChatMessage.create({ content: `${actor.name} souffre de ${maladie.name} (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
|
ChatMessage.create({ content: `${actor.name} souffre de ${maladie.name} (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
|
||||||
} else {
|
} else {
|
||||||
ChatMessage.create({ content: `${actor.name} souffre d'un mal inconnu (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
|
ChatMessage.create({ content: `${actor.name} souffre d'un mal inconnu (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
|
||||||
@ -293,7 +264,7 @@ export class RdDCalendrier extends Application {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async incrementerJour() {
|
async incrementerJour() {
|
||||||
const index = this.getCurrentDayIndex() + 1;
|
const index = this.getCurrentDayIndex() + 1;
|
||||||
this.calendrier = this.getCalendrier(index);
|
this.calendrier = RdDCalendrier.getCalendrier(index);
|
||||||
await this.rebuildListeNombreAstral();
|
await this.rebuildListeNombreAstral();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,15 +286,18 @@ export class RdDCalendrier extends Application {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
fillCalendrierData(formData = {}) {
|
fillCalendrierData(formData = {}) {
|
||||||
const mois = RdDCalendrier.getDefSigne(this.calendrier.moisRdD);
|
console.log(this.calendrier);
|
||||||
const heure = RdDCalendrier.getDefSigne(this.calendrier.heureRdD);
|
let moisKey = heuresList[this.calendrier.moisRdD];
|
||||||
console.log('fillCalendrierData', this.calendrier, mois, heure);
|
let heureKey = heuresList[this.calendrier.heureRdD];
|
||||||
|
console.log(moisKey, heureKey);
|
||||||
|
|
||||||
formData.heureKey = heure.key;
|
const mois = heuresDef[moisKey];
|
||||||
formData.moisKey = mois.key;
|
const heure = heuresDef[heureKey];
|
||||||
|
|
||||||
|
formData.heureKey = heureKey;
|
||||||
|
formData.moisKey = moisKey;
|
||||||
formData.jourMois = this.calendrier.jour + 1;
|
formData.jourMois = this.calendrier.jour + 1;
|
||||||
formData.nomMois = mois.label; // heures et mois nommés identiques
|
formData.nomMois = mois.label; // heures et mois nommés identiques
|
||||||
formData.annee = this.calendrier.annee;
|
|
||||||
formData.iconMois = dossierIconesHeures + mois.icon;
|
formData.iconMois = dossierIconesHeures + mois.icon;
|
||||||
formData.nomHeure = heure.label;
|
formData.nomHeure = heure.label;
|
||||||
formData.iconHeure = dossierIconesHeures + heure.icon;
|
formData.iconHeure = dossierIconesHeures + heure.icon;
|
||||||
@ -346,7 +320,7 @@ export class RdDCalendrier extends Application {
|
|||||||
if (Misc.isUniqueConnectedGM()) { // Only once
|
if (Misc.isUniqueConnectedGM()) { // Only once
|
||||||
console.log(request);
|
console.log(request);
|
||||||
let jourDiff = this.getLectureAstrologieDifficulte(request.date);
|
let jourDiff = this.getLectureAstrologieDifficulte(request.date);
|
||||||
let niveau = Number(request.astrologie.system.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
|
let niveau = Number(request.astrologie.data.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
|
||||||
let rollData = {
|
let rollData = {
|
||||||
caracValue: request.carac_vue,
|
caracValue: request.carac_vue,
|
||||||
finalLevel: niveau,
|
finalLevel: niveau,
|
||||||
@ -454,7 +428,7 @@ export class RdDCalendrier extends Application {
|
|||||||
function check() {
|
function check() {
|
||||||
let elmnt = document.getElementById("calendar-time-container");
|
let elmnt = document.getElementById("calendar-time-container");
|
||||||
if (elmnt) {
|
if (elmnt) {
|
||||||
elmnt.style.bottom = undefined;
|
elmnt.style.bottom = null;
|
||||||
let xPos = (pos.left) > window.innerWidth ? window.innerWidth - 200 : pos.left;
|
let xPos = (pos.left) > window.innerWidth ? window.innerWidth - 200 : pos.left;
|
||||||
let yPos = (pos.top) > window.innerHeight - 20 ? window.innerHeight - 100 : pos.top;
|
let yPos = (pos.top) > window.innerHeight - 20 ? window.innerHeight - 100 : pos.top;
|
||||||
elmnt.style.top = (yPos) + "px";
|
elmnt.style.top = (yPos) + "px";
|
||||||
@ -470,9 +444,9 @@ export class RdDCalendrier extends Application {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
updateDisplay() {
|
updateDisplay() {
|
||||||
let calendrier = this.fillCalendrierData();
|
let data = this.fillCalendrierData();
|
||||||
// Rebuild text du calendrier
|
// Rebuild data
|
||||||
let dateHTML = `${calendrier.jourMois} ${calendrier.nomMois} ${calendrier.annee} (${calendrier.nomSaison})`
|
let dateHTML = `Jour ${data.jourMois} de ${data.nomMois} (${data.nomSaison})`
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
dateHTML = dateHTML + " - NA: " + (this.getCurrentNombreAstral() ?? "indéterminé");
|
dateHTML = dateHTML + " - NA: " + (this.getCurrentNombreAstral() ?? "indéterminé");
|
||||||
}
|
}
|
||||||
@ -480,13 +454,13 @@ export class RdDCalendrier extends Application {
|
|||||||
handle.innerHTML = dateHTML;
|
handle.innerHTML = dateHTML;
|
||||||
}
|
}
|
||||||
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
|
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
|
||||||
heure.innerHTML = calendrier.nomHeure;
|
heure.innerHTML = data.nomHeure;
|
||||||
}
|
}
|
||||||
for (const minute of document.getElementsByClassName("calendar-time-disp")) {
|
for (const minute of document.getElementsByClassName("calendar-time-disp")) {
|
||||||
minute.innerHTML = `${calendrier.minutesRelative} minutes`;
|
minute.innerHTML = `${data.minutesRelative} minutes`;
|
||||||
}
|
}
|
||||||
for (const heureImg of document.getElementsByClassName("calendar-heure-img")) {
|
for (const heureImg of document.getElementsByClassName("calendar-heure-img")) {
|
||||||
heureImg.src = calendrier.iconHeure;
|
heureImg.src = data.iconHeure;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,7 +469,6 @@ export class RdDCalendrier extends Application {
|
|||||||
this.calendrier.minutesRelative = Number(calendrierData.minutesRelative);
|
this.calendrier.minutesRelative = Number(calendrierData.minutesRelative);
|
||||||
this.calendrier.jour = Number(calendrierData.jourMois) - 1;
|
this.calendrier.jour = Number(calendrierData.jourMois) - 1;
|
||||||
this.calendrier.moisRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.moisKey);
|
this.calendrier.moisRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.moisKey);
|
||||||
this.calendrier.annee = Number(calendrierData.annee);
|
|
||||||
this.calendrier.heureRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.heureKey);
|
this.calendrier.heureRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.heureKey);
|
||||||
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier));
|
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier));
|
||||||
|
|
||||||
@ -561,9 +534,9 @@ export class RdDCalendrier extends Application {
|
|||||||
async activateListeners(html) {
|
async activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
this.updateDisplay();
|
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
|
||||||
|
|
||||||
html.find('.ajout-chronologie').click(ev => DialogChronologie.create());
|
await this.updateDisplay();
|
||||||
|
|
||||||
html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
|
html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
|
||||||
|
|
||||||
@ -612,16 +585,16 @@ export class RdDCalendrier extends Application {
|
|||||||
pos3 = e.clientX;
|
pos3 = e.clientX;
|
||||||
pos4 = e.clientY;
|
pos4 = e.clientY;
|
||||||
// set the element's new position:
|
// set the element's new position:
|
||||||
elmnt.style.bottom = undefined
|
elmnt.style.bottom = null
|
||||||
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
|
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
|
||||||
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
|
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeDragElement() {
|
function closeDragElement() {
|
||||||
// stop moving when mouse button is released:
|
// stop moving when mouse button is released:
|
||||||
elmnt.onmousedown = undefined;
|
elmnt.onmousedown = null;
|
||||||
document.onmouseup = undefined;
|
document.onmouseup = null;
|
||||||
document.onmousemove = undefined;
|
document.onmousemove = null;
|
||||||
let xPos = (elmnt.offsetLeft - pos1) > window.innerWidth ? window.innerWidth - 200 : (elmnt.offsetLeft - pos1);
|
let xPos = (elmnt.offsetLeft - pos1) > window.innerWidth ? window.innerWidth - 200 : (elmnt.offsetLeft - pos1);
|
||||||
let yPos = (elmnt.offsetTop - pos2) > window.innerHeight - 20 ? window.innerHeight - 100 : (elmnt.offsetTop - pos2)
|
let yPos = (elmnt.offsetTop - pos2) > window.innerHeight - 20 ? window.innerHeight - 100 : (elmnt.offsetTop - pos2)
|
||||||
xPos = xPos < 0 ? 0 : xPos;
|
xPos = xPos < 0 ? 0 : xPos;
|
||||||
|
@ -52,11 +52,6 @@ export class RdDCarac {
|
|||||||
return selectedCarac?.label?.toLowerCase()?.match(/r(e|ê)ve(( |-)actuel)?/);
|
return selectedCarac?.label?.toLowerCase()?.match(/r(e|ê)ve(( |-)actuel)?/);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isActionPhysique(selectedCarac) {
|
|
||||||
return !selectedCarac ||
|
|
||||||
selectedCarac?.label.match(/(Apparence|Force|Agilité|Dextérité|Vue|Ouïe|Odorat-Goût|Empathie|Dérobée|Mêlée|Tir|Lancer)/);
|
|
||||||
}
|
|
||||||
|
|
||||||
static isIgnoreEtatGeneral(rollData) {
|
static isIgnoreEtatGeneral(rollData) {
|
||||||
const selectedCarac = rollData.selectedCarac;
|
const selectedCarac = rollData.selectedCarac;
|
||||||
return !selectedCarac ||
|
return !selectedCarac ||
|
||||||
@ -67,7 +62,7 @@ export class RdDCarac {
|
|||||||
|
|
||||||
|
|
||||||
static computeTotal(carac, beaute = undefined) {
|
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))
|
.map(it => parseInt(it.value))
|
||||||
.reduce(Misc.sum(), 0);
|
.reduce(Misc.sum(), 0);
|
||||||
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0);
|
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0);
|
||||||
@ -106,35 +101,35 @@ export class RdDCarac {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static computeCarac(system) {
|
static computeCarac(data) {
|
||||||
system.carac.force.value = Math.min(system.carac.force.value, parseInt(system.carac.taille.value) + 4);
|
data.carac.force.value = Math.min(data.carac.force.value, parseInt(data.carac.taille.value) + 4);
|
||||||
|
|
||||||
system.carac.derobee.value = Math.floor(parseInt(((21 - system.carac.taille.value)) + parseInt(system.carac.agilite.value)) / 2);
|
data.carac.derobee.value = Math.floor(parseInt(((21 - data.carac.taille.value)) + parseInt(data.carac.agilite.value)) / 2);
|
||||||
let bonusDomKey = Math.floor((parseInt(system.carac.force.value) + parseInt(system.carac.taille.value)) / 2);
|
let bonusDomKey = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2);
|
||||||
bonusDomKey = Math.min(Math.max(bonusDomKey, 0), 32); // Clamp de securite
|
bonusDomKey = Math.min(Math.max(bonusDomKey, 0), 32); // Clamp de securite
|
||||||
|
|
||||||
let tailleData = tableCaracDerivee[bonusDomKey];
|
let tailleData = tableCaracDerivee[bonusDomKey];
|
||||||
system.attributs.plusdom.value = tailleData.plusdom;
|
data.attributs.plusdom.value = tailleData.plusdom;
|
||||||
|
|
||||||
system.attributs.sconst.value = RdDCarac.calculSConst(system.carac.constitution.value);
|
data.attributs.sconst.value = RdDCarac.calculSConst(data.carac.constitution.value);
|
||||||
system.attributs.sust.value = tableCaracDerivee[Number(system.carac.taille.value)].sust;
|
data.attributs.sust.value = tableCaracDerivee[Number(data.carac.taille.value)].sust;
|
||||||
|
|
||||||
system.attributs.encombrement.value = (parseInt(system.carac.force.value) + parseInt(system.carac.taille.value)) / 2;
|
data.attributs.encombrement.value = (parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2;
|
||||||
system.carac.melee.value = Math.floor((parseInt(system.carac.force.value) + parseInt(system.carac.agilite.value)) / 2);
|
data.carac.melee.value = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.agilite.value)) / 2);
|
||||||
system.carac.tir.value = Math.floor((parseInt(system.carac.vue.value) + parseInt(system.carac.dexterite.value)) / 2);
|
data.carac.tir.value = Math.floor((parseInt(data.carac.vue.value) + parseInt(data.carac.dexterite.value)) / 2);
|
||||||
system.carac.lancer.value = Math.floor((parseInt(system.carac.tir.value) + parseInt(system.carac.force.value)) / 2);
|
data.carac.lancer.value = Math.floor((parseInt(data.carac.tir.value) + parseInt(data.carac.force.value)) / 2);
|
||||||
|
|
||||||
system.sante.vie.max = Math.ceil((parseInt(system.carac.taille.value) + parseInt(system.carac.constitution.value)) / 2);
|
data.sante.vie.max = Math.ceil((parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value)) / 2);
|
||||||
|
|
||||||
system.sante.vie.value = Math.min(system.sante.vie.value, system.sante.vie.max)
|
data.sante.vie.value = Math.min(data.sante.vie.value, data.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));
|
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));
|
||||||
system.sante.endurance.value = Math.min(system.sante.endurance.value, system.sante.endurance.max);
|
data.sante.endurance.value = Math.min(data.sante.endurance.value, data.sante.endurance.max);
|
||||||
system.sante.fatigue.max = system.sante.endurance.max * 2;
|
data.sante.fatigue.max = data.sante.endurance.max * 2;
|
||||||
system.sante.fatigue.value = Math.min(system.sante.fatigue.value, system.sante.fatigue.max);
|
data.sante.fatigue.value = Math.min(data.sante.fatigue.value, data.sante.fatigue.max);
|
||||||
|
|
||||||
//Compteurs
|
//Compteurs
|
||||||
system.reve.reve.max = system.carac.reve.value;
|
data.reve.reve.max = data.carac.reve.value;
|
||||||
system.compteurs.chance.max = system.carac.chance.value;
|
data.compteurs.chance.max = data.carac.chance.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
import { ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
import { DialogSelectTarget } from "./dialog-select-target.js";
|
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { RdDItemArme } from "./item-arme.js";
|
import { RdDItemArme } from "./item-arme.js";
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
@ -10,9 +9,7 @@ import { RdDBonus } from "./rdd-bonus.js";
|
|||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
import { RdDRoll } from "./rdd-roll.js";
|
import { RdDRoll } from "./rdd-roll.js";
|
||||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
|
||||||
import { Targets } from "./targets.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const premierRoundInit = [
|
const premierRoundInit = [
|
||||||
@ -69,7 +66,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async finDeRound(options = { terminer: false }) {
|
async finDeRound(options = { terminer: false }) {
|
||||||
for (let combatant of this.combatants) {
|
for (let combatant of this.data.combatants) {
|
||||||
if (combatant.actor) {
|
if (combatant.actor) {
|
||||||
await combatant.actor.finDeRound(options);
|
await combatant.actor.finDeRound(options);
|
||||||
}
|
}
|
||||||
@ -81,27 +78,28 @@ export class RdDCombatManager extends Combat {
|
|||||||
|
|
||||||
/************************************************************************************/
|
/************************************************************************************/
|
||||||
async rollInitiative(ids, formula = undefined, messageOptions = {}) {
|
async rollInitiative(ids, formula = undefined, messageOptions = {}) {
|
||||||
console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions);
|
console.log(`${game.data.system.data.title} | Combat.rollInitiative()`, ids, formula, messageOptions);
|
||||||
|
// Structure input data
|
||||||
ids = typeof ids === "string" ? [ids] : ids;
|
ids = typeof ids === "string" ? [ids] : ids;
|
||||||
|
const currentId = this.combatant._id;
|
||||||
// calculate initiative
|
// calculate initiative
|
||||||
for (let cId = 0; cId < ids.length; cId++) {
|
for (let cId = 0; cId < ids.length; cId++) {
|
||||||
const combatant = this.combatants.get(ids[cId]);
|
const combatant = this.combatants.get(ids[cId]);
|
||||||
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0);
|
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0);
|
||||||
if (!formula) {
|
if (!formula) {
|
||||||
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
|
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
|
||||||
const competence = combatant.actor.items.find(it => it.system.iscombat)
|
const competence = combatant.actor.data.items.find(it => it.data.data.iscombat)
|
||||||
if (competence) {
|
if (competence) {
|
||||||
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, 0);
|
rollFormula = RdDCombatManager.formuleInitiative(2, competence.data.carac_value, competence.data.niveau, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
|
const armeCombat = combatant.actor.data.items.find(it => it.type == 'arme' && itemData.data.equipe)
|
||||||
const compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.system.competence;
|
const compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.data.competence;
|
||||||
const competence = RdDItemCompetence.findCompetence(combatant.actor.items, compName);
|
const competence = RdDItemCompetence.findCompetence(combatant.actor.data.items, compName);
|
||||||
if (competence) {
|
if (competence) {
|
||||||
const carac = combatant.actor.system.carac[competence.system.defaut_carac].value;
|
const carac = combatant.actor.data.data.carac[competence.data.defaut_carac].value;
|
||||||
const niveau = competence.system.niveau;
|
const niveau = competence.data.niveau;
|
||||||
const bonusEcaille = (armeCombat?.system.magique) ? armeCombat.system.ecaille_efficacite : 0;
|
const bonusEcaille = (armeCombat?.data.magique) ? armeCombat.data.ecaille_efficacite : 0;
|
||||||
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, bonusEcaille);
|
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, bonusEcaille);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,7 +120,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
{
|
{
|
||||||
speaker: {
|
speaker: {
|
||||||
scene: canvas.scene._id,
|
scene: canvas.scene._id,
|
||||||
actor: combatant.actor?._id,
|
actor: combatant.actor ? combatant.actor._id : null,
|
||||||
token: combatant.token._id,
|
token: combatant.token._id,
|
||||||
alias: combatant.token.name,
|
alias: combatant.token.name,
|
||||||
sound: CONFIG.sounds.dice,
|
sound: CONFIG.sounds.dice,
|
||||||
@ -152,78 +150,50 @@ export class RdDCombatManager extends Combat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/** Retourne une liste triée d'actions d'armes avec le split arme1 main / arme 2 main / lancer */
|
/** Retourne une liste triée d'actions d'armes avec le split arme1 main / arme 2 main */
|
||||||
static listActionsArmes(armes, competences, carac) {
|
static listActionsArmes(armes, competences, carac) {
|
||||||
let actions = [];
|
// Gestion des armes 1/2 mains
|
||||||
|
let actionsArme = [];
|
||||||
for (const arme of armes) {
|
for (const arme of armes) {
|
||||||
if (arme.system.equipe) {
|
let action = duplicate(Misc.data(arme));
|
||||||
const dommages = arme.system.dommages.toString();
|
if (action.data.equipe) {
|
||||||
const tableauDommages = dommages.includes("/") ? dommages.split("/") : [dommages, dommages];
|
let compData = competences.map(c => Misc.data(c)).find(c => c.name == action.data.competence);
|
||||||
if (arme.system.unemain && arme.system.deuxmains && !dommages.includes("/")) {
|
|
||||||
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
|
actionsArme.push(action);
|
||||||
}
|
action.action = 'attaque';
|
||||||
console.log(">>>>", arme)
|
action.data.dommagesReels = Number(action.data.dommages);
|
||||||
if ((arme.system.unemain && arme.system.competence) ||
|
action.data.niveau = compData.data.niveau;
|
||||||
(arme.system.competence.toLowerCase().includes("corps à corps"))) {
|
action.data.initiative = RdDCombatManager.calculInitiative(compData.data.niveau, carac[compData.data.defaut_carac].value);
|
||||||
actions.push(RdDCombatManager.$prepareAttaqueArme({
|
// Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence
|
||||||
arme: arme,
|
if (action.data.unemain && !action.data.deuxmains) {
|
||||||
infoMain: "(1 main)",
|
action.data.mainInfo = "(1m)";
|
||||||
dommagesReel: Number(tableauDommages[0]),
|
} else if (!action.data.unemain && action.data.deuxmains) {
|
||||||
competence: arme.system.competence,
|
action.data.mainInfo = "(2m)";
|
||||||
carac: carac,
|
} else if (action.data.unemain && action.data.deuxmains) {
|
||||||
competences: competences
|
action.data.mainInfo = "(1m)";
|
||||||
}));
|
|
||||||
}
|
const comp2m = action.data.competence.replace(" 1 main", " 2 mains"); // Replace !
|
||||||
if (arme.system.deuxmains && arme.system.competence) {
|
const comp = Misc.data(competences.find(c => c.name == comp2m));
|
||||||
actions.push(RdDCombatManager.$prepareAttaqueArme({
|
|
||||||
arme: arme,
|
const arme2main = duplicate(action);
|
||||||
infoMain: "(2 mains)",
|
arme2main.data.mainInfo = "(2m)";
|
||||||
dommagesReel: Number(tableauDommages[1]),
|
arme2main.data.niveau = comp.data.niveau;
|
||||||
competence: arme.system.competence.replace(" 1 main", " 2 mains"),
|
arme2main.data.competence = comp2m;
|
||||||
carac: carac,
|
arme2main.data.initiative = RdDCombatManager.calculInitiative(arme2main.data.niveau, carac[comp.data.defaut_carac].value);
|
||||||
competences: competences
|
actionsArme.push(arme2main);
|
||||||
}));
|
const containsSlash = action.data.dommages.includes("/");
|
||||||
}
|
if (containsSlash) {
|
||||||
if (arme.system.lancer) {
|
const tableauDegats = action.data.dommages.split("/");
|
||||||
actions.push(RdDCombatManager.$prepareAttaqueArme({
|
action.data.dommagesReels = Number(tableauDegats[0]);
|
||||||
arme: arme,
|
arme2main.data.dommagesReels = Number(tableauDegats[1]);
|
||||||
infoMain: "(lancer)",
|
}
|
||||||
dommagesReel: Number(tableauDommages[0]),
|
else {
|
||||||
competence: arme.system.lancer,
|
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + action.name + " ne sont pas corrects (ie sous la forme X/Y)");
|
||||||
carac: carac,
|
}
|
||||||
competences: competences
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
if (arme.system.tir) {
|
|
||||||
actions.push(RdDCombatManager.$prepareAttaqueArme({
|
|
||||||
arme: arme,
|
|
||||||
infoMain: "(tir)",
|
|
||||||
dommagesReel: Number(tableauDommages[0]),
|
|
||||||
competence: arme.system.tir,
|
|
||||||
carac: carac,
|
|
||||||
competences: competences
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return actions.sort(Misc.ascending(action => action.name + (action.system.infoMain ?? '')));
|
return actionsArme.sort(Misc.ascending(armeData => armeData.name + (armeData.data.mainInfo ?? '')));
|
||||||
}
|
|
||||||
|
|
||||||
static $prepareAttaqueArme(infoAttaque) {
|
|
||||||
const comp = infoAttaque.competences.find(c => c.name == infoAttaque.competence);
|
|
||||||
const attaque = duplicate(infoAttaque.arme);
|
|
||||||
attaque.action = 'attaque';
|
|
||||||
attaque.system.competence = infoAttaque.competence;
|
|
||||||
attaque.system.dommagesReels = infoAttaque.dommagesReel;
|
|
||||||
attaque.system.infoMain = infoAttaque.infoMain;
|
|
||||||
attaque.system.niveau = comp.system.niveau;
|
|
||||||
attaque.system.initiative = RdDCombatManager.calculInitiative(comp.system.niveau, infoAttaque.carac[comp.system.defaut_carac].value);
|
|
||||||
return attaque;
|
|
||||||
}
|
|
||||||
|
|
||||||
static listActionsCreature(competences) {
|
|
||||||
return competences.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
|
|
||||||
.map(it => RdDItemCompetenceCreature.armeNaturelle(it));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static listActionsPossessions(actor) {
|
static listActionsPossessions(actor) {
|
||||||
@ -231,9 +201,9 @@ export class RdDCombatManager extends Combat {
|
|||||||
return {
|
return {
|
||||||
name: p.name,
|
name: p.name,
|
||||||
action: 'conjurer',
|
action: 'conjurer',
|
||||||
system: {
|
data: {
|
||||||
competence: p.name,
|
competence: p.name,
|
||||||
possessionid: p.system.possessionid,
|
possessionid: p.data.data.possessionid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@ -246,19 +216,21 @@ export class RdDCombatManager extends Combat {
|
|||||||
if (actions.length > 0) {
|
if (actions.length > 0) {
|
||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
|
let items = actor.data.items;
|
||||||
if (actor.isCreature()) {
|
if (actor.isCreature()) {
|
||||||
actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']));
|
actions = actions.concat(items.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
|
||||||
|
.map(competence => RdDItemCompetenceCreature.toActionArme(competence)));
|
||||||
} else {
|
} else {
|
||||||
// Recupération des items 'arme'
|
// Recupération des items 'arme'
|
||||||
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
|
let armes = items.filter(it => RdDItemArme.isArmeUtilisable(it))
|
||||||
//.concat(RdDItemArme.empoignade())
|
//.concat(RdDItemArme.empoignade())
|
||||||
.concat(RdDItemArme.mainsNues());
|
.concat(RdDItemArme.mainsNues());
|
||||||
|
|
||||||
const competences = actor.itemTypes['competence'];
|
let competences = items.filter(it => it.type == 'competence');
|
||||||
actions = actions.concat(RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac));
|
actions = actions.concat(RdDCombatManager.listActionsArmes(armes, competences, actor.data.data.carac));
|
||||||
|
|
||||||
if (actor.system.attributs.hautrevant.value) {
|
if (actor.data.data.attributs.hautrevant.value) {
|
||||||
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
|
actions.push({ name: "Draconic", action: 'haut-reve', data: { initOnly: true, competence: "Draconic" } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,14 +248,14 @@ export class RdDCombatManager extends Combat {
|
|||||||
static processPremierRoundInit() {
|
static processPremierRoundInit() {
|
||||||
// Check if we have the whole init !
|
// Check if we have the whole init !
|
||||||
if (Misc.isUniqueConnectedGM() && game.combat.current.round == 1) {
|
if (Misc.isUniqueConnectedGM() && game.combat.current.round == 1) {
|
||||||
let initMissing = game.combat.combatants.find(it => !it.initiative);
|
let initMissing = game.combat.data.combatants.find(it => !it.initiative);
|
||||||
if (!initMissing) { // Premier round !
|
if (!initMissing) { // Premier round !
|
||||||
for (let combatant of game.combat.combatants) {
|
for (let combatant of game.combat.data.combatants) {
|
||||||
let action = combatant.initiativeData?.arme;
|
let action = combatant.initiativeData?.arme;
|
||||||
//console.log("Parsed !!!", combatant, initDone, game.combat.current, arme);
|
//console.log("Parsed !!!", combatant, initDone, game.combat.current, arme);
|
||||||
if (action && action.type == "arme") {
|
if (action && action.type == "arme") {
|
||||||
for (let initData of premierRoundInit) {
|
for (let initData of premierRoundInit) {
|
||||||
if (Grammar.toLowerCaseNoAccentNoSpace(action.system.initpremierround).includes(initData.pattern)) {
|
if (Grammar.toLowerCaseNoAccentNoSpace(action.data.initpremierround).includes(initData.pattern)) {
|
||||||
let msg = `<h4>L'initiative de ${combatant.actor.name} a été modifiée !</h4>
|
let msg = `<h4>L'initiative de ${combatant.actor.name} a été modifiée !</h4>
|
||||||
<hr>
|
<hr>
|
||||||
<div>
|
<div>
|
||||||
@ -354,16 +326,22 @@ export class RdDCombatManager extends Combat {
|
|||||||
initOffset = 9;
|
initOffset = 9;
|
||||||
initInfo = "Draconic"
|
initInfo = "Draconic"
|
||||||
} else {
|
} else {
|
||||||
compData = RdDItemCompetence.findCompetence(combatant.actor.items, action.system.competence);
|
compData = Misc.data(RdDItemCompetence.findCompetence(combatant.actor.data.items, action.data.competence));
|
||||||
compNiveau = compData.system.niveau;
|
compNiveau = compData.data.niveau;
|
||||||
initInfo = action.name + " / " + action.system.competence;
|
initInfo = action.name + " / " + action.data.competence;
|
||||||
|
|
||||||
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
|
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
|
||||||
caracForInit = compData.system.carac_value;
|
caracForInit = compData.data.carac_value;
|
||||||
|
if (compData.data.categorie == "lancer") {
|
||||||
|
initOffset = 7;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
initOffset = 5;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
caracForInit = combatant.actor.system.carac[compData.system.defaut_carac].value;
|
caracForInit = Misc.data(combatant.actor).data.carac[compData.data.defaut_carac].value;
|
||||||
|
initOffset = RdDCombatManager._baseInitOffset(compData.data.categorie, action);
|
||||||
}
|
}
|
||||||
initOffset = RdDCombatManager._baseInitOffset(compData.system.categorie, action);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let malus = combatant.actor.getEtatGeneral(); // Prise en compte état général
|
let malus = combatant.actor.getEtatGeneral(); // Prise en compte état général
|
||||||
@ -374,7 +352,6 @@ export class RdDCombatManager extends Combat {
|
|||||||
game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo });
|
game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static _baseInitOffset(categorie, arme) {
|
static _baseInitOffset(categorie, arme) {
|
||||||
if (categorie == "tir") { // Offset de principe pour les armes de jet
|
if (categorie == "tir") { // Offset de principe pour les armes de jet
|
||||||
return 8;
|
return 8;
|
||||||
@ -382,12 +359,10 @@ export class RdDCombatManager extends Combat {
|
|||||||
if (categorie == "lancer") { // Offset de principe pour les armes de jet
|
if (categorie == "lancer") { // Offset de principe pour les armes de jet
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
switch (arme.system.cac) {
|
// Offset de principe pour les armes de jet
|
||||||
case "empoignade":
|
switch (arme.data.cac) {
|
||||||
return 3;
|
case "empoignade": return 3;
|
||||||
case "pugilat":
|
case "pugilat": return 4;
|
||||||
case "naturelle":
|
|
||||||
return 4;
|
|
||||||
}
|
}
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
@ -408,7 +383,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
let menuItems = [];
|
let menuItems = [];
|
||||||
for (let action of actions) {
|
for (let action of actions) {
|
||||||
menuItems.push({
|
menuItems.push({
|
||||||
name: action.system.competence,
|
name: action.data.competence,
|
||||||
icon: "<i class='fas fa-dice-d6'></i>",
|
icon: "<i class='fas fa-dice-d6'></i>",
|
||||||
callback: target => { RdDCombatManager.rollInitiativeAction(combatantId, action) }
|
callback: target => { RdDCombatManager.rollInitiativeAction(combatantId, action) }
|
||||||
});
|
});
|
||||||
@ -439,7 +414,7 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static onUpdateCombat(combat, change, options, userId) {
|
static onUpdateCombat(combat, change, options, userId) {
|
||||||
if (combat.round != 0 && combat.turns && combat.active) {
|
if (combat.data.round != 0 && combat.turns && combat.data.active) {
|
||||||
RdDCombat.combatNouveauTour(combat);
|
RdDCombat.combatNouveauTour(combat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -471,30 +446,49 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static rddCombatTarget(target, attacker) {
|
static createUsingTarget(attacker) {
|
||||||
const defender = target?.actor;
|
const target = RdDCombat.getTarget();
|
||||||
const defenderTokenId = target?.id;
|
if (target == undefined) {
|
||||||
|
ui.notifications.warn((game.user.targets?.size ?? 0) > 1
|
||||||
|
? "Vous devez choisir <strong>une seule</strong> cible à attaquer!"
|
||||||
|
: "Vous devez choisir une cible à attaquer!");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const defender = target?.actor;
|
||||||
|
const defenderTokenId = target?.data._id;
|
||||||
|
if (defender.type == 'entite' && defender.data.data.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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static getTarget() {
|
||||||
|
if (game.user.targets && game.user.targets.size == 1) {
|
||||||
|
for (let target of game.user.targets) {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static create(attacker, defender, defenderTokenId, target = undefined) {
|
||||||
return new RdDCombat(attacker, defender, defenderTokenId, target)
|
return new RdDCombat(attacker, defender, defenderTokenId, target)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static rddCombatForAttackerAndDefender(attackerId, defenderTokenId) {
|
static createForAttackerAndDefender(attackerId, defenderTokenId) {
|
||||||
const attacker = game.actors.get(attackerId);
|
const attacker = game.actors.get(attackerId);
|
||||||
let defender = defenderTokenId ? canvas.tokens.get(defenderTokenId)?.actor : undefined;
|
if (defenderTokenId) {
|
||||||
let target = undefined
|
const defenderToken = canvas.tokens.get(defenderTokenId);
|
||||||
if (!defenderTokenId || !defender) {
|
const defender = defenderToken.actor;
|
||||||
console.warn(`RdDCombat.rddCombatForAttackerAndDefender: appel avec defenderTokenId ${defenderTokenId} incorrect, ou pas de defender correspondant`);
|
|
||||||
target = Targets.getTarget()
|
return RdDCombat.create(attacker, defender, defenderTokenId);
|
||||||
if (!target) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
defenderTokenId = target.id;
|
|
||||||
defender = target.actor;
|
|
||||||
if (!defenderTokenId || !defender) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return new RdDCombat(attacker, defender, defenderTokenId, target)
|
return RdDCombat.createUsingTarget(attacker)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -502,10 +496,10 @@ export class RdDCombat {
|
|||||||
let defender = canvas.tokens.get(msg.defenderTokenId).actor;
|
let defender = canvas.tokens.get(msg.defenderTokenId).actor;
|
||||||
if (Misc.isOwnerPlayerOrUniqueConnectedGM()) {
|
if (Misc.isOwnerPlayerOrUniqueConnectedGM()) {
|
||||||
let attackerRoll = msg.attackerRoll;
|
let attackerRoll = msg.attackerRoll;
|
||||||
let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined;
|
let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : null;
|
||||||
|
|
||||||
defender.encaisserDommages(attackerRoll, attacker);
|
defender.encaisserDommages(attackerRoll, attacker);
|
||||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
||||||
rddCombat?.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
|
rddCombat?.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -514,7 +508,7 @@ export class RdDCombat {
|
|||||||
static onMsgDefense(msg) {
|
static onMsgDefense(msg) {
|
||||||
let defenderToken = canvas.tokens.get(msg.defenderTokenId);
|
let defenderToken = canvas.tokens.get(msg.defenderTokenId);
|
||||||
if (defenderToken && Misc.isUniqueConnectedGM()) {
|
if (defenderToken && Misc.isUniqueConnectedGM()) {
|
||||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
||||||
rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme);
|
rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme);
|
||||||
rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll);
|
rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll);
|
||||||
}
|
}
|
||||||
@ -541,10 +535,11 @@ export class RdDCombat {
|
|||||||
'#echec-total-attaque',
|
'#echec-total-attaque',
|
||||||
]) {
|
]) {
|
||||||
html.on("click", button, event => {
|
html.on("click", button, event => {
|
||||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(
|
const rddCombat = RdDCombat.createForAttackerAndDefender(
|
||||||
event.currentTarget.attributes['data-attackerId']?.value,
|
event.currentTarget.attributes['data-attackerId']?.value,
|
||||||
event.currentTarget.attributes['data-defenderTokenId']?.value);
|
event.currentTarget.attributes['data-defenderTokenId']?.value);
|
||||||
if (rddCombat) {
|
if (rddCombat) {
|
||||||
|
|
||||||
rddCombat.onEvent(button, event);
|
rddCombat.onEvent(button, event);
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
@ -559,12 +554,12 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(attacker, defender, defenderTokenId, target) {
|
constructor(attacker, defender, defenderTokenId, target) {
|
||||||
this.attacker = attacker
|
this.attacker = attacker;
|
||||||
this.defender = defender
|
this.defender = defender;
|
||||||
this.target = target
|
this.target = target;
|
||||||
this.attackerId = this.attacker.id
|
this.attackerId = this.attacker.data._id;
|
||||||
this.defenderId = this.defender.id
|
this.defenderId = this.defender.data._id;
|
||||||
this.defenderTokenId = defenderTokenId
|
this.defenderTokenId = defenderTokenId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -690,87 +685,12 @@ export class RdDCombat {
|
|||||||
return rollData.rolled.isSuccess;
|
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) {
|
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')) {
|
if (!await this.accorderEntite('avant-attaque')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (arme.system.cac == 'empoignade' && this.attacker.isCombatTouche()) {
|
if (arme.data.cac == 'empoignade' && this.attacker.isCombatTouche()) {
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
alias: this.attacker.name,
|
alias: this.attacker.name,
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
||||||
@ -787,24 +707,25 @@ export class RdDCombat {
|
|||||||
if (arme) {
|
if (arme) {
|
||||||
this.attacker.verifierForceMin(arme);
|
this.attacker.verifierForceMin(arme);
|
||||||
}
|
}
|
||||||
await this.proposerAjustementTirLancer(rollData)
|
|
||||||
|
|
||||||
const dialog = await RdDRoll.create(this.attacker, rollData,
|
const dialog = await RdDRoll.create(this.attacker, rollData,
|
||||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
|
|
||||||
{
|
{
|
||||||
name: 'jet-attaque',
|
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
|
||||||
label: 'Attaque: ' + (arme?.name ?? competence.name),
|
options: { height: 540 }
|
||||||
callbacks: [
|
}, {
|
||||||
this.attacker.createCallbackExperience(),
|
name: 'jet-attaque',
|
||||||
this.attacker.createCallbackAppelAuMoral(),
|
label: 'Attaque: ' + (arme?.name ?? competence.name),
|
||||||
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
|
callbacks: [
|
||||||
{ condition: r => arme && !RdDCombat.isParticuliere(r), action: r => this.attacker.incDecItemUse(arme._id) },
|
this.attacker.createCallbackExperience(),
|
||||||
{ condition: r => (RdDCombat.isReussite(r) && !RdDCombat.isParticuliere(r)), action: r => this._onAttaqueNormale(r) },
|
this.attacker.createCallbackAppelAuMoral(),
|
||||||
{ condition: RdDCombat.isParticuliere, action: r => this._onAttaqueParticuliere(r) },
|
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
|
||||||
{ condition: RdDCombat.isEchec, action: r => this._onAttaqueEchec(r) },
|
{ condition: r => arme && !RdDCombat.isParticuliere(r), action: r => this.attacker.incDecItemUse(arme._id) },
|
||||||
{ condition: RdDCombat.isEchecTotal, action: r => this._onAttaqueEchecTotal(r) },
|
{ condition: r => (RdDCombat.isReussite(r) && !RdDCombat.isParticuliere(r)), action: r => this._onAttaqueNormale(r) },
|
||||||
]
|
{ condition: RdDCombat.isParticuliere, action: r => this._onAttaqueParticuliere(r) },
|
||||||
});
|
{ condition: RdDCombat.isEchec, action: r => this._onAttaqueEchec(r) },
|
||||||
|
{ condition: RdDCombat.isEchecTotal, action: r => this._onAttaqueEchecTotal(r) },
|
||||||
|
]
|
||||||
|
});
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -812,12 +733,11 @@ export class RdDCombat {
|
|||||||
_prepareAttaque(competence, arme) {
|
_prepareAttaque(competence, arme) {
|
||||||
let rollData = {
|
let rollData = {
|
||||||
passeArme: randomID(16),
|
passeArme: randomID(16),
|
||||||
mortalite: arme?.system.mortalite,
|
mortalite: arme?.data.mortalite,
|
||||||
coupsNonMortels: false,
|
coupsNonMortels: false,
|
||||||
competence: competence,
|
competence: competence,
|
||||||
surprise: this.attacker.getSurprise(true),
|
surprise: this.attacker.getSurprise(true),
|
||||||
surpriseDefenseur: this.defender.getSurprise(true),
|
surpriseDefenseur: this.defender.getSurprise(true),
|
||||||
targetToken: Targets.extractTokenData(this.target),
|
|
||||||
essais: {}
|
essais: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -830,8 +750,8 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// sans armes: à mains nues
|
// sans armes: à mains nues
|
||||||
const niveau = competence.system.niveau;
|
const niveau = competence.data.niveau;
|
||||||
const init = RdDCombatManager.calculInitiative(niveau, this.attacker.system.carac['melee'].value);
|
const init = RdDCombatManager.calculInitiative(niveau, Misc.templateData(this.attacker).carac['melee'].value);
|
||||||
rollData.arme = RdDItemArme.mainsNues({ niveau: niveau, initiative: init });
|
rollData.arme = RdDItemArme.mainsNues({ niveau: niveau, initiative: init });
|
||||||
}
|
}
|
||||||
return rollData;
|
return rollData;
|
||||||
@ -844,9 +764,9 @@ export class RdDCombat {
|
|||||||
// force toujours, sauf empoignade
|
// force toujours, sauf empoignade
|
||||||
// finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum
|
// 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
|
// rapidité seulement en mêlée, si l'arme le permet, et si la difficulté libre est de -1 minimum
|
||||||
const isForce = !rollData.arme.system.empoignade;
|
const isForce = !rollData.arme.data.empoignade;
|
||||||
const isFinesse = rollData.arme.system.empoignade || isMeleeDiffNegative;
|
const isFinesse = rollData.arme.data.empoignade || isMeleeDiffNegative;
|
||||||
const isRapide = !rollData.arme.system.empoignade && isMeleeDiffNegative && rollData.arme.system.rapide;
|
const isRapide = !rollData.arme.data.empoignade && isMeleeDiffNegative && rollData.arme.data.rapide;
|
||||||
// si un seul choix possible, le prendre
|
// si un seul choix possible, le prendre
|
||||||
if (isForce && !isFinesse && !isRapide) {
|
if (isForce && !isFinesse && !isRapide) {
|
||||||
return await this.choixParticuliere(rollData, "force");
|
return await this.choixParticuliere(rollData, "force");
|
||||||
@ -881,7 +801,7 @@ export class RdDCombat {
|
|||||||
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntite());
|
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntite());
|
||||||
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
|
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
|
||||||
attackerRoll.show = {
|
attackerRoll.show = {
|
||||||
cible: this.target ? this.defender.name : 'la cible',
|
cible: this.target ? this.defender.data.name : 'la cible',
|
||||||
isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge')
|
isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge')
|
||||||
}
|
}
|
||||||
await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html');
|
await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html');
|
||||||
@ -902,7 +822,7 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _sendMessageDefense(attackerRoll, defenderRoll, essaisPrecedents = undefined) {
|
async _sendMessageDefense(attackerRoll, defenderRoll, essaisPrecedents = undefined) {
|
||||||
console.log("RdDCombat._sendMessageDefense", attackerRoll, defenderRoll, essaisPrecedents, " / ", this.attacker, this.target, this.attackerId, attackerRoll.competence.system.categorie);
|
console.log("RdDCombat._sendMessageDefense", attackerRoll, defenderRoll, essaisPrecedents, " / ", this.attacker, this.target, this.attackerId, attackerRoll.competence.data.categorie);
|
||||||
|
|
||||||
this.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
|
this.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
|
||||||
if (essaisPrecedents) {
|
if (essaisPrecedents) {
|
||||||
@ -910,16 +830,16 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// # utilisation esquive
|
// # utilisation esquive
|
||||||
const corpsACorps = this.defender.getCompetence("Corps à corps", { onMessage: it => console.info(it, this.defender) });
|
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) }))
|
const esquives = duplicate(this.defender.getCompetences("esquive", { onMessage: it => console.info(it, this.defender) }).map(c => Misc.data(c)));
|
||||||
esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0);
|
esquives.forEach(e => e.usages = e?.id ? this.defender.getItemUse(e.id) : 0);
|
||||||
|
|
||||||
const paramChatDefense = {
|
const paramChatDefense = {
|
||||||
passeArme: attackerRoll.passeArme,
|
passeArme: attackerRoll.passeArme,
|
||||||
essais: attackerRoll.essais,
|
essais: attackerRoll.essais,
|
||||||
isPossession: this.isPossession(attackerRoll),
|
isPossession: this.isPossession(attackerRoll),
|
||||||
defender: this.defender,
|
defender: Misc.data(this.defender),
|
||||||
attacker: this.attacker,
|
attacker: Misc.data(this.attacker),
|
||||||
attackerId: this.attackerId,
|
attackerId: this.attackerId,
|
||||||
esquives: esquives,
|
esquives: esquives,
|
||||||
defenderTokenId: this.defenderTokenId,
|
defenderTokenId: this.defenderTokenId,
|
||||||
@ -927,7 +847,7 @@ export class RdDCombat {
|
|||||||
armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme),
|
armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme),
|
||||||
diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0,
|
diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0,
|
||||||
attaqueParticuliere: attackerRoll.particuliere,
|
attaqueParticuliere: attackerRoll.particuliere,
|
||||||
attaqueCategorie: attackerRoll.competence.system.categorie,
|
attaqueCategorie: attackerRoll.competence.data.categorie,
|
||||||
attaqueArme: attackerRoll.arme,
|
attaqueArme: attackerRoll.arme,
|
||||||
surprise: this.defender.getSurprise(true),
|
surprise: this.defender.getSurprise(true),
|
||||||
dmg: attackerRoll.dmg,
|
dmg: attackerRoll.dmg,
|
||||||
@ -959,8 +879,8 @@ export class RdDCombat {
|
|||||||
// envoyer le message au destinataire
|
// envoyer le message au destinataire
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
msg: "msg_defense", data: {
|
msg: "msg_defense", data: {
|
||||||
attackerId: this.attacker?.id,
|
attackerId: this.attacker?.data._id,
|
||||||
defenderId: this.defender?.id,
|
defenderId: this.defender?.data._id,
|
||||||
defenderTokenId: this.defenderTokenId,
|
defenderTokenId: this.defenderTokenId,
|
||||||
defenderRoll: defenderRoll,
|
defenderRoll: defenderRoll,
|
||||||
paramChatDefense: paramChatDefense,
|
paramChatDefense: paramChatDefense,
|
||||||
@ -971,11 +891,13 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_filterArmesParade(defender, competence) {
|
_filterArmesParade(defender, competence) {
|
||||||
let items = defender.items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it))
|
let items = defender.data.items;
|
||||||
|
items = items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it))
|
||||||
|
.map(Misc.data);
|
||||||
for (let item of items) {
|
for (let item of items) {
|
||||||
item.system.nbUsage = defender.getItemUse(item.id); // Ajout du # d'utilisation ce round
|
item.data.nbUsage = defender.getItemUse(item._id); // Ajout du # d'utilisation ce round
|
||||||
}
|
}
|
||||||
switch (competence.system.categorie) {
|
switch (competence.data.categorie) {
|
||||||
case 'tir':
|
case 'tir':
|
||||||
case 'lancer':
|
case 'lancer':
|
||||||
return items.filter(item => RdDItemArme.getCategorieParade(item) == 'boucliers')
|
return items.filter(item => RdDItemArme.getCategorieParade(item) == 'boucliers')
|
||||||
@ -994,7 +916,7 @@ export class RdDCombat {
|
|||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
||||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', {
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', {
|
||||||
attackerId: this.attackerId,
|
attackerId: this.attackerId,
|
||||||
attacker: this.attacker,
|
attacker: Misc.data(this.attacker),
|
||||||
defenderTokenId: this.defenderTokenId,
|
defenderTokenId: this.defenderTokenId,
|
||||||
essais: attackerRoll.essais
|
essais: attackerRoll.essais
|
||||||
})
|
})
|
||||||
@ -1007,7 +929,7 @@ export class RdDCombat {
|
|||||||
console.log("RdDCombat._onEchecTotal >>>", rollData);
|
console.log("RdDCombat._onEchecTotal >>>", rollData);
|
||||||
|
|
||||||
const arme = rollData.arme;
|
const arme = rollData.arme;
|
||||||
const avecArme = !['', 'sans-armes', 'armes-naturelles'].includes(arme?.system.categorie_parade ?? '');
|
const avecArme = !['', 'sans-armes', 'armes-naturelles'].includes(arme?.data.categorie_parade ?? '');
|
||||||
const action = (rollData.attackerRoll ? (arme ? "la parade" : "l'esquive") : "l'attaque");
|
const action = (rollData.attackerRoll ? (arme ? "la parade" : "l'esquive") : "l'attaque");
|
||||||
ChatUtility.createChatWithRollMode(this.defender.name, {
|
ChatUtility.createChatWithRollMode(this.defender.name, {
|
||||||
content: `<strong>Maladresse à ${action}!</strong> ` + await RdDRollTables.getMaladresse({ arme: avecArme })
|
content: `<strong>Maladresse à ${action}!</strong> ` + await RdDRollTables.getMaladresse({ arme: avecArme })
|
||||||
@ -1026,7 +948,7 @@ export class RdDCombat {
|
|||||||
console.log("RdDCombat.choixParticuliere >>>", rollData, choix);
|
console.log("RdDCombat.choixParticuliere >>>", rollData, choix);
|
||||||
|
|
||||||
if (choix != "rapidite") {
|
if (choix != "rapidite") {
|
||||||
this.attacker.incDecItemUse(rollData.arme.id);
|
this.attacker.incDecItemUse(rollData.arme._id);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.removeChatMessageActionsPasseArme(rollData.passeArme);
|
this.removeChatMessageActionsPasseArme(rollData.passeArme);
|
||||||
@ -1038,29 +960,31 @@ export class RdDCombat {
|
|||||||
async parade(attackerRoll, armeParadeId) {
|
async parade(attackerRoll, armeParadeId) {
|
||||||
const arme = this.defender.getArmeParade(armeParadeId);
|
const arme = this.defender.getArmeParade(armeParadeId);
|
||||||
console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme);
|
console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme);
|
||||||
const competence = arme?.system?.competence;
|
const competence = Misc.templateData(arme)?.competence;
|
||||||
if (competence == undefined) {
|
if (competence == undefined) {
|
||||||
console.error("Pas de compétence de parade associée à ", arme?.name, armeParadeId);
|
console.error("Pas de compétence de parade associée à ", arme);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rollData = this._prepareParade(attackerRoll, arme, competence);
|
let rollData = this._prepareParade(attackerRoll, arme, competence);
|
||||||
|
|
||||||
const dialog = await RdDRoll.create(this.defender, rollData,
|
const dialog = await RdDRoll.create(this.defender, rollData,
|
||||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
|
|
||||||
{
|
{
|
||||||
name: 'jet-parade',
|
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
|
||||||
label: 'Parade: ' + (arme ? arme.name : rollData.competence.name),
|
options: { height: 540 }
|
||||||
callbacks: [
|
}, {
|
||||||
this.defender.createCallbackExperience(),
|
name: 'jet-parade',
|
||||||
this.defender.createCallbackAppelAuMoral(),
|
label: 'Parade: ' + (arme ? arme.name : rollData.competence.name),
|
||||||
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
|
callbacks: [
|
||||||
{ condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(armeParadeId) },
|
this.defender.createCallbackExperience(),
|
||||||
{ condition: RdDCombat.isReussite, action: r => this._onParadeNormale(r) },
|
this.defender.createCallbackAppelAuMoral(),
|
||||||
{ condition: RdDCombat.isParticuliere, action: r => this._onParadeParticuliere(r) },
|
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
|
||||||
{ condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) },
|
{ condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(armeParadeId) },
|
||||||
]
|
{ condition: RdDCombat.isReussite, action: r => this._onParadeNormale(r) },
|
||||||
});
|
{ condition: RdDCombat.isParticuliere, action: r => this._onParadeParticuliere(r) },
|
||||||
|
{ condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) },
|
||||||
|
]
|
||||||
|
});
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,12 +994,12 @@ export class RdDCombat {
|
|||||||
passeArme: attackerRoll.passeArme,
|
passeArme: attackerRoll.passeArme,
|
||||||
diffLibre: attackerRoll.diffLibre,
|
diffLibre: attackerRoll.diffLibre,
|
||||||
attackerRoll: attackerRoll,
|
attackerRoll: attackerRoll,
|
||||||
competence: this.defender.getCompetence(competenceParade),
|
competence: Misc.data(this.defender.getCompetence(competenceParade)),
|
||||||
arme: armeParade,
|
arme: armeParade,
|
||||||
surprise: this.defender.getSurprise(true),
|
surprise: this.defender.getSurprise(true),
|
||||||
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
||||||
needResist: RdDItemArme.needArmeResist(attackerRoll.arme, armeParade),
|
needResist: RdDItemArme.needArmeResist(attackerRoll.arme, armeParade),
|
||||||
carac: this.defender.system.carac,
|
carac: Misc.templateData(this.defender).carac,
|
||||||
show: {}
|
show: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1119,7 +1043,7 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async esquive(attackerRoll, compId, compName) {
|
async esquive(attackerRoll, compId, compName) {
|
||||||
const esquive = this.defender.getCompetence(compId) ?? this.defender.getCompetence(compName)
|
const esquive = Misc.data(this.defender.getCompetence(compId) ?? this.defender.getCompetence(compName));
|
||||||
if (esquive == undefined) {
|
if (esquive == undefined) {
|
||||||
ui.notifications.error(this.defender.name + " n'a pas de compétence " + compName);
|
ui.notifications.error(this.defender.name + " n'a pas de compétence " + compName);
|
||||||
return;
|
return;
|
||||||
@ -1128,20 +1052,19 @@ export class RdDCombat {
|
|||||||
let rollData = this._prepareEsquive(attackerRoll, esquive);
|
let rollData = this._prepareEsquive(attackerRoll, esquive);
|
||||||
|
|
||||||
const dialog = await RdDRoll.create(this.defender, rollData,
|
const dialog = await RdDRoll.create(this.defender, rollData,
|
||||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
|
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' }, {
|
||||||
{
|
name: 'jet-esquive',
|
||||||
name: 'jet-esquive',
|
label: 'Esquiver',
|
||||||
label: 'Esquiver',
|
callbacks: [
|
||||||
callbacks: [
|
this.defender.createCallbackExperience(),
|
||||||
this.defender.createCallbackExperience(),
|
this.defender.createCallbackAppelAuMoral(),
|
||||||
this.defender.createCallbackAppelAuMoral(),
|
{ condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(esquive._id) },
|
||||||
{ condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(esquive._id) },
|
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
|
||||||
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
|
{ condition: RdDCombat.isReussite, action: r => this._onEsquiveNormale(r) },
|
||||||
{ condition: RdDCombat.isReussite, action: r => this._onEsquiveNormale(r) },
|
{ condition: RdDCombat.isParticuliere, action: r => this._onEsquiveParticuliere(r) },
|
||||||
{ condition: RdDCombat.isParticuliere, action: r => this._onEsquiveParticuliere(r) },
|
{ condition: RdDCombat.isEchec, action: r => this._onEsquiveEchec(r) },
|
||||||
{ condition: RdDCombat.isEchec, action: r => this._onEsquiveEchec(r) },
|
]
|
||||||
]
|
});
|
||||||
});
|
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1154,7 +1077,7 @@ export class RdDCombat {
|
|||||||
competence: competence,
|
competence: competence,
|
||||||
surprise: this.defender.getSurprise(true),
|
surprise: this.defender.getSurprise(true),
|
||||||
surpriseDefenseur: this.defender.getSurprise(true),
|
surpriseDefenseur: this.defender.getSurprise(true),
|
||||||
carac: this.defender.system.carac,
|
carac: Misc.templateData(this.defender).carac,
|
||||||
show: {}
|
show: {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1204,11 +1127,11 @@ export class RdDCombat {
|
|||||||
|
|
||||||
const dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor;
|
const dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor;
|
||||||
let arme = defenderRoll.arme;
|
let arme = defenderRoll.arme;
|
||||||
let resistance = Misc.toInt(arme.system.resistance);
|
let resistance = Misc.toInt(arme.data.resistance);
|
||||||
if (arme.system.magique) {
|
if (arme.data.magique) {
|
||||||
defenderRoll.show.deteriorationArme = 'resiste'; // Par défaut
|
defenderRoll.show.deteriorationArme = 'resiste'; // Par défaut
|
||||||
if (arme.system.resistance_magique == undefined) arme.system.resistance_magique = 0; // Quick fix
|
if (arme.data.resistance_magique == undefined) arme.data.resistance_magique = 0; // Quick fix
|
||||||
if (dmg > arme.system.resistance_magique) { // Jet uniquement si dommages supérieur à résistance magique (cf. 274)
|
if (dmg > arme.data.resistance_magique) { // Jet uniquement si dommages supérieur à résistance magique (cf. 274)
|
||||||
// Jet de résistance de l'arme de parade (p.132)
|
// Jet de résistance de l'arme de parade (p.132)
|
||||||
let resistRoll = await RdDResolutionTable.rollData({
|
let resistRoll = await RdDResolutionTable.rollData({
|
||||||
caracValue: resistance,
|
caracValue: resistance,
|
||||||
@ -1216,11 +1139,11 @@ export class RdDCombat {
|
|||||||
showDice: HIDE_DICE
|
showDice: HIDE_DICE
|
||||||
});
|
});
|
||||||
if (!resistRoll.rolled.isSuccess) {
|
if (!resistRoll.rolled.isSuccess) {
|
||||||
let perteResistance = (dmg - arme.system.resistance_magique)
|
let perteResistance = (dmg - arme.data.resistance_magique)
|
||||||
resistance -= perteResistance;
|
resistance -= perteResistance;
|
||||||
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
|
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
|
||||||
defenderRoll.show.perteResistance = perteResistance;
|
defenderRoll.show.perteResistance = perteResistance;
|
||||||
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'system.resistance': resistance }]);
|
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'data.resistance': resistance }]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1236,14 +1159,14 @@ export class RdDCombat {
|
|||||||
resistance -= dmg;
|
resistance -= dmg;
|
||||||
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
|
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
|
||||||
defenderRoll.show.perteResistance = dmg;
|
defenderRoll.show.perteResistance = dmg;
|
||||||
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'system.resistance': resistance }]);
|
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'data.resistance': resistance }]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
|
// 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') {
|
if (ReglesOptionelles.isUsing('defenseurDesarme') && resistance > 0 && RdDItemArme.getCategorieParade(defenderRoll.arme) != 'boucliers') {
|
||||||
let desarme = await RdDResolutionTable.rollData({
|
let desarme = await RdDResolutionTable.rollData({
|
||||||
caracValue: this.defender.getForce(),
|
caracValue: this.defender.getForce(),
|
||||||
finalLevel: Misc.toInt(defenderRoll.competence.system.niveau) - dmg,
|
finalLevel: Misc.toInt(defenderRoll.competence.data.niveau) - dmg,
|
||||||
showDice: HIDE_DICE
|
showDice: HIDE_DICE
|
||||||
});
|
});
|
||||||
defenderRoll.show.desarme = desarme.rolled.isEchec;
|
defenderRoll.show.desarme = desarme.rolled.isEchec;
|
||||||
@ -1262,7 +1185,7 @@ export class RdDCombat {
|
|||||||
defenderRoll.show.recul = 'encaisse';
|
defenderRoll.show.recul = 'encaisse';
|
||||||
} else if (rollRecul.rolled.isETotal || this._isReculCauseChute(impact)) {
|
} else if (rollRecul.rolled.isETotal || this._isReculCauseChute(impact)) {
|
||||||
defenderRoll.show.recul = 'chute';
|
defenderRoll.show.recul = 'chute';
|
||||||
await this.defender.setEffect(STATUSES.StatusProne, true);
|
await this.defender.setStatusEffect("EFFECT.StatusProne", true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
defenderRoll.show.recul = 'recul';
|
defenderRoll.show.recul = 'recul';
|
||||||
@ -1286,7 +1209,7 @@ export class RdDCombat {
|
|||||||
_computeImpactRecul(attaque) {
|
_computeImpactRecul(attaque) {
|
||||||
const taille = this.defender.getTaille();
|
const taille = this.defender.getTaille();
|
||||||
const force = this.attacker.getForce();
|
const force = this.attacker.getForce();
|
||||||
const dommages = attaque.arme.system.dommagesReels ?? attaque.arme.system.dommages;
|
const dommages = attaque.arme.data.dommagesReels ?? attaque.arme.data.dommages;
|
||||||
return taille - (force + dommages);
|
return taille - (force + dommages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1304,7 +1227,7 @@ export class RdDCombat {
|
|||||||
attackerRoll.defenderTokenId = defenderTokenId;
|
attackerRoll.defenderTokenId = defenderTokenId;
|
||||||
|
|
||||||
await this.computeRecul(defenderRoll);
|
await this.computeRecul(defenderRoll);
|
||||||
this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll?.show);
|
this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll);
|
||||||
}
|
}
|
||||||
else { // envoi à un GM: les joueurs n'ont pas le droit de modifier les personnages qu'ils ne possèdent pas
|
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, {
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
@ -1322,6 +1245,8 @@ export class RdDCombat {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* retourne true si on peut continuer, false si on ne peut pas continuer */
|
/* retourne true si on peut continuer, false si on ne peut pas continuer */
|
||||||
async accorderEntite(when = 'avant-encaissement') {
|
async accorderEntite(when = 'avant-encaissement') {
|
||||||
|
console.log("TETETET", game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar"), this.defender.isEntite([ENTITE_INCARNE]), this.defender.isEntiteAccordee(this.attacker))
|
||||||
|
|
||||||
if (when != game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar")
|
if (when != game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar")
|
||||||
|| this.defender == undefined
|
|| this.defender == undefined
|
||||||
|| !this.defender.isEntite([ENTITE_INCARNE])
|
|| !this.defender.isEntite([ENTITE_INCARNE])
|
||||||
@ -1329,7 +1254,7 @@ export class RdDCombat {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(this.defender.system.carac.niveau.value));
|
let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(Misc.templateData(this.defender).carac.niveau.value));
|
||||||
|
|
||||||
let message = {
|
let message = {
|
||||||
content: "Jet de points actuels de rêve à " + rolled.finalLevel + RdDResolutionTable.explain(rolled) + "<br>",
|
content: "Jet de points actuels de rêve à " + rolled.finalLevel + RdDResolutionTable.explain(rolled) + "<br>",
|
||||||
@ -1350,25 +1275,25 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async displayActorCombatStatus(combat, actor) {
|
static async displayActorCombatStatus(combat, actor) {
|
||||||
let formData = {
|
let data = {
|
||||||
combatId: combat._id,
|
combatId: combat._id,
|
||||||
alias: actor.name,
|
alias: actor.name,
|
||||||
etatGeneral: actor.getEtatGeneral(),
|
etatGeneral: actor.getEtatGeneral(),
|
||||||
isSonne: actor.getSonne(),
|
isSonne: actor.getSonne(),
|
||||||
blessuresStatus: actor.computeResumeBlessure(),
|
blessuresStatus: actor.computeResumeBlessure(),
|
||||||
SConst: actor.getSConst(),
|
SConst: actor.getSConst(),
|
||||||
actorId: actor.id,
|
actorId: actor.data._id,
|
||||||
isGrave: false,
|
isGrave: false,
|
||||||
isCritique: false
|
isCritique: false
|
||||||
}
|
}
|
||||||
if (actor.countBlessuresNonSoigneeByName("critiques") > 0) { // Pour éviter le cumul grave + critique
|
if (actor.countBlessuresNonSoigneeByName("critiques") > 0) { // Pour éviter le cumul grave + critique
|
||||||
formData.isCritique = true;
|
data.isCritique = true;
|
||||||
} else if (actor.countBlessuresNonSoigneeByName("graves") > 0) {
|
} else if (actor.countBlessuresNonSoigneeByName("graves") > 0) {
|
||||||
formData.isGrave = true;
|
data.isGrave = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatUtility.createChatWithRollMode(actor.name, {
|
ChatUtility.createChatWithRollMode(actor.name, {
|
||||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, formData)
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, data)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
import { DialogChronologie } from "./dialog-chronologie.js";
|
|
||||||
import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js";
|
import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js";
|
||||||
import { DialogStress } from "./dialog-stress.js";
|
import { DialogStress } from "./dialog-stress.js";
|
||||||
|
import { Grammar } from "./grammar.js";
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
@ -13,7 +13,7 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
|||||||
import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
||||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { CompendiumTableHelpers } from "./settings/system-compendiums.js";
|
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
|
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
|
||||||
@ -22,100 +22,55 @@ const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
|
|||||||
export class RdDCommands {
|
export class RdDCommands {
|
||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
const rddCommands = new RdDCommands();
|
if (!game.system.rdd.commands) {
|
||||||
|
const rddCommands = new RdDCommands();
|
||||||
|
rddCommands.registerCommand({ path: ["/aide"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
|
||||||
|
rddCommands.registerCommand({ path: ["/help"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
|
||||||
|
rddCommands.registerCommand({ path: ["/table", "queues"], func: (content, msg, params) => RdDRollTables.getQueue(true), descr: "Tire une Queue de Dragon" });
|
||||||
|
rddCommands.registerCommand({ path: ["/table", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe(true), descr: "Tire une Idée fixe" });
|
||||||
|
rddCommands.registerCommand({ path: ["/table", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant(true), descr: "Tire un Désir Lancinant" });
|
||||||
|
rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre(true), descr: "Tire une Ombre de Dragon" });
|
||||||
|
rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR(true), descr: "Tire une Tête de Dragon pour Hauts Revants" });
|
||||||
|
rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete(true), descr: "Tire une Tête de Dragon" });
|
||||||
|
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" });
|
||||||
|
|
||||||
Hooks.on("chatMessage", (html, content, msg) => {
|
rddCommands.registerCommand({
|
||||||
if (content[0] == '/') {
|
path: ["/tmra"], func: (content, msg, params) => rddCommands.getTMRAleatoire(msg, params),
|
||||||
let regExp = /(\S+)/g;
|
descr: `Tire une case aléatoire des Terres médianes
|
||||||
let commands = content.match(regExp);
|
|
||||||
if (rddCommands.processChatCommand(commands, content, msg)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
|
|
||||||
game.system.rdd.commands = rddCommands;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.commandsTable = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
_registerCommands() {
|
|
||||||
this.commandsTable = {}
|
|
||||||
this.registerCommand({ path: ["/aide"], func: (content, msg, params) => this.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
|
|
||||||
this.registerCommand({ path: ["/help"], func: (content, msg, params) => this.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
|
|
||||||
|
|
||||||
this.registerCommand({ path: ["/liste", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('liste'), descr: "Affiche la liste des compétences" });
|
|
||||||
|
|
||||||
this.registerCommand({ path: ["/table", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('liste'), descr: "Affiche la table des Queues de Dragon" });
|
|
||||||
this.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre('liste'), descr: "Affiche la table des Ombres de Thanatos" });
|
|
||||||
this.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR('liste'), descr: "Affiche la table des Têtes de Dragon pour Hauts Revants" });
|
|
||||||
this.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete('liste'), descr: "Affiche la table des Tête de Dragon pour tous" });
|
|
||||||
this.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle('liste'), descr: "Affiche la table des Souffles de Dragon" });
|
|
||||||
this.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot('liste'), descr: "Affiche la table les cartes du Tarot Draconique" });
|
|
||||||
this.registerCommand({ path: ["/table", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe('liste'), descr: "Affiche la table des Idées fixes" });
|
|
||||||
this.registerCommand({ path: ["/table", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('liste'), descr: "Affiche la table des Désirs Lancinants" });
|
|
||||||
this.registerCommand({
|
|
||||||
path: ["/table", "rencontre"], func: (content, msg, params) => this.tableRencontres(msg, params),
|
|
||||||
descr: `Affiche la table des Rencontres
|
|
||||||
<br><strong>/table rencontre deso</strong> affiche la table des rencontres en Désolation
|
|
||||||
<br><strong>/table rencontre mauvaise</strong> affiche la table des mauvaises rencontres`
|
|
||||||
});
|
|
||||||
this.registerCommand({ path: ["/table", "milieu"], func: (content, msg, params) => this.tableMilieu(msg, params, 'liste'), descr: "Affiche la table des ressource naturelles pour un milieu donné" });
|
|
||||||
|
|
||||||
this.registerCommand({ path: ["/tirer", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('chat'), descr: "Tire une compétence au hasard" });
|
|
||||||
this.registerCommand({ path: ["/tirer", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('chat'), descr: "Tire une Queue de Dragon" });
|
|
||||||
this.registerCommand({ path: ["/tirer", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre('chat'), descr: "Tire une Ombre de Thanatos" });
|
|
||||||
this.registerCommand({ path: ["/tirer", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR('chat'), descr: "Tire une Tête de Dragon pour Hauts Revants" });
|
|
||||||
this.registerCommand({ path: ["/tirer", "tete"], func: (content, msg, params) => RdDRollTables.getTete('chat'), descr: "Tire une Tête de Dragon" });
|
|
||||||
this.registerCommand({ path: ["/tirer", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle('chat'), descr: "Tire un Souffle de Dragon" });
|
|
||||||
this.registerCommand({ path: ["/tirer", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot('chat'), descr: "Tire une carte du Tarot Draconique" });
|
|
||||||
this.registerCommand({ path: ["/tirer", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe('chat'), descr: "Tire une Idée fixe" });
|
|
||||||
this.registerCommand({ path: ["/tirer", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('chat'), descr: "Tire un Désir Lancinant" });
|
|
||||||
this.registerCommand({ path: ["/tirer", "rencontre"], func: (content, msg, params) => this.getRencontreTMR(params), descr: `Détermine une rencontre dans les TMR (synonyme de "/tmrr")` });
|
|
||||||
this.registerCommand({ path: ["/tirer", "milieu"], func: (content, msg, params) => this.tableMilieu(msg, params, 'chat'), descr: "Effectue un tirage dans la table desressource naturelles pour un milieu donné" });
|
|
||||||
|
|
||||||
this.registerCommand({ path: ["/meteo"], func: (content, msg, params) => this.getMeteo(msg, params), descr: "Propose une météo marine" });
|
|
||||||
this.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
|
|
||||||
|
|
||||||
this.registerCommand({
|
|
||||||
path: ["/tmr"], func: (content, msg, params) => this.findTMR(msg, params),
|
|
||||||
descr: `Cherche où se trouve une case des Terres médianes
|
|
||||||
<br><strong>/tmr sord</strong> indique que la cité Sordide est en D13
|
|
||||||
<br><strong>/tmr foret</strong> donne la liste des TMR dont le nom contient "foret" (donc, toutes les forêts)`
|
|
||||||
});
|
|
||||||
this.registerCommand({
|
|
||||||
path: ["/tmra"], func: (content, msg, params) => this.getTMRAleatoire(msg, params),
|
|
||||||
descr: `Tire une case aléatoire des Terres médianes
|
|
||||||
<br><strong>/tmra forêt</strong> détermine une 'forêt' aléatoire
|
<br><strong>/tmra forêt</strong> détermine une 'forêt' aléatoire
|
||||||
<br><strong>/tmra</strong> détermine une case aléatoire dans toutes les TMR`
|
<br><strong>/tmra</strong> détermine une case aléatoire dans toutes les TMR` });
|
||||||
});
|
rddCommands.registerCommand({
|
||||||
this.registerCommand({
|
path: ["/tmr"], func: (content, msg, params) => rddCommands.findTMR(msg, params),
|
||||||
path: ["/tmrr"], func: (content, msg, params) => this.getRencontreTMR(params),
|
descr: `Cherche où se trouve une case des Terres médianes
|
||||||
descr: `Détermine une rencontre dans les TMR
|
<br><strong>/tmr? sordide</strong> indique que la cité Sordide est en D13
|
||||||
<br><strong>/tmrr forêt</strong> détermine une rencontre aléatoire en 'forêt'
|
<br><strong>/tmr? foret</strong> donne la liste des TMR dont le nom contient "foret" (donc, toutes les forêts)` });
|
||||||
<br><strong>/tmrr mauvaise</strong> détermine une mauvaise rencontre aléatoire
|
rddCommands.registerCommand({
|
||||||
<br><strong>/tmrr for 47</strong> détermine la rencontre en 'forêt' pour un jet de dé de 47`
|
path: ["/tmrr"], func: (content, msg, params) => rddCommands.getRencontreTMR(params),
|
||||||
});
|
descr: `Détermine une rencontre dans un type de case
|
||||||
|
<br><strong>/tmrr foret</strong> lance un d100 et détermine la rencontre correspondante en 'forêt'
|
||||||
|
<br><strong>/tmrr forêt 47</strong> détermine la rencontre en 'forêt' pour un jet de dé de 47`
|
||||||
|
});
|
||||||
|
|
||||||
this.registerCommand({
|
rddCommands.registerCommand({
|
||||||
path: ["/xp", "comp"], func: (content, msg, params) => this.getCoutXpComp(msg, params),
|
path: ["/xp", "comp"], func: (content, msg, params) => rddCommands.getCoutXpComp(msg, params),
|
||||||
descr: `Détermine le coût d'expérience pour augmenter une compétence. Exemples:
|
descr: `Détermine le coût d'expérience pour augmenter une compétence. Exemples:
|
||||||
<br>/xp comp -6 1: pour passer de -6 à +1
|
<br>/xp comp -6 1: pour passer de -6 à +1
|
||||||
<br>/xp comp +4: pour atteindre le niveau 4 (depuis +3)`
|
<br>/xp comp +4: pour atteindre le niveau 4 (depuis +3)`
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand({
|
rddCommands.registerCommand({
|
||||||
path: ["/xp", "carac"], func: (content, msg, params) => this.getCoutXpCarac(msg, params),
|
path: ["/xp", "carac"], func: (content, msg, params) => rddCommands.getCoutXpCarac(msg, params),
|
||||||
descr: `Détermine le coût d'expérience pour augmenter une caractéristique. Exemples:
|
descr: `Détermine le coût d'expérience pour augmenter une caractéristique. Exemples:
|
||||||
<br>/xp carac 15: coût pour atteindre 15 (depuis 14)`
|
<br>/xp carac 15: coût pour atteindre 15 (depuis 14)`
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand({
|
rddCommands.registerCommand({
|
||||||
path: ["/rdd"], func: (content, msg, params) => this.rollRdd(msg, params),
|
path: ["/rdd"], func: (content, msg, params) => rddCommands.rollRdd(msg, params),
|
||||||
descr: `Effectue un jet de dés dans la table de résolution. Exemples:
|
descr: `Effectue un jet de dés dans la table de résolution. Exemples:
|
||||||
<br><strong>/rdd</strong> ouvre la table de résolution
|
<br><strong>/rdd</strong> ouvre la table de résolution
|
||||||
<br><strong>/rdd 10 3</strong> effectue un jet 10 à +3
|
<br><strong>/rdd 10 3</strong> effectue un jet 10 à +3
|
||||||
<br><strong>/rdd 15 -2</strong> effectue un jet 15 à -2
|
<br><strong>/rdd 15 -2</strong> effectue un jet 15 à -2
|
||||||
@ -123,46 +78,47 @@ export class RdDCommands {
|
|||||||
<br><strong>/rdd Vue Vigilance -2</strong> effectue un jet de Vue/Vigilance à -2 pour les tokens sélectionnés
|
<br><strong>/rdd Vue Vigilance -2</strong> effectue un jet de Vue/Vigilance à -2 pour les tokens sélectionnés
|
||||||
<br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés
|
<br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés
|
||||||
`
|
`
|
||||||
});
|
});
|
||||||
this.registerCommand({ path: ["/ddr"], func: (content, msg, params) => this.rollDeDraconique(msg), descr: "Lance un Dé Draconique" });
|
rddCommands.registerCommand({ path: ["/ddr"], func: (content, msg, params) => rddCommands.rollDeDraconique(msg), descr: "Lance un Dé Draconique" });
|
||||||
|
|
||||||
this.registerCommand({
|
rddCommands.registerCommand({
|
||||||
path: ["/payer"], func: (content, msg, params) => RdDUtility.afficherDemandePayer(params[0], params[1]),
|
path: ["/payer"], func: (content, msg, params) => RdDUtility.afficherDemandePayer(params[0], params[1]),
|
||||||
descr: `Demande aux joueurs de payer un montant. Exemples:
|
descr: `Permet de payer un montant. Exemples:
|
||||||
<br><strong>/payer 5s 10d</strong> permet d'envoyer un message pour payer 5 sols et 10 deniers
|
<br><strong>/payer 5s 10d</strong> permet d'envoyer un message pour payer 5 sols et 10 deniers
|
||||||
<br><strong>/payer 10d</strong> permet d'envoyer un message pour payer 10 deniers`
|
<br><strong>/payer 10d</strong> permet d'envoyer un message pour payer 10 deniers`
|
||||||
});
|
});
|
||||||
this.registerCommand({
|
rddCommands.registerCommand({
|
||||||
path: ["/astro"], func: (content, msg, params) => RdDUtility.afficherHeuresChanceMalchance(Misc.join(params, ' ')),
|
path: ["/astro"], func: (content, msg, params) => RdDUtility.afficherHeuresChanceMalchance(Misc.join(params, ' ')),
|
||||||
descr: `Affiche les heures de chance et de malchance selon l'heure de naissance donnée en argument. Exemples pour l'heure de la Lyre:
|
descr: `Affiche les heures de chance et de malchance selon l'heure de naissance donnée en argument. Exemples pour l'heure de la Lyre:
|
||||||
<br><strong>/astro 7</strong>
|
<br><strong>/astro 7</strong>
|
||||||
<br><strong>/astro Lyre</strong>
|
<br><strong>/astro Lyre</strong>
|
||||||
<br><strong>/astro Lyr</strong>`
|
<br><strong>/astro Lyr</strong>`
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand({
|
rddCommands.registerCommand({
|
||||||
path: ["/signe", "+"], func: (content, msg, params) => this.creerSignesDraconiques(),
|
path: ["/signe", "+"], func: (content, msg, params) => rddCommands.creerSignesDraconiques(),
|
||||||
descr: "Crée un signe draconique et l'ajoute aux haut-rêvants choisis."
|
descr: "Crée un signe draconique et l'ajoute aux haut-rêvants choisis."
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand({
|
rddCommands.registerCommand({
|
||||||
path: ["/signe", "-"], func: (content, msg, params) => this.supprimerSignesDraconiquesEphemeres(),
|
path: ["/signe", "-"], func: (content, msg, params) => rddCommands.supprimerSignesDraconiquesEphemeres(),
|
||||||
descr: "Supprime les signes draconiques éphémères"
|
descr: "Supprime les signes draconiques éphémères"
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand({
|
rddCommands.registerCommand({
|
||||||
path: ["/stress"], func: (content, msg, params) => this.distribuerStress(params),
|
path: ["/stress"], func: (content, msg, params) => rddCommands.distribuerStress(params),
|
||||||
descr: `Distribue du stress aux personnages. Exemples:
|
descr: `Distribue du stress aux personnages. Exemples:
|
||||||
<br><strong>/stress</strong> : Ouvre une fenêtre pour donner du stress ou de l'expérience à un ensemble de personnages
|
<br><strong>/stress</strong> : Ouvre une fenêtre pour donner du stress ou de l'expérience à un ensemble de personnages
|
||||||
<br><strong>/stress 6</strong> : Distribue 6 points des Stress à tout les personnages joueurs, sans raison renseignée
|
<br><strong>/stress 6</strong> : Distribue 6 points des Stress à tout les personnages joueurs, sans raison renseignée
|
||||||
<br><strong>/stress 6 Tigre</strong> : Distribue 6 points des Stress à tout les personnages joueurs, à cause d'un Tigre (Vert)
|
<br><strong>/stress 6 Tigre</strong> : Distribue 6 points des Stress à tout les personnages joueurs, à cause d'un Tigre (Vert)
|
||||||
<br><strong>/stress 6 Glou Paulo</strong> : Distribue 6 points de Stress au personnage Paulon ou au personnage joueur Paulo, à cause d'un Glou`
|
<br><strong>/stress 6 Glou Paulo</strong> : Distribue 6 points de Stress au personnage Paulon ou au personnage joueur Paulo, à cause d'un Glou`
|
||||||
});
|
});
|
||||||
|
|
||||||
this.registerCommand({
|
game.system.rdd.commands = rddCommands;
|
||||||
path: ["/chrono"], func: (content, msg, params) => DialogChronologie.create(),
|
}
|
||||||
descr: `Enregistre une entrée de chronologie dans un article de journal`
|
}
|
||||||
});
|
constructor() {
|
||||||
|
this.commandsTable = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -204,50 +160,37 @@ export class RdDCommands {
|
|||||||
processChatCommand(commandLine, content = '', msg = {}) {
|
processChatCommand(commandLine, content = '', msg = {}) {
|
||||||
// Setup new message's visibility
|
// Setup new message's visibility
|
||||||
let rollMode = game.settings.get("core", "rollMode");
|
let rollMode = game.settings.get("core", "rollMode");
|
||||||
if (["gmroll", "blindroll"].includes(rollMode)) {
|
if (["gmroll", "blindroll"].includes(rollMode)) msg["whisper"] = ChatMessage.getWhisperRecipients("GM");
|
||||||
msg["whisper"] = ChatMessage.getWhisperRecipients("GM");
|
if (rollMode === "blindroll") msg["blind"] = true;
|
||||||
}
|
|
||||||
if (rollMode === "blindroll"){
|
|
||||||
msg["blind"] = true;
|
|
||||||
}
|
|
||||||
msg["type"] = 0;
|
msg["type"] = 0;
|
||||||
|
|
||||||
if (!this.commandsTable) {
|
|
||||||
this._registerCommands();
|
|
||||||
}
|
|
||||||
|
|
||||||
let command = commandLine[0].toLowerCase();
|
let command = commandLine[0].toLowerCase();
|
||||||
if (this._isCommandHandled(command)) {
|
let params = commandLine.slice(1);
|
||||||
let params = commandLine.slice(1);
|
|
||||||
this._processCommand(this.commandsTable, command, params, content, msg);
|
return this.process(command, params, content, msg);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_isCommandHandled(command){
|
process(command, params, content, msg) {
|
||||||
return this.commandsTable[command] != undefined;
|
return this._processCommand(this.commandsTable, command, params, content, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _processCommand(commandsTable, name, params, content = '', msg = {}, path = "") {
|
_processCommand(commandsTable, name, params, content = '', msg = {}, path = "") {
|
||||||
let command = commandsTable[name];
|
let command = commandsTable[name];
|
||||||
path = path + name + " ";
|
path = path + name + " ";
|
||||||
if (command && command.subTable) {
|
if (command && command.subTable) {
|
||||||
if (params[0]) {
|
if (params[0]) {
|
||||||
this._processCommand(command.subTable, params[0], params.slice(1), content, msg, path)
|
return this._processCommand(command.subTable, params[0], params.slice(1), content, msg, path)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.help(msg, command.subTable);
|
this.help(msg, command.subTable);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
if (command && command.func) {
|
if (command && command.func) {
|
||||||
new Promise(async () => {
|
const result = command.func(content, msg, params);
|
||||||
const result = await command.func(content, msg, params);
|
if (result == false) {
|
||||||
if (result == false) {
|
RdDCommands._chatAnswer(msg, command.descr);
|
||||||
RdDCommands._chatAnswer(msg, command.descr);
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -258,10 +201,10 @@ export class RdDCommands {
|
|||||||
this.help(msg, undefined);
|
this.help(msg, undefined);
|
||||||
}
|
}
|
||||||
async help(msg, table) {
|
async help(msg, table) {
|
||||||
let commands = []
|
let list = []
|
||||||
this._buildSubTableHelp(commands, table ?? this.commandsTable);
|
this._buildSubTableHelp(list, table || this.commandsTable);
|
||||||
|
|
||||||
let html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/settings/dialog-aide-commands.html", { commands: commands });
|
let html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/settings/dialog-aide-commands.html", { commands: list });
|
||||||
let d = new Dialog(
|
let d = new Dialog(
|
||||||
{
|
{
|
||||||
title: "Commandes disponibles dans le tchat",
|
title: "Commandes disponibles dans le tchat",
|
||||||
@ -269,7 +212,7 @@ export class RdDCommands {
|
|||||||
buttons: {},
|
buttons: {},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
width: 600, height: 600,
|
width: 600, height: 500,
|
||||||
});
|
});
|
||||||
|
|
||||||
d.render(true);
|
d.render(true);
|
||||||
@ -299,9 +242,11 @@ export class RdDCommands {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getRencontreTMR(params) {
|
async getRencontreTMR(params) {
|
||||||
if (params.length == 1 || params.length == 2) {
|
if (params.length == 1 || params.length == 2) {
|
||||||
return game.system.rdd.rencontresTMR.rollRencontre(params[0], params[1])
|
return TMRRencontres.rollRencontre(params[0], params[1])
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -354,20 +299,20 @@ export class RdDCommands {
|
|||||||
show: { title: "Table de résolution" }
|
show: { title: "Table de résolution" }
|
||||||
};
|
};
|
||||||
await RdDResolutionTable.rollData(rollData);
|
await RdDResolutionTable.rollData(rollData);
|
||||||
return RdDCommands._chatAnswer(msg, await RdDResolutionTable.buildRollDataHtml(rollData));
|
RdDCommands._chatAnswer(msg, await RdDResolutionTable.buildRollDataHtml(rollData));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async rollDeDraconique(msg) {
|
async rollDeDraconique(msg) {
|
||||||
let ddr = await RdDDice.rollTotal("1dr + 7");
|
let ddr = await RdDDice.rollTotal("1dr + 7");
|
||||||
return RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr}`);
|
RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTMRAleatoire(msg, params) {
|
async getTMRAleatoire(msg, params) {
|
||||||
if (params.length < 2) {
|
if (params.length < 2) {
|
||||||
let type = params[0];
|
let type = params[0];
|
||||||
const tmr = await TMRUtility.getTMRAleatoire(type ? (it => it.type == type) : (it => true));
|
const tmr = await TMRUtility.getTMRAleatoire(type ? (it => it.type == type) : (it => true));
|
||||||
return RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`);
|
RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
@ -375,58 +320,20 @@ export class RdDCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async findTMR(msg, params) {
|
async findTMR(msg, params) {
|
||||||
if (params && params.length > 0) {
|
const search = Misc.join(params, ' ');
|
||||||
const search = Misc.join(params, ' ');
|
const found = TMRUtility.findTMR(search);
|
||||||
const found = TMRUtility.findTMR(search);
|
if (found?.length > 0) {
|
||||||
if (found?.length > 0) {
|
return RdDCommands._chatAnswer(msg, `Les TMRs correspondant à '${search}' sont:` + Misc.join(found.map(it => `<br>${it.coord}: ${it.label}`)));
|
||||||
return RdDCommands._chatAnswer(msg, `Les TMRs correspondant à '${search}' sont:` + Misc.join(found.map(it => `<br>${it.coord}: ${it.label}`)));
|
|
||||||
}
|
|
||||||
return RdDCommands._chatAnswer(msg, 'Aucune TMR correspondant à ' + search);
|
|
||||||
}
|
}
|
||||||
return false;
|
return RdDCommands._chatAnswer(msg, 'Aucune TMR correspondant à ' + search);
|
||||||
}
|
}
|
||||||
|
|
||||||
async tableRencontres(msg, params) {
|
|
||||||
if (params && params.length > 0) {
|
|
||||||
const search = Misc.join(params, ' ');
|
|
||||||
const solvedTerrain = TMRUtility.findTMRLike(search);
|
|
||||||
if (solvedTerrain == undefined) {
|
|
||||||
return RdDCommands._chatAnswer(msg, 'Aucune TMR correspondant à ' + search);
|
|
||||||
}
|
|
||||||
return await game.system.rdd.rencontresTMR.chatTable(solvedTerrain);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async tableMilieu(msg, params, toChat) {
|
|
||||||
if (params && params.length > 0) {
|
|
||||||
const search = Misc.join(params, ' ');
|
|
||||||
const milieux = await game.system.rdd.environnement.findEnvironnementsLike(search);
|
|
||||||
if (milieux.length == 0) {
|
|
||||||
return RdDCommands._chatAnswer(msg, 'Aucun milieu correspondant à ' + search);
|
|
||||||
}
|
|
||||||
if (milieux.length > 1) {
|
|
||||||
ui.notifications.warn(`<strong>Plusieurs milieux correspondent à '${search}'</strong>:
|
|
||||||
<br><ul><li>${milieux.reduce(Misc.joining('</li><li>'))}</li></ul>`);
|
|
||||||
}
|
|
||||||
const tableName = `ressources en ${milieux.reduce(Misc.joining(', '))}`;
|
|
||||||
if (toChat == 'liste') {
|
|
||||||
return await game.system.rdd.environnement.searchToChatMessage(milieux, tableName);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const row = await game.system.rdd.environnement.getRandom(milieux, tableName);
|
|
||||||
await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getCoutXpComp(msg, params) {
|
getCoutXpComp(msg, params) {
|
||||||
if (params && (params.length == 1 || params.length == 2)) {
|
if (params && (params.length == 1 || params.length == 2)) {
|
||||||
let to = params.length == 1 ? Number(params[0]) : Number(params[1]);
|
let to = params.length == 1 ? Number(params[0]) : Number(params[1]);
|
||||||
let from = params.length == 1 ? to - 1 : Number(params[0]);
|
let from = params.length == 1 ? to - 1 : Number(params[0]);
|
||||||
return RdDCommands._chatAnswer(msg, `Coût pour passer une compétence de ${from} à ${to}: ${RdDItemCompetence.getDeltaXp(from, to)}`);
|
RdDCommands._chatAnswer(msg, `Coût pour passer une compétence de ${from} à ${to}: ${RdDItemCompetence.getDeltaXp(from, to)}`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
@ -437,7 +344,7 @@ export class RdDCommands {
|
|||||||
getCoutXpCarac(msg, params) {
|
getCoutXpCarac(msg, params) {
|
||||||
if (params && params.length == 1) {
|
if (params && params.length == 1) {
|
||||||
let to = Number(params[0]);
|
let to = Number(params[0]);
|
||||||
return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to)}`);
|
RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to)}`);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
@ -451,9 +358,10 @@ export class RdDCommands {
|
|||||||
|
|
||||||
async supprimerSignesDraconiquesEphemeres() {
|
async supprimerSignesDraconiquesEphemeres() {
|
||||||
game.actors.forEach(actor => {
|
game.actors.forEach(actor => {
|
||||||
const ephemeres = actor.items.filter(item => item.type = 'signedraconique' && item.system.ephemere);
|
const ephemeres = actor.filterItems(item => Misc.data(item).type = 'signedraconique' && Misc.data(item).data.ephemere)
|
||||||
|
.map(item => item.id);
|
||||||
if (ephemeres.length > 0) {
|
if (ephemeres.length > 0) {
|
||||||
actor.deleteEmbeddedDocuments("Item", ephemeres.map(item => item.id));
|
actor.deleteEmbeddedDocuments("Item", ephemeres);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
@ -497,6 +405,5 @@ export class RdDCommands {
|
|||||||
async getMeteo(msg, params) {
|
async getMeteo(msg, params) {
|
||||||
return await RdDMeteo.getMeteo();
|
return await RdDMeteo.getMeteo();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
import { SYSTEM_RDD } from "./constants.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
|
|
||||||
export class RddCompendiumOrganiser {
|
export class RddCompendiumOrganiser {
|
||||||
static init() {
|
static init() {
|
||||||
Hooks.on('renderCompendium', async (pack, html, compendiumData) => RddCompendiumOrganiser.onRenderCompendium(pack, html, compendiumData))
|
Hooks.on('renderCompendium', async (pack, html, data) => RddCompendiumOrganiser.onRenderCompendium(pack, html, data))
|
||||||
}
|
}
|
||||||
|
|
||||||
static async onRenderCompendium(compendium, html, compendiumData) {
|
static async onRenderCompendium(compendium, html, data) {
|
||||||
console.log('onRenderCompendium', compendium, html, compendiumData);
|
console.log('onRenderCompendium', compendium, html, data);
|
||||||
const pack = compendium.collection
|
const pack = compendium.collection
|
||||||
if (pack.metadata.system === SYSTEM_RDD) {
|
if (pack.metadata.system === SYSTEM_RDD) {
|
||||||
html.find('.directory-item').each((i, element) => {
|
html.find('.directory-item').each((i, element) => {
|
||||||
@ -16,7 +17,7 @@ export class RddCompendiumOrganiser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async setEntityTypeName(pack, element) {
|
static async setEntityTypeName(pack, element) {
|
||||||
const label = RddCompendiumOrganiser.getEntityTypeLabel(await pack.getDocument(element.dataset.documentId));
|
const label = Misc.getEntityTypeLabel(await pack.getDocument(element.dataset.documentId));
|
||||||
RddCompendiumOrganiser.insertEntityType(element, label);
|
RddCompendiumOrganiser.insertEntityType(element, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -26,17 +27,4 @@ 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;
|
|
||||||
if (game.i18n.has(label)) {
|
|
||||||
return game.i18n.localize(label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,56 +0,0 @@
|
|||||||
import { Grammar } from "./grammar.js";
|
|
||||||
import { ReglesOptionelles } from "./settings/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: options.buttonLabel + "<br>et ne plus demander",
|
|
||||||
callback: () => {
|
|
||||||
ReglesOptionelles.set(options.settingConfirmer, false);
|
|
||||||
options.onAction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
@ -132,21 +132,21 @@ export class RdDDice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async rollTotal(formula, options = { showDice: HIDE_DICE }) {
|
|
||||||
return (await RdDDice.roll(formula, options)).total;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async roll(formula, options = { showDice: SHOW_DICE, rollMode: undefined }) {
|
static async roll(formula, options = { showDice: SHOW_DICE, rollMode: undefined }) {
|
||||||
const roll = new Roll(RdDDice._formulaOrFake(formula, options));
|
const roll = new Roll(formula);
|
||||||
await roll.evaluate({ async: true });
|
await roll.evaluate({ async: true });
|
||||||
await this.showDiceSoNice(roll, options);
|
if (options.showDice != HIDE_DICE) {
|
||||||
|
await this.showDiceSoNice(roll, options.rollMode ?? game.settings.get("core", "rollMode"));
|
||||||
|
}
|
||||||
return roll;
|
return roll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async rollTotal(formula, options = { showDice: HIDE_DICE}) {
|
||||||
|
const roll = await RdDDice.roll(formula, options);
|
||||||
|
return roll.total;
|
||||||
|
}
|
||||||
|
|
||||||
static async rollOneOf(array) {
|
static async rollOneOf(array) {
|
||||||
if (array == undefined || array.length == 0) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
const roll = await RdDDice.rollTotal(`1d${array.length}`);
|
const roll = await RdDDice.rollTotal(`1d${array.length}`);
|
||||||
return array[roll - 1];
|
return array[roll - 1];
|
||||||
}
|
}
|
||||||
@ -160,106 +160,27 @@ export class RdDDice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async showDiceSoNice(roll, options) {
|
static async showDiceSoNice(roll, rollMode) {
|
||||||
if (options.showDice == HIDE_DICE || !game.modules.get("dice-so-nice")?.active || !game.dice3d) {
|
if (game.modules.get("dice-so-nice")?.active) {
|
||||||
return;
|
if (game.dice3d) {
|
||||||
}
|
let whisper = null;
|
||||||
|
let blind = false;
|
||||||
let { whisper, blind } = RdDDice._getWhisperBlind(options);
|
rollMode = rollMode ?? game.settings.get("core", "rollMode");
|
||||||
if (options.forceDiceResult?.total) {
|
switch (rollMode) {
|
||||||
let terms = await RdDDice._getForcedTerms(options);
|
case "blindroll": //GM only
|
||||||
if (terms) {
|
blind = true;
|
||||||
await game.dice3d.show({ throws: [{ dice: terms }] })
|
case "gmroll": //GM + rolling player
|
||||||
return;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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 = undefined;
|
|
||||||
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,19 +18,18 @@ const tableGemmes = {
|
|||||||
export class RdDGemme extends Item {
|
export class RdDGemme extends Item {
|
||||||
|
|
||||||
static getGemmeTypeOptionList() {
|
static getGemmeTypeOptionList() {
|
||||||
// TODO: look how to map object key-value pairs
|
|
||||||
let options = ""
|
let options = ""
|
||||||
for (let gemmeKey in tableGemmes) {
|
for (let gemmeKey in tableGemmes) {
|
||||||
options += `<option value="${gemmeKey}">${tableGemmes[gemmeKey].label}</option>`
|
let gemmeData = tableGemmes[gemmeKey];
|
||||||
|
options += `<option value="${gemmeKey}">${gemmeData.label}</option>`
|
||||||
}
|
}
|
||||||
return options;
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static calculDataDerivees(data) {
|
||||||
static calculDataDerivees(gemme) {
|
data.cout = (data.taille * data.purete) + data.qualite;
|
||||||
gemme.system.cout = (gemme.system.taille * gemme.system.purete) + gemme.system.qualite;
|
data.inertie = 7 - data.purete;
|
||||||
gemme.system.inertie = 7 - gemme.system.purete;
|
data.enchantabilite = data.taille - data.inertie;
|
||||||
gemme.system.enchantabilite = gemme.system.taille - gemme.system.inertie;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,75 +1,76 @@
|
|||||||
|
/* -------------------------------------------- */
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
import { RdDCalendrier } from "./rdd-calendrier.js";
|
||||||
import { Grammar } from "./grammar.js";
|
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDHerbes extends Item {
|
export class RdDHerbes extends Item {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async initializeHerbes() {
|
static isHerbeSoin( botaniqueItem ) {
|
||||||
this.herbesSoins = await RdDHerbes.listCategorieHerbes('Soin');
|
return Misc.templateData(botaniqueItem).categorie == 'Soin';
|
||||||
this.herbesRepos = await RdDHerbes.listCategorieHerbes('Repos');
|
|
||||||
}
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
static async listCategorieHerbes(categorie) {
|
static isHerbeRepos( botaniqueItem ) {
|
||||||
const herbes = await SystemCompendiums.getWorldOrCompendiumItems('herbe', 'faune-flore-mineraux');
|
return Misc.templateData(botaniqueItem).categorie == 'Repos';
|
||||||
return herbes.filter(it => Grammar.equalsInsensitive(it.system.categorie, categorie));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static buildHerbesList(listeHerbes, max) {
|
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) {
|
||||||
let list = {}
|
let list = {}
|
||||||
for (let herbe of listeHerbes) {
|
for ( let herbe of listHerbes) {
|
||||||
let brins = max - herbe.system.niveau;
|
let herbeData = Misc.templateData(herbe);
|
||||||
list[herbe.name] = `${herbe.name} (Bonus: ${herbe.system.niveau}, Brins: ${brins})`;
|
let brins = max - herbeData.niveau;
|
||||||
|
list[herbe.data.name] = `${herbe.data.name} (Bonus: ${herbeData.niveau}, Brins: ${brins})`;
|
||||||
}
|
}
|
||||||
list['Autre'] = 'Autre (Bonus: variable, Brins: variable)'
|
list['Autre'] = 'Autre (Bonus: variable, Brins: variable)'
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async updatePotionData(formData) {
|
static updatePotionData( formData ) {
|
||||||
formData.isSoins = formData.system.categorie.includes('Soin');
|
formData.herbesSoins = this.buildHerbesList(this.herbesSoins, 12);
|
||||||
formData.isRepos = formData.system.categorie.includes('Repos');
|
formData.herbesRepos = this.buildHerbesList(this.herbesRepos, 7);
|
||||||
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.jourMoisOptions = RdDCalendrier.buildJoursMois();
|
||||||
formData.dateActuelle = game.system.rdd.calendrier.getDateFromIndex();
|
formData.dateActuelle = game.system.rdd.calendrier.getDateFromIndex();
|
||||||
formData.splitDate = game.system.rdd.calendrier.getDayMonthFromIndex(formData.system.prdate);
|
formData.splitDate = game.system.rdd.calendrier.getNumericDateFromIndex(formData.data.prdate);
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
if (formData.data.categorie.includes('Soin') ) {
|
||||||
static calculPuissancePotion(potion) {
|
formData.isHerbe = true;
|
||||||
return potion.system.herbebonus * potion.system.pr;
|
this.computeHerbeBonus(formData, this.herbesSoins, 12);
|
||||||
}
|
} else if (formData.data.categorie.includes('Repos')) {
|
||||||
|
formData.isRepos = true;
|
||||||
/* -------------------------------------------- */
|
this.computeHerbeBonus(formData, this.herbesRepos, 7);
|
||||||
static calculPointsRepos(potion) {
|
|
||||||
return potion.system.herbebonus * potion.system.pr;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static calculePointsRepos( data ) {
|
||||||
|
return data.herbebonus * data.pr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static calculePointsGuerison( data ){
|
||||||
|
return data.herbebonus * data.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,46 +2,64 @@ import { Misc } from "./misc.js";
|
|||||||
|
|
||||||
export class RdDHotbar {
|
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
|
* Create a macro when dropping an entity on the hotbar
|
||||||
* Item - open roll dialog for item
|
* Item - open roll dialog for item
|
||||||
* Actor - open actor sheet
|
* Actor - open actor sheet
|
||||||
* Journal - open journal sheet
|
* Journal - open journal sheet
|
||||||
*/
|
*/
|
||||||
static initDropbar() {
|
static initDropbar( ) {
|
||||||
|
|
||||||
Hooks.on("hotbarDrop", (bar, documentData, slot) => {
|
Hooks.on("hotbarDrop", async (bar, documentData, slot) => {
|
||||||
|
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill
|
||||||
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill
|
if (documentData.type == "Item") {
|
||||||
if (documentData.type == "Item") {
|
if (documentData.data.type != "arme" && documentData.data.type != "competence" )
|
||||||
let item = fromUuidSync(documentData.uuid)
|
return
|
||||||
if (item == undefined) {
|
let item = documentData.data
|
||||||
item = this.actor.items.get(documentData.uuid)
|
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));
|
||||||
console.log("DROP", documentData, item)
|
if (!macro) {
|
||||||
if (!item || (item.type != "arme" && item.type != "competence")) {
|
macro = await Macro.create({
|
||||||
return true
|
name: item.name,
|
||||||
}
|
type: "script",
|
||||||
this.addToHotbar(item, slot)
|
img: item.img,
|
||||||
return false
|
command: command
|
||||||
|
}, { displaySheet: false })
|
||||||
}
|
}
|
||||||
|
game.user.assignHotbarMacro(macro, slot);
|
||||||
return true
|
}
|
||||||
})
|
// 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;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Roll macro */
|
/** Roll macro */
|
||||||
@ -51,17 +69,15 @@ export class RdDHotbar {
|
|||||||
if (speaker.token) actor = game.actors.tokens[speaker.token];
|
if (speaker.token) actor = game.actors.tokens[speaker.token];
|
||||||
if (!actor) actor = game.actors.get(speaker.actor);
|
if (!actor) actor = game.actors.get(speaker.actor);
|
||||||
|
|
||||||
let item = actor?.items.find(it => it.name === itemName && it.type == itemType) ?? undefined;
|
let item = Misc.data(actor?.items.find(it => it.name === itemName && it.type == itemType));
|
||||||
if (!item) {
|
if (!item) return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`);
|
||||||
return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trigger the item roll
|
// Trigger the item roll
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case "arme":
|
case "arme":
|
||||||
return actor.rollArme(item);
|
return actor.rollArme(item);
|
||||||
case "competence":
|
case "competence":
|
||||||
return actor.rollCompetence(itemName);
|
return actor.rollCompetence( itemName );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,9 +23,10 @@ import { RdDTokenHud } from "./rdd-token-hud.js";
|
|||||||
import { RdDCommands } from "./rdd-commands.js";
|
import { RdDCommands } from "./rdd-commands.js";
|
||||||
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
|
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
|
||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { StatusEffects } from "./settings/status-effects.js";
|
import { StatusEffects } from "./status-effects.js";
|
||||||
import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js";
|
import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||||
|
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||||
import { RdDHotbar } from "./rdd-hotbar-drop.js"
|
import { RdDHotbar } from "./rdd-hotbar-drop.js"
|
||||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||||
import { RdDHerbes } from "./rdd-herbes.js";
|
import { RdDHerbes } from "./rdd-herbes.js";
|
||||||
@ -34,14 +35,6 @@ import { RdDDice } from "./rdd-dice.js";
|
|||||||
import { RdDPossession } from "./rdd-possession.js";
|
import { RdDPossession } from "./rdd-possession.js";
|
||||||
import { RdDSigneDraconiqueItemSheet } from "./item-signedraconique-sheet.js";
|
import { RdDSigneDraconiqueItemSheet } from "./item-signedraconique-sheet.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { Migrations } from './migrations.js';
|
|
||||||
import { DialogChronologie } from "./dialog-chronologie.js";
|
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
|
||||||
import { RdDRencontreItemSheet } from "./item-rencontre-sheet.js";
|
|
||||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
|
||||||
import { RdDHerbeItemSheet } from "./item-herbe-sheet.js";
|
|
||||||
import { Environnement } from "./environnement.js";
|
|
||||||
import { RdDIngredientItemSheet } from "./item-ingredient-sheet.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Foundry VTT Initialization */
|
/* Foundry VTT Initialization */
|
||||||
@ -83,7 +76,7 @@ Hooks.once("init", async function () {
|
|||||||
name: "calendrier",
|
name: "calendrier",
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: false,
|
config: false,
|
||||||
default: RdDCalendrier.createCalendrierInitial(),
|
default: RdDCalendrier.getCalendrier(0),
|
||||||
type: Object
|
type: Object
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -113,8 +106,6 @@ Hooks.once("init", async function () {
|
|||||||
default: RdDCalendrier.createCalendrierPos(),
|
default: RdDCalendrier.createCalendrierPos(),
|
||||||
type: Object
|
type: Object
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", {
|
game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", {
|
||||||
name: "Supprimer les dialogues de combat",
|
name: "Supprimer les dialogues de combat",
|
||||||
@ -156,16 +147,13 @@ Hooks.once("init", async function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => {
|
game.socket.on(SYSTEM_SOCKET_ID, sockmsg => {
|
||||||
console.log(">>>>> MSG RECV", sockmsg);
|
console.log(">>>>> MSG RECV", sockmsg);
|
||||||
try {
|
|
||||||
RdDUtility.onSocketMessage(sockmsg);
|
RdDUtility.onSocketMessage(sockmsg);
|
||||||
RdDCombat.onSocketMessage(sockmsg);
|
RdDCombat.onSocketMessage(sockmsg);
|
||||||
ChatUtility.onSocketMessage(sockmsg);
|
ChatUtility.onSocketMessage(sockmsg);
|
||||||
RdDActor.onSocketMessage(sockmsg);
|
RdDActor.onSocketMessage(sockmsg);
|
||||||
} catch(e) {
|
|
||||||
console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg,' => ', e)
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -192,29 +180,14 @@ Hooks.once("init", async function () {
|
|||||||
types: ["signedraconique"],
|
types: ["signedraconique"],
|
||||||
makeDefault: true
|
makeDefault: true
|
||||||
});
|
});
|
||||||
Items.registerSheet(SYSTEM_RDD, RdDRencontreItemSheet, {
|
|
||||||
label: "Rencontre",
|
|
||||||
types: ["rencontre"],
|
|
||||||
makeDefault: true
|
|
||||||
});
|
|
||||||
RdDHerbeItemSheet.register();
|
|
||||||
RdDIngredientItemSheet.register();
|
|
||||||
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
|
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
|
||||||
types: [
|
types: ["arme", "armure", "objet", "arme", "armure", "conteneur", "competence", "sort", "herbe", "ingredient", "livre", "potion", "munition", "rencontresTMR", "queue", "ombre", "souffle",
|
||||||
"competence", "competencecreature",
|
"tete", "competencecreature", "tarot", "monnaie", "nombreastral", "tache", "meditation", "casetmr", "recettealchimique", "gemme",
|
||||||
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
|
"musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre", "nourritureboisson", "possession"], makeDefault: true
|
||||||
"objet", "arme", "armure", "conteneur", "livre", "potion", "munition",
|
|
||||||
"monnaie", "nourritureboisson", "gemme",
|
|
||||||
"meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
|
|
||||||
"nombreastral", "tache", "maladie", "poison", "possession",
|
|
||||||
"tarot", "extraitpoetique"
|
|
||||||
], makeDefault: true
|
|
||||||
});
|
});
|
||||||
CONFIG.Combat.documentClass = RdDCombatManager;
|
CONFIG.Combat.documentClass = RdDCombatManager;
|
||||||
|
|
||||||
// préparation des différents modules
|
// préparation des différents modules
|
||||||
SystemCompendiums.init();
|
|
||||||
DialogChronologie.init();
|
|
||||||
ReglesOptionelles.init();
|
ReglesOptionelles.init();
|
||||||
RdDUtility.init();
|
RdDUtility.init();
|
||||||
RdDDice.init();
|
RdDDice.init();
|
||||||
@ -226,10 +199,9 @@ Hooks.once("init", async function () {
|
|||||||
RddCompendiumOrganiser.init();
|
RddCompendiumOrganiser.init();
|
||||||
EffetsDraconiques.init()
|
EffetsDraconiques.init()
|
||||||
TMRUtility.init();
|
TMRUtility.init();
|
||||||
|
TMRRencontres.init();
|
||||||
RdDHotbar.initDropbar();
|
RdDHotbar.initDropbar();
|
||||||
RdDPossession.init();
|
RdDPossession.init();
|
||||||
TMRRencontres.init();
|
|
||||||
Environnement.init();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -249,20 +221,19 @@ function messageDeBienvenue() {
|
|||||||
// Register world usage statistics
|
// Register world usage statistics
|
||||||
function registerUsageCount( registerKey ) {
|
function registerUsageCount( registerKey ) {
|
||||||
if ( game.user.isGM ) {
|
if ( game.user.isGM ) {
|
||||||
game.settings.register("world", "world-key", {
|
game.settings.register(registerKey, "world-key", {
|
||||||
name: "Unique world key",
|
name: "Unique world key",
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: false,
|
config: false,
|
||||||
default: "NONE",
|
|
||||||
type: String
|
type: String
|
||||||
});
|
});
|
||||||
|
|
||||||
let worldKey = game.settings.get("world", "world-key")
|
let worldKey = game.settings.get(registerKey, "world-key")
|
||||||
if ( worldKey == undefined || worldKey == "" ) {
|
if ( worldKey == undefined || worldKey == "" ) {
|
||||||
worldKey = randomID(32)
|
worldKey = randomID(32)
|
||||||
game.settings.set("world", "world-key", worldKey )
|
game.settings.set(registerKey, "world-key", worldKey )
|
||||||
}
|
}
|
||||||
let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.version}"`
|
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}"`
|
||||||
$.ajax(regURL)
|
$.ajax(regURL)
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
}
|
}
|
||||||
@ -273,9 +244,6 @@ function registerUsageCount( registerKey ) {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
Hooks.once("ready", async function () {
|
Hooks.once("ready", async function () {
|
||||||
await migrationPngWebp_1_5_34()
|
await migrationPngWebp_1_5_34()
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
|
||||||
new Migrations().migrate();
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusEffects.onReady();
|
StatusEffects.onReady();
|
||||||
RdDHerbes.initializeHerbes();
|
RdDHerbes.initializeHerbes();
|
||||||
@ -323,8 +291,8 @@ async function migrationPngWebp_1_5_34() {
|
|||||||
await Item.updateDocuments(itemsUpdates);
|
await Item.updateDocuments(itemsUpdates);
|
||||||
await Actor.updateDocuments(actorsUpdates);
|
await Actor.updateDocuments(actorsUpdates);
|
||||||
game.actors.forEach(actor => {
|
game.actors.forEach(actor => {
|
||||||
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
|
if (actor.data.token?.img && actor.data.token.img.match(regexOldPngJpg)) {
|
||||||
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
|
actor.update({ "token.img": convertImgToWebp(actor.data.token.img) });
|
||||||
}
|
}
|
||||||
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
|
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
|
||||||
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
|
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
|
||||||
@ -345,3 +313,17 @@ async function migrationPngWebp_1_5_34() {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d));
|
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d));
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Foundry VTT chat message */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
Hooks.on("chatMessage", (html, content, msg) => {
|
||||||
|
if (content[0] == '/') {
|
||||||
|
let regExp = /(\S+)/g;
|
||||||
|
let commands = content.match(regExp);
|
||||||
|
if (game.system.rdd.commands.processChatCommand(commands, content, msg)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ import { RdDCombat } from "./rdd-combat.js";
|
|||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
import { RdDRoll } from "./rdd-roll.js";
|
import { RdDRoll } from "./rdd-roll.js";
|
||||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||||
import { Targets } from "./targets.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* On part du principe qu'une entité démarre tjs
|
/* On part du principe qu'une entité démarre tjs
|
||||||
@ -20,155 +19,23 @@ export class RdDPossession {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static searchPossessionFromEntite(attacker, defender) {
|
static searchPossessionFromEntite(attacker, defender) {
|
||||||
let poss = attacker.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
|
let poss = attacker.data.items.find(poss => poss.type == 'possession' && poss.data.data.possedeid == defender.data._id);
|
||||||
if (!poss) {
|
if (!poss) {
|
||||||
poss = defender.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
|
poss = defender.data.items.find(poss => poss.type == 'possession' && poss.data.data.possedeid == defender.data._id);
|
||||||
}
|
}
|
||||||
return poss && duplicate(poss) || undefined;
|
return poss && duplicate(poss) || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) {
|
static updateEtatPossession(possession) {
|
||||||
const defender = target.actor;
|
|
||||||
const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender);
|
|
||||||
const isNouvelle = !suitePossession && ! fromEntite;
|
|
||||||
const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender)));
|
|
||||||
|
|
||||||
RdDPossession.$updateEtatPossession(possession)
|
|
||||||
|
|
||||||
let rollData = {
|
|
||||||
mode: "possession",
|
|
||||||
isECNIDefender: false,
|
|
||||||
competence: competence,
|
|
||||||
possession: possession,
|
|
||||||
attacker: attacker,
|
|
||||||
defender: defender,
|
|
||||||
targetToken: Targets.extractTokenData(target)
|
|
||||||
};
|
|
||||||
if (attacker.isCreature()) {
|
|
||||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
|
||||||
}
|
|
||||||
|
|
||||||
await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async onConjurerPossession(attacker, competence, possession) {
|
|
||||||
possession = duplicate(possession);
|
|
||||||
RdDPossession.$updateEtatPossession(possession)
|
|
||||||
let rollData = {
|
|
||||||
mode: "possession",
|
|
||||||
isECNIDefender: true,
|
|
||||||
competence: competence,
|
|
||||||
possession: possession,
|
|
||||||
attacker: attacker,
|
|
||||||
defender: game.actors.get(possession.system.possesseurid)
|
|
||||||
};
|
|
||||||
await RdDPossession.$rollAttaquePossession(attacker, rollData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async onDefensePossession(attackerId, defenderId, possessionId) {
|
|
||||||
let attacker = game.actors.get(attackerId)
|
|
||||||
let possession = attacker?.getPossession(possessionId)
|
|
||||||
defenderId = defenderId ?? possession?.system.possesseurid ?? undefined
|
|
||||||
let defender = game.actors.get(defenderId)
|
|
||||||
possession = possession ?? defender?.getPossession(possessionId) ?? undefined;
|
|
||||||
|
|
||||||
if (!possession) {
|
|
||||||
ui.notifications.warn("Une erreur s'est produite : Aucune possession trouvée !!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
possession = duplicate(possession)
|
|
||||||
// Update for draconic roll
|
|
||||||
let rollData = {
|
|
||||||
mode: "conjuration",
|
|
||||||
isECNIDefender: defender.type == "entite",
|
|
||||||
possession: possession,
|
|
||||||
attacker: attacker,
|
|
||||||
defender: defender,
|
|
||||||
competence: defender.getDraconicOuPossession(),
|
|
||||||
selectedCarac: defender.system.carac.reve,
|
|
||||||
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } }
|
|
||||||
}
|
|
||||||
rollData.competence.system.defaut_carac = 'reve-actuel'
|
|
||||||
|
|
||||||
await RdDPossession.$rollDefensePossession(defender, rollData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) {
|
|
||||||
const dialog = await RdDRoll.create(attacker, rollData,
|
|
||||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
|
|
||||||
{
|
|
||||||
name: 'jet-possession',
|
|
||||||
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
|
|
||||||
callbacks: [
|
|
||||||
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDPossession.$onRollPossession(r, true, isNouvelle) },
|
|
||||||
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDPossession.$onRollPossession(r, false, isNouvelle) },
|
|
||||||
]
|
|
||||||
});
|
|
||||||
dialog.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async $onRollPossession(rollData, isSuccess, isNouvelle = false) {
|
|
||||||
rollData.possession.isSuccess = isSuccess;
|
|
||||||
RdDPossession.$updateEtatPossession(rollData.possession);
|
|
||||||
if (isNouvelle) {
|
|
||||||
// Creer la possession sur le defenseur
|
|
||||||
rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()])
|
|
||||||
}
|
|
||||||
await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html');
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async $rollDefensePossession(defender, rollData) {
|
|
||||||
const dialog = await RdDRoll.create(defender, rollData,
|
|
||||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html' },
|
|
||||||
{
|
|
||||||
name: 'conjurer',
|
|
||||||
label: 'Conjurer une Possession',
|
|
||||||
callbacks: [
|
|
||||||
{ action: async (r) => await RdDPossession.$onRollConjuration(r) }
|
|
||||||
]
|
|
||||||
}
|
|
||||||
);
|
|
||||||
dialog.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async $onRollConjuration(rollData) {
|
|
||||||
let actor = game.actors.get(rollData.possession.system.possedeid)
|
|
||||||
if (!rollData.rolled.isSuccess) {
|
|
||||||
if (rollData.isECNIDefender) {
|
|
||||||
rollData.possession.system.compteur--
|
|
||||||
} else {
|
|
||||||
rollData.possession.system.compteur++
|
|
||||||
}
|
|
||||||
let update = { _id: rollData.possession._id, "system.compteur": rollData.possession.system.compteur }
|
|
||||||
await actor.updateEmbeddedDocuments('Item', [update])
|
|
||||||
}
|
|
||||||
|
|
||||||
RdDPossession.$updateEtatPossession(rollData.possession)
|
|
||||||
|
|
||||||
await RdDResolutionTable.displayRollData(rollData,rollData.defender, 'chat-resultat-possession.html')
|
|
||||||
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
|
|
||||||
// conjuration
|
|
||||||
actor.deleteEmbeddedDocuments("Item", [rollData.possession._id])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static $updateEtatPossession(possession) {
|
|
||||||
possession.ptsConjuration = 0
|
possession.ptsConjuration = 0
|
||||||
possession.ptsPossession = 0
|
possession.ptsPossession = 0
|
||||||
console.log("Possession", possession)
|
console.log("Possession", possession)
|
||||||
if (possession.system.compteur > 0) {
|
if (possession.data.compteur > 0) {
|
||||||
possession.ptsPossession = possession.system.compteur
|
possession.ptsPossession = possession.data.compteur
|
||||||
}
|
}
|
||||||
if (possession.system.compteur < 0) {
|
if (possession.data.compteur < 0) {
|
||||||
possession.ptsConjuration = Math.abs(possession.system.compteur)
|
possession.ptsConjuration = Math.abs(possession.data.compteur)
|
||||||
}
|
}
|
||||||
possession.isPosseder = false
|
possession.isPosseder = false
|
||||||
possession.isConjurer = false
|
possession.isConjurer = false
|
||||||
@ -181,15 +48,122 @@ export class RdDPossession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async createPossession(attacker, defender) {
|
static async resultConjuration(rollData) {
|
||||||
return await Item.create({
|
let actor = game.actors.get(rollData.possession.data.possedeid)
|
||||||
name: "Possession en cours de " + attacker.name, type: 'possession',
|
if (!rollData.rolled.isSuccess) {
|
||||||
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
if (rollData.isECNIDefender) {
|
||||||
system: { description: "", typepossession: attacker.name, possede: false, possessionid: randomID(16), possesseurid: attacker.id, possedeid: defender.id, date: 0, compteur: 0 }
|
rollData.possession.data.compteur--
|
||||||
|
} else {
|
||||||
|
rollData.possession.data.compteur++
|
||||||
|
}
|
||||||
|
let update = { _id: rollData.possession._id, "data.compteur": rollData.possession.data.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) {
|
||||||
|
actor.deleteEmbeddedDocuments("Item", [rollData.possession._id])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async onDefensePossession(attackerId, defenderId, possessionId) {
|
||||||
|
let attacker = game.actors.get(attackerId)
|
||||||
|
let defender = game.actors.get(defenderId)
|
||||||
|
let possession = attacker.getPossession(possessionId) ?? defender.getPossession(possessionId) ;
|
||||||
|
if (!possession) {
|
||||||
|
ui.notifications.warn("Une erreur s'est produite : Aucune possession trouvée !!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Update for draconic roll
|
||||||
|
let rollData = {
|
||||||
|
mode: "conjuration",
|
||||||
|
isECNIDefender: defender.type == "entite",
|
||||||
|
possession: duplicate(possession),
|
||||||
|
attacker: attacker,
|
||||||
|
defender: defender,
|
||||||
|
competence: defender.getDraconicOuPossession(),
|
||||||
|
selectedCarac: defender.data.data.carac.reve,
|
||||||
|
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } }
|
||||||
|
}
|
||||||
|
rollData.competence.data.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: 450 }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
temporary: true
|
name: 'conjurer',
|
||||||
})
|
label: 'Conjurer une Possession',
|
||||||
|
callbacks: [
|
||||||
|
{ action: async r => await this.resultConjuration(r) }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
dialog.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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;
|
||||||
|
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,
|
||||||
|
attacker: attacker,
|
||||||
|
defender: defender
|
||||||
|
};
|
||||||
|
if (attacker.isCreature()) {
|
||||||
|
RdDItemCompetenceCreature.setRollDataCreature(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: 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) },
|
||||||
|
]
|
||||||
|
});
|
||||||
|
dialog.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
// Creates only the possession on the personnage side
|
||||||
|
let poss = await defender.createEmbeddedDocuments('Item', [possessionData])
|
||||||
|
return duplicate(poss[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* difficultés au delà de -10
|
* difficultés au delà de -10
|
||||||
@ -54,7 +54,7 @@ export class RdDResolutionTable {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static explain(rolled) {
|
static explain(rolled) {
|
||||||
let message = "<br>Jet : <strong>" + rolled.roll + "</strong> sur " + rolled.score + "% ";
|
let message = "<br>Jet : <strong>" + rolled.roll + "</strong> sur " + rolled.score + "% ";
|
||||||
if (rolled.caracValue != undefined && rolled.finalLevel != undefined) {
|
if (rolled.caracValue != null && rolled.finalLevel != null) {
|
||||||
message += (rolled.diviseurSignificative > 1 ? `(1/${rolled.diviseurSignificative} de ` : "(")
|
message += (rolled.diviseurSignificative > 1 ? `(1/${rolled.diviseurSignificative} de ` : "(")
|
||||||
+ rolled.caracValue + " à " + Misc.toSignedString(rolled.finalLevel) + ") ";
|
+ rolled.caracValue + " à " + Misc.toSignedString(rolled.finalLevel) + ") ";
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ export class RdDResolutionTable {
|
|||||||
static _updateChancesFactor(chances, diviseur) {
|
static _updateChancesFactor(chances, diviseur) {
|
||||||
if (chances.level > -11 && diviseur && diviseur > 1) {
|
if (chances.level > -11 && diviseur && diviseur > 1) {
|
||||||
let newScore = Math.floor(chances.score / diviseur);
|
let newScore = Math.floor(chances.score / diviseur);
|
||||||
mergeObject(chances, this._computeCell(undefined, newScore), { overwrite: true });
|
mergeObject(chances, this._computeCell(null, newScore), { overwrite: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +124,7 @@ export class RdDResolutionTable {
|
|||||||
static _updateChancesWithBonus(chances, bonus, finalLevel) {
|
static _updateChancesWithBonus(chances, bonus, finalLevel) {
|
||||||
if (bonus && finalLevel>-11) {
|
if (bonus && finalLevel>-11) {
|
||||||
let newScore = Number(chances.score) + bonus;
|
let newScore = Number(chances.score) + bonus;
|
||||||
mergeObject(chances, this._computeCell(undefined, newScore), { overwrite: true });
|
mergeObject(chances, this._computeCell(null, newScore), { overwrite: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,8 +142,10 @@ export class RdDResolutionTable {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async rollChances(chances, diviseur, forceDiceResult = -1) {
|
static async rollChances(chances, diviseur, forceDiceResult = -1) {
|
||||||
chances.forceDiceResult = forceDiceResult <= 0 || forceDiceResult > 100 ? undefined : {total: forceDiceResult};
|
if (forceDiceResult <= 0 || forceDiceResult > 100) {
|
||||||
chances.roll = await RdDDice.rollTotal( "1d100", chances);
|
forceDiceResult = -1;
|
||||||
|
}
|
||||||
|
chances.roll = await RdDDice.rollTotal((forceDiceResult == -1) ? "1d100" : `${forceDiceResult}`, chances);
|
||||||
mergeObject(chances, this.computeReussite(chances, chances.roll, diviseur), { overwrite: true });
|
mergeObject(chances, this.computeReussite(chances, chances.roll, diviseur), { overwrite: true });
|
||||||
return chances;
|
return chances;
|
||||||
}
|
}
|
||||||
@ -156,6 +158,7 @@ export class RdDResolutionTable {
|
|||||||
if (difficulte < -10) {
|
if (difficulte < -10) {
|
||||||
return duplicate(levelDown.find(levelData => levelData.level == difficulte));
|
return duplicate(levelDown.find(levelData => levelData.level == difficulte));
|
||||||
}
|
}
|
||||||
|
console.log("DATA :", caracValue, difficulte)
|
||||||
return duplicate(RdDResolutionTable.resolutionTable[caracValue][difficulte + 10]);
|
return duplicate(RdDResolutionTable.resolutionTable[caracValue][difficulte + 10]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,7 +167,7 @@ export class RdDResolutionTable {
|
|||||||
if (rollData.selectedCarac?.label.toLowerCase().includes('chance')) {
|
if (rollData.selectedCarac?.label.toLowerCase().includes('chance')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (rollData.selectedSort?.system.isrituel) {
|
if (rollData.selectedSort?.data.isrituel) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ENTITE_BLURETTE, ENTITE_INCARNE} from "./constants.js";
|
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE } from "./constants.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the base Dialog entity by defining a custom window to perform roll.
|
* Extend the base Dialog entity by defining a custom window to perform roll.
|
||||||
@ -33,7 +33,7 @@ export class RdDEncaisser extends Dialog {
|
|||||||
let dialogOptions = {
|
let dialogOptions = {
|
||||||
classes: ["rdddialog"],
|
classes: ["rdddialog"],
|
||||||
width: 320,
|
width: 320,
|
||||||
height: 'fit-content'
|
height: 240
|
||||||
}
|
}
|
||||||
|
|
||||||
// Select proper roll dialog template and stuff
|
// Select proper roll dialog template and stuff
|
||||||
@ -51,7 +51,6 @@ export class RdDEncaisser extends Dialog {
|
|||||||
this.actor.encaisserDommages({
|
this.actor.encaisserDommages({
|
||||||
dmg: {
|
dmg: {
|
||||||
total: Number(this.modifier),
|
total: Number(this.modifier),
|
||||||
ajustement: Number(this.modifier),
|
|
||||||
encaisserSpecial: this.encaisserSpecial,
|
encaisserSpecial: this.encaisserSpecial,
|
||||||
loc: { result: 0, label: "" },
|
loc: { result: 0, label: "" },
|
||||||
mortalite: mortalite
|
mortalite: mortalite
|
||||||
|
@ -15,7 +15,7 @@ export class RdDRollDialogEthylisme extends Dialog {
|
|||||||
default: "rollButton",
|
default: "rollButton",
|
||||||
buttons: { "rollButton": { label: "Test d'éthylisme", callback: html => this.onButton(html) } }
|
buttons: { "rollButton": { label: "Test d'éthylisme", callback: html => this.onButton(html) } }
|
||||||
};
|
};
|
||||||
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 'fit-content', 'z-index': 99999 }
|
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 270, 'z-index': 99999 }
|
||||||
super(dialogConf, dialogOptions)
|
super(dialogConf, dialogOptions)
|
||||||
|
|
||||||
//console.log("ETH", rollData);
|
//console.log("ETH", rollData);
|
||||||
|
@ -53,7 +53,7 @@ export class RdDRollResolutionTable extends Dialog {
|
|||||||
'lancer-fermer': { label: 'Lancer les dés et fermer', callback: html => this.onLancerFermer() }
|
'lancer-fermer': { label: 'Lancer les dés et fermer', callback: html => this.onLancerFermer() }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
super(conf, { classes: ["rdddialog"], width: 800, height: 'fit-content', 'z-index': 99999 });
|
super(conf, { classes: ["rdddialog"], width: 800, height: 800, 'z-index': 99999 });
|
||||||
|
|
||||||
this.rollData = rollData;
|
this.rollData = rollData;
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,7 @@ import { Misc } from "./misc.js";
|
|||||||
import { RdDBonus } from "./rdd-bonus.js";
|
import { RdDBonus } from "./rdd-bonus.js";
|
||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the base Dialog entity to select roll parameters
|
* Extend the base Dialog entity to select roll parameters
|
||||||
@ -29,7 +29,7 @@ export class RdDRoll extends Dialog {
|
|||||||
|
|
||||||
const html = await renderTemplate(dialogConfig.html, rollData);
|
const html = await renderTemplate(dialogConfig.html, rollData);
|
||||||
|
|
||||||
let options = { classes: ["rdddialog"], width: 600, height: 'fit-content', 'z-index': 99999 };
|
let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 };
|
||||||
if (dialogConfig.options) {
|
if (dialogConfig.options) {
|
||||||
mergeObject(options, dialogConfig.options, { overwrite: true })
|
mergeObject(options, dialogConfig.options, { overwrite: true })
|
||||||
}
|
}
|
||||||
@ -38,27 +38,26 @@ export class RdDRoll extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _setDefaultOptions(actor, rollData) {
|
static _setDefaultOptions(actor, rollData) {
|
||||||
|
const actorData = Misc.data(actor);
|
||||||
let defaultRollData = {
|
let defaultRollData = {
|
||||||
alias: actor.name,
|
alias: actor.name,
|
||||||
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
|
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
|
||||||
difficultesLibres: CONFIG.RDD.difficultesLibres,
|
difficultesLibres: CONFIG.RDD.difficultesLibres,
|
||||||
etat: actor.getEtatGeneral(),
|
etat: actor.getEtatGeneral(),
|
||||||
moral: actor.getMoralTotal(), /* La valeur du moral pour les jets de volonté */
|
moral: actor.getMoralTotal(), /* La valeur du moral pour les jets de volonté */
|
||||||
carac: actor.system.carac,
|
carac: actorData.data.carac,
|
||||||
finalLevel: 0,
|
finalLevel: 0,
|
||||||
diffConditions: 0,
|
diffConditions: 0,
|
||||||
diffLibre: rollData.competence?.system.default_diffLibre ?? 0,
|
diffLibre: rollData.competence?.data.default_diffLibre ?? 0,
|
||||||
perteMoralEchec: false, /* Pour l'affichage dans le chat */
|
|
||||||
use: {
|
|
||||||
moral: false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */
|
|
||||||
libre: true,
|
|
||||||
conditions: true,
|
|
||||||
surenc: actor.isSurenc(),
|
|
||||||
encTotal: true
|
|
||||||
},
|
|
||||||
isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
|
||||||
malusArmureValue: actor.getMalusArmure(),
|
malusArmureValue: actor.getMalusArmure(),
|
||||||
|
surencMalusFlag: actor.isPersonnage() ? (actorData.data.compteurs.surenc.value < 0) : false,
|
||||||
surencMalusValue: actor.computeMalusSurEncombrement(),
|
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),
|
||||||
|
useMalusEncTotal: false,
|
||||||
encTotal: actor.getEncTotal(),
|
encTotal: actor.getEncTotal(),
|
||||||
ajustementAstrologique: actor.ajustementAstrologique(),
|
ajustementAstrologique: actor.ajustementAstrologique(),
|
||||||
surprise: actor.getSurprise(false),
|
surprise: actor.getSurprise(false),
|
||||||
@ -67,8 +66,8 @@ export class RdDRoll extends Dialog {
|
|||||||
forceDiceResult: -1
|
forceDiceResult: -1
|
||||||
}
|
}
|
||||||
// Mini patch :Ajout du rêve actuel
|
// Mini patch :Ajout du rêve actuel
|
||||||
if ( actor.system.type == "personnage") {
|
if ( actorData.type == "personnage") {
|
||||||
defaultRollData.carac["reve-actuel"] = actor.system.reve.reve
|
defaultRollData.carac["reve-actuel"] = actorData.data.reve.reve
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });
|
mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });
|
||||||
@ -145,7 +144,6 @@ export class RdDRoll extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onAction(action, html) {
|
async onAction(action, html) {
|
||||||
this.rollData.forceDiceResult = Number.parseInt($('#force-dice-result').val()) ?? -1;
|
|
||||||
await RdDResolutionTable.rollData(this.rollData);
|
await RdDResolutionTable.rollData(this.rollData);
|
||||||
console.log("RdDRoll -=>", this.rollData, this.rollData.rolled);
|
console.log("RdDRoll -=>", this.rollData, this.rollData.rolled);
|
||||||
this.actor.setRollWindowsOpened(false);
|
this.actor.setRollWindowsOpened(false);
|
||||||
@ -167,17 +165,17 @@ export class RdDRoll extends Dialog {
|
|||||||
|
|
||||||
function onLoad() {
|
function onLoad() {
|
||||||
let rollData = dialog.rollData;
|
let rollData = dialog.rollData;
|
||||||
console.log('Ouverture RdDRoll', rollData);
|
console.log(rollData);
|
||||||
// Update html, according to rollData
|
// Update html, according to data
|
||||||
if (rollData.competence) {
|
if (rollData.competence) {
|
||||||
const defaut_carac = rollData.competence.system.defaut_carac
|
const defaut_carac = Misc.templateData(rollData.competence).defaut_carac;
|
||||||
// Set the default carac from the competence item
|
// Set the default carac from the competence item
|
||||||
rollData.selectedCarac = rollData.carac[defaut_carac];
|
rollData.selectedCarac = rollData.carac[defaut_carac];
|
||||||
$("#carac").val(defaut_carac);
|
$("#carac").val(defaut_carac);
|
||||||
}
|
}
|
||||||
if (rollData.selectedSort) {
|
if (rollData.selectedSort) {
|
||||||
dialog.setSelectedSort(rollData.selectedSort);
|
dialog.setSelectedSort(rollData.selectedSort);
|
||||||
$(".draconic").val(rollData.selectedSort.system.listIndex); // Uniquement a la selection du sort, pour permettre de changer
|
$(".draconic").val(rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
|
||||||
}
|
}
|
||||||
RdDItemSort.setCoutReveReel(rollData.selectedSort);
|
RdDItemSort.setCoutReveReel(rollData.selectedSort);
|
||||||
$("#diffLibre").val(Misc.toInt(rollData.diffLibre));
|
$("#diffLibre").val(Misc.toInt(rollData.diffLibre));
|
||||||
@ -216,11 +214,6 @@ export class RdDRoll extends Dialog {
|
|||||||
this.updateRollResult();
|
this.updateRollResult();
|
||||||
$("#diffLibre").val(this.rollData.diffLibre);
|
$("#diffLibre").val(this.rollData.diffLibre);
|
||||||
});
|
});
|
||||||
html.find('.roll-carac-competence').change((event) => {
|
|
||||||
const competence = event.currentTarget.value;
|
|
||||||
this.rollData.competence = this.rollData.competences.find(it => it.name == competence);
|
|
||||||
this.updateRollResult();
|
|
||||||
});
|
|
||||||
html.find('.roll-signedraconique').change((event) => {
|
html.find('.roll-signedraconique').change((event) => {
|
||||||
let sortKey = Misc.toInt(event.currentTarget.value);
|
let sortKey = Misc.toInt(event.currentTarget.value);
|
||||||
this.setSelectedSigneDraconique(this.rollData.signes[sortKey]);
|
this.setSelectedSigneDraconique(this.rollData.signes[sortKey]);
|
||||||
@ -228,7 +221,7 @@ export class RdDRoll extends Dialog {
|
|||||||
});
|
});
|
||||||
html.find('#ptreve-variable').change((event) => {
|
html.find('#ptreve-variable').change((event) => {
|
||||||
let ptreve = Misc.toInt(event.currentTarget.value);
|
let ptreve = Misc.toInt(event.currentTarget.value);
|
||||||
this.rollData.selectedSort.system.ptreve_reel = ptreve;
|
this.rollData.selectedSort.data.ptreve_reel = ptreve;
|
||||||
console.log("RdDRollSelectDialog - Cout reve", ptreve);
|
console.log("RdDRollSelectDialog - Cout reve", ptreve);
|
||||||
this.updateRollResult();
|
this.updateRollResult();
|
||||||
});
|
});
|
||||||
@ -250,19 +243,11 @@ export class RdDRoll extends Dialog {
|
|||||||
this.rollData[attribute] = event.currentTarget.checked;
|
this.rollData[attribute] = event.currentTarget.checked;
|
||||||
this.updateRollResult();
|
this.updateRollResult();
|
||||||
});
|
});
|
||||||
html.find('input.use-encTotal').change((event) => {
|
|
||||||
this.rollData.use.encTotal = event.currentTarget.checked;
|
|
||||||
this.updateRollResult();
|
|
||||||
});
|
|
||||||
html.find('input.use-surenc').change((event) => {
|
|
||||||
this.rollData.use.surenc = event.currentTarget.checked;
|
|
||||||
this.updateRollResult();
|
|
||||||
});
|
|
||||||
html.find('.appel-moral').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */
|
html.find('.appel-moral').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */
|
||||||
this.rollData.use.moral = !this.rollData.use.moral;
|
this.rollData.useMoral = !this.rollData.useMoral;
|
||||||
const appelMoral = html.find('.icon-appel-moral')[0];
|
const appelMoral = html.find('.icon-appel-moral')[0];
|
||||||
const tooltip = html.find('.tooltipAppelAuMoralText')[0];
|
const tooltip = html.find('.tooltipAppelAuMoralText')[0];
|
||||||
if (this.rollData.use.moral) {
|
if (this.rollData.useMoral) {
|
||||||
if (this.rollData.moral > 0) {
|
if (this.rollData.moral > 0) {
|
||||||
tooltip.innerHTML = "Appel au moral";
|
tooltip.innerHTML = "Appel au moral";
|
||||||
appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg";
|
appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg";
|
||||||
@ -286,22 +271,21 @@ export class RdDRoll extends Dialog {
|
|||||||
|
|
||||||
async setSelectedSort(sort) {
|
async setSelectedSort(sort) {
|
||||||
this.rollData.selectedSort = sort; // Update the selectedCarac
|
this.rollData.selectedSort = sort; // Update the selectedCarac
|
||||||
this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.system.draconic);
|
this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.data.draconic);
|
||||||
this.rollData.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord);
|
this.rollData.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord);
|
||||||
this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7);
|
this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7);
|
||||||
RdDItemSort.setCoutReveReel(sort);
|
RdDItemSort.setCoutReveReel(sort);
|
||||||
const htmlSortDescription = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html", { sort: sort });
|
const htmlSortDescription = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html", { sort: sort });
|
||||||
$(".sort-ou-rituel").text(sort.system.isrituel ? "rituel" : "sort");
|
$(".sort-ou-rituel").text(sort.data.isrituel ? "rituel" : "sort");
|
||||||
$(".bonus-case").text(`${this.rollData.bonus}%`);
|
$(".bonus-case").text(`${this.rollData.bonus}%`);
|
||||||
$(".details-sort").remove();
|
$(".details-sort").remove();
|
||||||
$(".description-sort").append(htmlSortDescription);
|
$(".description-sort").append(htmlSortDescription);
|
||||||
$(".roll-draconic").val(sort.system.listIndex);
|
$(".roll-draconic").val(sort.data.listIndex);
|
||||||
$(".div-sort-difficulte-fixe").text(Misc.toSignedString(sort.system.difficulte));
|
$(".div-sort-difficulte-fixe").text(Misc.toSignedString(sort.data.difficulte));
|
||||||
$(".div-sort-ptreve-fixe").text(sort.system.ptreve);
|
$(".div-sort-ptreve-fixe").text(sort.data.ptreve);
|
||||||
const diffVariable = RdDItemSort.isDifficulteVariable(sort);
|
const diffVariable = RdDItemSort.isDifficulteVariable(sort);
|
||||||
const coutVariable = RdDItemSort.isCoutVariable(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-var"), diffVariable);
|
||||||
HtmlUtility._showControlWhen($(".div-sort-difficulte-fixe"), !diffVariable);
|
HtmlUtility._showControlWhen($(".div-sort-difficulte-fixe"), !diffVariable);
|
||||||
HtmlUtility._showControlWhen($(".div-sort-ptreve-var"), coutVariable);
|
HtmlUtility._showControlWhen($(".div-sort-ptreve-var"), coutVariable);
|
||||||
@ -310,7 +294,7 @@ export class RdDRoll extends Dialog {
|
|||||||
|
|
||||||
async setSelectedSigneDraconique(signe){
|
async setSelectedSigneDraconique(signe){
|
||||||
this.rollData.signe = signe;
|
this.rollData.signe = signe;
|
||||||
this.rollData.diffLibre = signe.system.difficulte,
|
this.rollData.diffLibre = Misc.data(signe).data.difficulte,
|
||||||
$(".signe-difficulte").text(Misc.toSignedString(this.rollData.diffLibre));
|
$(".signe-difficulte").text(Misc.toSignedString(this.rollData.diffLibre));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,9 +317,6 @@ export class RdDRoll extends Dialog {
|
|||||||
RollDataAjustements.calcul(rollData, this.actor);
|
RollDataAjustements.calcul(rollData, this.actor);
|
||||||
rollData.finalLevel = this._computeFinalLevel(rollData);
|
rollData.finalLevel = this._computeFinalLevel(rollData);
|
||||||
|
|
||||||
HtmlUtility._showControlWhen($(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac));
|
|
||||||
HtmlUtility._showControlWhen($(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
|
|
||||||
HtmlUtility._showControlWhen($(".utilisation-moral"), rollData.use.appelAuMoral);
|
|
||||||
HtmlUtility._showControlWhen($(".diffMoral"), rollData.ajustements.moralTotal.used);
|
HtmlUtility._showControlWhen($(".diffMoral"), rollData.ajustements.moralTotal.used);
|
||||||
HtmlUtility._showControlWhen($(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
HtmlUtility._showControlWhen($(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
||||||
HtmlUtility._showControlWhen($("#etat-general"), !RdDCarac.isIgnoreEtatGeneral(rollData));
|
HtmlUtility._showControlWhen($("#etat-general"), !RdDCarac.isIgnoreEtatGeneral(rollData));
|
||||||
@ -367,10 +348,10 @@ export class RdDRoll extends Dialog {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_computeDiffCompetence(rollData) {
|
_computeDiffCompetence(rollData) {
|
||||||
if (rollData.competence) {
|
if (rollData.competence) {
|
||||||
return Misc.toInt(rollData.competence.system.niveau);
|
return Misc.toInt(rollData.competence.data.niveau);
|
||||||
}
|
}
|
||||||
if (rollData.draconicList) {
|
if (rollData.draconicList) {
|
||||||
return Misc.toInt(rollData.competence.system.niveau);
|
return Misc.toInt(rollData.competence.data.niveau);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -407,7 +388,7 @@ export class RdDRoll extends Dialog {
|
|||||||
return compName + " - " + rollData.selectedSort.name;
|
return compName + " - " + rollData.selectedSort.name;
|
||||||
}
|
}
|
||||||
// If a weapon is there, add it in the title
|
// If a weapon is there, add it in the title
|
||||||
const niveau = Misc.toSignedString(rollData.competence.system.niveau)
|
const niveau = Misc.toSignedString(rollData.competence.data.niveau);
|
||||||
if (compName == carac) {
|
if (compName == carac) {
|
||||||
// cas des créatures
|
// cas des créatures
|
||||||
return carac + " Niveau " + niveau
|
return carac + " Niveau " + niveau
|
||||||
|
@ -1,109 +1,86 @@
|
|||||||
import { Grammar } from "./grammar.js";
|
|
||||||
import { CompendiumTable, CompendiumTableHelpers, SystemCompendiums } from "./settings/system-compendiums.js";
|
|
||||||
|
|
||||||
export class RdDRollTables {
|
export class RdDRollTables {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async genericGetTableResult(tableName, toChat) {
|
static async genericGetTableResult(tableName, toChat) {
|
||||||
let table = RdDRollTables.getWorldTable(tableName) ?? (await RdDRollTables.getSystemTable(tableName));
|
let table = game.tables.find(table => table.name.toLowerCase() == tableName.toLowerCase())
|
||||||
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll" });
|
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);
|
||||||
|
}
|
||||||
|
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll"});
|
||||||
|
console.log("RdDRollTables", tableName, toChat, ":", draw);
|
||||||
return draw.results.length > 0 ? draw.results[0] : undefined;
|
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 = SystemCompendiums.getPack("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) {
|
static async drawItemFromRollTable(tableName, toChat = false) {
|
||||||
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
||||||
const pack = game.packs.get(drawResult.documentCollection)
|
const pack = game.packs.get(drawResult.data.collection);
|
||||||
return await pack.getDocument(drawResult.documentId)
|
return await pack.getDocument(drawResult.data.resultId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async drawTextFromRollTable(tableName, toChat) {
|
static async drawTextFromRollTable(tableName, toChat) {
|
||||||
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
||||||
return drawResult.text;
|
return drawResult.data.text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getCompetence(toChat = false) {
|
static async getCompetence(toChat = false) {
|
||||||
if (toChat == 'liste') {
|
return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat);
|
||||||
return await RdDRollTables.listOrRoll('competences', 'Item', ['competence'], toChat, it => 1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getSouffle(toChat = false) {
|
static async getSouffle(toChat = false) {
|
||||||
return await RdDRollTables.listOrRoll('souffles-de-dragon', 'Item', ['souffle'], toChat);
|
return await RdDRollTables.drawItemFromRollTable("Souffles de Dragon", toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getQueue(toChat = false) {
|
static async getQueue(toChat = false) {
|
||||||
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat);
|
let queue = await RdDRollTables.drawItemFromRollTable("Queues de dragon", toChat);
|
||||||
|
if (queue.name.toLowerCase().includes('lancinant') ) {
|
||||||
|
return await RdDRollTables.getDesirLancinant(toChat);
|
||||||
|
}
|
||||||
|
if (queue.name.toLowerCase().includes('fixe') ) {
|
||||||
|
return await RdDRollTables.getIdeeFixe(toChat);
|
||||||
|
}
|
||||||
|
return queue;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getDesirLancinant(toChat = false) {
|
static async getDesirLancinant(toChat = false) {
|
||||||
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat,
|
return await RdDRollTables.drawItemFromRollTable("Désirs lancinants", toChat);
|
||||||
it => it.system.frequence,
|
|
||||||
it => it.system.categorie == 'lancinant');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getIdeeFixe(toChat = false) {
|
static async getIdeeFixe(toChat = false) {
|
||||||
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat,
|
return await RdDRollTables.drawItemFromRollTable("Idées fixes", toChat);
|
||||||
it => it.system.frequence,
|
|
||||||
it => it.system.categorie == 'ideefixe');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getTeteHR(toChat = false) {
|
static async getTeteHR(toChat = false) {
|
||||||
return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-haut-revants', 'Item', ['tete'], toChat);
|
return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour haut-rêvants", toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getTete(toChat = false) {
|
static async getTete(toChat = false) {
|
||||||
return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-tous-personnages', 'Item', ['tete'], toChat);
|
return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour tous personnages", toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getOmbre(toChat = false) {
|
static async getOmbre(toChat = false) {
|
||||||
return await RdDRollTables.listOrRoll('ombres-de-thanatos', 'Item', ['ombre'], toChat);
|
return await RdDRollTables.drawItemFromRollTable("Ombre de Thanatos", toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getTarot(toChat = true) {
|
static async getTarot(toChat = true) {
|
||||||
return await RdDRollTables.listOrRoll('tarot-draconique', 'Item', ['tarot'], toChat);
|
return await RdDRollTables.drawItemFromRollTable("Tarot Draconique", toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async listOrRoll(compendium, type, subTypes, toChat, itemFrequence = it => it.system.frequence, filter = it => true) {
|
static async getMaladresse(options = {toChat: false, arme: false}) {
|
||||||
const table = new CompendiumTable(compendium, type, subTypes);
|
|
||||||
if (toChat == 'liste') {
|
|
||||||
return await table.toChatMessage(itemFrequence, filter);
|
|
||||||
}
|
|
||||||
const row = await table.getRandom(itemFrequence, filter);
|
|
||||||
if (row) {
|
|
||||||
await CompendiumTableHelpers.tableRowToChatMessage(row, type);
|
|
||||||
}
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async getMaladresse(options = { toChat: false, arme: false }) {
|
|
||||||
return await RdDRollTables.drawTextFromRollTable(
|
return await RdDRollTables.drawTextFromRollTable(
|
||||||
options.arme ? "Maladresse armé" : "Maladresses non armé",
|
options.arme ? "Maladresse armé" : "Maladresses non armé",
|
||||||
options.toChat);
|
options.toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { DialogSplitItem } from "./dialog-split-item.js";
|
import { DialogSplitItem } from "./dialog-split-item.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
|
|
||||||
export class RdDSheetUtility {
|
export class RdDSheetUtility {
|
||||||
|
|
||||||
@ -20,14 +21,14 @@ export class RdDSheetUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static prepareItemDropParameters(destItemId, actorId, dragData, objetVersConteneur) {
|
static prepareItemDropParameters(destItemId, actorId, dragData, objetVersConteneur) {
|
||||||
const item = fromUuidSync(dragData.uuid)
|
const itemId = dragData.id || dragData.data._id;
|
||||||
return {
|
return {
|
||||||
destId: destItemId,
|
destId: destItemId,
|
||||||
targetActorId: actorId,
|
targetActorId: actorId,
|
||||||
itemId: item.id,
|
itemId: itemId,
|
||||||
sourceActorId: item.actor?.id,
|
sourceActorId: dragData.actorId,
|
||||||
srcId: objetVersConteneur[item.id],
|
srcId: objetVersConteneur[itemId],
|
||||||
onEnleverConteneur: () => { delete objetVersConteneur[item.id]; },
|
onEnleverConteneur: () => { delete objetVersConteneur[itemId]; },
|
||||||
onAjouterDansConteneur: (itemId, conteneurId) => { objetVersConteneur[itemId] = conteneurId; }
|
onAjouterDansConteneur: (itemId, conteneurId) => { objetVersConteneur[itemId] = conteneurId; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -41,12 +42,12 @@ export class RdDSheetUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static async _onSplitItem(item, split, actor) {
|
static async _onSplitItem(item, split, actor) {
|
||||||
if (split >= 1 && split < item.system.quantite) {
|
if (split >= 1 && split < Misc.data(item).data.quantite) {
|
||||||
await item.diminuerQuantite(split);
|
await item.diminuerQuantite(split);
|
||||||
const splitItem = duplicate(item);
|
const itemData = duplicate(Misc.data(item));
|
||||||
// todo: ajouter dans le même conteneur?
|
// todo: ajouter dans le même conteneur?
|
||||||
splitItem.system.quantite = split;
|
itemData.data.quantite = split;
|
||||||
await actor.createEmbeddedDocuments('Item', [splitItem])
|
await actor.createEmbeddedDocuments('Item', [itemData])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { SHOW_DICE } from "./constants.js";
|
import { SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
@ -12,19 +12,15 @@ import { Poetique } from "./poetique.js";
|
|||||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||||
import { PixiTMR } from "./tmr/pixi-tmr.js";
|
import { PixiTMR } from "./tmr/pixi-tmr.js";
|
||||||
import { Draconique } from "./tmr/draconique.js";
|
import { Draconique } from "./tmr/draconique.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
|
||||||
import { RdDRencontre } from "./item-rencontre.js";
|
|
||||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
export class RdDTMRDialog extends Dialog {
|
export class RdDTMRDialog extends Dialog {
|
||||||
|
|
||||||
static async create(actor, tmrData) {
|
static async create(html, actor, tmrData) {
|
||||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', tmrData);
|
|
||||||
|
|
||||||
if (tmrData.mode != 'visu') {
|
if (tmrData.mode != 'visu') {
|
||||||
// Notification au MJ
|
// Notification au MJ
|
||||||
@ -59,6 +55,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
this.fatigueParCase = this.viewOnly || !ReglesOptionelles.isUsing("appliquer-fatigue") ? 0 : this.actor.getTMRFatigue();
|
this.fatigueParCase = this.viewOnly || !ReglesOptionelles.isUsing("appliquer-fatigue") ? 0 : this.actor.getTMRFatigue();
|
||||||
this.cumulFatigue = 0;
|
this.cumulFatigue = 0;
|
||||||
this.loadRencontres();
|
this.loadRencontres();
|
||||||
|
this.loadSortsReserve();
|
||||||
this.loadCasesSpeciales();
|
this.loadCasesSpeciales();
|
||||||
this.allTokens = [];
|
this.allTokens = [];
|
||||||
this.rencontreState = 'aucune';
|
this.rencontreState = 'aucune';
|
||||||
@ -81,19 +78,12 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
loadCasesSpeciales() {
|
loadCasesSpeciales() {
|
||||||
this.casesSpeciales = this.actor.items.filter(item => Draconique.isCaseTMR(item));
|
this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item));
|
||||||
}
|
}
|
||||||
|
|
||||||
get sortsReserve() {
|
/* -------------------------------------------- */
|
||||||
return this.actor.itemTypes['sortreserve'];
|
loadSortsReserve() {
|
||||||
}
|
this.sortsReserves = Misc.data(this.actor).data.reve.reserve.list;
|
||||||
|
|
||||||
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
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -107,10 +97,10 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
this.updateTokens();
|
this.updateTokens();
|
||||||
this.forceDemiRevePositionView();
|
this.forceDemiRevePositionView();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_createTokens() {
|
_createTokens() {
|
||||||
if (!this.isDemiReveCache()) {
|
if (!this.isDemiReveCache()){
|
||||||
this.demiReve = this._tokenDemiReve();
|
this.demiReve = this._tokenDemiReve();
|
||||||
this._trackToken(this.demiReve);
|
this._trackToken(this.demiReve);
|
||||||
}
|
}
|
||||||
@ -127,6 +117,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
updateTokens() {
|
updateTokens() {
|
||||||
this._removeTokens(t => true);
|
this._removeTokens(t => true);
|
||||||
this.loadRencontres();
|
this.loadRencontres();
|
||||||
|
this.loadSortsReserve();
|
||||||
this.loadCasesSpeciales();
|
this.loadCasesSpeciales();
|
||||||
this._createTokens();
|
this._createTokens();
|
||||||
}
|
}
|
||||||
@ -145,24 +136,25 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
return this.rencontresExistantes.map(it => this._tokenRencontre(it));
|
return this.rencontresExistantes.map(it => this._tokenRencontre(it));
|
||||||
}
|
}
|
||||||
_getTokensSortsReserve() {
|
_getTokensSortsReserve() {
|
||||||
return this.actor.itemTypes['sortreserve'].map(it => this._tokenSortEnReserve(it));
|
return this.sortsReserves.map(it => this._tokenSortEnReserve(it));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_tokenRencontre(rencontre) {
|
_tokenRencontre(rencontre) {
|
||||||
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.system.coord);
|
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord);
|
||||||
}
|
}
|
||||||
_tokenCaseSpeciale(casetmr) {
|
_tokenCaseSpeciale(casetmr) {
|
||||||
const caseData = casetmr;
|
const caseData = Misc.data(casetmr);
|
||||||
const draconique = Draconique.get(caseData.system.specific);
|
const draconique = Draconique.get(caseData.data.specific);
|
||||||
return draconique?.token(this.pixiTMR, caseData, () => caseData.system.coord);
|
return draconique?.token(this.pixiTMR, caseData, () => caseData.data.coord);
|
||||||
}
|
}
|
||||||
_tokenSortEnReserve(sortReserve) {
|
_tokenSortEnReserve(sortEnReserve) {
|
||||||
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortReserve, () => sortReserve.system.coord);
|
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortEnReserve.sort, () => sortEnReserve.coord);
|
||||||
}
|
}
|
||||||
|
|
||||||
_tokenDemiReve() {
|
_tokenDemiReve() {
|
||||||
return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor, () => this.actor.system.reve.tmrpos.coord);
|
const actorData = Misc.data(this.actor);
|
||||||
|
return EffetsDraconiques.demiReve.token(this.pixiTMR, actorData, () => actorData.data.reve.tmrpos.coord);
|
||||||
}
|
}
|
||||||
|
|
||||||
forceDemiRevePositionView() {
|
forceDemiRevePositionView() {
|
||||||
@ -171,7 +163,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_getActorCoord() {
|
_getActorCoord() {
|
||||||
return this.actor.system.reve.tmrpos.coord;
|
return Misc.data(this.actor).data.reve.tmrpos.coord;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -218,12 +210,24 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
this.actor.rollLireSigneDraconique(this._getActorCoord());
|
this.actor.rollLireSigneDraconique(this._getActorCoord());
|
||||||
});
|
});
|
||||||
|
|
||||||
html.find('#dir-top').click((event) => this.moveFromKey("top"));
|
html.find('#dir-top').click((event) => {
|
||||||
html.find('#dir-top-left').click((event) => this.moveFromKey("top-left"));
|
this.moveFromKey("top");
|
||||||
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-top-left').click((event) => {
|
||||||
html.find('#dir-bottom-right').click((event) => this.moveFromKey("bottom-right"));
|
this.moveFromKey("top-left");
|
||||||
html.find('#dir-bottom').click((event) => this.moveFromKey("bottom"));
|
});
|
||||||
|
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
|
// 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();
|
let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse();
|
||||||
@ -235,94 +239,75 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
// Le reste...
|
// Le reste...
|
||||||
this.updateValuesDisplay();
|
this.updateValuesDisplay();
|
||||||
let tmr = TMRUtility.getTMR(this._getActorCoord());
|
let tmr = TMRUtility.getTMR(this._getActorCoord());
|
||||||
await this.manageRencontre(tmr);
|
await this.manageRencontre(tmr, () => {
|
||||||
|
this.postRencontre(tmr);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async updateValuesDisplay() {
|
async updateValuesDisplay() {
|
||||||
if (!this.rendered) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const coord = this._getActorCoord();
|
const coord = this._getActorCoord();
|
||||||
|
const actorData = Misc.data(this.actor);
|
||||||
|
|
||||||
HtmlUtility._showControlWhen($(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
|
HtmlUtility._showControlWhen($(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
|
||||||
|
|
||||||
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
||||||
ptsreve.innerHTML = this.actor.system.reve.reve.value;
|
ptsreve.innerHTML = actorData.data.reve.reve.value;
|
||||||
|
|
||||||
let tmrpos = document.getElementById("tmr-pos");
|
let tmrpos = document.getElementById("tmr-pos");
|
||||||
if (this.isDemiReveCache()) {
|
if (this.isDemiReveCache()) {
|
||||||
tmrpos.innerHTML = `?? ( ${TMRUtility.getTMRType(coord)})`;
|
tmrpos.innerHTML = '?? (' + TMRUtility.getTMRType(coord) + ')';
|
||||||
} else {
|
} else {
|
||||||
tmrpos.innerHTML = `${coord} ( ${TMRUtility.getTMRLabel(coord)})`;
|
tmrpos.innerHTML = coord + " (" + TMRUtility.getTMRLabel(coord) + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
let etat = document.getElementById("tmr-etatgeneral-value");
|
let etat = document.getElementById("tmr-etatgeneral-value");
|
||||||
etat.innerHTML = this.actor.getEtatGeneral();
|
etat.innerHTML = this.actor.getEtatGeneral();
|
||||||
|
|
||||||
let refoulement = document.getElementById("tmr-refoulement-value");
|
let refoulement = document.getElementById("tmr-refoulement-value");
|
||||||
refoulement.innerHTML = this.actor.system.reve.refoulement.value;
|
refoulement.innerHTML = actorData.data.reve.refoulement.value;
|
||||||
|
|
||||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||||
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
||||||
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(this.actor.system.sante.fatigue.value, this.actor.system.sante.endurance.max).html() + "</table>";
|
//console.log("Refresh : ", actorData.data.sante.fatigue.value);
|
||||||
|
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(actorData.data.sante.fatigue.value, actorData.data.sante.endurance.max).html() + "</table>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async close() {
|
close() {
|
||||||
this.descenteTMR = true;
|
if ( this.actor.tmrApp ) {
|
||||||
if (this.actor.tmrApp) {
|
|
||||||
this.actor.tmrApp = undefined; // Cleanup reference
|
this.actor.tmrApp = undefined; // Cleanup reference
|
||||||
if (!this.viewOnly) {
|
if ( !this.viewOnly ) {
|
||||||
await this.actor.setEffect(STATUSES.StatusDemiReve, false)
|
this.actor.setStatusEffect("EFFECT.StatusDemiReve", false);
|
||||||
this._tellToGM(this.actor.name + " a quitté les terres médianes");
|
this._tellToGM(this.actor.name + " a quitté les terres médianes");
|
||||||
}
|
}
|
||||||
await this.actor.santeIncDec("fatigue", this.cumulFatigue)
|
this.actor.santeIncDec("fatigue", this.cumulFatigue).then(super.close()); // moving 1 cell costs 1 fatigue
|
||||||
}
|
}
|
||||||
await super.close(); // moving 1 cell costs 1 fatigue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onActionRencontre(action, tmr) {
|
|
||||||
switch (action) {
|
|
||||||
case 'derober':
|
|
||||||
await this.derober();
|
|
||||||
return;
|
|
||||||
case 'refouler':
|
|
||||||
await this.refouler();
|
|
||||||
break;
|
|
||||||
case 'maitriser':
|
|
||||||
await this.maitriserRencontre();
|
|
||||||
break;
|
|
||||||
case 'ignorer':
|
|
||||||
await this.ignorerRencontre();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
await this.postRencontre(tmr);
|
|
||||||
}
|
|
||||||
|
|
||||||
async derober() {
|
async derober() {
|
||||||
console.log("-> derober", this.currentRencontre);
|
|
||||||
await this.actor.addTMRRencontre(this.currentRencontre);
|
await this.actor.addTMRRencontre(this.currentRencontre);
|
||||||
|
console.log("-> derober", this.currentRencontre);
|
||||||
this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR.");
|
this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR.");
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async refouler() {
|
async refouler() {
|
||||||
console.log("-> refouler", this.currentRencontre);
|
this._tellToGM(this.actor.name + " a refoulé : " + this.currentRencontre.name);
|
||||||
await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`);
|
|
||||||
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
|
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
|
||||||
|
await this.actor.ajouterRefoulement(this.currentRencontre.refoulement ?? 1);
|
||||||
this.updateTokens();
|
this.updateTokens();
|
||||||
|
console.log("-> refouler", this.currentRencontre)
|
||||||
this.updateValuesDisplay();
|
this.updateValuesDisplay();
|
||||||
this.nettoyerRencontre();
|
this.nettoyerRencontre();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async ignorerRencontre() {
|
async ignorerRencontre() {
|
||||||
console.log("-> ignorer", this.currentRencontre);
|
this._tellToGM(this.actor.name + " a ignoré : " + this.currentRencontre.name);
|
||||||
this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
|
|
||||||
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
|
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary
|
||||||
this.updateTokens();
|
this.updateTokens();
|
||||||
this.updateValuesDisplay();
|
this.updateValuesDisplay();
|
||||||
@ -330,22 +315,15 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// garder la trace de l'état en cours
|
colorierZoneRencontre(listCoordTMR) {
|
||||||
setRencontreState(state, listCoordTMR) {
|
|
||||||
this.rencontreState = state;
|
|
||||||
this.$marquerCasesTMR(listCoordTMR ?? []);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
$marquerCasesTMR(listCoordTMR) {
|
|
||||||
this.currentRencontre.graphics = []; // Keep track of rectangles to delete it
|
this.currentRencontre.graphics = []; // Keep track of rectangles to delete it
|
||||||
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location
|
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location
|
||||||
for (let coordTMR of listCoordTMR) {
|
for (let coordTMR of listCoordTMR) {
|
||||||
const rect = this._getCaseRectangleCoord(coordTMR);
|
let rect = this._getCaseRectangleCoord(coordTMR);
|
||||||
const rectDraw = new PIXI.Graphics();
|
var rectDraw = new PIXI.Graphics();
|
||||||
rectDraw.beginFill(0xffff00, 0.3);
|
rectDraw.beginFill(0xFFFF00, 0.3);
|
||||||
// set the line style to have a width of 5 and set the color to red
|
// 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
|
// draw a rectangle
|
||||||
rectDraw.drawRect(rect.x, rect.y, rect.w, rect.h);
|
rectDraw.drawRect(rect.x, rect.y, rect.w, rect.h);
|
||||||
this.pixiApp.stage.addChild(rectDraw);
|
this.pixiApp.stage.addChild(rectDraw);
|
||||||
@ -353,6 +331,29 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
// garder la trace de l'état en cours
|
||||||
|
setStateRencontre(state) {
|
||||||
|
this.rencontreState = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async choisirCasePortee(coord, portee) {
|
||||||
|
if (this.actor.isTMRCache())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Récupère la liste des cases à portées
|
||||||
|
let locList = TMRUtility.getTMRPortee(coord, portee);
|
||||||
|
this.colorierZoneRencontre(locList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async choisirCaseType(type) {
|
||||||
|
const locList = TMRUtility.filterTMR(it => it.type == type).map(it => it.coord);
|
||||||
|
this.colorierZoneRencontre(locList);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
checkQuitterTMR() {
|
checkQuitterTMR() {
|
||||||
|
|
||||||
@ -377,15 +378,15 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async quitterLesTMRInconscient() {
|
async quitterLesTMRInconscient() {
|
||||||
await this.refouler();
|
if (this.currentRencontre?.isPersistant) {
|
||||||
|
await this.refouler();
|
||||||
|
}
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async maitriserRencontre() {
|
async maitriserRencontre() {
|
||||||
console.log("-> maitriser", this.currentRencontre);
|
this.actor.deleteTMRRencontreAtPosition();
|
||||||
|
|
||||||
await this.actor.deleteTMRRencontreAtPosition();
|
|
||||||
this.updateTokens();
|
this.updateTokens();
|
||||||
|
|
||||||
let rencontreData = {
|
let rencontreData = {
|
||||||
@ -396,7 +397,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
rencontre: this.currentRencontre,
|
rencontre: this.currentRencontre,
|
||||||
nbRounds: 1,
|
nbRounds: 1,
|
||||||
canClose: false,
|
canClose: false,
|
||||||
selectedCarac: { label: "reve-actuel" },
|
selectedCarac: {label: "reve-actuel"},
|
||||||
tmr: TMRUtility.getTMR(this._getActorCoord())
|
tmr: TMRUtility.getTMR(this._getActorCoord())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,6 +406,8 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _tentativeMaitrise(rencData) {
|
async _tentativeMaitrise(rencData) {
|
||||||
|
console.log("-> matriser", rencData);
|
||||||
|
|
||||||
rencData.reve = this.actor.getReveActuel();
|
rencData.reve = this.actor.getReveActuel();
|
||||||
rencData.etat = this.actor.getEtatGeneral();
|
rencData.etat = this.actor.getEtatGeneral();
|
||||||
|
|
||||||
@ -414,67 +417,41 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
? this._rollPresentCite(rencData)
|
? this._rollPresentCite(rencData)
|
||||||
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
|
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
|
||||||
|
|
||||||
const result = rencData.rolled.isSuccess
|
let postProcess = await TMRRencontres.gererRencontre(this, rencData);
|
||||||
? rencData.rencontre.system.succes
|
|
||||||
: rencData.rencontre.system.echec;
|
|
||||||
|
|
||||||
await RdDRencontre.appliquer(result.effets, this, rencData);
|
|
||||||
|
|
||||||
rencData.poesie = { extrait: result.poesie, reference: result.reference };
|
|
||||||
rencData.message = this.formatMessageRencontre(rencData, result.message);
|
|
||||||
|
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencData)
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencData)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (postProcess) {
|
||||||
|
/** Gère les rencontres avec du post-processing (passeur, messagers, tourbillons, ...) */
|
||||||
|
await postProcess(this, rencData);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.currentRencontre = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
this.updateValuesDisplay();
|
this.updateValuesDisplay();
|
||||||
if (this.checkQuitterTMR()) {
|
if (this.checkQuitterTMR()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.rencontreState == 'persistant') {
|
else if (rencData.rolled.isEchec && rencData.rencontre.isPersistant) {
|
||||||
this._nouvelleTentativeMaitrise(rencData);
|
setTimeout(() => {
|
||||||
}
|
rencData.nbRounds++;
|
||||||
else if (!this.isRencontreDeplacement()) {
|
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||||
this.nettoyerRencontre();
|
this.cumulFatigue += this.fatigueParCase;
|
||||||
}
|
}
|
||||||
}
|
this._tentativeMaitrise(rencData);
|
||||||
|
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
|
||||||
_nouvelleTentativeMaitrise(rencData) {
|
}, 2000);
|
||||||
setTimeout(() => {
|
|
||||||
// TODO: remplacer par une boucle while(this.currentRencontre) ?
|
|
||||||
rencData.nbRounds++;
|
|
||||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
|
||||||
this.cumulFatigue += this.fatigueParCase;
|
|
||||||
}
|
|
||||||
this._tentativeMaitrise(rencData);
|
|
||||||
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
|
|
||||||
}, 2000);
|
|
||||||
this.rencontreState == 'normal';
|
|
||||||
}
|
|
||||||
|
|
||||||
formatMessageRencontre(rencData, template) {
|
|
||||||
let messageDuree = ''
|
|
||||||
if (rencData.nbRounds > 1) {
|
|
||||||
if (rencData.rolled.isSuccess) {
|
|
||||||
messageDuree = ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
messageDuree = ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const compiled = Handlebars.compile(template);
|
|
||||||
return compiled(rencData) + messageDuree ;
|
|
||||||
} catch (error) {
|
|
||||||
return template + messageDuree ;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_rollPresentCite(rencData) {
|
_rollPresentCite(rencontreData) {
|
||||||
let rolled = RdDResolutionTable.computeChances(rencData.reve, 0);
|
let rolled = RdDResolutionTable.computeChances(rencontreData.reve, 0);
|
||||||
mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score });
|
mergeObject(rolled, { caracValue: rencontreData.reve, finalLevel: 0, roll: rolled.score });
|
||||||
RdDResolutionTable.succesRequis(rolled);
|
RdDResolutionTable.succesRequis(rolled);
|
||||||
return rolled;
|
return rolled;
|
||||||
}
|
}
|
||||||
@ -509,49 +486,44 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async manageRencontre(tmr) {
|
async manageRencontre(tmr, postRencontre) {
|
||||||
if (this.viewOnly) {
|
if (this.viewOnly) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.descenteTMR = false;
|
|
||||||
this.currentRencontre = undefined;
|
this.currentRencontre = undefined;
|
||||||
if (this._presentCite(tmr)) {
|
if (this._presentCite(tmr, postRencontre)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.currentRencontre = await this._jetDeRencontre(tmr);
|
let rencontre = await this._jetDeRencontre(tmr);
|
||||||
if (this.currentRencontre) {
|
|
||||||
if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)){
|
if (rencontre) { // Manages it
|
||||||
// rencontre en attente suite à dérobade
|
if (rencontre.rencontre) rencontre = rencontre.rencontre; // Manage stored rencontres
|
||||||
await this.maitriserRencontre();
|
console.log("manageRencontre", rencontre);
|
||||||
}
|
this.currentRencontre = duplicate(rencontre);
|
||||||
else {
|
|
||||||
let dialog = new RdDTMRRencontreDialog(this, this.currentRencontre, tmr);
|
let dialog = new RdDTMRRencontreDialog("", this, this.currentRencontre, postRencontre);
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.postRencontre(tmr);
|
postRencontre();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_presentCite(tmr) {
|
_presentCite(tmr, postRencontre) {
|
||||||
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
|
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
|
||||||
if (presentCite) {
|
if (presentCite) {
|
||||||
this.minimize();
|
this.minimize();
|
||||||
const caseData = presentCite;
|
const caseData = Misc.data(presentCite);
|
||||||
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (present => this._utiliserPresentCite(presentCite, present, tmr)));
|
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (type => this._utiliserPresentCite(presentCite, type, tmr, postRencontre)));
|
||||||
}
|
}
|
||||||
return presentCite;
|
return presentCite;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _utiliserPresentCite(presentCite, present, tmr) {
|
async _utiliserPresentCite(presentCite, typeRencontre, tmr, postRencontre) {
|
||||||
this.currentRencontre = present.clone({
|
this.currentRencontre = TMRRencontres.getRencontre(typeRencontre);
|
||||||
'system.force': await RdDDice.rollTotal(present.system.formule),
|
await TMRRencontres.evaluerForceRencontre(this.currentRencontre);
|
||||||
'system.coord': tmr.coord
|
|
||||||
}, {save: false});
|
|
||||||
|
|
||||||
await EffetsDraconiques.presentCites.ouvrirLePresent(this.actor, presentCite);
|
await EffetsDraconiques.presentCites.ouvrirLePresent(this.actor, presentCite);
|
||||||
this.removeToken(tmr, presentCite);
|
this.removeToken(tmr, presentCite);
|
||||||
|
|
||||||
@ -568,38 +540,42 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
await this._tentativeMaitrise(rencontreData);
|
await this._tentativeMaitrise(rencontreData);
|
||||||
|
|
||||||
this.maximize();
|
this.maximize();
|
||||||
this.postRencontre(tmr);
|
postRencontre();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _jetDeRencontre(tmr) {
|
async _jetDeRencontre(tmr) {
|
||||||
let rencontre = this.lookupRencontreExistente(tmr);
|
let rencontre = this.rencontresExistantes.find(prev => prev.coord == tmr.coord);
|
||||||
if (rencontre) {
|
if (rencontre) {
|
||||||
return game.system.rdd.rencontresTMR.calculRencontre(rencontre, tmr);
|
return rencontre;
|
||||||
}
|
}
|
||||||
let locTMR = (this.isDemiReveCache()
|
let locTMR = (this.isDemiReveCache()
|
||||||
? TMRUtility.getTMRType(tmr.coord) + " ??"
|
? Misc.upperFirst(tmr.type) + " ??"
|
||||||
: tmr.label + " (" + tmr.coord + ")");
|
: tmr.label + " (" + tmr.coord + ")");
|
||||||
|
|
||||||
let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
|
let myRoll = await RdDDice.rollTotal("1dt");
|
||||||
if (myRoll == 7) {
|
if (TMRUtility.isForceRencontre() || myRoll == 7) {
|
||||||
this._tellToUser(myRoll + ": Rencontre en " + locTMR);
|
this._tellToUser(myRoll + ": Rencontre en " + locTMR);
|
||||||
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
|
return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale());
|
||||||
} else {
|
} else {
|
||||||
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
|
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lookupRencontreExistente(tmr) {
|
/* -------------------------------------------- */
|
||||||
return this.rencontresExistantes.find(it => it.system.coord == tmr.coord)
|
async rencontreTMRRoll(tmr, isMauvaise = false) {
|
||||||
?? this.rencontresExistantes.find(it => it.system.coord == "");
|
let rencontre = TMRUtility.utiliseForceRencontre() ??
|
||||||
|
(isMauvaise
|
||||||
|
? await TMRRencontres.getMauvaiseRencontre()
|
||||||
|
: await TMRRencontres.getRencontreAleatoire(tmr.type));
|
||||||
|
rencontre.coord = tmr.coord;
|
||||||
|
rencontre.date = game.system.rdd.calendrier.getDateFromIndex();
|
||||||
|
rencontre.heure = game.system.rdd.calendrier.getCurrentHeure();
|
||||||
|
return rencontre;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async manageTmrInnaccessible(tmr) {
|
async manageTmrInnaccessible(tmr) {
|
||||||
if (!tmr) {
|
|
||||||
return await this.actor.reinsertionAleatoire('Sortie de carte');
|
|
||||||
}
|
|
||||||
const caseTmrInnaccessible = this.casesSpeciales.find(c => EffetsDraconiques.isInnaccessible(c, tmr.coord));
|
const caseTmrInnaccessible = this.casesSpeciales.find(c => EffetsDraconiques.isInnaccessible(c, tmr.coord));
|
||||||
if (caseTmrInnaccessible) {
|
if (caseTmrInnaccessible) {
|
||||||
return await this.actor.reinsertionAleatoire(caseTmrInnaccessible.name);
|
return await this.actor.reinsertionAleatoire(caseTmrInnaccessible.name);
|
||||||
@ -620,7 +596,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
|
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
|
||||||
}
|
}
|
||||||
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined,
|
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined,
|
||||||
rollData.competence.system.defaut_carac = 'reve-actuel';
|
rollData.competence.data.defaut_carac = 'reve-actuel';
|
||||||
await this._rollMaitriseCaseHumide(rollData);
|
await this._rollMaitriseCaseHumide(rollData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -632,6 +608,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
async _resultatMaitriseCaseHumide(rollData) {
|
async _resultatMaitriseCaseHumide(rollData) {
|
||||||
await this.souffleSiEchecTotal(rollData);
|
await this.souffleSiEchecTotal(rollData);
|
||||||
|
this.toclose = rollData.rolled.isEchec;
|
||||||
if (rollData.rolled.isSuccess && rollData.double) {
|
if (rollData.rolled.isSuccess && rollData.double) {
|
||||||
rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements };
|
rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements };
|
||||||
rollData.double = undefined;
|
rollData.double = undefined;
|
||||||
@ -644,7 +621,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
|
||||||
});
|
});
|
||||||
if (rollData.rolled.isEchec) {
|
if (rollData.rolled.isEchec) {
|
||||||
await this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -658,16 +635,16 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
isCaseHumide(tmr) {
|
isCaseHumide(tmr) {
|
||||||
if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) {
|
if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) {
|
||||||
return false;
|
return undefined;
|
||||||
}
|
}
|
||||||
if (this.isCaseMaitrisee(tmr.coord)) {
|
if (this.isCaseMaitrisee(tmr.coord)) {
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
content: tmr.label + ": cette case humide est déja maitrisée grâce à votre Tête <strong>Quête des Eaux</strong>",
|
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)
|
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||||
});
|
});
|
||||||
return false;
|
return undefined;
|
||||||
}
|
}
|
||||||
return true;
|
return -7;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -744,7 +721,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
|
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
|
||||||
maitrise: { verbe: 'conquérir', action: options.action }
|
maitrise: { verbe: 'conquérir', action: options.action }
|
||||||
};
|
};
|
||||||
rollData.competence.system.defaut_carac = 'reve-actuel';
|
rollData.competence.data.defaut_carac = 'reve-actuel';
|
||||||
|
|
||||||
await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options));
|
await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options));
|
||||||
}
|
}
|
||||||
@ -754,6 +731,8 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
if (rollData.rolled.isETotal) {
|
if (rollData.rolled.isETotal) {
|
||||||
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
|
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
|
||||||
}
|
}
|
||||||
|
this.toclose = rollData.rolled.isEchec;
|
||||||
|
|
||||||
rollData.poesie = await Poetique.getExtrait();
|
rollData.poesie = await Poetique.getExtrait();
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||||
@ -775,6 +754,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
const dialog = await RdDRoll.create(this.actor, rollData,
|
const dialog = await RdDRoll.create(this.actor, rollData,
|
||||||
{
|
{
|
||||||
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
|
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
|
||||||
|
options: { height: 420 },
|
||||||
close: html => { this.maximize(); } // Re-display TMR
|
close: html => { this.maximize(); } // Re-display TMR
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -797,8 +777,9 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async declencheSortEnReserve(coord) {
|
async declencheSortEnReserve(coord) {
|
||||||
let sorts = this.getSortsReserve(coord);
|
|
||||||
if (sorts.length > 0) {
|
let sortsEnCoord = TMRUtility.getSortsReserve(this.sortsReserves, coord);
|
||||||
|
if (sortsEnCoord.length > 0) {
|
||||||
if (EffetsDraconiques.isSortReserveImpossible(this.actor)) {
|
if (EffetsDraconiques.isSortReserveImpossible(this.actor)) {
|
||||||
ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!");
|
ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!");
|
||||||
return;
|
return;
|
||||||
@ -806,8 +787,8 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) &&
|
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) &&
|
||||||
(EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord))) {
|
(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>";
|
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 sort of sorts) {
|
for (let sortReserve of sortsEnCoord) {
|
||||||
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 += "<li><a class='chat-card-button' id='sort-reserve' data-actor-id='" + this.actor._id + "' data-tmr-coord='" + coord + "' data-sort-id='" + sortReserve.sort._id + "'>" + sortReserve.sort.name + "</a></li>";
|
||||||
}
|
}
|
||||||
msg += "</ol>";
|
msg += "</ol>";
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
@ -816,36 +797,33 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.processSortReserve(sorts[0]);
|
await this.processSortReserve(sortsEnCoord[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
lancerSortEnReserve(coord, sortId) {
|
lancerSortEnReserve(coord, sortId) {
|
||||||
let sorts = this.getSortsReserve(coord);
|
let sortEnCoord = TMRUtility.getSortsReserve(this.sortsReserves, coord);
|
||||||
let sort = sorts.find(it => it.id == sortId);
|
let sortReserve = sortEnCoord.find(sortReserve => sortReserve.sort._id == sortId);
|
||||||
if (sort) {
|
if (sortReserve) {
|
||||||
this.processSortReserve(sort);
|
this.processSortReserve(sortReserve);
|
||||||
} else {
|
} else {
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
content:
|
content: "Une erreur est survenue : impossible de récupérer le sort en réserve demandé.",
|
||||||
"Une erreur est survenue : impossible de récupérer le sort en réserve demandé.",
|
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||||
whisper: ChatMessage.getWhisperRecipients(game.user.name),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async processSortReserve(sortReserve) {
|
async processSortReserve(sortReserve) {
|
||||||
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
|
await this.actor.deleteSortReserve(sortReserve);
|
||||||
console.log("declencheSortEnReserve", sortReserve);
|
//this.updateSortReserve();
|
||||||
const heureCible = RdDCalendrier.getSigneAs('label', sortReserve.system.heurecible);
|
console.log("declencheSortEnReserve", sortReserve)
|
||||||
this._tellToUserAndGM(`Vous avez déclenché
|
this._tellToUserAndGM(`Vous avez déclenché le sort en réserve <strong> ${sortReserve.sort.name}</strong>
|
||||||
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"}
|
avec ${sortReserve.sort.data.ptreve_reel} points de Rêve
|
||||||
en réserve <strong>${sortReserve.name}</strong>
|
en ${sortReserve.coord} (${TMRUtility.getTMRLabel(sortReserve.coord)})
|
||||||
avec ${sortReserve.system.ptreve} points de Rêve
|
`);
|
||||||
en ${sortReserve.system.coord} (${TMRUtility.getTMRLabel(sortReserve.system.coord)}).
|
|
||||||
L'heure ciblée est ${heureCible}`);
|
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,6 +875,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
if (this.viewOnly) {
|
if (this.viewOnly) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let clickOddq = RdDTMRDialog._computeEventOddq(event.data.originalEvent);
|
let clickOddq = RdDTMRDialog._computeEventOddq(event.data.originalEvent);
|
||||||
await this._onClickTMRPos(clickOddq); // Vérifier l'état des compteurs reve/fatigue/vie
|
await this._onClickTMRPos(clickOddq); // Vérifier l'état des compteurs reve/fatigue/vie
|
||||||
}
|
}
|
||||||
@ -911,14 +890,14 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
if (this.isDemiReveCache()) {
|
if (this.isDemiReveCache()) {
|
||||||
if (this.isTerreAttache(targetCoord)
|
if (this.isTerreAttache(targetCoord)
|
||||||
|| this.isConnaissanceFleuve(currentCoord, targetCoord)
|
|| (this.isCaseHumide(currentCoord) && this.isCaseHumide(targetCoord))
|
||||||
|| deplacementType == 'changeur') {
|
|| deplacementType == 'changeur')
|
||||||
|
{
|
||||||
// déplacement possible
|
// déplacement possible
|
||||||
await this.actor.setTMRVisible(true);
|
await this.actor.montreTMR();
|
||||||
this.demiReve = this._tokenDemiReve();
|
|
||||||
this._trackToken(this.demiReve);
|
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
ui.notifications.error(`Vous ne connaissez plus votre position dans les TMR.
|
ui.notifications.error(`Vous ne connaissez plus votre position dans les TMR.
|
||||||
Vous devez utiliser les boutons de direction pour vous déplacer.
|
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.
|
Une fois que vous aurez retrouvé votre demi-rêve, demandez au gardien de vérifier et rendre les TMR visibles.
|
||||||
@ -927,18 +906,20 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (deplacementType) {
|
switch (deplacementType){
|
||||||
case 'normal':
|
case 'normal':
|
||||||
case 'changeur':
|
|
||||||
case 'passeur':
|
|
||||||
await this._deplacerDemiReve(targetCoord, deplacementType);
|
await this._deplacerDemiReve(targetCoord, deplacementType);
|
||||||
break;
|
break;
|
||||||
case 'messager':
|
case 'messager':
|
||||||
await this._messagerDemiReve(targetCoord);
|
await this._messagerDemiReve(targetCoord);
|
||||||
break;
|
break;
|
||||||
|
case 'changeur':
|
||||||
|
case 'passeur':
|
||||||
|
await this._deplacerDemiReve(targetCoord, deplacementType);
|
||||||
|
break;
|
||||||
default:
|
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");
|
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);
|
console.log("STATUS :", this.rencontreState, this.currentRencontre);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkQuitterTMR();
|
this.checkQuitterTMR();
|
||||||
@ -946,23 +927,19 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_calculDeplacement(targetCoord, currentCoord, fromOddq, toOddq) {
|
_calculDeplacement(targetCoord, currentCoord, fromOddq, toOddq) {
|
||||||
if (this.isRencontreDeplacement()) {
|
|
||||||
if (this.currentRencontre?.locList?.find(coord => coord == targetCoord)) {
|
const isInArea = this.rencontreState == 'aucune'
|
||||||
return this.rencontreState;
|
? (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || TMRUtility.distanceOddq(fromOddq, toOddq) <= 1)
|
||||||
}
|
: this.currentRencontre?.locList.find(coord => coord == targetCoord) ?? false
|
||||||
}
|
if (isInArea) {
|
||||||
else {
|
switch (this.rencontreState) {
|
||||||
if (this.isTerreAttache(targetCoord) || this.isConnaissanceFleuve(currentCoord, targetCoord) || TMRUtility.distanceOddq(fromOddq, toOddq) <= 1) {
|
case 'aucune': return 'normal';
|
||||||
return 'normal'
|
case 'passeur': case 'changeur': case 'messager': return this.rencontreState;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 'erreur';
|
return 'erreur';
|
||||||
}
|
}
|
||||||
|
|
||||||
isRencontreDeplacement() {
|
|
||||||
return ['passeur', 'changeur', 'messager'].includes(this.rencontreState);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _messagerDemiReve(targetCoord) {
|
async _messagerDemiReve(targetCoord) {
|
||||||
/*
|
/*
|
||||||
@ -1002,7 +979,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
this.actor.notifyRefreshTMR();
|
this.actor.notifyRefreshTMR();
|
||||||
|
|
||||||
if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/...
|
if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/...
|
||||||
await this.manageRencontre(tmr);
|
await this.manageRencontre(tmr, () => this.postRencontre(tmr));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
await this.postRencontre(tmr);
|
await this.postRencontre(tmr);
|
||||||
@ -1021,14 +998,13 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async postRencontre(tmr) {
|
async postRencontre(tmr) {
|
||||||
if (!(this.viewOnly || this.currentRencontre)) {
|
if (!(this.viewOnly || this.currentRencontre)) {
|
||||||
// TODO: vérifier que la méthode s'arrête en cas de non-maîtrise
|
await this.manageCaseHumide(tmr);
|
||||||
if (!this.descenteTMR) await this.manageCaseHumide(tmr);
|
await this.conquerirCiteFermee(tmr);
|
||||||
if (!this.descenteTMR) await this.conquerirCiteFermee(tmr);
|
await this.purifierPeriple(tmr);
|
||||||
if (!this.descenteTMR) await this.purifierPeriple(tmr);
|
await this.conquerirTMR(tmr);
|
||||||
if (!this.descenteTMR) await this.conquerirTMR(tmr);
|
await this.validerVisite(tmr);
|
||||||
if (!this.descenteTMR) await this.validerVisite(tmr);
|
await this.declencheSortEnReserve(tmr.coord);
|
||||||
if (!this.descenteTMR) await this.declencheSortEnReserve(tmr.coord);
|
await this.actor.checkSoufflePeage(tmr);
|
||||||
if (!this.descenteTMR) await this.actor.checkSoufflePeage(tmr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1047,7 +1023,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
let x = origEvent.clientX - canvasRect.left;
|
let x = origEvent.clientX - canvasRect.left;
|
||||||
let y = origEvent.clientY - canvasRect.top;
|
let y = origEvent.clientY - canvasRect.top;
|
||||||
let col = Math.floor(x / tmrConstants.cellw); // [From 0 -> 12]
|
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]
|
let row = Math.floor(y / tmrConstants.cellh); // [From 0 -> 14]
|
||||||
return { col: col, row: row };
|
return { col: col, row: row };
|
||||||
}
|
}
|
||||||
@ -1057,7 +1033,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
_getCaseRectangleCoord(coord) {
|
_getCaseRectangleCoord(coord) {
|
||||||
return this.pixiTMR.getCaseRectangle(TMRUtility.coordTMRToOddq(coord));
|
return this.pixiTMR.getCaseRectangle(TMRUtility.coordTMRToOddq(coord));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_removeTokens(filter) {
|
_removeTokens(filter) {
|
||||||
const tokensToRemove = this.allTokens.filter(filter);
|
const tokensToRemove = this.allTokens.filter(filter);
|
||||||
@ -1065,7 +1041,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
this.pixiApp.stage.removeChild(token.sprite);
|
this.pixiApp.stage.removeChild(token.sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_trackToken(token) {
|
_trackToken(token) {
|
||||||
if (this.demiReve === token && this.isDemiReveCache()) {
|
if (this.demiReve === token && this.isDemiReveCache()) {
|
||||||
|
@ -2,41 +2,46 @@
|
|||||||
export class RdDTMRRencontreDialog extends Dialog {
|
export class RdDTMRRencontreDialog extends Dialog {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(tmrApp, rencontre, tmr) {
|
constructor(html, tmrApp, rencontre, postRencontre) {
|
||||||
const dialogConf = {
|
const dialogConf = {
|
||||||
title: "Rencontre en TMR!",
|
title: "Rencontre en TMR!",
|
||||||
content: "Vous rencontrez un " + rencontre.name + " de force " + rencontre.system.force + "<br>",
|
content: "Vous rencontrez un " + rencontre.name + " de force " + rencontre.force + "<br>",
|
||||||
buttons: {
|
buttons: {
|
||||||
derober: { icon: '<i class="fas fa-check"></i>', label: "Se dérober", callback: () => this.onButtonAction('derober') },
|
derober: { icon: '<i class="fas fa-check"></i>', label: "Se dérober", callback: () => { this.onButtonFuir(() => tmrApp.derober()); } },
|
||||||
maitiser: { icon: '<i class="fas fa-check"></i>', label: "Maîtriser", callback: () => this.onButtonAction('maitriser') }
|
refouler: { icon: '<i class="fas fa-check"></i>', label: "Refouler", callback: () => this.onButtonAction(() => tmrApp.refouler()) },
|
||||||
|
maitiser: { icon: '<i class="fas fa-check"></i>', label: "Maîtriser", callback: () => this.onButtonAction(() => tmrApp.maitriserRencontre()) }
|
||||||
},
|
},
|
||||||
default: "derober"
|
default: "derober"
|
||||||
}
|
};
|
||||||
if ((rencontre.system.refoulement ?? 0) == 0) {
|
if (rencontre.ignorer) {
|
||||||
dialogConf.buttons.ignorer = { icon: '<i class="fas fa-check"></i>', label: "Ignorer", callback: () => this.onButtonAction('ignorer') }
|
dialogConf.buttons.ignorer = { icon: '<i class="fas fa-check"></i>', label: "Ignorer", callback: () => this.onButtonAction(() => tmrApp.ignorerRencontre()) }
|
||||||
}
|
};
|
||||||
else {
|
|
||||||
dialogConf.buttons.refouler = { icon: '<i class="fas fa-check"></i>', label: "Refouler", callback: () => this.onButtonAction('refouler') }
|
|
||||||
}
|
|
||||||
|
|
||||||
const dialogOptions = {
|
const dialogOptions = {
|
||||||
classes: ["tmrrencdialog"],
|
classes: ["tmrrencdialog"],
|
||||||
width: 320, height: 'fit-content',
|
width: 320, height: 240,
|
||||||
'z-index': 50
|
'z-index': 50
|
||||||
}
|
}
|
||||||
super(dialogConf, dialogOptions);
|
super(dialogConf, dialogOptions);
|
||||||
|
|
||||||
this.toClose = false;
|
this.toClose = false;
|
||||||
this.tmr = tmr;
|
this.rencontreData = duplicate(rencontre);
|
||||||
|
this.postRencontre = postRencontre;
|
||||||
this.tmrApp = tmrApp;
|
this.tmrApp = tmrApp;
|
||||||
this.tmrApp.minimize();
|
this.tmrApp.minimize();
|
||||||
}
|
}
|
||||||
|
|
||||||
async onButtonAction(action) {
|
async onButtonAction(action) {
|
||||||
this.toClose = true;
|
this.toClose = true;
|
||||||
this.tmrApp.onActionRencontre(action, this.tmr)
|
await action();
|
||||||
|
this.postRencontre();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onButtonFuir(action) {
|
||||||
|
this.toClose = true;
|
||||||
|
await action();
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
close() {
|
close() {
|
||||||
if (this.toClose) {
|
if (this.toClose) {
|
||||||
|
@ -8,7 +8,7 @@ export class RdDTokenHud {
|
|||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
// Integration du TokenHUD
|
// Integration du TokenHUD
|
||||||
Hooks.on('renderTokenHUD', (app, html, token) => { RdDTokenHud.addTokenHudExtensions(app, html, token._id) });
|
Hooks.on('renderTokenHUD', (app, html, data) => { RdDTokenHud.addTokenHudExtensions(app, html, data._id) });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -22,7 +22,7 @@ export class RdDTokenHud {
|
|||||||
|
|
||||||
let token = canvas.tokens.get(tokenId);
|
let token = canvas.tokens.get(tokenId);
|
||||||
let actor = token.actor;
|
let actor = token.actor;
|
||||||
let combatant = game.combat.combatants.find(c => c.tokenId == tokenId);
|
let combatant = game.combat.combatants.find(c => Misc.data(c).tokenId == tokenId);
|
||||||
if (! (combatant?.actor) ) {
|
if (! (combatant?.actor) ) {
|
||||||
ui.notifications.warn(`Le combatant ${token.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
|
ui.notifications.warn(`Le combatant ${token.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
|
||||||
return;
|
return;
|
||||||
@ -63,7 +63,7 @@ export class RdDTokenHud {
|
|||||||
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
|
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
|
||||||
const action = actionsCombat[actionIndex];
|
const action = actionsCombat[actionIndex];
|
||||||
if (action.action == 'conjurer') {
|
if (action.action == 'conjurer') {
|
||||||
actor.conjurerPossession(actor.getPossession(action.system.possessionid));
|
actor.conjurerPossession(actor.getPossession(action.data.possessionid));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
actor.rollArme(action);
|
actor.rollArme(action);
|
||||||
@ -76,7 +76,7 @@ export class RdDTokenHud {
|
|||||||
case 'inc': return RdDCombatManager.incDecInit(combatantId, 0.01);
|
case 'inc': return RdDCombatManager.incDecInit(combatantId, 0.01);
|
||||||
case 'dec': return RdDCombatManager.incDecInit(combatantId, -0.01);
|
case 'dec': return RdDCombatManager.incDecInit(combatantId, -0.01);
|
||||||
case 'autre': return RdDCombatManager.rollInitiativeAction(combatantId,
|
case 'autre': return RdDCombatManager.rollInitiativeAction(combatantId,
|
||||||
{ name: "Autre action", action: 'autre', system: { initOnly: true, competence: "Autre action" } });
|
{ name: "Autre action", action: 'autre', data: { initOnly: true, competence: "Autre action" } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,16 +6,12 @@ import { Misc } from "./misc.js";
|
|||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
import { DialogItemAchat } from "./dialog-item-achat.js";
|
import { DialogItemAchat } from "./dialog-item-achat.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
import { Monnaie } from "./item-monnaie.js";
|
import { Monnaie } from "./item-monnaie.js";
|
||||||
import { RdDPossession } from "./rdd-possession.js";
|
import { RdDPossession } from "./rdd-possession.js";
|
||||||
import { RdDNameGen } from "./rdd-namegen.js";
|
import { RdDNameGen } from "./rdd-namegen.js";
|
||||||
import { RdDConfirm } from "./rdd-confirm.js";
|
|
||||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
|
||||||
import { RdDCarac } from "./rdd-carac.js";
|
|
||||||
import { Environnement } from "./environnement.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// This table starts at 0 -> niveau -10
|
// This table starts at 0 -> niveau -10
|
||||||
@ -108,7 +104,7 @@ export class RdDUtility {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async init() {
|
static async init() {
|
||||||
Hooks.on("renderChatMessage", async (app, html, msg) => RdDUtility.onRenderChatMessage(app, html, msg));
|
Hooks.on("renderChatMessage", async (app, html, msg) => RdDUtility.onRenderChatMessage(app, html, msg));
|
||||||
Hooks.on('renderChatLog', (log, html, chatLog) => RdDUtility.chatListeners(html));
|
Hooks.on('renderChatLog', (log, html, data) => RdDUtility.chatListeners(html));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -119,63 +115,21 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html',
|
'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-entite-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html',
|
||||||
// sous-parties de feuilles de personnages
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-competence-partial.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-buttons.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-categorie-competences-partial.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-etat.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-effects-partial.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-oeuvre-partial.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-liste-blessures-partial.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html',
|
// Conteneur/item in Actor sheet
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-item.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html',
|
"systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-monnaie.html",
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-liens-animaux.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-liens-suivants.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-liens-vehicules.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-editor-notes-mj.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
|
//Items
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.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-competencecreature-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-arme-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-arme-sheet.html',
|
||||||
@ -188,7 +142,7 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/item-livre-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-livre-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-tache-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-tache-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-potion-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-potion-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-rencontresTMR-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-souffle-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-souffle-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-tarot-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-tarot-sheet.html',
|
||||||
@ -199,26 +153,32 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/item-nourritureboisson-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-nourritureboisson-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-possession-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-possession-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-extraitpoetique-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/competence-carac-defaut.html',
|
||||||
// partial enums
|
'systems/foundryvtt-reve-de-dragon/templates/competence-base.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-competence.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-competence.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-herbesoin-ingredient.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-herbesoin-ingredient.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
|
'systems/foundryvtt-reve-de-dragon/templates/sort-draconic.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
|
'systems/foundryvtt-reve-de-dragon/templates/sort-tmr.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
|
'systems/foundryvtt-reve-de-dragon/templates/niveau-ethylisme.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/casetmr-specific-list.html',
|
||||||
|
// Dialogs
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
|
||||||
|
'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-roll-meditation.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html',
|
||||||
// Partials
|
// Partials
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html',
|
||||||
@ -230,25 +190,12 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html',
|
||||||
// Dialogs
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
|
|
||||||
'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',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html',
|
|
||||||
// Calendrier
|
// Calendrier
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/calendar-template.html',
|
'systems/foundryvtt-reve-de-dragon/templates/calendar-template.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html',
|
'systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/heures-select-option.html',
|
||||||
// HUD
|
// HUD
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
|
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html',
|
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html',
|
||||||
@ -256,7 +203,6 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html',
|
'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-description.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.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-defense.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html',
|
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html',
|
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html',
|
||||||
@ -290,14 +236,11 @@ export class RdDUtility {
|
|||||||
Handlebars.registerHelper('buildContenu', (objet) => { return new Handlebars.SafeString(RdDUtility.buildContenu(objet, 1, true)); });
|
Handlebars.registerHelper('buildContenu', (objet) => { return new Handlebars.SafeString(RdDUtility.buildContenu(objet, 1, true)); });
|
||||||
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
|
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
|
||||||
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
|
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
|
||||||
Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type));
|
Handlebars.registerHelper('typeTmr-name', coord => TMRUtility.typeTmrName(coord));
|
||||||
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
|
|
||||||
Handlebars.registerHelper('signeHeure', (key, heure) => RdDCalendrier.getSigneAs(key, heure));
|
|
||||||
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
|
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
|
||||||
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
|
|
||||||
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
|
Handlebars.registerHelper('filtreTriCompetences', competences => competences.filter(it => it.visible)
|
||||||
Handlebars.registerHelper('filtreTriCompetences', competences => competences.filter(it => it.system.isVisible)
|
.sort((a, b) => {
|
||||||
.sort((a, b) => {
|
|
||||||
if (a.name.startsWith("Survie") && b.name.startsWith("Survie")) {
|
if (a.name.startsWith("Survie") && b.name.startsWith("Survie")) {
|
||||||
if (a.name.includes("Cité")) return -1;
|
if (a.name.includes("Cité")) return -1;
|
||||||
if (b.name.includes("Cité")) return 1;
|
if (b.name.includes("Cité")) return 1;
|
||||||
@ -305,7 +248,7 @@ export class RdDUtility {
|
|||||||
if (b.name.includes("Extérieur")) return 1;
|
if (b.name.includes("Extérieur")) return 1;
|
||||||
return a.name.localeCompare(b.name);
|
return a.name.localeCompare(b.name);
|
||||||
}
|
}
|
||||||
if (a.system.categorie.startsWith("melee") && b.system.categorie.startsWith("melee")) {
|
if (a.data.categorie.startsWith("melee") && b.data.categorie.startsWith("melee")) {
|
||||||
if (a.name.includes("Corps")) return -1;
|
if (a.name.includes("Corps")) return -1;
|
||||||
if (b.name.includes("Corps")) return 1;
|
if (b.name.includes("Corps")) return 1;
|
||||||
if (a.name.includes("Dague")) return -1;
|
if (a.name.includes("Dague")) return -1;
|
||||||
@ -327,12 +270,8 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
return a.name.localeCompare(b.name);
|
return a.name.localeCompare(b.name);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
Handlebars.registerHelper('linkCompendium', (compendium, id, name) => `@Compendium[${compendium}.${id}]{${name}}`);
|
|
||||||
Handlebars.registerHelper('uniteQuantite', (type) => RdDItem.getUniteQuantite(type));
|
|
||||||
Handlebars.registerHelper('isEquipementFieldEditable', (type, field) => RdDItem.isEquipementFieldEditable(type, field));
|
|
||||||
Handlebars.registerHelper('getFrequenceRarete', (rarete, field) => Environnement.getFrequenceRarete(rarete, field));
|
|
||||||
Handlebars.registerHelper('either', (a, b) => a ?? b);
|
|
||||||
return loadTemplates(templatePaths);
|
return loadTemplates(templatePaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,7 +283,7 @@ export class RdDUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async selectObjetType(actorSheet) {
|
static async selectObjetType(actorSheet) {
|
||||||
let typeObjets = RdDItem.getTypesObjetsEquipement();
|
let typeObjets = RdDItem.getTypeObjetsEquipement();
|
||||||
let options = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
|
let options = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
|
||||||
for (let typeName of typeObjets) {
|
for (let typeName of typeObjets) {
|
||||||
options += `<option value="${typeName}">${typeName}</option>`
|
options += `<option value="${typeName}">${typeName}</option>`
|
||||||
@ -426,51 +365,48 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static filterItemsPerTypeForSheet(formData, itemTypes) {
|
static filterItemsPerTypeForSheet(formData) {
|
||||||
|
|
||||||
RdDUtility.filterEquipementParType(formData, itemTypes);
|
RdDUtility.filterEquipementParType(formData);
|
||||||
|
|
||||||
formData.sorts = this.arrayOrEmpty(itemTypes['sort']);
|
formData.sorts = this.arrayOrEmpty(formData.itemsByType['sort']);
|
||||||
formData.rencontres = this.arrayOrEmpty(itemTypes['rencontre']);
|
formData.signesdraconiques = this.arrayOrEmpty(formData.itemsByType['signedraconique']);
|
||||||
formData.casestmr = this.arrayOrEmpty(itemTypes['casetmr']);
|
formData.queues = this.arrayOrEmpty(formData.itemsByType['queue']);
|
||||||
formData.signesdraconiques = this.arrayOrEmpty(itemTypes['signedraconique']);
|
formData.souffles = this.arrayOrEmpty(formData.itemsByType['souffle']);
|
||||||
formData.queues = this.arrayOrEmpty(itemTypes['queue']);
|
formData.ombres = this.arrayOrEmpty(formData.itemsByType['ombre']);
|
||||||
formData.souffles = this.arrayOrEmpty(itemTypes['souffle']);
|
formData.tetes = this.arrayOrEmpty(formData.itemsByType['tete']);
|
||||||
formData.ombres = this.arrayOrEmpty(itemTypes['ombre']);
|
formData.taches = this.arrayOrEmpty(formData.itemsByType['tache']);
|
||||||
formData.tetes = this.arrayOrEmpty(itemTypes['tete']);
|
formData.meditations = this.arrayOrEmpty(formData.itemsByType['meditation']);
|
||||||
formData.taches = this.arrayOrEmpty(itemTypes['tache']);
|
formData.chants = this.arrayOrEmpty(formData.itemsByType['chant']);
|
||||||
formData.meditations = this.arrayOrEmpty(itemTypes['meditation']);
|
formData.danses = this.arrayOrEmpty(formData.itemsByType['danse']);
|
||||||
formData.chants = this.arrayOrEmpty(itemTypes['chant']);
|
formData.musiques = this.arrayOrEmpty(formData.itemsByType['musique']);
|
||||||
formData.danses = this.arrayOrEmpty(itemTypes['danse']);
|
formData.oeuvres = this.arrayOrEmpty(formData.itemsByType['oeuvre']);
|
||||||
formData.musiques = this.arrayOrEmpty(itemTypes['musique']);
|
formData.jeux = this.arrayOrEmpty(formData.itemsByType['jeu']);
|
||||||
formData.oeuvres = this.arrayOrEmpty(itemTypes['oeuvre']);
|
|
||||||
formData.jeux = this.arrayOrEmpty(itemTypes['jeu']);
|
|
||||||
|
|
||||||
formData.recettescuisine = this.arrayOrEmpty(itemTypes['recettecuisine']);
|
formData.recettescuisine = this.arrayOrEmpty(formData.itemsByType['recettecuisine']);
|
||||||
formData.recettesAlchimiques = this.arrayOrEmpty(itemTypes['recettealchimique']);
|
formData.recettesAlchimiques = this.arrayOrEmpty(formData.itemsByType['recettealchimique']);
|
||||||
formData.maladies = this.arrayOrEmpty(itemTypes['maladie']);
|
formData.maladies = this.arrayOrEmpty(formData.itemsByType['maladie']);
|
||||||
formData.poisons = this.arrayOrEmpty(itemTypes['poison']);
|
formData.poisons = this.arrayOrEmpty(formData.itemsByType['poison']);
|
||||||
formData.possessions = this.arrayOrEmpty(itemTypes['possession']);
|
formData.possessions = this.arrayOrEmpty(formData.itemsByType['possession']);
|
||||||
formData.maladiesPoisons = formData.maladies.concat(formData.poisons);
|
formData.maladiesPoisons = formData.maladies.concat(formData.poisons);
|
||||||
formData.competences = (itemTypes['competence'] ?? []).concat(itemTypes['competencecreature'] ?? []);
|
formData.competences = (formData.itemsByType.competence ?? []).concat(formData.itemsByType.competencecreature ?? []);
|
||||||
formData.sortsReserve = this.arrayOrEmpty(itemTypes['sortreserve']);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static filterEquipementParType(formData, itemTypes) {
|
static filterEquipementParType(formData) {
|
||||||
formData.conteneurs = this.arrayOrEmpty(itemTypes['conteneur']);
|
formData.conteneurs = this.arrayOrEmpty(formData.itemsByType['conteneur']);
|
||||||
|
|
||||||
formData.materiel = this.arrayOrEmpty(itemTypes['objet']);
|
formData.materiel = this.arrayOrEmpty(formData.itemsByType['objet']);
|
||||||
formData.armes = this.arrayOrEmpty(itemTypes['arme']);
|
formData.armes = this.arrayOrEmpty(formData.itemsByType['arme']);
|
||||||
formData.armures = this.arrayOrEmpty(itemTypes['armure']);
|
formData.armures = this.arrayOrEmpty(formData.itemsByType['armure']);
|
||||||
formData.munitions = this.arrayOrEmpty(itemTypes['munition']);
|
formData.munitions = this.arrayOrEmpty(formData.itemsByType['munition']);
|
||||||
formData.livres = this.arrayOrEmpty(itemTypes['livre']);
|
formData.livres = this.arrayOrEmpty(formData.itemsByType['livre']);
|
||||||
formData.potions = this.arrayOrEmpty(itemTypes['potion']);
|
formData.potions = this.arrayOrEmpty(formData.itemsByType['potion']);
|
||||||
formData.ingredients = this.arrayOrEmpty(itemTypes['ingredient']);
|
formData.ingredients = this.arrayOrEmpty(formData.itemsByType['ingredient']);
|
||||||
formData.herbes = this.arrayOrEmpty(itemTypes['herbe']);
|
formData.herbes = this.arrayOrEmpty(formData.itemsByType['herbe']);
|
||||||
formData.monnaie = this.arrayOrEmpty(itemTypes['monnaie']);
|
formData.monnaie = this.arrayOrEmpty(formData.itemsByType['monnaie']);
|
||||||
formData.monnaie.sort(Monnaie.triValeurEntiere());
|
formData.monnaie.sort(Monnaie.triValeurDenier());
|
||||||
formData.nourritureboissons = this.arrayOrEmpty(itemTypes['nourritureboisson']);
|
formData.nourritureboissons = this.arrayOrEmpty(formData.itemsByType['nourritureboisson']);
|
||||||
formData.gemmes = this.arrayOrEmpty(itemTypes['gemme']);
|
formData.gemmes = this.arrayOrEmpty(formData.itemsByType['gemme']);
|
||||||
|
|
||||||
formData.objets = formData.conteneurs
|
formData.objets = formData.conteneurs
|
||||||
.concat(formData.materiel)
|
.concat(formData.materiel)
|
||||||
@ -492,7 +428,7 @@ export class RdDUtility {
|
|||||||
// Attribution des objets aux conteneurs
|
// Attribution des objets aux conteneurs
|
||||||
for (let conteneur of conteneurs) {
|
for (let conteneur of conteneurs) {
|
||||||
conteneur.subItems = [];
|
conteneur.subItems = [];
|
||||||
for (let id of conteneur.system.contenu ?? []) {
|
for (let id of conteneur.data.contenu ?? []) {
|
||||||
let objet = objets.find(objet => (id == objet._id));
|
let objet = objets.find(objet => (id == objet._id));
|
||||||
if (objet) {
|
if (objet) {
|
||||||
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template
|
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template
|
||||||
@ -502,26 +438,27 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let conteneur of conteneurs) {
|
for (let conteneur of conteneurs) {
|
||||||
conteneur.system.encTotal = RdDUtility.calculEncContenu(conteneur, objets);
|
conteneur.data.encTotal = RdDUtility.calculEncContenu(conteneur, objets);
|
||||||
}
|
}
|
||||||
return objetVersConteneur;
|
return objetVersConteneur;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static calculEncContenu(conteneur, objets) {
|
static calculEncContenu(conteneur, objets) {
|
||||||
const contenus = (conteneur.system.contenu ?? []).filter(id => id != undefined)
|
const itemData = Misc.data(conteneur);
|
||||||
.map(id => objets.find(it => (id == it.id)))
|
const contenuDatas = (itemData.data.contenu ?? []).filter(id => id != undefined)
|
||||||
|
.map(id => Misc.data(objets.find(it => (id == it._id))))
|
||||||
.filter(it => it);
|
.filter(it => it);
|
||||||
let enc = Number(conteneur.system.encombrement ?? 0) * Number(conteneur.system.quantite ?? 1);
|
let enc = Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
|
||||||
for (let contenu of contenus) {
|
for (let itemData of contenuDatas) {
|
||||||
if (contenu.type == 'conteneur') {
|
if (itemData.type == 'conteneur') {
|
||||||
enc += RdDUtility.calculEncContenu(contenu, objets);
|
enc += RdDUtility.calculEncContenu(itemData, objets);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
enc += Number(contenu.system.encombrement ?? 0) * Number(contenu.system.quantite ?? 1)
|
enc += Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return enc
|
return enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -539,8 +476,8 @@ export class RdDUtility {
|
|||||||
objet.niveau = profondeur;
|
objet.niveau = profondeur;
|
||||||
const isConteneur = objet.type == 'conteneur';
|
const isConteneur = objet.type == 'conteneur';
|
||||||
const isOuvert = isConteneur && this.getAfficheContenu(objet._id);
|
const isOuvert = isConteneur && this.getAfficheContenu(objet._id);
|
||||||
const isVide = isConteneur && objet.system.contenu.length == 0;
|
const isVide = isConteneur && Misc.templateData(objet).contenu.length == 0;
|
||||||
const conteneur = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html']({
|
const conteneur = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-item.html']({
|
||||||
item: objet,
|
item: objet,
|
||||||
vide: isVide,
|
vide: isVide,
|
||||||
ouvert: isOuvert
|
ouvert: isOuvert
|
||||||
@ -554,7 +491,8 @@ export class RdDUtility {
|
|||||||
if (!profondeur) profondeur = 1;
|
if (!profondeur) profondeur = 1;
|
||||||
objet.niveau = profondeur;
|
objet.niveau = profondeur;
|
||||||
const display = afficherContenu ? 'item-display-show' : 'item-display-hide';
|
const display = afficherContenu ? 'item-display-show' : 'item-display-hide';
|
||||||
let strContenu = `<ul class='item-list alterne-list ${display} list-item-margin${Math.min(profondeur,6)}'>`;
|
//console.log("ITEM DISPLAYED", objet );
|
||||||
|
let strContenu = `<ul class='item-list alterne-list ${display} list-item-margin${profondeur}'>`;
|
||||||
for (let subItem of objet.subItems) {
|
for (let subItem of objet.subItems) {
|
||||||
strContenu += this.buildConteneur(subItem, profondeur + 1);
|
strContenu += this.buildConteneur(subItem, profondeur + 1);
|
||||||
}
|
}
|
||||||
@ -673,68 +611,7 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) {
|
static selectEncaissement(degats, mortalite) {
|
||||||
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];
|
const table = definitionsEncaissement[mortalite] === undefined ? definitionsEncaissement["mortel"] : definitionsEncaissement[mortalite];
|
||||||
for (let encaissement of table) {
|
for (let encaissement of table) {
|
||||||
if ((encaissement.minimum === undefined || encaissement.minimum <= degats)
|
if ((encaissement.minimum === undefined || encaissement.minimum <= degats)
|
||||||
@ -745,13 +622,6 @@ export class RdDUtility {
|
|||||||
return duplicate(table[0]);
|
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) {
|
static currentFatigueMalus(value, max) {
|
||||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||||
@ -772,9 +642,21 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async responseNombreAstral(callData) {
|
static async loadCompendiumData(compendium) {
|
||||||
let actor = game.actors.get(callData.id);
|
const pack = game.packs.get(compendium);
|
||||||
actor.ajouteNombreAstral(callData);
|
return await pack?.getDocuments() ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -809,13 +691,12 @@ export class RdDUtility {
|
|||||||
actor.tmrApp.positionnerDemiReve(coord);
|
actor.tmrApp.positionnerDemiReve(coord);
|
||||||
});
|
});
|
||||||
// Gestion spécifique des sorts en réserve multiples (ie têtes)
|
// Gestion spécifique des sorts en réserve multiples (ie têtes)
|
||||||
html.on("click", '.declencher-sort-reserve', event => {
|
html.on("click", '#sort-reserve', event => {
|
||||||
let coord = event.currentTarget.attributes['data-tmr-coord'].value;
|
let coord = event.currentTarget.attributes['data-tmr-coord'].value;
|
||||||
let sortId = event.currentTarget.attributes['data-sort-id'].value;
|
let sortId = event.currentTarget.attributes['data-sort-id'].value;
|
||||||
let actorId = event.currentTarget.attributes['data-actor-id'].value;
|
let actorId = event.currentTarget.attributes['data-actor-id'].value;
|
||||||
let actor = game.actors.get(actorId);
|
let actor = game.actors.get(actorId);
|
||||||
actor.tmrApp.lancerSortEnReserve(coord, sortId);
|
actor.tmrApp.lancerSortEnReserve(coord, sortId);
|
||||||
// TODO: supprimer le message?
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// gestion bouton tchat Possession
|
// gestion bouton tchat Possession
|
||||||
@ -827,20 +708,22 @@ export class RdDUtility {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// gestion bouton tchat Acheter
|
// gestion bouton tchat Acheter
|
||||||
html.on("click", '.button-acheter', event => {
|
html.on("click", '.button-acheter', event => DialogItemAchat.onButtonAcheter(event));
|
||||||
const venteData = DialogItemAchat.venteData(event.currentTarget);
|
|
||||||
if (venteData) {
|
|
||||||
DialogItemAchat.onAcheter(venteData);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
html.on("click", '.button-creer-acteur', event => RdDNameGen.onCreerActeur(event));
|
html.on("click", '.button-creer-acteur', event => RdDNameGen.onCreerActeur(event));
|
||||||
|
|
||||||
// Gestion du bouton payer
|
// Gestion du bouton payer
|
||||||
html.on("click", '.payer-button', event => {
|
html.on("click", '.payer-button', event => {
|
||||||
let sommeAPayer = Number(event.currentTarget.attributes['data-somme-a-payer']?.value ?? 0);
|
let sumdenier = event.currentTarget.attributes['data-somme-denier']?.value ?? 0;
|
||||||
|
let quantite = event.currentTarget.attributes['data-quantite']?.value ?? 1;
|
||||||
|
let fromActorId = event.currentTarget.attributes['data-actor-id']?.value;
|
||||||
|
let jsondata = event.currentTarget.attributes['data-jsondata']
|
||||||
|
let objData
|
||||||
|
if (jsondata) {
|
||||||
|
objData = JSON.parse(jsondata.value)
|
||||||
|
}
|
||||||
let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:");
|
let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:");
|
||||||
if (actor) {
|
if (actor) {
|
||||||
actor.payerSols(sommeAPayer);
|
actor.depenserDeniers(sumdenier, objData, quantite, fromActorId);
|
||||||
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget));
|
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -871,7 +754,7 @@ export class RdDUtility {
|
|||||||
static getSelectedActor(msgPlayer = undefined) {
|
static getSelectedActor(msgPlayer = undefined) {
|
||||||
if (canvas.tokens.controlled.length == 1) {
|
if (canvas.tokens.controlled.length == 1) {
|
||||||
let token = canvas.tokens.controlled[0];
|
let token = canvas.tokens.controlled[0];
|
||||||
if (token.actor) {
|
if (token.actor && token.data.actorLink) {
|
||||||
return token.actor;
|
return token.actor;
|
||||||
}
|
}
|
||||||
if (msgPlayer != undefined) {
|
if (msgPlayer != undefined) {
|
||||||
@ -891,12 +774,12 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static createMonnaie(name, cout, img = "", enc = 0.01) {
|
static createMonnaie(name, valeur_deniers, img = "", enc = 0.01) {
|
||||||
let piece = {
|
let piece = {
|
||||||
name: name, type: 'monnaie', img: img, _id: randomID(16),
|
name: name, type: 'monnaie', img: img, _id: randomID(16),
|
||||||
dasystemta: {
|
data: {
|
||||||
quantite: 0,
|
quantite: 0,
|
||||||
cout: cout,
|
valeur_deniers: valeur_deniers,
|
||||||
encombrement: enc,
|
encombrement: enc,
|
||||||
description: ""
|
description: ""
|
||||||
}
|
}
|
||||||
@ -908,20 +791,20 @@ export class RdDUtility {
|
|||||||
static afficherDemandePayer(som1, som2) {
|
static afficherDemandePayer(som1, som2) {
|
||||||
som1 = (som1) ? som1.toLowerCase() : "0d";
|
som1 = (som1) ? som1.toLowerCase() : "0d";
|
||||||
som2 = (som2) ? som2.toLowerCase() : "0d";
|
som2 = (som2) ? som2.toLowerCase() : "0d";
|
||||||
let regExp1 = /(\d+)(\w+)/g;
|
let regExp = /(\d+)(\w+)/g;
|
||||||
let p1 = regExp1.exec(som1);
|
let p1 = regExp.exec(som1);
|
||||||
let regExp2 = /(\d+)(\w+)/g;
|
regExp = /(\d+)(\w+)/g;
|
||||||
let p2 = regExp2.exec(som2);
|
let p2 = regExp.exec(som2);
|
||||||
let deniers = 0;
|
let sumd = 0;
|
||||||
let sols = 0;
|
let sums = 0;
|
||||||
if (p1[2] == 'd') deniers += Number(p1[1]);
|
if (p1[2] == 'd') sumd += Number(p1[1]);
|
||||||
if (p1[2] == 's') sols += Number(p1[1]);
|
if (p1[2] == 's') sums += Number(p1[1]);
|
||||||
if (p2[2] == 'd') deniers += Number(p2[1]);
|
if (p2[2] == 'd') sumd += Number(p2[1]);
|
||||||
if (p2[2] == 's') sols += Number(p2[1]);
|
if (p2[2] == 's') sums += Number(p2[1]);
|
||||||
|
|
||||||
let sommeAPayer = sols + deniers/100;
|
let sumtotald = sumd + (sums * 100);
|
||||||
let msgPayer = `La somme de ${sols} Sols et ${deniers} Deniers est à payer<br>
|
let msgPayer = "La somme de " + sums + " Sols et " + sumd + " Deniers est à payer, cliquer sur le lien ci-dessous si besoin.<br>";
|
||||||
<a class='payer-button chat-card-button' data-somme-a-payer='${sommeAPayer}'>Payer</a>`
|
msgPayer += "<a class='payer-button chat-card-button' data-somme-denier='" + sumtotald + "'>Payer</a>"
|
||||||
ChatMessage.create({ content: msgPayer });
|
ChatMessage.create({ content: msgPayer });
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -946,57 +829,80 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete) {
|
static confirmerSuppressionSubacteur(actorSheet, li) {
|
||||||
RdDConfirm.confirmer({
|
let actorId = li.data("actor-id");
|
||||||
settingConfirmer: "confirmation-supprimer-lien-acteur",
|
let actor = game.actors.get(actorId);
|
||||||
content: `<p>Etes vous certain de vouloir supprimer le lien vers ${subActor.name} ?</p>`,
|
let msgTxt = "<p>Etes vous certain de vouloir supprimer le lien vers ce véhicule/monture/suivant : " + actor.data.name + " ?</p>";
|
||||||
title: 'Confirmer la suppression',
|
let d = new Dialog({
|
||||||
buttonLabel: 'Supprimer le lien',
|
title: "Confirmer la suppression du lien",
|
||||||
onAction: () => {
|
content: msgTxt,
|
||||||
console.log('Delete : ', subActor.id);
|
buttons: {
|
||||||
sheet.actor.removeSubacteur(subActor.id);
|
delete: {
|
||||||
RdDUtility.slideOnDelete(sheet, htmlToDelete);
|
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 async confirmerSuppressionItem(sheet, item, htmlToDelete) {
|
static async confirmerSuppression(actorSheet, li) {
|
||||||
const itemId = item.id;
|
let itemId = li.data("item-id");
|
||||||
const confirmationSuppression = {
|
let objet = actorSheet.actor.getObjet(itemId);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
RdDConfirm.confirmer(confirmationSuppression)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static slideOnDelete(sheet, htmlToDelete) {
|
if (objet.type == 'monnaie' && Monnaie.isSystemMonnaie(objet)) {
|
||||||
return htmlToDelete.slideUp(200, () => sheet.render(false));
|
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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msgTxt += "</p>";
|
||||||
|
let d = new Dialog({
|
||||||
|
title: "Confirmer la suppression",
|
||||||
|
content: msgTxt,
|
||||||
|
buttons: buttons,
|
||||||
|
default: "cancel"
|
||||||
|
});
|
||||||
|
d.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
91
module/regles-optionelles.js
Normal file
91
module/regles-optionelles.js
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
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 },
|
||||||
|
];
|
||||||
|
|
||||||
|
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.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
|
||||||
|
name: "Choisir les règles optionelles",
|
||||||
|
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
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static _getIdRegle(name) {
|
||||||
|
return `rdd-option-${name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get defaultOptions() {
|
||||||
|
const options = super.defaultOptions;
|
||||||
|
mergeObject(options, {
|
||||||
|
id: "optional-settings",
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/regles-optionelles.html",
|
||||||
|
height: 600,
|
||||||
|
width: 350,
|
||||||
|
minimizable: false,
|
||||||
|
closeOnSubmit: true,
|
||||||
|
title: "Règles optionnelles"
|
||||||
|
});
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
let formData = super.getData();
|
||||||
|
const regles = listeReglesOptionelles.map(it => {
|
||||||
|
it = duplicate(it);
|
||||||
|
it.id = ReglesOptionelles._getIdRegle(it.name);
|
||||||
|
it.active = ReglesOptionelles.isUsing(it.name);
|
||||||
|
return it;
|
||||||
|
});
|
||||||
|
formData.regles = regles;
|
||||||
|
formData.groups = Misc.classify(regles, it => it.group);
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isUsing(name) {
|
||||||
|
return game.settings.get(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
html.find(".select-option").click((event) => {
|
||||||
|
if (event.currentTarget.attributes.name) {
|
||||||
|
let id = event.currentTarget.attributes.name.value;
|
||||||
|
let isChecked = event.currentTarget.checked;
|
||||||
|
game.settings.set(SYSTEM_RDD, id, isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async _updateObject(event, formData) {
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ import { Misc } from "./misc.js";
|
|||||||
import { RdDBonus } from "./rdd-bonus.js";
|
import { RdDBonus } from "./rdd-bonus.js";
|
||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tous les ajustements pouvant s'appliquer.
|
* tous les ajustements pouvant s'appliquer.
|
||||||
@ -19,9 +19,9 @@ import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
|||||||
*/
|
*/
|
||||||
export const referenceAjustements = {
|
export const referenceAjustements = {
|
||||||
competence: {
|
competence: {
|
||||||
isUsed: (rollData, actor) => rollData.competence,
|
isUsed: (rollData, actor) => Misc.data(rollData.competence),
|
||||||
getLabel: (rollData, actor) => rollData.competence?.name,
|
getLabel: (rollData, actor) => Misc.data(rollData.competence)?.name,
|
||||||
getValue: (rollData, actor) => rollData.competence?.system?.niveau,
|
getValue: (rollData, actor) => Misc.data(rollData.competence)?.data?.niveau,
|
||||||
},
|
},
|
||||||
meditation: {
|
meditation: {
|
||||||
isUsed: (rollData, actor) => rollData.meditation,
|
isUsed: (rollData, actor) => rollData.meditation,
|
||||||
@ -33,7 +33,7 @@ export const referenceAjustements = {
|
|||||||
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ? 'Imposée' : 'Libre',
|
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ? 'Imposée' : 'Libre',
|
||||||
getValue: (rollData, actor) => rollData.selectedSort
|
getValue: (rollData, actor) => rollData.selectedSort
|
||||||
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
|
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
|
||||||
: rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0
|
: rollData.diffLibre ?? Misc.data(rollData.competence)?.data.default_diffLibre ?? 0
|
||||||
},
|
},
|
||||||
diffConditions: {
|
diffConditions: {
|
||||||
isUsed: (rollData, actor) => rollData.diffConditions != undefined,
|
isUsed: (rollData, actor) => rollData.diffConditions != undefined,
|
||||||
@ -62,20 +62,20 @@ export const referenceAjustements = {
|
|||||||
getValue: (rollData, actor) => actor.getMalusArmure()
|
getValue: (rollData, actor) => actor.getMalusArmure()
|
||||||
},
|
},
|
||||||
encTotal: {
|
encTotal: {
|
||||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
isVisible: (rollData, actor) => RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
||||||
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) && rollData.use.encTotal,
|
isUsed: (rollData, actor) => rollData.useMalusEncTotal,
|
||||||
getLabel: (rollData, actor) => 'Encombrement total',
|
getLabel: (rollData, actor) => 'Encombrement total',
|
||||||
getValue: (rollData, actor) => -actor.getEncTotal()
|
getValue: (rollData, actor) => -actor.getEncTotal()
|
||||||
},
|
},
|
||||||
surenc: {
|
surenc: {
|
||||||
isVisible: (rollData, actor) => actor.isSurenc(),
|
isVisible: (rollData, actor) => rollData.useMalusSurenc,
|
||||||
isUsed: (rollData, actor) => rollData.use?.surenc,
|
isUsed: (rollData, actor) => rollData.useMalusSurenc,
|
||||||
getLabel: (rollData, actor) => 'Sur-encombrement',
|
getLabel: (rollData, actor) => 'Sur-encombrement',
|
||||||
getValue: (rollData, actor) => actor.computeMalusSurEncombrement()
|
getValue: (rollData, actor) => actor.computeMalusSurEncombrement()
|
||||||
},
|
},
|
||||||
moral: {
|
moral: {
|
||||||
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac) && rollData.use?.moral,
|
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac) && rollData.useMoral,
|
||||||
isUsed: (rollData, actor) => rollData.use?.moral,
|
isUsed: (rollData, actor) => rollData.useMoral,
|
||||||
getLabel: (rollData, actor) => 'Appel au moral',
|
getLabel: (rollData, actor) => 'Appel au moral',
|
||||||
getValue: (rollData, actor) => 1
|
getValue: (rollData, actor) => 1
|
||||||
},
|
},
|
||||||
@ -95,10 +95,10 @@ export const referenceAjustements = {
|
|||||||
getDescr: (rollData, actor) => rollData.diviseurSignificative > 1 ? `Facteur significative <span class="rdd-diviseur">×${Misc.getFractionHtml(rollData.diviseurSignificative)}</span>` : ''
|
getDescr: (rollData, actor) => rollData.diviseurSignificative > 1 ? `Facteur significative <span class="rdd-diviseur">×${Misc.getFractionHtml(rollData.diviseurSignificative)}</span>` : ''
|
||||||
},
|
},
|
||||||
isEcaille: {
|
isEcaille: {
|
||||||
isVisible: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
|
isVisible: (rollData, actor) => Misc.data(rollData.arme)?.data.magique && Number(Misc.data(rollData.arme)?.data.ecaille_efficacite) > 0,
|
||||||
isUsed: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
|
isUsed: (rollData, actor) => Misc.data(rollData.arme)?.data.magique && Number(Misc.data(rollData.arme)?.data.ecaille_efficacite) > 0,
|
||||||
getLabel: (rollData, actor) => "Ecaille d'Efficacité: ",
|
getLabel: (rollData, actor) => "Ecaille d'Efficacité: ",
|
||||||
getValue: (rollData, actor) => Math.max(Number(rollData.arme?.system.ecaille_efficacite), 0),
|
getValue: (rollData, actor) => Math.max(Number(Misc.data(rollData.arme)?.data.ecaille_efficacite), 0),
|
||||||
},
|
},
|
||||||
finesse: {
|
finesse: {
|
||||||
isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData),
|
isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData),
|
||||||
@ -120,7 +120,7 @@ export const referenceAjustements = {
|
|||||||
isVisible: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
|
isVisible: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
|
||||||
isUsed: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
|
isUsed: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
|
||||||
getLabel: (rollData, actor) => rollData.rencontre?.name,
|
getLabel: (rollData, actor) => rollData.rencontre?.name,
|
||||||
getValue: (rollData, actor) => - (rollData.rencontre?.system.force ?? 0)
|
getValue: (rollData, actor) => - (rollData.rencontre?.force ?? 0)
|
||||||
},
|
},
|
||||||
ethylismeAlcool: {
|
ethylismeAlcool: {
|
||||||
isVisible: (rollData, actor) => rollData.nbDoses != undefined,
|
isVisible: (rollData, actor) => rollData.nbDoses != undefined,
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
import { SYSTEM_RDD } from "../constants.js";
|
|
||||||
import { Misc } from "../misc.js";
|
|
||||||
|
|
||||||
const listeReglesOptionelles = [
|
|
||||||
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
|
|
||||||
{ 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: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},
|
|
||||||
{ 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: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean });
|
|
||||||
}
|
|
||||||
|
|
||||||
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
|
|
||||||
name: "Choisir les règles optionelles",
|
|
||||||
label: "Règles optionelles",
|
|
||||||
hint: "Ouvre la fenêtre de sélection des règles optionelles",
|
|
||||||
icon: "fas fa-bars",
|
|
||||||
type: ReglesOptionelles
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
static _getIdRegle(name) {
|
|
||||||
return `rdd-option-${name}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
const options = super.defaultOptions;
|
|
||||||
mergeObject(options, {
|
|
||||||
id: "regles-optionelles",
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionelles.html",
|
|
||||||
height: 600,
|
|
||||||
width: 450,
|
|
||||||
minimizable: false,
|
|
||||||
closeOnSubmit: true,
|
|
||||||
title: "Règles optionnelles"
|
|
||||||
});
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
getData() {
|
|
||||||
let formData = super.getData();
|
|
||||||
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.isSet(it.name);
|
|
||||||
return it;
|
|
||||||
});
|
|
||||||
formData.regles = regles;
|
|
||||||
formData.groups = Misc.classify(regles, it => it.group);
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
let id = event.currentTarget.attributes.name.value;
|
|
||||||
let isChecked = event.currentTarget.checked;
|
|
||||||
game.settings.set(SYSTEM_RDD, id, isChecked);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async _updateObject(event, formData) {
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,141 +0,0 @@
|
|||||||
import { SYSTEM_RDD } from "../constants.js";
|
|
||||||
|
|
||||||
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 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 extends FormApplication {
|
|
||||||
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",
|
|
||||||
scope: "world",
|
|
||||||
config: false,
|
|
||||||
default: defaultStatusEffectIds.join(),
|
|
||||||
type: String
|
|
||||||
});
|
|
||||||
|
|
||||||
game.settings.registerMenu(SYSTEM_RDD, "select-status-effect", {
|
|
||||||
name: "Choisir les effets disponibles",
|
|
||||||
label: "Choix des effets",
|
|
||||||
hint: "Ouvre la fenêtre de sélection des effets/status appliqués aux acteurs",
|
|
||||||
icon: "fas fa-bars",
|
|
||||||
type: StatusEffects,
|
|
||||||
restricted: true
|
|
||||||
});
|
|
||||||
|
|
||||||
CONFIG.RDD.allEffects = rddStatusEffects.concat(CONFIG.statusEffects.filter(it => !rddStatusIds.includes(it.id)));
|
|
||||||
|
|
||||||
StatusEffects._setUseStatusEffects(StatusEffects._getUseStatusEffects());
|
|
||||||
console.log('statusEffects', CONFIG.statusEffects);
|
|
||||||
}
|
|
||||||
|
|
||||||
static valeurSurprise(effect, isCombat) {
|
|
||||||
// const id = StatusEffects.statusId(effect);
|
|
||||||
if (statusSurpriseTotale.includes(effect.flags?.core?.statusId)) {
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
return statusDemiSurprise.includes(effect.flags?.core?.statusId) || (isCombat && effect.flags?.core?.statusId == STATUSES.StatusDemiReve) ? 1 : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _getUseStatusEffects() {
|
|
||||||
return game.settings.get(SYSTEM_RDD, "use-status-effects")?.split(',') ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
static _setUseStatusEffects(statusIds) {
|
|
||||||
if (game.user.isGM) {
|
|
||||||
game.settings.set(SYSTEM_RDD, "use-status-effects", statusIds.join());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let effect of CONFIG.RDD.allEffects) {
|
|
||||||
effect.active = effect.rdd || statusIds.includes(effect.flags?.core?.statusId);
|
|
||||||
}
|
|
||||||
CONFIG.statusEffects = CONFIG.RDD.allEffects.filter(it => it.active);
|
|
||||||
}
|
|
||||||
|
|
||||||
static status(statusId) {
|
|
||||||
return rddStatusEffects.find(it => it.flags?.core?.statusId == statusId);
|
|
||||||
}
|
|
||||||
|
|
||||||
static demiReve() {
|
|
||||||
return demiReveStatusEffect;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
const options = super.defaultOptions;
|
|
||||||
mergeObject(options, {
|
|
||||||
id: "status-effects",
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/settings/status-effects.html",
|
|
||||||
height: 800,
|
|
||||||
width: 350,
|
|
||||||
minimizable: false,
|
|
||||||
closeOnSubmit: true,
|
|
||||||
title: "Choix des status/effets"
|
|
||||||
});
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
getData() {
|
|
||||||
const used = StatusEffects._getUseStatusEffects();
|
|
||||||
let formData = super.getData();
|
|
||||||
formData.effects = duplicate(CONFIG.RDD.allEffects);
|
|
||||||
formData.effects.forEach(it => it.active = used.includes(it.id))
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
html.find(".select-effect").click((event) => {
|
|
||||||
let id = event.currentTarget.attributes.name?.value;
|
|
||||||
if (id) {
|
|
||||||
let selected = StatusEffects._getUseStatusEffects();
|
|
||||||
let isChecked = event.currentTarget.checked;
|
|
||||||
if (isChecked) {
|
|
||||||
selected.push(id);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
selected = selected.filter(it => it != id)
|
|
||||||
}
|
|
||||||
StatusEffects._setUseStatusEffects(selected);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async _updateObject(event, formData) {
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,287 +0,0 @@
|
|||||||
import { HIDE_DICE, SYSTEM_RDD } from "../constants.js";
|
|
||||||
import { RdDItem } from "../item.js";
|
|
||||||
import { Misc } from "../misc.js";
|
|
||||||
import { RdDDice } from "../rdd-dice.js";
|
|
||||||
|
|
||||||
const COMPENDIUM_SETTING_PREFIX = 'compendium-';
|
|
||||||
|
|
||||||
const CONFIGURABLE_COMPENDIUMS = {
|
|
||||||
'tables-diverses': { label: "Tables aléatoires", type: "RollTable" },
|
|
||||||
'competences': { label: "Compétences", type: "Item" },
|
|
||||||
'extrait-poetique': { label: "Extraits poetiques", type: "Item" },
|
|
||||||
'queues-de-dragon': { label: "Queues de dragon", type: "Item" },
|
|
||||||
'ombres-de-thanatos': { label: "Ombres de Thanatos", type: "Item" },
|
|
||||||
'souffles-de-dragon': { label: "Souffles de Dragon", type: "Item" },
|
|
||||||
'tarot-draconique': { label: "Tarots draconiques", type: "Item" },
|
|
||||||
'rencontres': { label: "Rencontres dans les TMR", type: "Item" },
|
|
||||||
'tetes-de-dragon-pour-haut-revants': { label: "Têtes de dragons (haut-rêvant)", type: "Item" },
|
|
||||||
'tetes-de-dragon-pour-tous-personnages': { label: "Têtes de dragons (tous)", type: "Item" },
|
|
||||||
'faune-flore-mineraux': { label: "Herbes & plantes", type: "Item" },
|
|
||||||
'equipement': { label: "Equipements", type: "Item" },
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ======= Gestion des accès aux compendiums systèmes (ou surchargés) =======
|
|
||||||
*/
|
|
||||||
export class SystemCompendiums extends FormApplication {
|
|
||||||
static init() {
|
|
||||||
Object.keys(CONFIGURABLE_COMPENDIUMS).forEach(compendium => {
|
|
||||||
const definition = CONFIGURABLE_COMPENDIUMS[compendium];
|
|
||||||
mergeObject(definition, {
|
|
||||||
compendium: compendium,
|
|
||||||
default: SystemCompendiums._getDefaultCompendium(compendium),
|
|
||||||
setting: SystemCompendiums._getSettingCompendium(compendium)
|
|
||||||
});
|
|
||||||
|
|
||||||
game.settings.register(SYSTEM_RDD, definition.setting, {
|
|
||||||
name: definition.label,
|
|
||||||
default: definition.default,
|
|
||||||
scope: "world",
|
|
||||||
config: false,
|
|
||||||
type: String
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
game.settings.registerMenu(SYSTEM_RDD, "compendium-settings", {
|
|
||||||
name: "Choisir les compendiums système",
|
|
||||||
label: "Compendiums système",
|
|
||||||
hint: "Ouvre la fenêtre de sélection des compendiums système",
|
|
||||||
icon: "fas fa-bars",
|
|
||||||
type: SystemCompendiums
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
static getPack(compendium) {
|
|
||||||
return game.packs.get(SystemCompendiums.getCompendium(compendium));
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getPackContent(compendium, docType) {
|
|
||||||
const pack = SystemCompendiums.getPack(compendium);
|
|
||||||
if (pack.metadata.type == docType) {
|
|
||||||
return await pack.getDocuments();
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getCompetences(actorType) {
|
|
||||||
switch (actorType ?? 'personnage') {
|
|
||||||
case 'personnage': return await SystemCompendiums.getWorldOrCompendiumItems('competence', 'competences');
|
|
||||||
case 'creature': return await SystemCompendiums.getWorldOrCompendiumItems('competencecreature', 'competences-creatures');
|
|
||||||
case 'entite': return await SystemCompendiums.getWorldOrCompendiumItems('competencecreature', 'competences-entites');
|
|
||||||
case 'vehicule': return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async getWorldOrCompendiumItems(itemType, compendium) {
|
|
||||||
let items = game.items.filter(it => it.type == itemType);
|
|
||||||
if (compendium) {
|
|
||||||
const ids = items.map(it => it.id);
|
|
||||||
const names = items.map(it => it.name.toLowerCase());
|
|
||||||
const compendiumItems = await SystemCompendiums.getItems(compendium);
|
|
||||||
items = items.concat(compendiumItems
|
|
||||||
.filter(it => it.type == itemType)
|
|
||||||
.filter(it => !ids.includes(it.id))
|
|
||||||
.filter(it => !names.includes(it.name.toLowerCase())));
|
|
||||||
}
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getItems(compendium, itemType = undefined) {
|
|
||||||
const items = await SystemCompendiums.getPackContent(compendium, 'Item');
|
|
||||||
return (itemType ? items.filter(it => it.type == itemType) : items);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getContent(compendium, type, filter, itemFrequence, sorting) {
|
|
||||||
let elements = await SystemCompendiums.getPackContent(compendium, type);
|
|
||||||
elements = elements.filter(filter).filter(it => itemFrequence(it) > 0);
|
|
||||||
if (sorting) {
|
|
||||||
elements = elements.sort(sorting);
|
|
||||||
}
|
|
||||||
return elements;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getDefaultItems(compendium) {
|
|
||||||
const pack = game.packs.get(SystemCompendiums._getDefaultCompendium(compendium));
|
|
||||||
if (pack.metadata.type == 'Item') {
|
|
||||||
return await pack.getDocuments();
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
static getCompendium(compendium) {
|
|
||||||
const setting = CONFIGURABLE_COMPENDIUMS[compendium]?.setting;
|
|
||||||
return setting ? game.settings.get(SYSTEM_RDD, setting) : SystemCompendiums._getDefaultCompendium(compendium);
|
|
||||||
}
|
|
||||||
|
|
||||||
static _getSettingCompendium(compendium) {
|
|
||||||
return COMPENDIUM_SETTING_PREFIX + compendium;
|
|
||||||
}
|
|
||||||
|
|
||||||
static _getDefaultCompendium(compendium) {
|
|
||||||
return `${SYSTEM_RDD}.${compendium}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
const options = super.defaultOptions;
|
|
||||||
mergeObject(options, {
|
|
||||||
id: "system-compendiums",
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/settings/system-compendiums.html",
|
|
||||||
height: 'fit-content',
|
|
||||||
width: 600,
|
|
||||||
minimizable: false,
|
|
||||||
closeOnSubmit: true,
|
|
||||||
title: "Compendiums système"
|
|
||||||
});
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
getData() {
|
|
||||||
const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS)
|
|
||||||
.map(it => mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) }));
|
|
||||||
const availableCompendiums = game.packs.map(pack => {
|
|
||||||
return {
|
|
||||||
name: pack.collection,
|
|
||||||
path: pack.collection.replace('.', " / "),
|
|
||||||
type: pack.metadata.type
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return mergeObject(super.getData(), {
|
|
||||||
systemCompendiums: systemCompendiums,
|
|
||||||
availableCompendiums: availableCompendiums
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
html.find("select.system-compendium-setting").change((event) => {
|
|
||||||
const compendium = $(event.currentTarget).data('compendium')
|
|
||||||
const value = $(event.currentTarget).val();
|
|
||||||
const systemCompendium = CONFIGURABLE_COMPENDIUMS[compendium];
|
|
||||||
|
|
||||||
game.settings.set(SYSTEM_RDD, systemCompendium.setting, value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ======= Gestion de jets dans une table correspondant à un compendium =======
|
|
||||||
*/
|
|
||||||
export class CompendiumTable {
|
|
||||||
|
|
||||||
constructor(compendium, type, subTypes, sorting = undefined) {
|
|
||||||
this.compendium = compendium;
|
|
||||||
this.type = type;
|
|
||||||
this.subTypes = subTypes;
|
|
||||||
this.sorting = sorting ?? Misc.ascending(it => it.name);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getContent(itemFrequence = it => it.system.frequence, filter = it => true) {
|
|
||||||
return await SystemCompendiums.getContent(this.compendium,
|
|
||||||
this.type,
|
|
||||||
it => this.subTypes.includes(it.type) && filter(it),
|
|
||||||
itemFrequence,
|
|
||||||
this.sorting);
|
|
||||||
}
|
|
||||||
|
|
||||||
async buildTable(itemFrequence = it => it.system.frequence, filter = it => true) {
|
|
||||||
const elements = await this.getContent(filter, itemFrequence);
|
|
||||||
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRandom(itemFrequence = it => it.system.frequence, filter = it => true, forcedRoll = undefined) {
|
|
||||||
const table = await this.buildTable(itemFrequence, filter);
|
|
||||||
return await CompendiumTableHelpers.getRandom(table, this.type, this.subTypes, forcedRoll, SystemCompendiums.getCompendium(compendium));
|
|
||||||
}
|
|
||||||
|
|
||||||
async toChatMessage(itemFrequence = it => it.system.frequence, filter = it => true, typeName = undefined) {
|
|
||||||
const table = await this.buildTable(itemFrequence, filter);
|
|
||||||
await CompendiumTableHelpers.tableToChatMessage(table, this.type, this.subTypes, typeName);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ======= Gestion de tables correspondant à un compendium =======
|
|
||||||
*/
|
|
||||||
export class CompendiumTableHelpers {
|
|
||||||
|
|
||||||
static buildTable(elements, itemFrequence) {
|
|
||||||
let max = 0;
|
|
||||||
const total = elements.map(it => itemFrequence(it)).reduce(Misc.sum(), 0);
|
|
||||||
return elements.map(it => {
|
|
||||||
const frequence = itemFrequence(it);
|
|
||||||
let row = { document: it, frequence: frequence, min: max + 1, max: max + frequence, total: total };
|
|
||||||
max += frequence;
|
|
||||||
return row;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getRandom(table, type, subTypes, forcedRoll = undefined, localisation = undefined) {
|
|
||||||
if (table.length == 0) {
|
|
||||||
ui.notifications.warn(`Aucun ${Misc.typeName(type, subTypes[0])} trouvé dans ${localisation ?? ' les compendiums'}`);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return await CompendiumTableHelpers.selectRow(table, forcedRoll);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async selectRow(table, forcedRoll = undefined) {
|
|
||||||
if (table.length == 0) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
const total = table[0].total;
|
|
||||||
const formula = `1d${total}`;
|
|
||||||
if (forcedRoll == undefined && (forcedRoll > total || forcedRoll <= 0)) {
|
|
||||||
ui.notifications.warn(`Jet de rencontre ${forcedRoll} en dehors de la table [1..${total}], le jet est relancé`);
|
|
||||||
forcedRoll = undefined;
|
|
||||||
}
|
|
||||||
const roll = forcedRoll ? { total: forcedRoll, formula } : await RdDDice.roll(formula, { showDice: HIDE_DICE });
|
|
||||||
const row = table.find(it => it.min <= roll.total && roll.total <= it.max);
|
|
||||||
row.roll = roll;
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async tableRowToChatMessage(row, type = 'Item') {
|
|
||||||
if (!row) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const percentages = (row.total == 100) ? '%' : ''
|
|
||||||
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table-roll.html', {
|
|
||||||
roll: row.roll,
|
|
||||||
document: row.document,
|
|
||||||
percentages,
|
|
||||||
typeName: Misc.typeName(type, row.document.type),
|
|
||||||
isGM: game.user.isGM,
|
|
||||||
});
|
|
||||||
const messageData = {
|
|
||||||
// flavor: flavorContent,
|
|
||||||
user: game.user.id,
|
|
||||||
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
|
|
||||||
roll: row.roll,
|
|
||||||
sound: CONFIG.sounds.dice,
|
|
||||||
content: flavorContent
|
|
||||||
};
|
|
||||||
ChatMessage.create(messageData, { rollMode: "gmroll" });
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async tableToChatMessage(table, type, subTypes, typeName = undefined) {
|
|
||||||
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table.html', {
|
|
||||||
img: RdDItem.getDefaultImg(subTypes[0]),
|
|
||||||
typeName: typeName ?? Misc.typeName(type, subTypes[0]),
|
|
||||||
table,
|
|
||||||
isGM: game.user.isGM,
|
|
||||||
});
|
|
||||||
ChatMessage.create({
|
|
||||||
user: game.user.id,
|
|
||||||
whisper: game.user.id,
|
|
||||||
content: flavorContent
|
|
||||||
}, { rollMode: "gmroll" });
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
135
module/status-effects.js
Normal file
135
module/status-effects.js
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
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');
|
||||||
|
|
||||||
|
const statusDemiSurprise = new Set(['EFFECT.StatusStunned', 'EFFECT.StatusProne', 'EFFECT.StatusRestrain']);
|
||||||
|
const statusSurpriseTotale = new Set(['EFFECT.StatusUnconscious', 'EFFECT.StatusBlind', 'EFFECT.StatusComma']);
|
||||||
|
|
||||||
|
export class StatusEffects {
|
||||||
|
static onReady() {
|
||||||
|
const rddStatusIds = rddStatusEffects.map(it => it.id);
|
||||||
|
const defaultStatusEffectIds = CONFIG.statusEffects.map(it => it.id);
|
||||||
|
game.settings.register(SYSTEM_RDD, "use-status-effects", {
|
||||||
|
name: "use-status-effects",
|
||||||
|
scope: "world",
|
||||||
|
config: false,
|
||||||
|
default: defaultStatusEffectIds.join(),
|
||||||
|
type: String
|
||||||
|
});
|
||||||
|
|
||||||
|
game.settings.registerMenu(SYSTEM_RDD, "select-status-effect", {
|
||||||
|
name: "Choisir les effets disponibles",
|
||||||
|
label: "Choix des effets",
|
||||||
|
hint: "Ouvre la fenêtre de sélection des effets/status appliqués aux acteurs",
|
||||||
|
icon: "fas fa-bars",
|
||||||
|
type: StatusEffectsSettings,
|
||||||
|
restricted: true
|
||||||
|
});
|
||||||
|
|
||||||
|
CONFIG.RDD.allEffects = rddStatusEffects.concat(CONFIG.statusEffects.filter(it => !rddStatusIds.includes(it.id)));
|
||||||
|
|
||||||
|
StatusEffects._setUseStatusEffects(StatusEffects._getUseStatusEffects());
|
||||||
|
console.log('statusEffects', CONFIG.statusEffects);
|
||||||
|
}
|
||||||
|
|
||||||
|
static valeurSurprise(effect, isCombat) {
|
||||||
|
// const id = StatusEffects.statusId(effect);
|
||||||
|
if (statusSurpriseTotale.has(effect.label)) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static _getUseStatusEffects() {
|
||||||
|
const setting = game.settings.get(SYSTEM_RDD, "use-status-effects");
|
||||||
|
return setting ? new Set(setting.split(',')) : new Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
static _setUseStatusEffects(useStatusEffects) {
|
||||||
|
if (game.user.isGM) {
|
||||||
|
game.settings.set(SYSTEM_RDD, "use-status-effects", StatusEffects._toSetting(useStatusEffects));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let effect of CONFIG.RDD.allEffects) {
|
||||||
|
effect.active = effect.rdd || useStatusEffects.has(effect.id);
|
||||||
|
}
|
||||||
|
CONFIG.statusEffects = CONFIG.RDD.allEffects.filter(it => it.active);
|
||||||
|
}
|
||||||
|
|
||||||
|
static _toSetting(useStatusEffects) {
|
||||||
|
return Array.from(useStatusEffects).join();
|
||||||
|
}
|
||||||
|
|
||||||
|
static status(label) {
|
||||||
|
return rddStatusEffects.find(it => it.label == label) ?? { label: label };
|
||||||
|
}
|
||||||
|
static demiReve() {
|
||||||
|
return demiReveStatusEffect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StatusEffectsSettings extends FormApplication {
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static get defaultOptions() {
|
||||||
|
const options = super.defaultOptions;
|
||||||
|
mergeObject(options, {
|
||||||
|
id: "status-effects-settings",
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/status-effects-settings.html",
|
||||||
|
height: "800",
|
||||||
|
width: 350,
|
||||||
|
minimizable: false,
|
||||||
|
closeOnSubmit: true,
|
||||||
|
title: "Choix des status/effets"
|
||||||
|
});
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
let formData = super.getData();
|
||||||
|
formData.effects = CONFIG.RDD.allEffects;
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
html.find(".select-effect").click((event) => {
|
||||||
|
let id = event.currentTarget.attributes.name?.value;
|
||||||
|
if (id) {
|
||||||
|
let selected = StatusEffects._getUseStatusEffects();
|
||||||
|
let isChecked = event.currentTarget.checked;
|
||||||
|
if (isChecked) {
|
||||||
|
selected.add(id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
selected.delete(id);
|
||||||
|
}
|
||||||
|
StatusEffects._setUseStatusEffects(selected);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async _updateObject(event, formData) {
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,56 +0,0 @@
|
|||||||
import { ENTITE_NONINCARNE } from "./constants.js";
|
|
||||||
import { DialogSelectTarget } from "./dialog-select-target.js";
|
|
||||||
|
|
||||||
export class Targets {
|
|
||||||
static listTargets() {
|
|
||||||
return Array.from(game.user.targets);
|
|
||||||
}
|
|
||||||
|
|
||||||
static hasTargets() {
|
|
||||||
return Targets.listTargets().length > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static extractTokenData(target) {
|
|
||||||
if (!target) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
return { id: target.id, name: target.document.name, img: target.document.texture.src ?? target.actor.img ?? 'icons/svg/mystery-man.svg' };
|
|
||||||
}
|
|
||||||
|
|
||||||
static isTargetEntite(target) {
|
|
||||||
return target?.actor.type == 'entite' && target?.actor.system.definition.typeentite == ENTITE_NONINCARNE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static async selectOneToken(onSelectTarget = target => { }) {
|
|
||||||
const targets = Targets.listTargets();
|
|
||||||
switch (targets.length) {
|
|
||||||
case 0: return;
|
|
||||||
case 1:
|
|
||||||
onSelectTarget(targets[0]);
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
const tokens = targets.map(it => Targets.extractTokenData(it))
|
|
||||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-select-target.html", {
|
|
||||||
tokens: tokens
|
|
||||||
});
|
|
||||||
new DialogSelectTarget(html, onSelectTarget, targets).render(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTarget() {
|
|
||||||
const targets = Targets.listTargets();
|
|
||||||
switch (targets.length) {
|
|
||||||
case 1:
|
|
||||||
return targets[0];
|
|
||||||
case 0:
|
|
||||||
ui.notifications.warn("Vous devez choisir une cible à attaquer!");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ui.notifications.warn("Vous devez choisir une cible (et <strong>une seule</strong>) à attaquer!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,129 +1,500 @@
|
|||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { SystemCompendiums, CompendiumTable, CompendiumTableHelpers } from "./settings/system-compendiums.js";
|
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
import { TMRType } from "./tmr-utility.js";
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
const typeRencontres = {
|
||||||
|
|
||||||
|
messager: {
|
||||||
|
msgSucces: async (rencData) => {
|
||||||
|
if (rencData.actor.isTMRCache()){
|
||||||
|
return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort, mais vous ne savez pas où vous êtes.`;
|
||||||
|
}
|
||||||
|
return `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`;
|
||||||
|
},
|
||||||
|
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`,
|
||||||
|
postSucces: async (tmrDialog, rencData) => {
|
||||||
|
tmrDialog.setStateRencontre(rencData.rencontre.type);
|
||||||
|
tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
|
||||||
|
},
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "La chevelure, Charles Baudelaire",
|
||||||
|
extrait: `J'irai là-bas où l'arbre et l'homme, pleins de sève,
|
||||||
|
<br>Se pâment longuement sous l'ardeur des climats ;
|
||||||
|
<br>Fortes tresses, soyez la houle qui m'enlève !`
|
||||||
|
},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||||
|
extrait: `En réalité, tous les éléments du rêve des Dragons expriment
|
||||||
|
le Draconic : chaque pierre, chaque fleur, chaque goutte d'eau,
|
||||||
|
chaque nuage est porteur d'un message dans la langue des Dragons`}
|
||||||
|
},
|
||||||
|
|
||||||
|
passeur: {
|
||||||
|
msgSucces: async (rencData) => {
|
||||||
|
if (rencData.actor.isTMRCache()){
|
||||||
|
return `Le ${rencData.rencontre.name} vous propose de vous transporter, mais vous ne savez pas où vous êtes.`;
|
||||||
|
}
|
||||||
|
return `Le ${rencData.rencontre.name} vous propose de vous transporter à ${rencData.rencontre.force} cases des ${rencData.tmr.label}.`;
|
||||||
|
},
|
||||||
|
msgEchec: async (rencData)=> `Le prix que demande le ${rencData.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`,
|
||||||
|
postSucces: async (tmrDialog, rencData) => {
|
||||||
|
tmrDialog.setStateRencontre(rencData.rencontre.type);
|
||||||
|
tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
|
||||||
|
},
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "Femmes damnées (2), Charles Baudelaire",
|
||||||
|
extrait: `Comme je descendais des Fleuves impassibles,
|
||||||
|
<br>Je ne me sentis plus guidé par les haleurs :
|
||||||
|
<br>Des Peaux-Rouges criards les avaient pris pour cibles,
|
||||||
|
<br>Les ayant cloués nus aux poteaux de couleurs.`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "Le bateau ivre, Arthur Rimbaud",
|
||||||
|
extrait: `Loin des peuples vivants, errantes, condamnées,
|
||||||
|
<br>A travers les déserts courez comme les loups ;
|
||||||
|
<br>Faites votre destin, âmes désordonnées,
|
||||||
|
<br>Et fuyez l'infini que vous portez en vous !`}
|
||||||
|
},
|
||||||
|
|
||||||
|
fleur: {
|
||||||
|
msgSucces: async (rencData) => `Vous cueillez la ${rencData.rencontre.name}, son parfum vous apporte ${rencData.rencontre.force} points de Rêve.`,
|
||||||
|
msgEchec: async (rencData)=> `La ${rencData.rencontre.name} se fâne et disparaît entre vos doigts.`,
|
||||||
|
postSucces: async (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(rencData.rencontre.force),
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "L'Ennemi, Charles Baudelaire",
|
||||||
|
extrait: `Et qui sait si les fleurs nouvelles que je rêve
|
||||||
|
<br>Trouveront dans ce sol lavé comme une grève
|
||||||
|
<br>Le mystique aliment qui ferait leur vigueur ?`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "Une charogne, Charles Baudelaire",
|
||||||
|
extrait: `Et le ciel regardait la carcasse superbe
|
||||||
|
<br>Comme une fleur s'épanouir.
|
||||||
|
<br>La puanteur était si forte, que sur l'herbe
|
||||||
|
<br>Vous crûtes vous évanouir.`},
|
||||||
|
},
|
||||||
|
|
||||||
|
mangeur: {
|
||||||
|
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} claque de sa machoire dans le vide avant de fuir.`,
|
||||||
|
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} croque votre Rêve ! Il emporte ${rencData.rencontre.force} de vos points de rêve actuels`,
|
||||||
|
postEchec: async (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(-rencData.rencontre.force),
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "Conseil, Victor Hugo",
|
||||||
|
extrait: `Rois ! la bure est souvent jalouse du velours.
|
||||||
|
<br>Le peuple a froid l'hiver, le peuple a faim toujours.
|
||||||
|
<br>Rendez-lui son sort plus facile.
|
||||||
|
<br>Le peuple souvent porte un bien rude collier.
|
||||||
|
<br>Ouvrez l'école aux fils, aux pères l'atelier,
|
||||||
|
<br>À tous vos bras, auguste asile !`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "El Desdichado, Gérard de Nerval",
|
||||||
|
extrait: `Suis-je Amour ou Phébus ?... Lusignan ou Biron ?
|
||||||
|
<br>Mon front est rouge encor du baiser de la Reine ;
|
||||||
|
<br>J'ai rêvé dans la Grotte où nage la sirène...`}
|
||||||
|
},
|
||||||
|
|
||||||
|
changeur: {
|
||||||
|
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[rencData.tmr.type].name} de votre choix en échange de sa liberté.`,
|
||||||
|
msgEchec: async (rencData) => `Le ${rencData.rencontre.name} vous embobine avec des promesses, et vous transporte sur une autre ${TMRType[rencData.tmr.type].name} sans attendre votre avis.`,
|
||||||
|
postSucces: async (tmrDialog, rencData) => {
|
||||||
|
tmrDialog.setStateRencontre(rencData.rencontre.type);
|
||||||
|
tmrDialog.choisirCaseType(rencData.tmr.type);
|
||||||
|
},
|
||||||
|
postEchec: async (tmrDialog, rencData) => {
|
||||||
|
const newTMR = await TMRUtility.getTMRAleatoire(it => it.type == rencData.tmr.type && it.coord != rencData.tmr.coord);
|
||||||
|
await tmrDialog.actor.forcerPositionTMRInconnue(newTMR);
|
||||||
|
tmrDialog.positionnerDemiReve(newTMR.coord);
|
||||||
|
},
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "Caligula - IIIème chant, Gérard de Nerval",
|
||||||
|
extrait: `Allez, que le caprice emporte
|
||||||
|
<br>Chaque âme selon son désir,
|
||||||
|
<br>Et que, close après vous, la porte
|
||||||
|
<br>Ne se rouvre plus qu'au plaisir.`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||||
|
extrait: `Les sages ont encore coutume de dire :
|
||||||
|
<br>« Mais comment les Dragons peuvent-ils
|
||||||
|
être influencés par une créature qui, tout
|
||||||
|
bien considéré, n'existe pas vraiment pour eux,
|
||||||
|
qui n'est que le fantasme de leur activité nocturne ? »`}
|
||||||
|
},
|
||||||
|
|
||||||
|
briseur: {
|
||||||
|
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`,
|
||||||
|
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`,
|
||||||
|
postEchec: async (tmrDialog, rencData) => tmrDialog.close(),
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||||
|
extrait: `La légende affirme que ce sont les Gnomes qui furent
|
||||||
|
les premiers haut-rêvants. En observant les pierres précieuses,
|
||||||
|
les gemmes qui sont les larmes de joie des Dragons, ils parvinrent à
|
||||||
|
en comprendre la langue. Et l'ayant comprise, ils purent s'en servir
|
||||||
|
pour influencer le cours du rêve`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "Quand le rêve se brise, Cypora Sebagh",
|
||||||
|
extrait: `Quand le rêve se brise,
|
||||||
|
<br>Dans la plainte du jour,
|
||||||
|
<br>Ma mémoire devient grise
|
||||||
|
<br>Et sombre, tour à tour,
|
||||||
|
<br>Dans le puits du silence
|
||||||
|
<br>Et de la solitude ;
|
||||||
|
<br>Elle reprend son errance
|
||||||
|
<br>Parmi la multitude.`}
|
||||||
|
},
|
||||||
|
|
||||||
|
reflet: {
|
||||||
|
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} s'estompe dans l'oubli.`,
|
||||||
|
msgEchec: async (rencData)=> `Vous êtes submergé par un ${rencData.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`,
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "Une charogne, Charles Baudelaire",
|
||||||
|
extrait: `Les formes s'effaçaient et n'étaient plus qu'un rêve,
|
||||||
|
<br>Une ébauche lente à venir
|
||||||
|
<br>Sur la toile oubliée, et que l'artiste achève
|
||||||
|
<br>Seulement par le souvenir.`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "La chevelure, Charles Baudelaire",
|
||||||
|
extrait: `Longtemps ! toujours ! ma main dans ta crinière lourde
|
||||||
|
<br>Sèmera le rubis, la perle et le saphir,
|
||||||
|
<br>Afin qu'à mon désir tu ne sois jamais sourde !
|
||||||
|
<br>N'es-tu pas l'oasis où je rêve, et la gourde
|
||||||
|
<br>Où je hume à longs traits le vin du souvenir`}
|
||||||
|
},
|
||||||
|
|
||||||
|
passeurfou: {
|
||||||
|
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`,
|
||||||
|
msgEchec: async (rencData)=> TMRRencontres.msgEchecPasseurFou(rencData),
|
||||||
|
postEchec: async (tmrDialog, rencData) => TMRRencontres.postEchecPasseurFou(tmrDialog, rencData),
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "Un Fou et un Sage, Jean de La Fontaine",
|
||||||
|
extrait: `Certain Fou poursuivait à coups de pierre un Sage.
|
||||||
|
<br>Le Sage se retourne et lui dit : Mon ami,
|
||||||
|
<br>C'est fort bien fait à toi ; reçois cet écu-ci :
|
||||||
|
<br>Tu fatigues assez pour gagner davantage.`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "Guitare, Victor Hugo",
|
||||||
|
extrait: `Je la voyais passer de ma demeure,
|
||||||
|
<br>Et c'était tout.
|
||||||
|
<br>Mais à présent je m'ennuie à toute heure,
|
||||||
|
<br>Plein de dégoût,
|
||||||
|
<br>Rêveur oisif, l'âme dans la campagne,
|
||||||
|
<br>La dague au clou ... –
|
||||||
|
<br>Le vent qui vient à travers la montagne
|
||||||
|
<br>M'a rendu fou !`}
|
||||||
|
},
|
||||||
|
|
||||||
|
tbblanc: {
|
||||||
|
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`,
|
||||||
|
msgEchec: async (rencData)=> `Le souffle du ${rencData.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`,
|
||||||
|
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 1),
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||||
|
extrait: `Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement
|
||||||
|
des temps, le commencement des rêves. Durant cette période plus mythique
|
||||||
|
que réellement historique, les Dragons aimaient à se rêver eux-mêmes.`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "Les Djinns, Victor Hugo",
|
||||||
|
extrait: `C'est l'essaim des Djinns qui passe,
|
||||||
|
<br>Et tourbillonne en sifflant !
|
||||||
|
<br>Les ifs, que leur vol fracasse,
|
||||||
|
<br>Craquent comme un pin brûlant.`},
|
||||||
|
},
|
||||||
|
|
||||||
|
tbnoir: {
|
||||||
|
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`,
|
||||||
|
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`,
|
||||||
|
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 2),
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||||
|
extrait: `Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les
|
||||||
|
Gnomes s'enfoncèrent profondément sous les montagnes et la magie passa aux
|
||||||
|
mains des Humains qui en usèrent et abusèrent, se croyant devenus les maîtres du monde`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "Lily, Pierre Perret",
|
||||||
|
extrait: `Elle aurait pas cru sans le voir
|
||||||
|
<br>Que la couleur du désespoir
|
||||||
|
<br>Là-bas aussi ce fût le noir.`},
|
||||||
|
},
|
||||||
|
|
||||||
|
tbrouge: {
|
||||||
|
msgSucces: async (rencData) => `Le ${rencData.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`,
|
||||||
|
msgEchec: async (rencData)=> `Le ${rencData.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`,
|
||||||
|
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, rencData),
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet",
|
||||||
|
extrait: `Qu'est-ce de votre vie ? un tourbillon rouant
|
||||||
|
<br>De fumière à flot gris, parmi l'air se jouant,
|
||||||
|
<br>Qui passe plus soudain que foudre meurtrière.`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "Les Djinns, poème Victor Hugo",
|
||||||
|
extrait: `Cris de l'enfer! voix qui hurle et qui pleure !
|
||||||
|
<br>L'horrible essaim, poussé par l'aquilon,
|
||||||
|
<br>Sans doute, ô ciel ! s'abat sur ma demeure.
|
||||||
|
<br>Le mur fléchit sous le noir bataillon.
|
||||||
|
<br>La maison crie et chancelle penchée,
|
||||||
|
<br>Et l'on dirait que, du sol arrachée,
|
||||||
|
<br>Ainsi qu'il chasse une feuille séchée,
|
||||||
|
<br>Le vent la roule avec leur tourbillon !`},
|
||||||
|
},
|
||||||
|
|
||||||
|
rdd: {
|
||||||
|
msgSucces: async (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${rencData.rencontre.force} points de rêve`,
|
||||||
|
msgEchec: async (rencData)=> `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${rencData.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`,
|
||||||
|
postSucces: async (tmrDialog, rencData) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, rencData),
|
||||||
|
postEchec: async (tmrDialog, rencData) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, rencData),
|
||||||
|
poesieSucces: {
|
||||||
|
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||||
|
extrait: `Le monde est Rêve de Dragons, mais nous ne savons
|
||||||
|
<br>ni leur apparence ni qui sont les dragons.
|
||||||
|
<br>En dépit de l'iconographie qui les clame
|
||||||
|
<br>immenses créatures ailées crachant des flammes`},
|
||||||
|
poesieEchec: {
|
||||||
|
reference: "El Desdichado, Gérard de Nerval",
|
||||||
|
extrait: `Je suis le Ténébreux, – le Veuf, – l'Inconsolé,
|
||||||
|
<br>Le Prince d'Aquitaine à la Tour abolie :
|
||||||
|
<br>Ma seule Etoile est morte, – et mon luth constellé
|
||||||
|
<br>Porte le Soleil noir de la Mélancolie.`}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
const mauvaisesRencontres = [
|
||||||
|
{ code: "mangeur", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6", refoulement: 2, isMauvaise: true },
|
||||||
|
{ code: "mangeur2d6", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "2d6", refoulement: 2, isMauvaise: true },
|
||||||
|
{ code: "reflet+4", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true },
|
||||||
|
{ code: "tbblanc+4", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true },
|
||||||
|
{ code: "tbnoir+4", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8+4", refoulement: 2, isPersistant: true, isMauvaise: true },
|
||||||
|
{ code: "passfou", name: "Passeur fou", type: "passeurfou", genre: "m", force: "2d8", refoulement: 2, isMauvaise: true },
|
||||||
|
{ code: "tbrouge", name: "Tourbillon rouge", type: "tbrouge", genre: "m", force: "2d8", refoulement: 3, isPersistant: true, isMauvaise: true }
|
||||||
|
]
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
const rencontresStandard = [
|
||||||
|
{ code: "messager", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d4", ignorer: true },
|
||||||
|
{ code: "passeur", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d4", ignorer: true },
|
||||||
|
{ code: "fleur", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "1d6", ignorer: true },
|
||||||
|
{ code: "mangeur", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6" },
|
||||||
|
{ code: "changeur", name: "Changeur de Rêve", type: "changeur", genre: "m", force: "2d6" },
|
||||||
|
{ code: "briseur", name: "Briseur de Rêve", type: "briseur", genre: "m", force: "2d6", quitterTMR: true },
|
||||||
|
{ code: "reflet", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6", isPersistant: true },
|
||||||
|
{ code: "tbblanc", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6", isPersistant: true },
|
||||||
|
{ code: "tbnoir", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8", isPersistant: true },
|
||||||
|
{ code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1dr + 7", refoulement: 2, quitterTMR: true }
|
||||||
|
];
|
||||||
|
|
||||||
|
const rencontresPresentCite = [
|
||||||
|
{ code: "messager2d6", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d6", ignorer: true },
|
||||||
|
{ code: "passeur2d6", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d6", ignorer: true },
|
||||||
|
{ code: "fleur2d6", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "2d6", ignorer: true }
|
||||||
|
]
|
||||||
|
const rencontresAll = [].concat(rencontresStandard).concat(mauvaisesRencontres).concat(rencontresPresentCite);
|
||||||
|
|
||||||
|
const tableRencontres = {
|
||||||
|
cite: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
sanctuaire: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
plaines: [{ code: 'messager', range: [1, 20] }, { code: 'passeur', range: [21, 40] }, { code: 'fleur', range: [41, 55] }, { code: 'mangeur', range: [56, 60] }, { code: 'changeur', range: [61, 75] }, { code: 'briseur', range: [76, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
pont: [{ code: 'messager', range: [1, 20] }, { code: 'passeur', range: [21, 40] }, { code: 'fleur', range: [41, 55] }, { code: 'mangeur', range: [56, 60] }, { code: 'changeur', range: [61, 75] }, { code: 'briseur', range: [76, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
collines: [{ code: 'messager', range: [1, 15] }, { code: 'passeur', range: [16, 30] }, { code: 'fleur', range: [31, 42] }, { code: 'mangeur', range: [43, 54] }, { code: 'changeur', range: [55, 69] }, { code: 'briseur', range: [70, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
foret: [{ code: 'messager', range: [1, 15] }, { code: 'passeur', range: [16, 30] }, { code: 'fleur', range: [31, 42] }, { code: 'mangeur', range: [43, 54] }, { code: 'changeur', range: [55, 69] }, { code: 'briseur', range: [70, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
monts: [{ code: 'messager', range: [1, 10] }, { code: 'passeur', range: [11, 20] }, { code: 'fleur', range: [21, 26] }, { code: 'mangeur', range: [27, 44] }, { code: 'changeur', range: [45, 59] }, { code: 'briseur', range: [60, 75] }, { code: 'reflet', range: [76, 85] }, { code: 'tbblanc', range: [86, 92] }, { code: 'tbnoir', range: [93, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
desert: [{ code: 'messager', range: [1, 10] }, { code: 'passeur', range: [11, 20] }, { code: 'fleur', range: [21, 26] }, { code: 'mangeur', range: [27, 44] }, { code: 'changeur', range: [45, 59] }, { code: 'briseur', range: [60, 75] }, { code: 'reflet', range: [76, 85] }, { code: 'tbblanc', range: [86, 92] }, { code: 'tbnoir', range: [93, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
fleuve: [{ code: 'messager', range: [1, 5] }, { code: 'passeur', range: [6, 10] }, { code: 'fleur', range: [11, 13] }, { code: 'mangeur', range: [14, 37] }, { code: 'changeur', range: [38, 49] }, { code: 'briseur', range: [50, 65] }, { code: 'reflet', range: [66, 79] }, { code: 'tbblanc', range: [80, 89] }, { code: 'tbnoir', range: [90, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
lac: [{ code: 'messager', range: [1, 5] }, { code: 'passeur', range: [6, 10] }, { code: 'fleur', range: [11, 13] }, { code: 'mangeur', range: [14, 37] }, { code: 'changeur', range: [38, 49] }, { code: 'briseur', range: [50, 65] }, { code: 'reflet', range: [66, 79] }, { code: 'tbblanc', range: [80, 89] }, { code: 'tbnoir', range: [90, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
marais: [{ code: 'messager', range: [1, 2] }, { code: 'passeur', range: [3, 4] }, { code: 'fleur', range: [5, 5] }, { code: 'mangeur', range: [6, 29] }, { code: 'changeur', range: [30, 39] }, { code: 'briseur', range: [40, 60] }, { code: 'reflet', range: [61, 75] }, { code: 'tbblanc', range: [76, 86] }, { code: 'tbnoir', range: [87, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
gouffre: [{ code: 'messager', range: [1, 2] }, { code: 'passeur', range: [3, 4] }, { code: 'fleur', range: [5, 5] }, { code: 'mangeur', range: [6, 29] }, { code: 'changeur', range: [30, 39] }, { code: 'briseur', range: [40, 60] }, { code: 'reflet', range: [61, 75] }, { code: 'tbblanc', range: [76, 86] }, { code: 'tbnoir', range: [87, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
necropole: [{ code: 'mangeur', range: [1, 20] }, { code: 'changeur', range: [21, 30] }, { code: 'briseur', range: [31, 50] }, { code: 'reflet', range: [51, 65] }, { code: 'tbblanc', range: [66, 80] }, { code: 'tbnoir', range: [81, 97] }, { code: 'rdd', range: [98, 100] }],
|
||||||
|
desolation: [{ code: 'mangeur', range: [1, 20] }, { code: 'changeur', range: [21, 30] }, { code: 'briseur', range: [31, 50] }, { code: 'reflet', range: [51, 65] }, { code: 'tbblanc', range: [66, 80] }, { code: 'tbnoir', range: [81, 97] }, { code: 'rdd', range: [98, 100] }]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class TMRRencontres {
|
export class TMRRencontres {
|
||||||
|
static gestionRencontre = {}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
static init() {
|
static init() {
|
||||||
const tmrRencontre = new TMRRencontres();
|
for (let type in typeRencontres) {
|
||||||
game.system.rdd.rencontresTMR = tmrRencontre;
|
TMRRencontres.register(type, typeRencontres[type]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(){
|
/* -------------------------------------------- */
|
||||||
this.table = new CompendiumTable('rencontres', 'Item', 'rencontre', Misc.ascending(it => it.system.ordreTri));
|
static register(type, rencontre) {
|
||||||
|
TMRRencontres.gestionRencontre[type] = rencontre;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/**
|
/**
|
||||||
* Retourne une recontre en fonction de la case et du tirage
|
* Retourne une recontre en fonction de la case et du tirage
|
||||||
* @param {*} terrain
|
* @param {*} terrain
|
||||||
* @param {*} forcedRoll
|
* @param {*} roll
|
||||||
*/
|
*/
|
||||||
async rollRencontre(terrain, forcedRoll) {
|
static async rollRencontre(terrain, roll = undefined) {
|
||||||
terrain = TMRUtility.findTMRLike(terrain);
|
if (!terrain) {
|
||||||
if (terrain == undefined) {
|
ChatMessage.create({ content: "Un type de case doit être indiqué (par exemple sanctuaire, desert ou cité)" });
|
||||||
return undefined;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!roll || roll <= 0 || roll > 100) {
|
||||||
if (forcedRoll && (forcedRoll <= 0 || forcedRoll > 100)) {
|
roll = await RdDDice.rollTotal("1d100");
|
||||||
forcedRoll = undefined;
|
|
||||||
}
|
}
|
||||||
const codeTerrain = Grammar.toLowerCaseNoAccent(terrain)
|
let rencontre = await TMRRencontres.getRencontreAleatoire(terrain, roll);
|
||||||
const filtreMauvaise = codeTerrain == 'mauvaise' ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
|
ChatMessage.create({
|
||||||
const frequence = it => it.system.frequence[codeTerrain];
|
user: game.user.id,
|
||||||
const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll);
|
whisper: [game.user.id],
|
||||||
if (row) {
|
content: `Rencontre en ${terrain} (jet : ${roll}%)<br>Vous rencontrez un ${rencontre.name} de ${rencontre.force} Points de Rêve`
|
||||||
await CompendiumTableHelpers.tableRowToChatMessage(row);
|
});
|
||||||
}
|
return false;
|
||||||
|
|
||||||
return row?.document;
|
|
||||||
}
|
|
||||||
|
|
||||||
async chatTable(terrain) {
|
|
||||||
const codeTerrain = Grammar.toLowerCaseNoAccent(terrain)
|
|
||||||
const isMauvaise = codeTerrain == 'mauvaise';
|
|
||||||
const filtreMauvaise = isMauvaise ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
|
|
||||||
const frequence = it => it.system.frequence[codeTerrain];
|
|
||||||
const typeName = isMauvaise ? 'Mauvaises rencontres' : `Rencontres en ${Misc.upperFirst(terrain)}`;
|
|
||||||
return await this.table.toChatMessage(frequence, filtreMauvaise, typeName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async createRencontre(rencontre, tmr = undefined) {
|
static getRencontre(index) {
|
||||||
return rencontre.clone({
|
let rencontre;
|
||||||
'system.force': await RdDDice.rollTotal(rencontre.system.formule),
|
if (isNaN(index)) {
|
||||||
'system.coord': tmr?.coord,
|
rencontre = rencontresAll.find(r => r.type == index) ?? rencontresAll.find(r => r.code == index)
|
||||||
'system.date': game.system.rdd.calendrier.getDateFromIndex(),
|
}
|
||||||
'system.heure': game.system.rdd.calendrier.getCurrentHeure()
|
else if (0 <= index && index < rencontresAll.length) {
|
||||||
}, { save: false });
|
rencontre = rencontresAll[index];
|
||||||
|
}
|
||||||
|
if (rencontre) {
|
||||||
|
return duplicate(rencontre);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.info(`Pas de rencontre pour ${index}, seulement ${rencontresAll.length} rencontres sont connues.<br>Vous pouvez aussi essayer par type (ie: mangeur, fleur, fleur2d6, ...)`)
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
async calculRencontre(rencontre, tmr = undefined) {
|
/* -------------------------------------------- */
|
||||||
if (rencontre.system.coord == "") {
|
static async getRencontreAleatoire(terrain, roll = undefined) {
|
||||||
rencontre.system.coord = tmr?.coord;
|
if (!roll || roll <= 0 || roll > 100) {
|
||||||
}
|
roll = await RdDDice.rollTotal("1d100");
|
||||||
if (rencontre.system.force == 0) {
|
|
||||||
rencontre.system.force = await RdDDice.rollTotal(rencontre.system.formule);
|
|
||||||
}
|
|
||||||
if (rencontre.system.date == "") {
|
|
||||||
rencontre.system.date = game.system.rdd.calendrier.getDateFromIndex();
|
|
||||||
}
|
|
||||||
if (rencontre.system.heure == "") {
|
|
||||||
rencontre.system.heure = game.system.rdd.calendrier.getCurrentHeure();
|
|
||||||
}
|
}
|
||||||
|
terrain = Grammar.toLowerCaseNoAccent(terrain);
|
||||||
|
const code = tableRencontres[terrain].find(it => it.range[0] <= roll && roll <= it.range[1]).code;
|
||||||
|
const rencontre = duplicate(rencontresStandard.find(it => it.code == code));
|
||||||
|
rencontre.roll = roll;
|
||||||
|
await TMRRencontres.evaluerForceRencontre(rencontre);
|
||||||
return rencontre;
|
return rencontre;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
async getPresentsCite() {
|
static async getMauvaiseRencontre(index = undefined) {
|
||||||
const rencontres = await SystemCompendiums.getDefaultItems('rencontres');
|
const rencontre = duplicate(
|
||||||
return rencontres.filter(it => !it.system.mauvaiseRencontre && it.system.presentCite).map(it =>
|
(index && index >= 0 && index < mauvaisesRencontres.length)
|
||||||
it.clone({ 'system.formule': "2d6" }, { save: false }));
|
? mauvaisesRencontres[index]
|
||||||
}
|
: await RdDDice.rollOneOf(mauvaisesRencontres));
|
||||||
|
await TMRRencontres.evaluerForceRencontre(rencontre);
|
||||||
async getReveDeDragon(force) {
|
return rencontre;
|
||||||
const rencontres = await SystemCompendiums.getDefaultItems('rencontres');
|
|
||||||
const reveDeDragon = rencontres.find(it => Grammar.equalsInsensitive(it.name, 'Rêve de Dragon'));
|
|
||||||
return reveDeDragon?.clone({ 'system.force': force }, { save: false });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getRencontreAleatoire(tmr, mauvaise) {
|
static async evaluerForceRencontre(rencontre) {
|
||||||
const codeTerrain = mauvaise ? 'mauvaise' : tmr.type;
|
const rollForce = new Roll(rencontre.force);
|
||||||
const filtreMauvaise = codeTerrain == 'mauvaise' ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
|
await rollForce.evaluate();
|
||||||
const frequence = it => it.system.frequence[codeTerrain];
|
rencontre.force = rollForce.total;
|
||||||
|
return rencontre.force;
|
||||||
|
}
|
||||||
|
|
||||||
const row = await this.table.getRandom(frequence, filtreMauvaise);
|
/* -------------------------------------------- */
|
||||||
if (row) {
|
static isReveDeDragon(rencontre) {
|
||||||
row.document = this.createRencontre(row.document, tmr);
|
return rencontre.type == "rdd";
|
||||||
await this.$chatRolledRencontre(row, tmr);
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static getGestionRencontre(name) {
|
||||||
|
let gestion = TMRRencontres.gestionRencontre[name];
|
||||||
|
if (!gestion) {
|
||||||
|
ui.notifications.error(`La rencontre ${name} est inconnue, pas de méthode de gestion associée`)
|
||||||
|
gestion = TMRRencontres.gestionRencontre['messager'];
|
||||||
}
|
}
|
||||||
return row?.document;
|
return gestion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async gererRencontre(tmrDialog, rencData) {
|
||||||
|
let gestion = TMRRencontres.getGestionRencontre(rencData.rencontre.type);
|
||||||
|
if (rencData.rolled.isSuccess) {
|
||||||
|
rencData.message = await gestion.msgSucces(rencData);
|
||||||
|
if (rencData.nbRounds > 1) {
|
||||||
|
rencData.message += ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
|
||||||
|
}
|
||||||
|
rencData.poesie = gestion.poesieSucces;
|
||||||
|
return gestion.postSucces;
|
||||||
|
}
|
||||||
|
|
||||||
|
rencData.message = await gestion.msgEchec(rencData);
|
||||||
|
if (rencData.nbRounds > 1) {
|
||||||
|
rencData.message += ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
|
||||||
|
}
|
||||||
|
rencData.poesie = gestion.poesieEchec;
|
||||||
|
return gestion.postEchec;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async $chatRolledRencontre(row, tmr) {
|
static async msgEchecPasseurFou(tmrData) {
|
||||||
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table-roll-rencontre.html',
|
tmrData.sortReserve = Misc.templateData(tmrData.actor).reve.reserve.list[0];
|
||||||
{
|
if (tmrData.sortReserve) {
|
||||||
roll: row.roll,
|
// Passeur fou positionne sur la case d'un ort en réserve // TODO : Choisir le sort le plus loin ou au hasard
|
||||||
rencontre: row?.document,
|
tmrData.newTMR = TMRUtility.getTMR(tmrData.sortReserve.coord);
|
||||||
percentages: (row.total == 100) ? '%' : '',
|
} else {
|
||||||
tmr,
|
// Déplacement aléatoire de la force du Passeur Fou
|
||||||
isGM: game.user.isGM,
|
const newCoord = await RdDDice.rollOneOf(TMRUtility.getTMRPortee(tmrData.tmr.coord, tmrData.rencontre.force));
|
||||||
});
|
tmrData.newTMR = TMRUtility.getTMR(newCoord);
|
||||||
const messageData = {
|
}
|
||||||
user: game.user.id,
|
if (tmrData.sortReserve) {
|
||||||
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
|
return `Le ${tmrData.rencontre.name} vous dérobe la clé de vos sorts. Vous vous saisissez de lui, mais dans un nuage violet, il vous emporte en ${tmrData.newTMR.label} déclencher votre sort en réserve de ${tmrData.sortReserve.name}.`;
|
||||||
roll: row.roll,
|
}
|
||||||
sound: CONFIG.sounds.dice,
|
else {
|
||||||
content: flavorContent
|
return `Le ${tmrData.rencontre.name} tente de vous dérober la clé de vos sorts. Ne la trouvant pas, il déclenche un nuage violet et vous emporte en ${tmrData.newTMR.label}`;
|
||||||
};
|
}
|
||||||
ChatMessage.create(messageData, { rollMode: "gmroll" });
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async postEchecPasseurFou(tmrDialog, tmrData) {
|
||||||
|
if (tmrData.sortReserve) {
|
||||||
|
await tmrDialog.processSortReserve(tmrData.sortReserve);
|
||||||
|
}
|
||||||
|
await tmrDialog.positionnerDemiReve(tmrData.newTMR.coord);
|
||||||
|
if (tmrData.sortReserve) {
|
||||||
|
tmrDialog.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async onPostEchecTourbillon(tmrDialog, tmrData, cases) {
|
||||||
|
await tmrData.actor.reveActuelIncDec(-cases);
|
||||||
|
await TMRRencontres._toubillonner(tmrDialog, tmrData.actor, cases);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async onPostEchecTourbillonRouge(tmrDialog, 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 _toubillonner(tmrDialog, actor, cases) {
|
||||||
|
let coord = Misc.templateData(actor).reve.tmrpos.coord;
|
||||||
|
for (let i = 0; i < cases; i++) {
|
||||||
|
coord = await TMRUtility.deplaceTMRAleatoire(actor, coord).coord;
|
||||||
|
}
|
||||||
|
await tmrDialog.positionnerDemiReve(coord)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async onPostSuccessReveDeDragon(tmrDialog, tmrData) {
|
||||||
|
if (tmrData.rolled.isPart) {
|
||||||
|
await tmrData.actor.appliquerAjoutExperience(tmrData, true);
|
||||||
|
}
|
||||||
|
await tmrData.actor.resultCombatReveDeDragon(tmrData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async onPostEchecReveDeDragon(tmrDialog, tmrData) {
|
||||||
|
await tmrData.actor.resultCombatReveDeDragon(tmrData);
|
||||||
|
tmrDialog.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
@ -286,43 +287,49 @@ export class TMRUtility {
|
|||||||
const tmr = TMRMapping[coord];
|
const tmr = TMRMapping[coord];
|
||||||
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
|
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
static findTMRLike(type, options = {inclusMauvaise:true}) {
|
|
||||||
const choix = [...Object.values(TMRType)]
|
|
||||||
if (options.inclusMauvaise){
|
|
||||||
choix.push({name: 'Mauvaise'});
|
|
||||||
}
|
|
||||||
const selection = Misc.findAllLike(type, choix).map(it => it.name);
|
|
||||||
if (selection.length == 0) {
|
|
||||||
ui.notifications.warn(`Un type de TMR doit être indiqué, '${type}' n'est pas trouvé dans ${choix}`);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (selection.length > 1) {
|
|
||||||
ui.notifications.warn(`Plusieurs types de TMR pourraient correspondre à '${type}': ${selection}`);
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return selection[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
static typeTmrName(type) {
|
static typeTmrName(type) {
|
||||||
return Misc.upperFirst(TMRType[Grammar.toLowerCaseNoAccent(type)].name);
|
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))
|
return Object.values(TMRType).map(value => Misc.upperFirst(value.name))
|
||||||
.sort()
|
.sort()
|
||||||
.map(name => { return { name: name, selected: typesTMR.includes(name) } });
|
.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) {
|
static isCaseHumide(tmr) {
|
||||||
return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais';
|
return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** Some debug functions */
|
||||||
|
static async setForceRencontre(index, force = undefined) {
|
||||||
|
this.prochaineRencontre = TMRRencontres.getRencontre(index);
|
||||||
|
if (this.prochaineRencontre) {
|
||||||
|
if (force) {
|
||||||
|
this.prochaineRencontre.force = force;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await TMRRencontres.evaluerForceRencontre(this.prochaineRencontre);
|
||||||
|
}
|
||||||
|
console.log("La prochaine rencontre sera:", this.prochaineRencontre.name, " force:", this.prochaineRencontre.force);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.warn("Pas de prochaine rencontre valide pour " + index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static isForceRencontre() {
|
||||||
|
return this.prochaineRencontre;
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static utiliseForceRencontre() {
|
||||||
|
const rencontre = this.prochaineRencontre;
|
||||||
|
this.prochaineRencontre = undefined;
|
||||||
|
return rencontre;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getDirectionPattern() {
|
static async getDirectionPattern() {
|
||||||
return await RdDDice.rollOneOf(tmrRandomMovePatten);
|
return await RdDDice.rollOneOf(tmrRandomMovePatten);
|
||||||
@ -330,15 +337,24 @@ export class TMRUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async deplaceTMRAleatoire(actor, coord) {
|
static async deplaceTMRAleatoire(actor, coord) {
|
||||||
const currentOddq = TMRUtility.coordTMRToOddq(coord);
|
return TMRUtility.deplaceTMRSelonPattern(actor, coord, await TMRUtility.getDirectionPattern(), 1);
|
||||||
const direction = await TMRUtility.getDirectionPattern();
|
}
|
||||||
currentOddq.col = currentOddq.col + direction.col;
|
|
||||||
currentOddq.row = currentOddq.row + direction.row;
|
/* -------------------------------------------- */
|
||||||
if (this.isOddqInTMR(currentOddq)) { // Sortie de carte ! Ré-insertion aléatoire
|
static async deplaceTMRSelonPattern(actor, coordTMR, direction, nTime) {
|
||||||
return TMRUtility.getTMR(TMRUtility.oddqToCoordTMR(currentOddq));
|
let coord;
|
||||||
} else {
|
for (let i = 0; i < nTime; i++) {
|
||||||
return await actor.reinsertionAleatoire('Sortie de carte');
|
let currentOddq = TMRUtility.coordTMRToOddq(coordTMR);
|
||||||
|
currentOddq.col = currentOddq.col + direction.col;
|
||||||
|
currentOddq.row = currentOddq.row + direction.row;
|
||||||
|
if (this.isOddqInTMR(currentOddq)) { // Sortie de carte ! Ré-insertion aléatoire
|
||||||
|
coord = TMRUtility.getTMR(TMRUtility.oddqToCoordTMR(currentOddq));
|
||||||
|
} else {
|
||||||
|
coord = await actor.reinsertionAleatoire('Sortie de carte');
|
||||||
|
}
|
||||||
|
console.log("Nouvelle case iteration !!!", i, coord);
|
||||||
}
|
}
|
||||||
|
return coord;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -350,12 +366,9 @@ export class TMRUtility {
|
|||||||
return Object.values(TMRMapping).filter(filter);
|
return Object.values(TMRMapping).filter(filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getCasesType(type) {
|
|
||||||
return TMRUtility.filterTMR(it => it.type == type).map(it => it.coord);
|
|
||||||
}
|
|
||||||
|
|
||||||
static findTMR(search) {
|
static findTMR(search) {
|
||||||
return TMRUtility.filterTMR(it => Grammar.includesLowerCaseNoAccent(it.label, search) || it.coord == search);
|
const labelSearch = Grammar.toLowerCaseNoAccent(search)
|
||||||
|
return TMRUtility.filterTMR(it => Grammar.toLowerCaseNoAccent(it.label).match(labelSearch) || it.coord == search);
|
||||||
}
|
}
|
||||||
|
|
||||||
static filterTMRCoord(filter) {
|
static filterTMRCoord(filter) {
|
||||||
@ -366,6 +379,18 @@ export class TMRUtility {
|
|||||||
return await RdDDice.rollOneOf(TMRUtility.filterTMR(filter))
|
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
|
/** Returns a list of case inside a given distance
|
||||||
*
|
*
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
import { Grammar } from "../grammar.js";
|
|
||||||
import { Draconique } from "./draconique.js";
|
|
||||||
import { Misc } from "../misc.js";
|
|
||||||
|
|
||||||
export class AugmentationSeuil extends Draconique {
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
type() { return 'tete' }
|
|
||||||
match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('augmentation du seuil de reve'); }
|
|
||||||
manualMessage() { return false }
|
|
||||||
async onActorCreateOwned(actor, tete) {
|
|
||||||
const seuil = Misc.toInt(actor.system.reve.seuil.value) + 2;
|
|
||||||
await actor.update({ "system.reve.seuil.value": seuil })
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,5 @@
|
|||||||
import { Grammar } from "../grammar.js";
|
import { Grammar } from "../grammar.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
import { RdDDice } from "../rdd-dice.js";
|
import { RdDDice } from "../rdd-dice.js";
|
||||||
import { TMRUtility } from "../tmr-utility.js";
|
import { TMRUtility } from "../tmr-utility.js";
|
||||||
import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js";
|
import { tmrConstants, tmrColors, tmrTokenZIndex } from "../tmr-constants.js";
|
||||||
@ -31,14 +32,14 @@ export class Conquete extends Draconique {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _creerConquete(actor, queue) {
|
async _creerConquete(actor, queue) {
|
||||||
let existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => Misc.data(it).data.coord);
|
||||||
let possibles = TMRUtility.filterTMR(tmr => !TMRUtility.isCaseHumide(tmr) && !existants.includes(tmr.coord));
|
let possibles = TMRUtility.filterTMR(tmr => !TMRUtility.isCaseHumide(tmr) && !existants.includes(tmr.coord));
|
||||||
let conquete = await RdDDice.rollOneOf(possibles);
|
let conquete = await RdDDice.rollOneOf(possibles);
|
||||||
await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue.id);
|
await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.system.sourceid]);
|
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ export class Debordement extends Draconique {
|
|||||||
match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('debordement'); }
|
match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('debordement'); }
|
||||||
manualMessage() { return false }
|
manualMessage() { return false }
|
||||||
async onActorCreateOwned(actor, souffle) {
|
async onActorCreateOwned(actor, souffle) {
|
||||||
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
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 tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord)));
|
||||||
await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr, souffle.id);
|
await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr, souffle.id);
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ export class Desorientation extends Draconique {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_typesPossibles(actor) {
|
_typesPossibles(actor) {
|
||||||
const dejaDesorientes = Misc.distinct(actor.items.filter(it => this.isCase(it)).map(it => it.type));
|
const dejaDesorientes = Misc.distinct(actor.data.items.filter(it => this.isCase(it)).map(it => it.type));
|
||||||
return Object.keys(TMRType).filter(it => !dejaDesorientes.includes(it));
|
return Object.keys(TMRType).filter(it => !dejaDesorientes.includes(it));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,7 +42,7 @@ export class Desorientation extends Draconique {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _creerCasesTmr(actor, type, souffle) {
|
async _creerCasesTmr(actor, type, souffle) {
|
||||||
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||||
let tmrs = TMRUtility.filterTMR(it => it.type == type && !existants.includes(it.coord));
|
let tmrs = TMRUtility.filterTMR(it => it.type == type && !existants.includes(it.coord));
|
||||||
for (let tmr of tmrs) {
|
for (let tmr of tmrs) {
|
||||||
await this.createCaseTmr(actor, 'Désorientation: ' + tmr.label, tmr, souffle.id);
|
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
|
* Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR
|
||||||
*/
|
*/
|
||||||
export class Draconique {
|
export class Draconique {
|
||||||
static isCaseTMR(item) { return item.type == 'casetmr'; }
|
static isCaseTMR(itemData) { return itemData.type == 'casetmr'; }
|
||||||
static isQueueDragon(item) { return item.type == 'queue' || item.type == 'ombre'; }
|
static isQueueDragon(itemData) { return itemData.type == 'queue' || itemData.type == 'ombre'; }
|
||||||
static isSouffleDragon(item) { return item.type == 'souffle'; }
|
static isSouffleDragon(itemData) { return itemData.type == 'souffle'; }
|
||||||
static isTeteDragon(item) { return item.type == 'tete'; }
|
static isTeteDragon(itemData) { return itemData.type == 'tete'; }
|
||||||
static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); }
|
static isQueueSouffle(itemData) { return Draconique.isQueueDragon(itemData) || Draconique.isSouffleDragon(itemData); }
|
||||||
|
|
||||||
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.system.coord); }
|
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.data.coord); }
|
||||||
|
|
||||||
static register(draconique) {
|
static register(draconique) {
|
||||||
registeredEffects[draconique.code()] = draconique;
|
registeredEffects[draconique.code()] = draconique;
|
||||||
@ -38,7 +38,8 @@ export class Draconique {
|
|||||||
* @returns true si l'item correspond
|
* @returns true si l'item correspond
|
||||||
*/
|
*/
|
||||||
match(item) {
|
match(item) {
|
||||||
return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item) || Draconique.isTeteDragon(item);
|
const itemData = Misc.data(item);
|
||||||
|
return Draconique.isQueueDragon(itemData) || Draconique.isSouffleDragon(itemData) || Draconique.isTeteDragon(itemData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -114,32 +115,34 @@ export class Draconique {
|
|||||||
* @param {*} coord les coordonnées d'une case. Si undefined toute case du type correspondra,
|
* @param {*} coord les coordonnées d'une case. Si undefined toute case du type correspondra,
|
||||||
*/
|
*/
|
||||||
isCase(item, coord = undefined) {
|
isCase(item, coord = undefined) {
|
||||||
return Draconique.isCaseTMR(item) && item.system.specific == this.code() && (coord ? item.system.coord == coord : true);
|
const itemData = Misc.data(item);
|
||||||
|
return Draconique.isCaseTMR(itemData) && itemData.data.specific == this.code() && (coord ? itemData.data.coord == coord : true);
|
||||||
}
|
}
|
||||||
|
|
||||||
find(list, coord = undefined) {
|
find(list, coord = undefined) {
|
||||||
return list.find(c => this.isCase(c, coord));
|
return list.find(c => this.isCase(Misc.data(c), coord));
|
||||||
}
|
}
|
||||||
|
|
||||||
async createCaseTmr(actor, label, tmr, sourceId = undefined) {
|
async createCaseTmr(actor, label, tmr, sourceId = undefined) {
|
||||||
const casetmrData = {
|
const casetmrData = {
|
||||||
name: label, type: 'casetmr', img: this.img(),
|
name: label, type: 'casetmr', img: this.img(),
|
||||||
system: { coord: tmr.coord, specific: this.code(), sourceid: sourceId }
|
data: { coord: tmr.coord, specific: this.code(), sourceid: sourceId }
|
||||||
};
|
};
|
||||||
await actor.createEmbeddedDocuments('Item', [casetmrData]);
|
await actor.createEmbeddedDocuments('Item', [casetmrData]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteCasesTmr(actor, draconique) {
|
async deleteCasesTmr(actor, draconique) {
|
||||||
let caseTmrs = actor.items.filter(it => this.isCaseForSource(it, draconique));
|
let caseTmrs = actor.data.items.filter(it => this.isCaseForSource(it, draconique));
|
||||||
await actor.deleteEmbeddedDocuments('Item', caseTmrs.map(it => it.id));
|
await actor.deleteEmbeddedDocuments('Item', caseTmrs.map(it => it.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
isCaseForSource(item, draconique) {
|
isCaseForSource(item, draconique) {
|
||||||
return Draconique.isCaseTMR(item) && item.system.specific == this.code() && item.system.sourceid == draconique.id;
|
const itemData = Misc.data(item);
|
||||||
|
return Draconique.isCaseTMR(itemData) && itemData.data.specific == this.code() && itemData.data.sourceid == draconique.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
async onVisiteSupprimer(actor, tmr, onRemoveToken) {
|
async onVisiteSupprimer(actor, tmr, onRemoveToken) {
|
||||||
let existants = actor.items.filter(it => this.isCase(it, tmr.coord));
|
let existants = actor.data.items.filter(it => this.isCase(it, tmr.coord));
|
||||||
await actor.deleteEmbeddedDocuments('Item', existants.map(it => it.id));
|
await actor.deleteEmbeddedDocuments('Item', existants.map(it => it.id));
|
||||||
for (let casetmr of existants) {
|
for (let casetmr of existants) {
|
||||||
onRemoveToken(tmr, casetmr);
|
onRemoveToken(tmr, casetmr);
|
||||||
|
@ -17,7 +17,6 @@ import { Pelerinage } from "./pelerinage.js";
|
|||||||
import { Periple } from "./periple.js";
|
import { Periple } from "./periple.js";
|
||||||
import { UrgenceDraconique } from "./urgence-draconique.js";
|
import { UrgenceDraconique } from "./urgence-draconique.js";
|
||||||
import { Grammar } from "../grammar.js";
|
import { Grammar } from "../grammar.js";
|
||||||
import { AugmentationSeuil } from "./augmentation-seuil.js";
|
|
||||||
|
|
||||||
|
|
||||||
export class EffetsDraconiques {
|
export class EffetsDraconiques {
|
||||||
@ -38,7 +37,6 @@ export class EffetsDraconiques {
|
|||||||
static pelerinage = new Pelerinage();
|
static pelerinage = new Pelerinage();
|
||||||
static periple = new Periple();
|
static periple = new Periple();
|
||||||
static urgenceDraconique = new UrgenceDraconique();
|
static urgenceDraconique = new UrgenceDraconique();
|
||||||
static augmentationSeuil = new AugmentationSeuil();
|
|
||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
Draconique.register(EffetsDraconiques.carteTmr);
|
Draconique.register(EffetsDraconiques.carteTmr);
|
||||||
@ -58,7 +56,6 @@ export class EffetsDraconiques {
|
|||||||
Draconique.register(EffetsDraconiques.pelerinage);
|
Draconique.register(EffetsDraconiques.pelerinage);
|
||||||
Draconique.register(EffetsDraconiques.periple);
|
Draconique.register(EffetsDraconiques.periple);
|
||||||
Draconique.register(EffetsDraconiques.urgenceDraconique);
|
Draconique.register(EffetsDraconiques.urgenceDraconique);
|
||||||
Draconique.register(EffetsDraconiques.augmentationSeuil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -98,7 +95,7 @@ export class EffetsDraconiques {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isSortImpossible(actor) {
|
static isSortImpossible(actor) {
|
||||||
return actor.items.find(it =>
|
return actor.data.items.find(it =>
|
||||||
EffetsDraconiques.conquete.match(it) ||
|
EffetsDraconiques.conquete.match(it) ||
|
||||||
EffetsDraconiques.periple.match(it) ||
|
EffetsDraconiques.periple.match(it) ||
|
||||||
EffetsDraconiques.urgenceDraconique.match(it) ||
|
EffetsDraconiques.urgenceDraconique.match(it) ||
|
||||||
@ -107,7 +104,7 @@ export class EffetsDraconiques {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isSortReserveImpossible(actor) {
|
static isSortReserveImpossible(actor) {
|
||||||
return actor.items.find(it =>
|
return actor.data.items.find(it =>
|
||||||
EffetsDraconiques.conquete.match(it) ||
|
EffetsDraconiques.conquete.match(it) ||
|
||||||
EffetsDraconiques.periple.match(it) ||
|
EffetsDraconiques.periple.match(it) ||
|
||||||
EffetsDraconiques.pelerinage.match(it)
|
EffetsDraconiques.pelerinage.match(it)
|
||||||
@ -115,14 +112,10 @@ export class EffetsDraconiques {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static filterItems(actor, filter, name) {
|
static filterItems(actor, filter, name) {
|
||||||
return actor.filterItems(filter)
|
return actor.data.items.filter(filter)
|
||||||
.filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
|
.filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
static countAugmentationSeuil(actor) {
|
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Augmentation du seuil de rêve').length;
|
|
||||||
}
|
|
||||||
|
|
||||||
static isDonDoubleReve(actor) {
|
static isDonDoubleReve(actor) {
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Don de double-rêve').length>0;
|
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Don de double-rêve').length>0;
|
||||||
}
|
}
|
||||||
@ -157,11 +150,11 @@ export class EffetsDraconiques {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isPontImpraticable(actor) {
|
static isPontImpraticable(actor) {
|
||||||
return actor.items.find(it => EffetsDraconiques.pontImpraticable.match(it));
|
return actor.data.items.find(it => EffetsDraconiques.pontImpraticable.match(it));
|
||||||
}
|
}
|
||||||
|
|
||||||
static isUrgenceDraconique(actor) {
|
static isUrgenceDraconique(actor) {
|
||||||
return actor.items.find(it => EffetsDraconiques.urgenceDraconique.match(it));
|
return actor.data.items.find(it => EffetsDraconiques.urgenceDraconique.match(it));
|
||||||
}
|
}
|
||||||
|
|
||||||
static isPeage(actor) {
|
static isPeage(actor) {
|
||||||
|
@ -30,7 +30,7 @@ export class FermetureCites extends Draconique {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _fermerLesCites(actor, souffle) {
|
async _fermerLesCites(actor, souffle) {
|
||||||
let existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||||
let ouvertes = TMRUtility.filterTMR(it => it.type == 'cite' && !existants.includes(it.coord));
|
let ouvertes = TMRUtility.filterTMR(it => it.type == 'cite' && !existants.includes(it.coord));
|
||||||
for (let tmr of ouvertes) {
|
for (let tmr of ouvertes) {
|
||||||
await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr, souffle.id);
|
await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr, souffle.id);
|
||||||
|
@ -33,7 +33,7 @@ export class Pelerinage extends Draconique {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.system.sourceid]);
|
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ export class PixiTMR {
|
|||||||
for (const [name, img] of Object.entries(PixiTMR.textures)) {
|
for (const [name, img] of Object.entries(PixiTMR.textures)) {
|
||||||
loader = loader.add(name, img);
|
loader = loader.add(name, img);
|
||||||
}
|
}
|
||||||
loader.onError.add((error, reason) => { console.log("ERROR", error, reason) });
|
loader.onLoad.add((error, reason) => { console.log("ERROR", error, reason) });
|
||||||
loader.load( (loader, resources) => {
|
loader.load( (loader, resources) => {
|
||||||
onLoad(loader, resources);
|
onLoad(loader, resources);
|
||||||
for (let onAnimate of this.callbacksOnAnimate) {
|
for (let onAnimate of this.callbacksOnAnimate) {
|
||||||
|
@ -30,7 +30,7 @@ export class PresentCites extends Draconique {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _ajouterPresents(actor, tete) {
|
async _ajouterPresents(actor, tete) {
|
||||||
let existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||||
if (existants.length > 0) {
|
if (existants.length > 0) {
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||||
@ -46,13 +46,15 @@ export class PresentCites extends Draconique {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async choisirUnPresent(casetmr, onChoixPresent) {
|
async choisirUnPresent(casetmr, onChoixPresent) {
|
||||||
const presents = await game.system.rdd.rencontresTMR.getPresentsCite()
|
|
||||||
const buttons = {};
|
|
||||||
presents.forEach(r => buttons['present'+r.id] = { icon: '<i class="fas fa-check"></i>', label: r.name, callback: async () => onChoixPresent(r) });
|
|
||||||
let d = new Dialog({
|
let d = new Dialog({
|
||||||
title: "Présent des cités",
|
title: "Présent des cités",
|
||||||
content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faites votre choix`,
|
content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faite votre choix`,
|
||||||
buttons: buttons
|
buttons: {
|
||||||
|
messager: { icon: '<i class="fas fa-check"></i>', label: "Un Messager des rêves", callback: () => onChoixPresent('messager2d6') },
|
||||||
|
passeur: { icon: '<i class="fas fa-check"></i>', label: "Un Passeur des rêves", callback: () => onChoixPresent('passeur2d6') },
|
||||||
|
fleur: { icon: '<i class="fas fa-check"></i>', label: "Une Fleur des rêves", callback: () => onChoixPresent('fleur2d6') },
|
||||||
|
},
|
||||||
|
default: "fleur"
|
||||||
});
|
});
|
||||||
d.render(true);
|
d.render(true);
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ export class Rencontre extends Draconique {
|
|||||||
async onActorCreateOwned(actor, item) { }
|
async onActorCreateOwned(actor, item) { }
|
||||||
|
|
||||||
code() { return 'rencontre' }
|
code() { return 'rencontre' }
|
||||||
tooltip(rencontre) { return `${rencontre.name} de force ${rencontre.system.force}` }
|
tooltip(rencontre) { return `${rencontre.name} de force ${rencontre.force}` }
|
||||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp' }
|
img() { return 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp' }
|
||||||
|
|
||||||
createSprite(pixiTMR) {
|
createSprite(pixiTMR) {
|
||||||
|
@ -12,8 +12,8 @@ export class ReserveExtensible extends Draconique {
|
|||||||
match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes("reserve extensible"); }
|
match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes("reserve extensible"); }
|
||||||
manualMessage() { return "Vous pouvez re-configurer votre Réserve extensible" }
|
manualMessage() { return "Vous pouvez re-configurer votre Réserve extensible" }
|
||||||
async onActorCreateOwned(actor, tete) {
|
async onActorCreateOwned(actor, tete) {
|
||||||
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
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.system.coord)));
|
const tmr = await TMRUtility.getTMRAleatoire(it => !(it.type == 'fleuve' || existants.includes(it.coord)));
|
||||||
await this.createCaseTmr(actor, "Nouvelle Réserve extensible", tmr, tete.id);
|
await this.createCaseTmr(actor, "Nouvelle Réserve extensible", tmr, tete.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ export class SortReserve extends Draconique {
|
|||||||
manualMessage() { return false }
|
manualMessage() { return false }
|
||||||
async onActorCreateOwned(actor, item) { }
|
async onActorCreateOwned(actor, item) { }
|
||||||
|
|
||||||
code() { return 'sortreserve' }
|
code() { return 'sort' }
|
||||||
tooltip(sort) { return `${sort.name}, r${sort.system.ptreve}` }
|
tooltip(sort) { return `${sort.name}, r${sort.data.ptreve_reel}` }
|
||||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/scroll.webp' }
|
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/scroll.webp' }
|
||||||
|
|
||||||
createSprite(pixiTMR) {
|
createSprite(pixiTMR) {
|
||||||
|
@ -13,8 +13,8 @@ export class TrouNoir extends Draconique {
|
|||||||
manualMessage() { return false }
|
manualMessage() { return false }
|
||||||
|
|
||||||
async onActorCreateOwned(actor, souffle) {
|
async onActorCreateOwned(actor, souffle) {
|
||||||
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
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.system.coord)));
|
const tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord)));
|
||||||
await this.createCaseTmr(actor, 'Trou noir: ' + tmr.label, tmr, souffle.id);
|
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'); }
|
match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
|
||||||
manualMessage() { return false }
|
manualMessage() { return false }
|
||||||
async onActorCreateOwned(actor, queue) {
|
async onActorCreateOwned(actor, queue) {
|
||||||
const coordSortsReserve = (actor.system.reve.reserve?.list.map(it => it.coord)) ?? [];
|
const coordSortsReserve = (Misc.templateData(actor).reve.reserve?.list.map(it => it.coord)) ?? [];
|
||||||
if (coordSortsReserve.length == 0) {
|
if (coordSortsReserve.length == 0) {
|
||||||
// La queue se transforme en idée fixe
|
// La queue se transforme en idée fixe
|
||||||
const ideeFixe = await RdDRollTables.getIdeeFixe();
|
const ideeFixe = await RdDRollTables.getIdeeFixe();
|
||||||
@ -37,7 +37,7 @@ export class UrgenceDraconique extends Draconique {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.system.sourceid]);
|
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
|
||||||
}
|
}
|
||||||
|
|
||||||
code() { return 'urgence' }
|
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
61
packs/botanique.db
Normal file
61
packs/botanique.db
Normal file
File diff suppressed because one or more lines are too long
@ -1,29 +1,27 @@
|
|||||||
{"_id":"0zRL8bOpCXNQnIR4","name":"Ruade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.0zRL8bOpCXNQnIR4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":4,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"0zRL8bOpCXNQnIR4","name":"Ruade","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","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.4GmpkphbsmQjvVVK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"4GmpkphbsmQjvVVK","name":"Escalade","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","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.6DK46pyO0hzEuuUg"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"generale","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"6DK46pyO0hzEuuUg","name":"Morsure","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":[]}
|
||||||
{"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","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":"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","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":"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","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":"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","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":"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","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":"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","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":"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","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":"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","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":"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","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":"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","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":"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","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":"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","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":"Zpl2Bi451vB3r91W","name":"Coup de pied","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Zpl2Bi451vB3r91W"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-coup_de_pied.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":3,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
{"_id":"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":[]}
|
||||||
{"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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":"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,4 +12,3 @@
|
|||||||
{"_id":"gPOQd9NI7AFH0whX","name":"Epée Bâtarde","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":4,"description":"","carac-value":null,"categorie_parade":"epees-lourdes","isparade":true},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-humanoides.YTKld5ggDsHqwYoR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_epee_1_main.webp","effects":[]}
|
{"_id":"gPOQd9NI7AFH0whX","name":"Epée Bâtarde","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":"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":[]}
|
{"_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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"0uc2pMIGL03Hq2Hn"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"1l59lWbtvYp74OTb"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"22EQLBJfHVYs96iC"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"2Rtm78bMKPy8eG4q"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"2i3PndTKG1n3hEUU"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"2j1q9e07ZLlIQDYl"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"3BcC8lSsP5WIyva7"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"3ZjwYyQRatCMnBCi"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"6G0lF06jSryTduAt"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"7TKsit2Mv9mWGq3C"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"8sLXQBqo8XwjAFG0"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"E902EEYZHg3zFKq6"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"F6qL4d4g3qjh045R"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"F8G3rdU1nfJzYwYR"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"HSNOvBR890dsEDw2"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"I0CtQ05xFW6ghcdP"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"JcTX8qMS0z8bmdVt"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"LlELEB0FhymLx6VM"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"NpTDqICR7ZuToQrg"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"NzJJNK0YMAbobu0p"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"OjG8XRbeYtq2jcgB"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"QHUOwjMR6AvepGPm"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"S8PVNgxb7TcFXq9g"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"SY0SsWtZdxSodMcl"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"UUTbsktTcxsIe5L5"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"VChJbtGFtWoiFNky"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"YCHBbRLiMzTH7IBj"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"afGp9CewfyJKecEE"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"df5oN8Ub3dWTVxNj"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"diCCimukdNM6bPub"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"el4lofhhSucMv5xv"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"gMmqdJ9I7Mt8Tg3f"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"gadh6aI5iCM82qpP"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"hghw6Cldrad1CIiJ"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"iPYPgxL2uUnphStc"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"j2xIrFWYqhDM4TcN"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"jShpKV8mVcqWmYvp"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"mN0yghXkFfj2YctJ"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"_id":"sjXBBr85OBk4Yg4t"}
|
{"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":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"_id":"xa4t9Lbt6uLEjap6"}
|
{"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"}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user