Compare commits

..

7 Commits

Author SHA1 Message Date
773b3756a6 Fix odorat-gout 2022-10-28 08:46:46 +02:00
d57cdc2af4 Merge pull request 'Fix: rollCarac pour odorat-goût' (#569) from VincentVk/foundryvtt-reve-de-dragon:v1.5 into v1.5
Reviewed-on: #569
2022-10-28 08:45:31 +02:00
f2d1879135 Fix: rollCarac pour odorat-goût
Recherche d'abord par clé (name)
2022-10-27 22:37:55 +02:00
ea7132468d Merge conteneur 2022-09-25 21:23:50 +02:00
2391fbc4bc Merge pull request 'Drop sur un objet met dans le conteneur parent' (#558) from VincentVk/foundryvtt-reve-de-dragon:v1.5 into v1.5
Reviewed-on: #558
2022-09-25 21:22:46 +02:00
0d2bb2d9a3 Drop sur un objet met dans le conteneur parent
Augmenter la zone pour lacher un objet:
* si c'est un objet similaire, on regroupe
* si c'est un conteneur: on met dans le conteneur
* si c'est un objet dans un conteneur, on met dans le conteneur
* si c'est un objet porté, on met dans les objets portés
2022-09-25 17:47:58 +02:00
7198eb621d Fix entite 2022-09-11 16:11:13 +02:00
160 changed files with 3159 additions and 2731 deletions

1
foundryvtt-reve-de-dragon Symbolic link
View File

@ -0,0 +1 @@
foundryvtt-reve-de-dragon

View File

@ -27,11 +27,11 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
/* -------------------------------------------- */
async getData() {
let formData = await super.getData()
//console.log("Creature : ", formData, formData.system)
let formData = await super.getData();
console.log("Creature : ", formData);
formData.calc = {
caracTotal: RdDCarac.computeTotal(formData.system.carac),
resumeBlessures: this.actor.computeResumeBlessure(formData.system.blessures),
caracTotal: RdDCarac.computeTotal(formData.data.carac),
resumeBlessures: this.actor.computeResumeBlessure(formData.data.blessures),
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
surEncombrementMessage: this.actor.getMessageSurEncombrement()
}

View File

@ -25,21 +25,23 @@ export class RdDActorEntiteSheet extends ActorSheet {
/* -------------------------------------------- */
async getData() {
const objectData = Misc.data(this.object);
let formData = {
title: this.title,
id: this.actor.id,
type: this.actor.type,
img: this.actor.img,
name: this.actor.name,
id: objectData.id,
type: objectData.type,
img: objectData.img,
name: objectData.name,
// actor: this.object,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
system: foundry.utils.deepClone(this.actor.system),
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
data: foundry.utils.deepClone(Misc.templateData(this.object)),
effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)),
// items: items,
limited: this.actor.limited,
limited: this.object.limited,
options: this.options,
owner: this.actor.isOwner,
itemsByType: Misc.classify(this.actor.items.map(i => foundry.utils.deepClone(i))),
owner: this.document.isOwner,
itemsByType: Misc.classify(this.object.items.map(i => foundry.utils.deepClone(i.data))),
};
formData.options.isGM = game.user.isGM;
@ -139,6 +141,6 @@ export class RdDActorEntiteSheet extends ActorSheet {
/** @override */
_updateObject(event, formData) {
// Update the Actor
return this.actor.update(formData);
return this.object.update(formData);
}
}

View File

@ -36,51 +36,54 @@ export class RdDActorSheet extends ActorSheet {
/* -------------------------------------------- */
async getData() {
const objectData = Misc.data(this.object);
this.timerRecherche = undefined;
let formData = {
title: this.title,
id: this.actor.id,
type: this.actor.type,
img: this.actor.img,
name: this.actor.name,
id: objectData.id,
type: objectData.type,
img: objectData.img,
name: objectData.name,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
system: foundry.utils.deepClone(this.actor.system),
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
limited: this.actor.limited,
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.actor.isOwner,
itemsByType: Misc.classify(this.actor.items.map(i => foundry.utils.deepClone(i))),
}
RdDUtility.filterItemsPerTypeForSheet(formData)
owner: this.document.isOwner,
itemsByType: Misc.classify(this.object.items.map(i => foundry.utils.deepClone(i.data))),
};
RdDUtility.filterItemsPerTypeForSheet(formData);
formData.options.isGM = game.user.isGM;
if (formData.type == 'creature') return formData; // Shortcut
formData.competenceByCategory = Misc.classify(formData.competences, it => it.system.categorie)
formData.competenceByCategory = Misc.classify(formData.competences, it => it.data.categorie);
formData.calc = {
comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.competences),
competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.competences),
caracTotal: RdDCarac.computeTotal(formData.system.carac, formData.system.beaute),
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.system.sante.fatigue.value, formData.system.sante.endurance.max),
resumeBlessures: this.actor.computeResumeBlessure(formData.system.blessures),
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.system.isVisible = this.options.recherche
item.visible = this.options.recherche
? RdDItemCompetence.nomContientTexte(item, this.options.recherche.text)
: (!this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item));
RdDItemCompetence.levelUp(item, formData.system.compteurs.experience.value);
RdDItemCompetence.levelUp(item, formData.data.compteurs.experience.value);
});
Object.values(formData.system.carac).forEach(c => {
Object.values(formData.data.carac).forEach(c => {
RdDCarac.levelUp(c);
});
@ -88,9 +91,9 @@ export class RdDActorSheet extends ActorSheet {
// 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);
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;
@ -100,8 +103,8 @@ export class RdDActorSheet extends ActorSheet {
formData.hautreve = {
isDemiReve: this.actor.getEffectByLabel("Demi-rêve"),
sortsReserve: formData.system.reve.reserve.list,
rencontres: duplicate(formData.system.reve.rencontre.list),
sortsReserve: formData.data.reve.reserve.list,
rencontres: duplicate(formData.data.reve.rencontre.list),
casesTmr: formData.itemsByType.casetmr,
cacheTMR: this.actor.isTMRCache()
}
@ -114,7 +117,7 @@ export class RdDActorSheet extends ActorSheet {
montures: this.actor.listeMontures(),
suivants: this.actor.listeSuivants()
}
if (this.actor.getBestDraconic().system.niveau > -11 && !this.actor.isHautRevant()) {
if (this.actor.getBestDraconic().data.niveau > -11 && !this.actor.isHautRevant()) {
ui.notifications.error(`${this.actor.name} a des compétences draconiques, mais pas le don de Haut-Rêve!
<br>Ajoutez-lui la tête "Don de Haut-Rêve" pour lui permettre d'utiliser ses compétences et d'accéder aux terres médianes du rêve`);
}
@ -127,16 +130,16 @@ export class RdDActorSheet extends ActorSheet {
/* -------------------------------------------- */
async _onDropActor(event, dragData) {
const dropActor = fromUuidSync(dragData.uuid);
this.actor.addSubActeur(dropActor);
console.log("_onDropActor", this.actor.id, dragData);
this.actor.addSubActeur(dragData.id || dragData.data._id);
super._onDropActor(event, dragData);
}
/* -------------------------------------------- */
async _onDropItem(event, dragData) {
const destItemId = $(event.target)?.closest('.item').attr('data-item-id')
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor.id, dragData, this.objetVersConteneur)
const callSuper = await this.actor.processDropItem(dropParams)
const destItemId = $(event.target)?.closest('.item').attr('data-item-id');
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor.id, dragData, this.objetVersConteneur);
const callSuper = await this.actor.processDropItem(dropParams);
if (callSuper) {
await super._onDropItem(event, dragData)
}
@ -329,7 +332,7 @@ export class RdDActorSheet extends ActorSheet {
});
// Initiative pour l'arme
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) {
let action = this._getEventArmeCombat(event);
RdDCombatManager.rollInitiativeAction(combatant._id, action);
@ -380,11 +383,13 @@ export class RdDActorSheet extends ActorSheet {
if (this.options.editCaracComp) {
// On carac change
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));
});
html.find('input.carac-xp').change(async event => {
let caracName = event.currentTarget.name.replace(".xp", "").replace("system.carac.", "");
html.find('.carac-xp').change(async event => {
let caracName = event.currentTarget.name.replace(".xp", "").replace("data.carac.", "");
//console.log("Value changed :", event, caracName);
this.actor.updateCaracXP(caracName, parseInt(event.target.value));
});
// On competence change
@ -394,12 +399,12 @@ export class RdDActorSheet extends ActorSheet {
this.actor.updateCompetence(compName, parseInt(event.target.value));
});
// 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;
this.actor.updateCompetenceXP(compName, parseInt(event.target.value));
});
// 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;
this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value));
});
@ -450,7 +455,7 @@ export class RdDActorSheet extends ActorSheet {
// On pts de reve change
html.find('.pointsreve-value').change(async event => {
let reveValue = event.currentTarget.value;
this.actor.update({ "system.reve.reve.value": reveValue });
this.actor.update({ "data.reve.reve.value": reveValue });
});
// On seuil de reve change
@ -543,9 +548,9 @@ export class RdDActorSheet extends ActorSheet {
const li = $(event.currentTarget)?.parents(".item");
let armeName = li.data("arme-name");
let compName = li.data('competence-name');
const arme = this.armesList.find(a => a.name == armeName && a.system.competence == compName);
const arme = this.armesList.find(a => a.name == armeName && a.data.competence == compName);
if (!arme) {
return { name: armeName, system: { competence: compName } };
return { name: armeName, data: { competence: compName } };
}
return arme;
}
@ -567,7 +572,7 @@ export class RdDActorSheet extends ActorSheet {
/** @override */
_updateObject(event, formData) {
// Update the Actor
return this.actor.update(formData);
return this.object.update(formData);
}
async splitItem(item) {
@ -576,11 +581,11 @@ export class RdDActorSheet extends ActorSheet {
}
async _onSplitItem(item, split) {
if (split >= 1 && split < item.system.quantite) {
if (split >= 1 && split < Misc.data(item).data.quantite) {
await item.diminuerQuantite(split);
const splitItem = duplicate(item);
splitItem.system.quantite = split;
await this.actor.createEmbeddedDocuments('Item', [splitItem])
const itemData = duplicate(Misc.data(item));
itemData.data.quantite = split;
await this.actor.createEmbeddedDocuments('Item', [itemData])
}
}

View File

@ -27,20 +27,21 @@ export class RdDActorVehiculeSheet extends ActorSheet {
/* -------------------------------------------- */
async getData() {
const objectData = Misc.data(this.object);
let formData = {
title: this.title,
id: this.actor.id,
type: this.actor.type,
img: this.actor.img,
name: this.actor.name,
id: objectData.id,
type: objectData.type,
img: objectData.img,
name: objectData.name,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
system: foundry.utils.deepClone(this.actor.system),
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
limited: this.actor.limited,
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.actor.isOwner,
itemsByType: Misc.classify(this.actor.items.map(i => foundry.utils.deepClone(i))),
owner: this.document.isOwner,
itemsByType: Misc.classify(this.object.items.map(i => foundry.utils.deepClone(i.data))),
};
RdDUtility.filterItemsPerTypeForSheet(formData);
@ -81,7 +82,7 @@ export class RdDActorVehiculeSheet extends ActorSheet {
async monnaieIncDec(id, value) {
let monnaie = this.getMonnaie(id);
if (monnaie) {
const quantite = Math.max(0, monnaie.system.quantite + value);
const quantite = Math.max(0, Misc.templateData(monnaie).quantite + value);
await this.updateEmbeddedDocuments('Item', [{ _id: monnaie.id, 'data.quantite': quantite }]);
}
}
@ -159,6 +160,6 @@ export class RdDActorVehiculeSheet extends ActorSheet {
/** @override */
_updateObject(event, formData) {
// Update the Actor
return this.actor.update(formData);
return this.object.update(formData);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
import { Misc } from "./misc.js";
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
export const MESSAGE_DATA = 'message-data';
/**
* Class providing helper methods to get the list of users, and
@ -18,50 +19,61 @@ export class ChatUtility {
/* -------------------------------------------- */
static notifyUser(userId, level = 'info', message) {
const socketData = {
const data = {
userId: userId, level: level, message: message
};
if (game.user.id == userId) {
ChatUtility.onNotifyUser(socketData);
ChatUtility.onNotifyUser(data);
}
else {
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_user_ui_notifications", data: socketData
msg: "msg_user_ui_notifications", data: data
});
}
}
static onNotifyUser(socketData) {
if (game.user.id == socketData.userId) {
switch (socketData.level) {
case 'warn': ui.notifications.warn(socketData.message); break;
case 'error': ui.notifications.error(socketData.message); break;
default: ui.notifications.info(socketData.message); break;
static onNotifyUser(data) {
if (game.user.id == data.userId) {
switch (data.level) {
case 'warn': ui.notifications.warn(data.message); break;
case 'error': ui.notifications.error(data.message); break;
default: ui.notifications.info(data.message); break;
}
}
}
/* -------------------------------------------- */
static onRemoveMessages(socketData) {
static onRemoveMessages(data) {
if (Misc.isUniqueConnectedGM()) {
if (socketData.part) {
const toDelete = game.messages.filter(it => it.content.includes(socketData.part));
if (data.part) {
const toDelete = game.messages.filter(it => it.data.content.includes(data.part));
toDelete.forEach(it => it.delete());
}
if (socketData.messageId) {
game.messages.get(socketData.messageId)?.delete();
if (data.messageId) {
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()) {
ChatUtility.onRemoveMessages(socketData);
ChatUtility.onRemoveMessages(data);
}
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) {
return Misc.getUsers().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) {
console.log("blindMessageToGM", socketData);
static handleGMChatMessage(data) {
console.log("blindMessageToGM", data);
if (game.user.isGM) { // message privé pour GM only
socketData.user = game.user.id;
ChatMessage.create(socketData);
data.user = game.user.id;
ChatMessage.create(data);
}
}
static async setMessageData(chatMessage, key, flag) {
if (flag) {
await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(flag));
static async setMessageData(chatMessage, key, data) {
if (data) {
await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(data));
}
}

View File

@ -10,9 +10,9 @@ export class DialogCreateSigneDraconique extends Dialog {
const signe = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
let dialogData = {
signe: signe,
tmrs: TMRUtility.listSelectedTMR(signe.system.typesTMR ?? []),
tmrs: TMRUtility.listSelectedTMR(signe.data.typesTMR ?? []),
actors: game.actors.filter(actor => actor.isHautRevant()).map(actor => {
let actorData = duplicate(actor);
let actorData = duplicate(Misc.data(actor));
actorData.selected = actor.hasPlayerOwner;
return actorData;
})
@ -38,7 +38,7 @@ export class DialogCreateSigneDraconique extends Dialog {
}
async _onCreerSigneActeurs() {
await $("[name='signe.system.ephemere']").change();
await $("[name='signe.data.ephemere']").change();
await $(".signe-xp-sort").change();
this.validerSigne();
this.dialogData.actors.filter(it => it.selected).map(it => game.actors.get(it._id))
@ -48,31 +48,31 @@ export class DialogCreateSigneDraconique extends Dialog {
async _createSigneForActor(actor, signe) {
actor.createEmbeddedDocuments("Item", [signe]);
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", {
signe: signe,
alias: actor.name
alias: Misc.data(actor).name
})
});
}
validerSigne() {
this.dialogData.signe.name = $("[name='signe.name']").val();
this.dialogData.signe.system.valeur.norm = $("[name='signe.system.valeur.norm']").val();
this.dialogData.signe.system.valeur.sign = $("[name='signe.system.valeur.sign']").val();
this.dialogData.signe.system.valeur.part = $("[name='signe.system.valeur.part']").val();
this.dialogData.signe.system.difficulte = $("[name='signe.system.difficulte']").val();
this.dialogData.signe.system.ephemere = $("[name='signe.system.ephemere']").prop("checked");
this.dialogData.signe.system.duree = $("[name='signe.system.duree']").val();
this.dialogData.signe.system.typesTMR = $(".select-tmr").val();
this.dialogData.signe.data.valeur.norm = $("[name='signe.data.valeur.norm']").val();
this.dialogData.signe.data.valeur.sign = $("[name='signe.data.valeur.sign']").val();
this.dialogData.signe.data.valeur.part = $("[name='signe.data.valeur.part']").val();
this.dialogData.signe.data.difficulte = $("[name='signe.data.difficulte']").val();
this.dialogData.signe.data.ephemere = $("[name='signe.data.ephemere']").prop("checked");
this.dialogData.signe.data.duree = $("[name='signe.data.duree']").val();
this.dialogData.signe.data.typesTMR = $(".select-tmr").val();
}
/* -------------------------------------------- */
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("[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));
}
@ -81,19 +81,19 @@ export class DialogCreateSigneDraconique extends Dialog {
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
$("[name='signe.name']").val(newSigne.name);
$("[name='signe.system.valeur.norm']").val(newSigne.system.valeur.norm);
$("[name='signe.system.valeur.sign']").val(newSigne.system.valeur.sign);
$("[name='signe.system.valeur.part']").val(newSigne.system.valeur.part);
$("[name='signe.system.difficulte']").val(newSigne.system.difficulte);
$("[name='signe.system.duree']").val(newSigne.system.duree);
$("[name='signe.system.ephemere']").prop("checked", newSigne.system.ephemere);
$(".select-tmr").val(newSigne.system.typesTMR);
this.setEphemere(newSigne.system.ephemere);
$("[name='signe.data.valeur.norm']").val(newSigne.data.valeur.norm);
$("[name='signe.data.valeur.sign']").val(newSigne.data.valeur.sign);
$("[name='signe.data.valeur.part']").val(newSigne.data.valeur.part);
$("[name='signe.data.difficulte']").val(newSigne.data.difficulte);
$("[name='signe.data.duree']").val(newSigne.data.duree);
$("[name='signe.data.ephemere']").prop("checked", newSigne.data.ephemere);
$(".select-tmr").val(newSigne.data.typesTMR);
this.setEphemere(newSigne.data.ephemere);
}
async setEphemere(ephemere) {
this.dialogData.signe.system.ephemere = ephemere;
HtmlUtility._showControlWhen($(".signe-system-duree"), ephemere);
this.dialogData.signe.data.ephemere = ephemere;
HtmlUtility._showControlWhen($(".signe-data-duree"), ephemere);
}
async onSelectActor(event) {
@ -111,8 +111,8 @@ export class DialogCreateSigneDraconique extends Dialog {
onValeurXpSort(event) {
const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0;
const xp = Number(event.currentTarget.value);
const oldValeur = this.dialogData.signe.system.valeur;
this.dialogData.signe.system.valeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
const oldValeur = this.dialogData.signe.data.valeur;
this.dialogData.signe.data.valeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
}
}

View File

@ -9,7 +9,7 @@ export class DialogFabriquerPotion extends Dialog {
let potionData = DialogFabriquerPotion.prepareData(actor, item);
let conf = {
title: `Fabriquer une potion de ${potionData.system.categorie}`,
title: `Fabriquer une potion de ${potionData.data.categorie}`,
content: await renderTemplate(dialogConfig.html, potionData),
default: potionData.buttonName,
};
@ -24,9 +24,9 @@ export class DialogFabriquerPotion extends Dialog {
/* -------------------------------------------- */
static prepareData(actor, item) {
let potionData = duplicate(item)
potionData.nbBrinsSelect = RdDUtility.buildListOptions(1, potionData.system.quantite);
potionData.nbBrins = Math.min(potionData.system.quantite, DialogFabriquerPotion.getNombreBrinOptimal(potionData));
let potionData = duplicate(Misc.data(item));
potionData.nbBrinsSelect = RdDUtility.buildListOptions(1, potionData.data.quantite);
potionData.nbBrins = Math.min(potionData.data.quantite, DialogFabriquerPotion.getNombreBrinOptimal(potionData));
potionData.buttonName = "Fabriquer";
return potionData;
}
@ -46,9 +46,9 @@ export class DialogFabriquerPotion extends Dialog {
}
static getNombreBrinOptimal(herbeData) {
switch (herbeData.system.categorie ?? '') {
case "Soin": return 12 - herbeData.system.niveau;
case "Repos": return 7 - herbeData.system.niveau;
switch (herbeData.data.categorie ?? '') {
case "Soin": return 12 - herbeData.data.niveau;
case "Repos": return 7 - herbeData.data.niveau;
}
return 1;
}

View File

@ -34,7 +34,7 @@ export class DialogItemAchat extends Dialog {
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
const buttons = {};
if (isConsommable) {
buttons["consommer"] = { label: venteData.item.system.boisson ? "Boire" : "Manger", callback: it => { this.onAchatConsommer(); } }
buttons["consommer"] = { label: venteData.item.data.boisson ? "Boire" : "Manger", callback: it => { this.onAchatConsommer(); } }
}
buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
buttons["decliner"] = { label: "Décliner", callback: it => { } };
@ -59,8 +59,8 @@ export class DialogItemAchat extends Dialog {
let venteData = {
item: JSON.parse(jsondata),
vendeurId: vendeurId,
vendeur: vendeur,
acheteur:acheteur,
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),

View File

@ -38,22 +38,22 @@ export class DialogConsommer extends Dialog {
/* -------------------------------------------- */
static prepareData(actor, item) {
item = duplicate(item);
const itemData = duplicate(Misc.data(item));
let consommerData = {
item: item,
cuisine: actor.getCompetence('cuisine'),
item: itemData,
cuisine: Misc.data(actor.getCompetence('cuisine')),
choix: {
doses: 1,
seForcer: false,
}
}
switch (item.type) {
switch (itemData.type) {
case 'nourritureboisson':
consommerData.title = item.system.boisson ? `${item.name}: boire une dose` : `${item.name}: manger une portion`;
consommerData.buttonName = item.system.boisson ? "Boire" : "Manger";
consommerData.title = itemData.data.boisson ? `${itemData.name}: boire une dose` : `${itemData.name}: manger une portion`;
consommerData.buttonName = itemData.data.boisson ? "Boire" : "Manger";
break;
case 'potion':
consommerData.title = `${item.name}: boire la potion`;
consommerData.title = `${itemData.name}: boire la potion`;
consommerData.buttonName = "Boire";
break;
}
@ -61,11 +61,11 @@ export class DialogConsommer extends Dialog {
return consommerData;
}
static calculDoses(consommer) {
const doses = consommer.choix.doses;
consommer.totalSust = Misc.keepDecimals(doses * (consommer.item.system.sust ?? 0), 2);
consommer.totalDesaltere = consommer.item.system.boisson
? Misc.keepDecimals(doses * (consommer.item.system.desaltere ?? 0), 2)
static calculDoses(consommerData) {
const doses = consommerData.choix.doses;
consommerData.totalSust = Misc.keepDecimals(doses * (consommerData.item.data.sust ?? 0), 2);
consommerData.totalDesaltere = consommerData.item.data.boisson
? Misc.keepDecimals(doses * (consommerData.item.data.desaltere ?? 0), 2)
: 0;
}

View File

@ -4,14 +4,15 @@ import { Misc } from "./misc.js";
export class DialogItemVente extends Dialog {
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 = {
item: item,
item: itemData,
alias: item.actor?.name ?? game.user.name,
vendeurId: item.actor?.id,
prixOrigine: item.system.cout,
prixUnitaire: item.system.cout,
prixLot: item.system.cout,
prixOrigine: itemData.data.cout,
prixUnitaire: itemData.data.cout,
prixLot: itemData.data.cout,
tailleLot: 1,
quantiteNbLots: quantite,
quantiteMaxLots: quantite,

View File

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

View File

@ -3,9 +3,10 @@ import { Misc } from "./misc.js";
export class DialogSplitItem extends Dialog {
static async create(item, callback) {
const itemData = Misc.data(item);
const splitData = {
item: item,
choix: { quantite: 1, max: item.system.quantite - 1 }
item: itemData,
choix: { quantite: 1, max: itemData.data.quantite - 1 }
};
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-split.html`, splitData);
return new DialogSplitItem(item, splitData, html, callback)

View File

@ -9,7 +9,7 @@ export class DialogStress extends Dialog {
immediat: false,
actors: game.actors.filter(actor => actor.hasPlayerOwner && actor.isPersonnage())
.map(actor => {
let actorData = duplicate(actor);
let actorData = duplicate(Misc.data(actor));
actorData.selected = actor.hasPlayerOwner;
return actorData;
})

View File

@ -0,0 +1,9 @@
/* -------------------------------------------- */
import { RdDUtility } from "./rdd-utility.js";
/* -------------------------------------------- */
// Activate chat listeners defined
// Hooks.on('renderChatLog', (log, html, data) => {
// RdDUtility.chatListeners(html);
// });

View File

@ -19,34 +19,36 @@ const nomCategorieParade = {
/* -------------------------------------------- */
export class RdDItemArme extends Item {
static isArme(item) {
return (item.type == 'competencecreature' && item.system.iscombat) || item.type == 'arme';
static isArme(itemData) {
itemData = Misc.data(itemData);
return (itemData.type == 'competencecreature' && itemData.data.iscombat) || itemData.type == 'arme';
}
/* -------------------------------------------- */
static getArme(arme) {
switch (arme ? arme.type : '') {
case 'arme': return arme;
static getArmeData(armeData) {
armeData = Misc.data(armeData);
switch (armeData ? armeData.type : '') {
case 'arme': return armeData;
case 'competencecreature':
return RdDItemCompetenceCreature.toActionArme(arme);
return RdDItemCompetenceCreature.toActionArme(armeData);
}
return RdDItemArme.mainsNues();
}
static computeNiveauArmes(armes, competences) {
for (const arme of armes) {
arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
arme.data.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
}
}
static niveauCompetenceArme(arme, competences) {
const compArme = competences.find(it => it.name == arme.system.competence);
return compArme?.system.niveau ?? -8;
const compArme = competences.find(it => it.name == arme.data.competence);
return compArme?.data.niveau ?? -8;
}
/* -------------------------------------------- */
static getNomCategorieParade(arme) {
const categorie = arme?.system ? RdDItemArme.getCategorieParade(arme) : arme;
const categorie = arme?.data ? RdDItemArme.getCategorieParade(arme) : arme;
return nomCategorieParade[categorie];
}
@ -64,20 +66,21 @@ export class RdDItemArme extends Item {
/* -------------------------------------------- */
static getCategorieParade(armeData) {
if (armeData.system.categorie_parade) {
return armeData.system.categorie_parade;
armeData = Misc.data(armeData);
if (armeData.data.categorie_parade) {
return armeData.data.categorie_parade;
}
// pour compatibilité avec des personnages existants
if (armeData.type == 'competencecreature' || armeData.system.categorie == 'creature') {
return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '');
if (armeData.type == 'competencecreature' || armeData.data.categorie == 'creature') {
return armeData.data.categorie_parade || (armeData.data.isparade ? 'armes-naturelles' : '');
}
if (!armeData.type.match(/arme|competencecreature/)) {
return '';
}
if (armeData.system.competence == undefined) {
if (armeData.data.competence == undefined) {
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('hache')) return 'haches';
@ -134,21 +137,22 @@ export class RdDItemArme extends Item {
/* -------------------------------------------- */
static armeUneOuDeuxMains(armeData, aUneMain) {
if (armeData && !armeData.system.cac) {
armeData.system.unemain = armeData.system.unemain || !armeData.system.deuxmains;
const uneOuDeuxMains = armeData.system.unemain && armeData.system.deuxmains;
const containsSlash = !Number.isInteger(armeData.system.dommages) && armeData.system.dommages.includes("/");
armeData = Misc.data(armeData);
if (armeData && !armeData.data.cac) {
armeData.data.unemain = armeData.data.unemain || !armeData.data.deuxmains;
const uneOuDeuxMains = armeData.data.unemain && armeData.data.deuxmains;
const containsSlash = !Number.isInteger(armeData.data.dommages) && armeData.data.dommages.includes("/");
if (containsSlash) { // Sanity check
armeData = duplicate(armeData);
const tableauDegats = armeData.system.dommages.split("/");
const tableauDegats = armeData.data.dommages.split("/");
if (aUneMain)
armeData.system.dommagesReels = Number(tableauDegats[0]);
armeData.data.dommagesReels = Number(tableauDegats[0]);
else // 2 mains
armeData.system.dommagesReels = Number(tableauDegats[1]);
armeData.data.dommagesReels = Number(tableauDegats[1]);
}
else {
armeData.system.dommagesReels = Number(armeData.system.dommages);
armeData.data.dommagesReels = Number(armeData.data.dommages);
}
if (uneOuDeuxMains != containsSlash) {
@ -158,22 +162,23 @@ export class RdDItemArme extends Item {
return armeData;
}
static isArmeUtilisable(arme) {
return arme.type == 'arme' && arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0);
static isArmeUtilisable(itemData) {
itemData = Misc.data(itemData);
return itemData.type == 'arme' && itemData.data.equipe && (itemData.data.resistance > 0 || itemData.data.portee_courte > 0);
}
static ajoutCorpsACorps(armes, competences, carac) {
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { system: { niveau: -6 } };
let init = RdDCombatManager.calculInitiative(corpsACorps.system.niveau, carac['melee'].value);
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.system.niveau, initiative: init }));
//armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { data: { niveau: -6 } };
let init = RdDCombatManager.calculInitiative(corpsACorps.data.niveau, carac['melee'].value);
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.data.niveau, initiative: init }));
//armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.data.niveau, initiative: init }));
}
static corpsACorps(mainsNuesActor) {
static corpsACorps(actorData) {
const corpsACorps = {
name: 'Corps à corps',
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
system: {
data: {
equipe: true,
rapide: true,
force: 0,
@ -184,24 +189,24 @@ export class RdDItemArme extends Item {
categorie_parade: 'sans-armes'
}
};
mergeObject(corpsACorps.system, mainsNuesActor ?? {}, { overwrite: false });
mergeObject(corpsACorps.data, actorData ?? {}, { overwrite: false });
return corpsACorps;
}
static mainsNues(mainsNuesActor) {
const mainsNues = RdDItemArme.corpsACorps(mainsNuesActor)
mainsNues.name = 'Mains nues'
mainsNues.system.cac = 'pugilat'
mainsNues.system.baseInit = 4
static mainsNues(actorData) {
const mainsNues = RdDItemArme.corpsACorps(actorData);
mainsNues.name = 'Mains nues';
mainsNues.data.cac = 'pugilat';
mainsNues.data.baseInit = 4;
return mainsNues;
}
static empoignade(mainsNuesActor) {
const empoignade = RdDItemArme.corpsACorps(mainsNuesActor)
empoignade.name = 'Empoignade'
empoignade.system.cac = 'empoignade'
empoignade.system.baseInit = 3
empoignade.system.mortalite = 'empoignade'
return empoignade
static empoignade(actorData) {
const empoignade = RdDItemArme.corpsACorps(actorData);
empoignade.name = 'Empoignade';
empoignade.data.cac = 'empoignade';
empoignade.data.baseInit = 3;
empoignade.data.mortalite = 'empoignade';
return empoignade;
}
}

View File

@ -76,10 +76,10 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static getCategorie(competence) {
return competence?.system.categorie;
return Misc.data(competence)?.data.categorie;
}
static isDraconic(competence) {
return competence?.system.categorie == 'draconic';
return Misc.data(competence)?.data.categorie == 'draconic';
}
/* -------------------------------------------- */
@ -89,9 +89,9 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static isCompetenceArme(competence) {
switch (competence.system.categorie) {
switch (Misc.templateData(competence).categorie) {
case 'melee':
return competence.name != 'Esquive';
return Misc.data(competence).name != 'Esquive';
case 'tir':
case 'lancer':
return true;
@ -101,15 +101,15 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static isArmeUneMain(competence) {
return competence.name.toLowerCase().includes("1 main");
return Misc.data(competence)?.name.toLowerCase().includes("1 main");
}
static isArme2Main(competence) {
return competence.name.toLowerCase().includes("2 main");
return Misc.data(competence)?.name.toLowerCase().includes("2 main");
}
/* -------------------------------------------- */
static isMalusEncombrementTotal(competence) {
return competence?.name.toLowerCase().match(/(natation|acrobatie)/) || 0;
return Misc.data(competence)?.name.toLowerCase().match(/(natation|acrobatie)/);
}
/* -------------------------------------------- */
@ -133,10 +133,11 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static computeXP(competence) {
const factor = competence.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double !
const xpNiveau = RdDItemCompetence.computeDeltaXP(competence.system.base, competence.system.niveau ?? competence.system.base);
const xp = competence.system.xp ?? 0;
const xpSort = competence.system.xp_sort ?? 0;
const itemData = Misc.data(competence);
const factor = itemData.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double !
const xpNiveau = RdDItemCompetence.computeDeltaXP(itemData.data.base, itemData.data.niveau ?? itemData.data.base);
const xp = itemData.data.xp ?? 0;
const xpSort = itemData.data.xp_sort ?? 0;
return factor * (xpNiveau + xp) + xpSort;
}
@ -145,7 +146,7 @@ export class RdDItemCompetence extends Item {
return competenceTroncs.map(
list => list.map(name => RdDItemCompetence.findCompetence(competences, name))
// calcul du coût xp jusqu'au niveau 0 maximum
.map(it => RdDItemCompetence.computeDeltaXP(it?.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())
.splice(0, list.length - 1) // prendre toutes les valeurs sauf l'une des plus élevées
.reduce(Misc.sum(), 0)
@ -161,10 +162,11 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static computeCompetenceXPCost(competence) {
let xp = RdDItemCompetence.getDeltaXp(competence.system.base, competence.system.niveau ?? competence.system.base);
xp += competence.system.xp ?? 0;
const compData = Misc.data(competence);
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 !
xp += competence.system.xp_sort ?? 0;
xp += compData.data.xp_sort ?? 0;
return xp;
}
@ -173,39 +175,39 @@ export class RdDItemCompetence extends Item {
let economie = 0;
for (let troncList of competenceTroncs) {
let list = troncList.map(name => RdDItemCompetence.findCompetence(competences, name))
.sort(Misc.descending(c => 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.map(c => c).forEach(c => {
economie += RdDItemCompetence.getDeltaXp(c.system.base, Math.min(c.system.niveau, 0))
list.map(c => Misc.templateData(c)).forEach(tplData => {
economie += RdDItemCompetence.getDeltaXp(tplData.base, Math.min(tplData.niveau, 0));
});
}
return economie;
}
/* -------------------------------------------- */
static levelUp(item, stressTransforme) {
item.system.xpNext = RdDItemCompetence.getCompetenceNextXp(item.system.niveau);
const xpManquant = item.system.xpNext - item.system.xp;
item.system.isLevelUp = xpManquant <= 0;
item.system.isStressLevelUp = (xpManquant > 0 && stressTransforme >= xpManquant && item.system.niveau < item.system.niveau_archetype);
item.system.stressXpMax = 0;
if (xpManquant > 0 && stressTransforme > 0 && item.system.niveau < item.system.niveau_archetype) {
item.system.stressXpMax = Math.min(xpManquant , stressTransforme);
static levelUp(itemData, stressTransforme) {
itemData.data.xpNext = RdDItemCompetence.getCompetenceNextXp(itemData.data.niveau);
const xpManquant = itemData.data.xpNext - itemData.data.xp;
itemData.data.isLevelUp = xpManquant <= 0;
itemData.data.isStressLevelUp = (xpManquant > 0 && stressTransforme >= xpManquant && itemData.data.niveau < itemData.data.niveau_archetype);
itemData.data.stressXpMax = 0;
if (xpManquant > 0 && stressTransforme > 0 && itemData.data.niveau < itemData.data.niveau_archetype) {
itemData.data.stressXpMax = Math.min(xpManquant , stressTransforme);
}
}
/* -------------------------------------------- */
static isVisible(item) {
return Number(item.system.niveau) != RdDItemCompetence.getNiveauBase(item.system.categorie);
static isVisible(itemData) {
return Number(itemData.data.niveau) != RdDItemCompetence.getNiveauBase(itemData.data.categorie);
}
static nomContientTexte(item, texte) {
return Grammar.toLowerCaseNoAccent(item.name).includes(Grammar.toLowerCaseNoAccent(texte))
static nomContientTexte(itemData, texte) {
return Grammar.toLowerCaseNoAccent(itemData.name).includes(Grammar.toLowerCaseNoAccent(texte))
}
/* -------------------------------------------- */
static isNiveauBase(item) {
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie);
static isNiveauBase(itemData) {
return Number(itemData.data.niveau) == RdDItemCompetence.getNiveauBase(itemData.data.categorie);
}
/* -------------------------------------------- */
@ -258,7 +260,7 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static computeResumeArchetype(competences) {
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 => {
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;

View File

@ -5,12 +5,12 @@ export class RdDItemCompetenceCreature extends Item {
/* -------------------------------------------- */
static setRollDataCreature(rollData) {
rollData.competence = rollData.competence
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
rollData.competence.system.defaut_carac = "carac_creature"
rollData.competence.system.categorie = "creature"
rollData.competence = Misc.data(rollData.competence);
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.data.carac_value } };
rollData.competence.data.defaut_carac = "carac_creature"
rollData.competence.data.categorie = "creature"
rollData.selectedCarac = rollData.carac.carac_creature
if (rollData.competence.system.iscombat) {
if (rollData.competence.data.iscombat) {
rollData.arme = RdDItemCompetenceCreature.toActionArme(rollData.competence);
}
}
@ -18,14 +18,14 @@ export class RdDItemCompetenceCreature extends Item {
/* -------------------------------------------- */
static toActionArme(item) {
if (RdDItemCompetenceCreature.isCompetenceAttaque(item)) {
// si c'est un Item compétence: cloner pour ne pas modifier lma compétence
let arme = (item instanceof Item) ? item.clone(): item;
mergeObject(arme.system,
// si c'est un Item compétence: cloner pour ne pas modifier la compétence
let arme = Misc.data( (item instanceof Item) ? item.clone(): item);
mergeObject(arme.data,
{
competence: arme.name,
resistance: 100,
equipe: true,
dommagesReels: arme.system.dommages,
dommagesReels: arme.data.dommages,
penetration: 0,
force: 0,
rapide: true,
@ -38,12 +38,14 @@ export class RdDItemCompetenceCreature extends Item {
}
/* -------------------------------------------- */
static isCompetenceAttaque(item) {
return item.type == 'competencecreature' && item.system.iscombat;
static isCompetenceAttaque(itemData) {
itemData = Misc.data(itemData);
return itemData.type == 'competencecreature' && itemData.data.iscombat;
}
/* -------------------------------------------- */
static isCompetenceParade(item) {
return item.type == 'competencecreature' && item.system.isparade;
static isCompetenceParade(itemData) {
itemData = Misc.data(itemData);
return itemData.type == 'competencecreature' && itemData.data.isparade;
}
}

View File

@ -3,7 +3,7 @@ export class RdDItemMeditation {
static calculDifficulte(rollData) {
if (rollData.meditation) {
// 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.isVeture) diff -= 2;
if (!rollData.conditionMeditation.isComportement) diff -= 2;

View File

@ -1,60 +1,54 @@
import { Misc } from "./misc.js";
const MONNAIES_STANDARD = [
const monnaiesData = [
{
name: "Etain (1 denier)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
system: { quantite: 0, valeur_deniers: 1, encombrement: 0.001, description: "" }
data: { quantite: 0, valeur_deniers: 1, encombrement: 0.001, description: "" }
},
{
name: "Bronze (10 deniers)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp",
system: { quantite: 0, valeur_deniers: 10, encombrement: 0.002, description: "" }
data: { quantite: 0, valeur_deniers: 10, encombrement: 0.002, description: "" }
},
{
name: "Argent (1 sol)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp",
system: { quantite: 0, valeur_deniers: 100, encombrement: 0.003, description: "" }
data: { quantite: 0, valeur_deniers: 100, encombrement: 0.003, description: "" }
},
{
name: "Or (10 sols)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
system: { quantite: 0, valeur_deniers: 1000, encombrement: 0.004, description: "" }
data: { quantite: 0, valeur_deniers: 1000, encombrement: 0.004, description: "" }
}
]
const VALEURS_STANDARDS = MONNAIES_STANDARD.map(it =>it.system.valeur_deniers);
export class Monnaie {
static isSystemMonnaie(item, items) {
if (item.type == 'monnaie') {
const valeur = item.system.valeur_deniers;
if (VALEURS_STANDARDS.includes(valeur)) {
const monnaiesDeValeur = items.filter(it => it.type == 'monnaie' && it.system.valeur_deniers == valeur)
return monnaiesDeValeur.length<=1;
}
}
return false;
static isSystemMonnaie(item) {
let present = monnaiesData.find(monnaie => monnaie.data.valeur_deniers == Misc.data(item)?.data?.valeur_deniers);
return present;
}
static monnaiesData() {
return MONNAIES_STANDARD;
return monnaiesData;
}
static filtrerMonnaies(items) {
return items.filter(it => it.type == 'monnaie');
return items.filter(it => Misc.data(it).type == 'monnaie');
}
static monnaiesManquantes(disponibles) {
const manquantes = MONNAIES_STANDARD.filter(standard => !disponibles.find(disponible => Monnaie.deValeur(disponible, standard.system?.valeur_deniers)));
if (manquantes.length > 0) {
console.error('monnaiesManquantes', manquantes, ' avec monnaies', disponibles, MONNAIES_STANDARD);
}
return manquantes;
static monnaiesManquantes(items) {
const valeurs = Monnaie.filtrerMonnaies(items)
.map(it => Misc.templateData(it).valeur_deniers);
const manquantes = monnaiesData.filter(monnaie => !valeurs.find(v => v != Misc.templateData(monnaie).valeur_deniers));
//const manquantes = monnaiesData.filter(monnaie => !valeurs.find(v => v != Misc.templateData(monnaie).valeur_deniers) );
//console.log("Valeurs : ", valeurs, manquantes);
return []; //manquantes;
}
static deValeur(monnaie, valeur) {
return valeur == monnaie.system.valeur_deniers
static deValeur(monnaie, v) {
return v != monnaie.data.valeur_deniers;
}
static arrondiDeniers(sols) {
@ -62,6 +56,6 @@ export class Monnaie {
}
static triValeurDenier() {
return Misc.ascending(item => item.system.valeur_deniers)
return Misc.ascending(item => Misc.data(item).data.valeur_deniers);
}
}

View File

@ -32,7 +32,7 @@ export class RdDItemSheet extends ItemSheet {
let buttons = super._getHeaderButtons();
// Add "Post to chat" button
// We previously restricted this to GM and editable items only. If you ever find this comment because it broke something: eh, sorry!
if ("cout" in this.item.system && this.item.isVideOuNonConteneur()) {
if ("cout" in Misc.templateData(this.object) && this.object.isVideOuNonConteneur()) {
buttons.unshift({
class: "vendre",
icon: "fas fa-comments-dollar",
@ -60,25 +60,24 @@ export class RdDItemSheet extends ItemSheet {
/* -------------------------------------------- */
async getData() {
const objectData = Misc.data(this.object)
let formData = {
id: this.item.id,
title: this.item.name,
type: this.item.type,
img: this.item.img,
name: this.item.name,
system: this.item.system,
// TODO: v10 remove
data: this.item.system,
id: this.object.id,
title: objectData.name,
type: objectData.type,
img: objectData.img,
name: objectData.name,
data: objectData.data,
isGM: game.user.isGM,
actorId: this.actor?.id,
owner: this.item.isOwner,
owner: this.document.isOwner,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
isSoins: false
}
if (this.actor) {
formData.isOwned = true;
if (this.item.type == 'conteneur') {
if (objectData.type == 'conteneur') {
this.prepareConteneurData(formData);
}
}
@ -94,20 +93,20 @@ export class RdDItemSheet extends ItemSheet {
console.log(formData.competences)
}
if (formData.type == 'recettealchimique') {
RdDAlchimie.processManipulation(this.item, this.actor && this.actor.id);
RdDAlchimie.processManipulation(objectData, this.actor && this.actor.id);
}
if (formData.type == 'gemme') {
formData.gemmeTypeList = RdDGemme.getGemmeTypeOptionList();
RdDGemme.calculDataDerivees(this.item);
RdDGemme.calculDataDerivees(formData.data);
}
if (formData.type == 'potion') {
if (this.dateUpdated) {
formData.system.prdate = this.dateUpdated;
formData.data.prdate = this.dateUpdated;
this.dateUpdated = undefined;
}
RdDHerbes.updatePotionData(formData);
}
if (formData.isOwned && formData.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.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
@ -117,11 +116,11 @@ export class RdDItemSheet extends ItemSheet {
/* -------------------------------------------- */
prepareConteneurData(formData) {
formData.itemsByType = Misc.classify(this.actor.items.map(i => foundry.utils.deepClone(i)))
RdDUtility.filterEquipementParType(formData)
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);
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
formData.subItems = formData.conteneurs.find(it => it._id == this.object.id)?.subItems;
}
@ -130,15 +129,15 @@ export class RdDItemSheet extends ItemSheet {
activateListeners(html) {
super.activateListeners(html);
if (this.item.type == 'conteneur') {
if (this.object.type == 'conteneur') {
this.form.ondragstart = (event) => this._onDragStart(event);
this.form.ondrop = (event) => this._onDrop(event);
}
let itemSheetDialog = this;
HtmlUtility._showControlWhen($(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.item.isOwned);
HtmlUtility._showControlWhen($(".item-magique"), this.item.isMagique());
HtmlUtility._showControlWhen($(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.object.isOwned);
HtmlUtility._showControlWhen($(".item-magique"), this.object.isMagique());
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
@ -147,8 +146,8 @@ export class RdDItemSheet extends ItemSheet {
html.find(".categorie").change(event => this._onSelectCategorie(event));
html.find('.sheet-competence-xp').change((event) => {
if (this.item.type == 'competence') {
RdDUtility.checkThanatosXP(this.item.name);
if (this.object.data.type == 'competence') {
RdDUtility.checkThanatosXP(this.object.data.name);
}
});
@ -183,7 +182,7 @@ export class RdDItemSheet extends ItemSheet {
if (actor) {
actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData);
} 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.");
}
});
@ -221,16 +220,16 @@ export class RdDItemSheet extends ItemSheet {
async _onSelectCategorie(event) {
event.preventDefault();
if (this.item.isCompetence()) {
if (this.object.isCompetence()) {
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
this.item.system.base = level;
Misc.templateData(this.object).base = level;
$("#base").val(level);
}
}
/* -------------------------------------------- */
get template() {
let type = this.item.type
let type = this.object.data.type;
return `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`;
}
@ -241,7 +240,7 @@ export class RdDItemSheet extends ItemSheet {
// Données de bonus de cases ?
formData = RdDItemSort.buildBonusCaseStringFromFormData(formData);
return this.item.update(formData);
return this.object.update(formData);
}
async _onDragStart(event) {
@ -254,28 +253,28 @@ export class RdDItemSheet extends ItemSheet {
const dragData = {
actorId: this.actor.id,
type: "Item",
data: item.system
data: item.data
};
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
}
async _onDrop(event) {
// Try to extract the dragData
let dragData;
// Try to extract the data
let data;
try {
dragData = JSON.parse(event.dataTransfer.getData('text/plain'));
data = JSON.parse(event.dataTransfer.getData('text/plain'));
} catch (err) {
return false;
}
const allowed = Hooks.call("dropActorSheetData", this.actor, this, dragData);
const allowed = Hooks.call("dropActorSheetData", this.actor, this, data);
if (allowed === false) return;
// Handle different dragData types
switch (dragData.type) {
// Handle different data types
switch (data.type) {
case "Item":
return this._onDropItem(event, dragData);
return this._onDropItem(event, data);
}
return super._onDrop(event);
}
@ -283,7 +282,7 @@ export class RdDItemSheet extends ItemSheet {
/* -------------------------------------------- */
async _onDropItem(event, dragData) {
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.render(true);
}

View File

@ -40,17 +40,17 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet {
/* -------------------------------------------- */
async getData() {
const formData = duplicate(this.item);
const formData = duplicate(Misc.data(this.object));
mergeObject(formData, {
title: formData.name,
isGM: game.user.isGM,
owner: this.actor.isOwner,
owner: this.document.isOwner,
isOwned: this.actor ? true : false,
actorId: this.actor?.id,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
});
formData.tmrs = TMRUtility.listSelectedTMR(formData.system.typesTMR ?? []);
formData.tmrs = TMRUtility.listSelectedTMR(formData.data.typesTMR ?? []);
return formData;
}
@ -68,21 +68,21 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet {
async setSigneAleatoire() {
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique();
this.item.update(newSigne);
this.object.update(newSigne);
}
async onSelectTmr(event) {
event.preventDefault();
const selectedTMR = $(".select-tmr").val();
this.item.update({ 'system.typesTMR': selectedTMR });
this.object.update({ 'data.typesTMR': selectedTMR });
}
async onValeurXpSort(event) {
const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0;
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);
await this.item.update({ 'system.valeur': newValeur });
await this.object.update({ 'data.valeur': newValeur });
}
/* -------------------------------------------- */

View File

@ -18,12 +18,13 @@ const DIFFICULTE_LECTURE_SIGNE_MANQUE = +11;
export class RdDItemSigneDraconique {
static prepareSigneDraconiqueMeditation(meditation, rolled) {
meditation = Misc.data(meditation);
return {
name: "de la " + meditation.name,
type: "signedraconique",
img: meditation.img,
system: {
typesTMR: [TMRUtility.typeTmrName(meditation.system.tmr)],
data: {
typesTMR: [TMRUtility.typeTmrName(meditation.data.tmr)],
difficulte: rolled.isSuccess ? RdDItemSigneDraconique.getDiffSigneMeditation(rolled.code) : DIFFICULTE_LECTURE_SIGNE_MANQUE,
ephemere: true,
duree: "1 round",
@ -42,7 +43,7 @@ export class RdDItemSigneDraconique {
}
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) {
@ -74,7 +75,7 @@ export class RdDItemSigneDraconique {
name: await RdDItemSigneDraconique.randomSigneDescription(),
type: "signedraconique",
img: defaultItemImg.signedraconique,
system: {
data: {
typesTMR: await RdDItemSigneDraconique.randomTmrs(modele.nbCases),
ephemere: options?.ephemere == undefined ? RdDDice.rollTotal("1d2") == 2 : options.ephemere,
duree: "1 round",

View File

@ -7,25 +7,25 @@ export class RdDItemSort extends Item {
/* -------------------------------------------- */
static isDifficulteVariable(sort) {
return sort && (sort.system.difficulte.toLowerCase() == "variable");
return sort && (sort.data.difficulte.toLowerCase() == "variable");
}
/* -------------------------------------------- */
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){
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) {
if (sort && !RdDItemSort.isDifficulteVariable(sort)) {
return Misc.toInt(sort.system.difficulte);
return Misc.toInt(sort.data.difficulte);
}
return variable;
}
@ -54,40 +54,40 @@ export class RdDItemSort extends Item {
static getBonusCaseList( item, newCase = false ) {
// Gestion spéciale case bonus
if ( item.type == 'sort') {
return this.buildBonusCaseList(item.system.bonuscase, newCase );
return this.buildBonusCaseList(item.data.bonuscase, newCase );
}
return undefined;
}
/* -------------------------------------------- */
/** Met à jour les données de formulaire
* si static des bonus de cases sont présents
* */
static buildBonusCaseStringFromFormData( formData ) {
if ( formData.bonusValue ) {
let list = [];
let caseCheck = {};
for(let i=0; i<formData.bonusValue.length; i++) {
let coord = formData.caseValue[i] || 'A1';
coord = coord.toUpperCase();
if ( TMRUtility.verifyTMRCoord( coord ) ) { // Sanity check
let bonus = formData.bonusValue[i] || 0;
if ( bonus > 0 && caseCheck[coord] == undefined ) {
caseCheck[coord] = bonus;
list.push( coord+":"+bonus );
/* -------------------------------------------- */
/** Met à jour les données de formulaire
* si static des bonus de cases sont présents
* */
static buildBonusCaseStringFromFormData( formData ) {
if ( formData.bonusValue ) {
let list = [];
let caseCheck = {};
for(let i=0; i<formData.bonusValue.length; i++) {
let coord = formData.caseValue[i] || 'A1';
coord = coord.toUpperCase();
if ( TMRUtility.verifyTMRCoord( coord ) ) { // Sanity check
let bonus = formData.bonusValue[i] || 0;
if ( bonus > 0 && caseCheck[coord] == undefined ) {
caseCheck[coord] = bonus;
list.push( coord+":"+bonus );
}
}
}
formData.bonusValue = undefined;
formData.caseValue = undefined;
formData['data.bonuscase'] = list.toString(); // Reset
}
formData.bonusValue = undefined;
formData.caseValue = undefined;
formData.system.bonuscase = list.toString(); // Reset
}
return formData;
return formData;
}
/* -------------------------------------------- */
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);
let found = false;
@ -106,12 +106,12 @@ export class RdDItemSort extends Item {
// Sauvegarde/update
let bonuscase = StringList.toString();
//console.log("Bonus cae :", bonuscase);
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }] );
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'data.bonuscase': bonuscase }] );
}
/* -------------------------------------------- */
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) {
if (bc.case == coord) { // Case existante
return Number(bc.bonus);

View File

@ -1,7 +1,6 @@
import { DialogItemVente } from "./dialog-item-vente.js";
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { RdDHerbes } from "./rdd-herbes.js";
import { RdDUtility } from "./rdd-utility.js";
const typesObjetsEquipement = ["objet", "arme", "armure", "gemme", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "nourritureboisson", "monnaie"]
@ -42,11 +41,11 @@ export const defaultItemImg = {
/* -------------------------------------------- */
export class RdDItem extends Item {
constructor(itemData, context) {
if (!itemData.img) {
itemData.img = defaultItemImg[itemData.type];
constructor(data, context) {
if (!data.img) {
data.img = defaultItemImg[data.type];
}
super(itemData, context);
super(data, context);
}
static getTypeObjetsEquipement() {
@ -58,56 +57,61 @@ export class RdDItem extends Item {
}
isCompetence() {
return this.type == 'competence';
return Misc.data(this).type == 'competence';
}
isConteneur() {
return this.type == 'conteneur';
return Misc.data(this).type == 'conteneur';
}
isConteneurNonVide() {
return this.isConteneur() && (this.system.contenu?.length ?? 0) > 0;
return this.isConteneur() && (Misc.templateData(this).contenu?.length ?? 0) > 0;
}
isConteneurVide() {
return this.isConteneur() && (this.system.contenu?.length ?? 0) == 0;
return this.isConteneur() && (Misc.templateData(this).contenu?.length ?? 0) == 0;
}
isVideOuNonConteneur() {
return !this.isConteneur() || (this.system.contenu?.length ?? 0) == 0;
return !this.isConteneur() || (Misc.templateData(this).contenu?.length ?? 0) == 0;
}
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() {
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() {
return this.type == 'potion';
return Misc.data(this).type == 'potion';
}
isEquipement() {
return RdDItem.getTypeObjetsEquipement().includes(this.type)
return RdDItem.getTypeObjetsEquipement().includes(Misc.data(this).type);
}
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() {
return this.system.magique
return Misc.templateData(this).magique;
}
getEncTotal() {
return Number(this.system.encombrement ?? 0) * Number(this.system.quantite ?? 1)
const itemData = Misc.data(this);
return Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
}
getEnc() {
switch (this.type) {
const itemData = Misc.data(this);
switch (itemData.type) {
case 'herbe':
return encBrin;
}
return this.system.encombrement ?? 0;
return itemData.data.encombrement ?? 0;
}
prepareDerivedData() {
@ -118,48 +122,51 @@ export class RdDItem extends Item {
if (this.isPotion()) {
this.prepareDataPotion()
}
this.system.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
const itemData = Misc.data(this);
itemData.data.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
}
}
prepareDataPotion() {
const categorie = Grammar.toLowerCaseNoAccent(this.system.categorie);
this.system.magique = categorie.includes('enchante');
if (this.system.magique) {
const tplData = Misc.templateData(this);
const categorie = Grammar.toLowerCaseNoAccent(tplData.categorie);
tplData.magique = categorie.includes('enchante');
if (tplData.magique) {
if (categorie.includes('soin') || categorie.includes('repos')) {
// TODO: utiliser calculePointsRepos / calculePointsGuerison
this.system.puissance = RdDHerbes.calculePuissancePotion(this);
tplData.puissance = tplData.herbebonus * tplData.pr;
}
}
}
_calculsEquipement() {
const quantite = this.isConteneur() ? 1 : (this.system.quantite ?? 0);
const tplData = Misc.templateData(this);
const quantite = this.isConteneur() ? 1 : (tplData.quantite ?? 0);
const enc = this.getEnc();
if (enc != undefined) {
this.system.encTotal = Math.max(enc, 0) * quantite;
tplData.encTotal = Math.max(enc, 0) * quantite;
}
if (this.cout != undefined) {
this.system.prixTotal = Math.max(this.cout, 0) * quantite;
if (tplData.cout != undefined) {
tplData.prixTotal = Math.max(tplData.cout, 0) * quantite;
}
}
getActionPrincipale(options = { warnIfNot: true }) {
if (!this.isConteneur() && (this.system.quantite ?? 0) <= 0) {
const itemData = Misc.data(this);
if (!this.isConteneur() && (itemData.data.quantite ?? 0) <= 0) {
if (options.warnIfNot) {
ui.notifications.warn(`Vous n'avez plus de ${this.name}.`);
ui.notifications.warn(`Vous n'avez plus de ${itemData.name}.`);
}
return undefined;
}
switch (this.type) {
case 'nourritureboisson': return this.boisson ? 'Boire' : 'Manger';
switch (itemData.type) {
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 ${this.name}, aucune action associée définie.`);
ui.notifications.warn(`Impossible d'utiliser un ${itemData.name}, aucune action associée définie.`);
}
return undefined;
@ -171,22 +178,23 @@ export class RdDItem extends Item {
}
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) {
const reste = Math.max(quantite + Number(nombre), 0);
if (reste == 0) {
if (options.supprimerSiZero) {
ui.notifications.notify(`${this.name} supprimé de votre équipement`);
ui.notifications.notify(`${itemData.name} supprimé de votre équipement`);
await this.delete();
}
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.`);
await this.update({ "system.quantite": 0 });
ui.notifications.notify(`Il ne vous reste plus de ${itemData.name}, vous pouvez le supprimer de votre équipement, ou trouver un moyen de vous en procurer.`);
await this.update({ "data.quantite": 0 });
}
}
else {
await this.update({ "system.quantite": reste });
await this.update({ "data.quantite": reste });
}
}
}
@ -194,28 +202,22 @@ export class RdDItem extends Item {
/* -------------------------------------------- */
// détermine si deux équipements sont similaires: de même type, et avec les même champs hormis la quantité
isEquipementSimilaire(other) {
const itemData = Misc.data(this);
const otherData = Misc.data(other);
const tplData = Misc.templateData(this);
const otherTplData = Misc.templateData(other);
if (!this.isEquipement()) return false;
let message = undefined;
if (this.type != other.type) {
message = `Impossible de regrouper ${this.type} avec ${other.type}`;
}
else if (this.name != other.name) {
message = `Impossible de regrouper ${this.name} avec ${other.name}`;
}
else if (this.system.quantite == undefined) {
message = `Impossible de regrouper des ${this.type}, ils ne sont pas empilables`;
}
else {
const differences = Object.entries(this.system)
.filter(([key, value]) => !['quantite', 'encTotal', 'prixTotal', 'cout'].includes(key) && value != other.system[key]);
if (differences.length > 0) {
message = `Impossible de regrouper les ${this.type} ${this.name}: `;
for (const [key, value] of differences) {
message += `<br>${key}: ${value} vs ${other.system[key]}`;
}
if (itemData.type != otherData.type) return false;
if (itemData.name != otherData.name) return false;
if (tplData.quantite == undefined) return false;
const differences = Object.entries(tplData).filter(([key, value]) => !['quantite', 'encTotal', 'prixTotal', 'cout'].includes(key))
.filter(([key, value]) => value != otherTplData[key]);
if (differences.length > 0) {
let message = `Impossible de regrouper les ${itemData.type} ${itemData.name}: `;
for (const [key, value] of differences) {
message += `<br>${key}: ${value} vs ${otherTplData[key]}`;
}
}
if (message){
ui.notifications.info(message)
return false;
}
@ -249,13 +251,13 @@ export class RdDItem extends Item {
/* -------------------------------------------- */
getProprietes() {
return this[`_${this.type}ChatData`]();
return this[`_${Misc.data(this).type}ChatData`]();
}
/* -------------------------------------------- */
async postItem(modeOverride) {
console.log(this);
let chatData = duplicate(this);
let chatData = duplicate(Misc.data(this));
const properties = this.getProprietes();
chatData["properties"] = properties
if (this.actor) {
@ -280,7 +282,7 @@ export class RdDItem extends Item {
/* -------------------------------------------- */
_objetChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [].concat(
RdDItem.propertyIfDefined('Résistance', tplData.resistance, tplData.resistance),
RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
@ -291,7 +293,7 @@ export class RdDItem extends Item {
/* -------------------------------------------- */
_nourritureboissonChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [].concat(
RdDItem.propertyIfDefined('Sustentation', tplData.sust, tplData.sust > 0),
RdDItem.propertyIfDefined('Désaltère', tplData.desaltere, tplData.boisson),
@ -304,7 +306,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_armeChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Compétence</b>: ${tplData.competence}`,
`<b>Dommages</b>: ${tplData.dommages}`,
@ -316,7 +318,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_conteneurChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Capacité</b>: ${tplData.capacite} Enc.`,
`<b>Encombrement</b>: ${tplData.encombrement}`
@ -325,7 +327,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_munitionChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Encombrement</b>: ${tplData.encombrement}`
]
@ -333,7 +335,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_armureChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Protection</b>: ${tplData.protection}`,
`<b>Détérioration</b>: ${tplData.deterioration}`,
@ -344,7 +346,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_competenceChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Catégorie</b>: ${tplData.categorie}`,
`<b>Niveau</b>: ${tplData.niveau}`,
@ -355,7 +357,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_competencecreatureChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Catégorie</b>: ${tplData.categorie}`,
`<b>Niveau</b>: ${tplData.niveau}`,
@ -366,7 +368,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_sortChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Draconic</b>: ${tplData.draconic}`,
`<b>Difficulté</b>: ${tplData.difficulte}`,
@ -377,7 +379,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_herbeChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Milieu</b>: ${tplData.milieu}`,
`<b>Rareté</b>: ${tplData.rarete}`,
@ -387,7 +389,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_ingredientChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Milieu</b>: ${tplData.milieu}`,
`<b>Rareté</b>: ${tplData.rarete}`,
@ -397,7 +399,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_tacheChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Caractéristique</b>: ${tplData.carac}`,
`<b>Compétence</b>: ${tplData.competence}`,
@ -413,7 +415,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_livreChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Compétence</b>: ${tplData.competence}`,
`<b>Auteur</b>: ${tplData.auteur}`,
@ -425,7 +427,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_potionChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Rareté</b>: ${tplData.rarete}`,
`<b>Catégorie</b>: ${tplData.categorie}`,
@ -435,7 +437,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_queueChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Refoulement</b>: ${tplData.refoulement}`
]
@ -443,7 +445,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_ombreChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Refoulement</b>: ${tplData.refoulement}`
]
@ -451,19 +453,19 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_souffleChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [];
return properties;
}
/* -------------------------------------------- */
_teteChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [];
return properties;
}
/* -------------------------------------------- */
_tarotChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Concept</b>: ${tplData.concept}`,
`<b>Aspect</b>: ${tplData.aspect}`,
@ -472,7 +474,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_nombreastralChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Valeur</b>: ${tplData.value}`,
`<b>Jour</b>: ${tplData.jourlabel}`,
@ -481,7 +483,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_monnaieChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Valeur en Deniers</b>: ${tplData.valeur_deniers}`,
`<b>Encombrement</b>: ${tplData.encombrement}`
@ -490,7 +492,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_meditationChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Thème</b>: ${tplData.theme}`,
`<b>Compétence</b>: ${tplData.competence}`,
@ -505,7 +507,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_casetmrChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Coordonnée</b>: ${tplData.coord}`,
`<b>Spécificité</b>: ${tplData.specific}`
@ -514,7 +516,7 @@ export class RdDItem extends Item {
}
/* -------------------------------------------- */
_maladieChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties
if (tplData.identifie) {
properties = [
@ -539,7 +541,7 @@ export class RdDItem extends Item {
/* -------------------------------------------- */
_gemmeChatData() {
const tplData = this.system
const tplData = Misc.templateData(this);
let properties = [
`<b>Pureté</b>: ${tplData.purete}`,
`<b>Taille</b>: ${tplData.taille}`,

View File

@ -69,9 +69,9 @@ export class Misc {
}
static classify(items, classifier = it => it.type) {
let itemsBy = {}
Misc.classifyInto(itemsBy, items, classifier)
return itemsBy
let itemsBy = {};
Misc.classifyInto(itemsBy, items, classifier);
return itemsBy;
}
static classifyFirst(items, classifier) {
@ -87,13 +87,13 @@ export class Misc {
static classifyInto(itemsBy, items, classifier = it => it.type) {
for (const item of items) {
const classification = classifier(item)
const classification = classifier(item);
let list = itemsBy[classification];
if (!list) {
list = []
itemsBy[classification] = list
list = [];
itemsBy[classification] = list;
}
list.push(item)
list.push(item);
}
}
@ -106,9 +106,20 @@ export class Misc {
}
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?.type
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;

View File

@ -7,9 +7,9 @@ const matchOperationTerms = new RegExp(/@(\w*){([\w\-]+)}/i);
export class RdDAlchimie {
/* -------------------------------------------- */
static processManipulation(recette, actorId = undefined) {
static processManipulation(recetteData, actorId = undefined) {
//console.log("CALLED", recette, recette.isOwned, actorId );
let manip = recette.system.manipulation;
let manip = recetteData.data.manipulation;
let matchArray = manip.match(matchOperations);
if (matchArray) {
for (let matchStr of matchArray) {
@ -17,12 +17,12 @@ export class RdDAlchimie {
//console.log("RESULT ", result);
if (result[1] && result[2]) {
let commande = Misc.upperFirst(result[1]);
let replacement = this[`_alchimie${commande}`](recette, result[2], actorId);
let replacement = this[`_alchimie${commande}`](recetteData, result[2], actorId);
manip = manip.replace(result[0], replacement);
}
}
}
recette.system.manipulation_update = manip;
recetteData.data.manipulation_update = manip;
}
/* -------------------------------------------- */

View File

@ -12,23 +12,23 @@ export class RdDAstrologieJoueur extends Dialog {
/* -------------------------------------------- */
static async create(actor, dialogConfig) {
let dialogData = {
let data = {
nombres: this.organizeNombres(actor),
dates: game.system.rdd.calendrier.getJoursSuivants(10),
etat: actor.getEtatGeneral(),
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 };
if (dialogConfig.options) {
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 = {
saveButton: { label: "Fermer", callback: html => this.quitDialog() }
@ -41,7 +41,7 @@ export class RdDAstrologieJoueur extends Dialog {
super(dialogConf, dialogOptions);
this.actor = actor;
this.dataNombreAstral = duplicate(dialogData);
this.dataNombreAstral = duplicate(data);
}
/* -------------------------------------------- */
@ -49,12 +49,12 @@ export class RdDAstrologieJoueur extends Dialog {
let itemNombres = actor.listItemsData('nombreastral');
let itemFiltered = {};
for (let item of itemNombres) {
if (itemFiltered[item.system.jourindex]) {
itemFiltered[item.system.jourindex].listValues.push(item.system.value);
if (itemFiltered[item.data.jourindex]) {
itemFiltered[item.data.jourindex].listValues.push(item.data.value);
} else {
itemFiltered[item.system.jourindex] = {
listValues: [item.system.value],
jourlabel: item.system.jourlabel
itemFiltered[item.data.jourindex] = {
listValues: [item.data.value],
jourlabel: item.data.jourlabel
}
}
}
@ -63,9 +63,9 @@ export class RdDAstrologieJoueur extends Dialog {
/* -------------------------------------------- */
requestJetAstrologie() {
let socketData = {
id: this.actor.id,
carac_vue: this.actor.system.carac['vue'].value,
let data = {
id: this.actor.data._id,
carac_vue: Misc.data(this.actor).data.carac['vue'].value,
etat: this.dataNombreAstral.etat,
astrologie: this.dataNombreAstral.astrologie,
conditions: $("#diffConditions").val(),
@ -73,11 +73,11 @@ export class RdDAstrologieJoueur extends Dialog {
userId: game.user.id
}
if (Misc.isUniqueConnectedGM()) {
game.system.rdd.calendrier.requestNombreAstral(socketData);
game.system.rdd.calendrier.requestNombreAstral(data);
} else {
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_request_nombre_astral",
data: socketData
data: data
});
}
this.close();

View File

@ -20,7 +20,7 @@ export class RdDBonus {
static isAjustementAstrologique(rollData) {
return RdDCarac.isChance(rollData.selectedCarac) ||
rollData.selectedSort?.system.isrituel;
rollData.selectedSort?.data.isrituel;
}
/* -------------------------------------------- */
static isDefenseAttaqueFinesse(rollData) {
@ -68,23 +68,23 @@ export class RdDBonus {
}
return isCauchemar ? "cauchemar"
: rollData.dmg?.mortalite
?? rollData.arme?.system.mortalite
?? rollData.arme?.data.mortalite
?? "mortel";
}
/* -------------------------------------------- */
static _dmgArme(rollData) {
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)
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;
}
/* -------------------------------------------- */
static _peneration(rollData) {
return parseInt(rollData.arme?.system.penetration ?? 0);
return parseInt(rollData.arme?.data.penetration ?? 0);
}
/* -------------------------------------------- */

View File

@ -223,9 +223,9 @@ export class RdDCalendrier extends Application {
checkMaladie( periode) {
for (let actor of game.actors) {
if (actor.type == 'personnage') {
let maladies = actor.items.find( 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) {
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 !` });
} else {
ChatMessage.create({ content: `${actor.name} souffre d'un mal inconnu (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
@ -320,7 +320,7 @@ export class RdDCalendrier extends Application {
if (Misc.isUniqueConnectedGM()) { // Only once
console.log(request);
let jourDiff = this.getLectureAstrologieDifficulte(request.date);
let niveau = Number(request.astrologie.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 = {
caracValue: request.carac_vue,
finalLevel: niveau,
@ -444,9 +444,9 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */
updateDisplay() {
let calendrier = this.fillCalendrierData();
// Rebuild text du calendrier
let dateHTML = `Jour ${calendrier.jourMois} de ${calendrier.nomMois} (${calendrier.nomSaison})`
let data = this.fillCalendrierData();
// Rebuild data
let dateHTML = `Jour ${data.jourMois} de ${data.nomMois} (${data.nomSaison})`
if (game.user.isGM) {
dateHTML = dateHTML + " - NA: " + (this.getCurrentNombreAstral() ?? "indéterminé");
}
@ -454,13 +454,13 @@ export class RdDCalendrier extends Application {
handle.innerHTML = dateHTML;
}
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
heure.innerHTML = calendrier.nomHeure;
heure.innerHTML = data.nomHeure;
}
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")) {
heureImg.src = calendrier.iconHeure;
heureImg.src = data.iconHeure;
}
}

View File

@ -101,35 +101,35 @@ export class RdDCarac {
}
/* -------------------------------------------- */
static computeCarac(system) {
system.carac.force.value = Math.min(system.carac.force.value, parseInt(system.carac.taille.value) + 4);
static computeCarac(data) {
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);
let bonusDomKey = Math.floor((parseInt(system.carac.force.value) + parseInt(system.carac.taille.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(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2);
bonusDomKey = Math.min(Math.max(bonusDomKey, 0), 32); // Clamp de securite
let tailleData = tableCaracDerivee[bonusDomKey];
system.attributs.plusdom.value = tailleData.plusdom;
data.attributs.plusdom.value = tailleData.plusdom;
system.attributs.sconst.value = RdDCarac.calculSConst(system.carac.constitution.value);
system.attributs.sust.value = tableCaracDerivee[Number(system.carac.taille.value)].sust;
data.attributs.sconst.value = RdDCarac.calculSConst(data.carac.constitution.value);
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;
system.carac.melee.value = Math.floor((parseInt(system.carac.force.value) + parseInt(system.carac.agilite.value)) / 2);
system.carac.tir.value = Math.floor((parseInt(system.carac.vue.value) + parseInt(system.carac.dexterite.value)) / 2);
system.carac.lancer.value = Math.floor((parseInt(system.carac.tir.value) + parseInt(system.carac.force.value)) / 2);
data.attributs.encombrement.value = (parseInt(data.carac.force.value) + parseInt(data.carac.taille.value)) / 2;
data.carac.melee.value = Math.floor((parseInt(data.carac.force.value) + parseInt(data.carac.agilite.value)) / 2);
data.carac.tir.value = Math.floor((parseInt(data.carac.vue.value) + parseInt(data.carac.dexterite.value)) / 2);
data.carac.lancer.value = Math.floor((parseInt(data.carac.tir.value) + parseInt(data.carac.force.value)) / 2);
system.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)
system.sante.endurance.max = Math.max(parseInt(system.carac.taille.value) + parseInt(system.carac.constitution.value), parseInt(system.sante.vie.max) + parseInt(system.carac.volonte.value));
system.sante.endurance.value = Math.min(system.sante.endurance.value, system.sante.endurance.max);
system.sante.fatigue.max = system.sante.endurance.max * 2;
system.sante.fatigue.value = Math.min(system.sante.fatigue.value, system.sante.fatigue.max);
data.sante.vie.value = Math.min(data.sante.vie.value, data.sante.vie.max)
data.sante.endurance.max = Math.max(parseInt(data.carac.taille.value) + parseInt(data.carac.constitution.value), parseInt(data.sante.vie.max) + parseInt(data.carac.volonte.value));
data.sante.endurance.value = Math.min(data.sante.endurance.value, data.sante.endurance.max);
data.sante.fatigue.max = data.sante.endurance.max * 2;
data.sante.fatigue.value = Math.min(data.sante.fatigue.value, data.sante.fatigue.max);
//Compteurs
system.reve.reve.max = system.carac.reve.value;
system.compteurs.chance.max = system.carac.chance.value;
data.reve.reve.max = data.carac.reve.value;
data.compteurs.chance.max = data.carac.chance.value;
}

View File

@ -66,7 +66,7 @@ export class RdDCombatManager extends Combat {
/* -------------------------------------------- */
async finDeRound(options = { terminer: false }) {
for (let combatant of this.combatants) {
for (let combatant of this.data.combatants) {
if (combatant.actor) {
await combatant.actor.finDeRound(options);
}
@ -78,8 +78,8 @@ export class RdDCombatManager extends Combat {
/************************************************************************************/
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;
const currentId = this.combatant._id;
// calculate initiative
@ -87,27 +87,27 @@ export class RdDCombatManager extends Combat {
const combatant = this.combatants.get(ids[cId]);
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0);
if (!formula) {
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
const competence = combatant.actor.items.find(it => it.system.iscombat)
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
const competence = combatant.actor.data.items.find(it => it.data.data.iscombat)
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 {
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
const compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.system.competence;
const competence = RdDItemCompetence.findCompetence(combatant.actor.items, compName);
const armeCombat = combatant.actor.data.items.find(it => it.type == 'arme' && itemData.data.equipe)
const compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.data.competence;
const competence = RdDItemCompetence.findCompetence(combatant.actor.data.items, compName);
if (competence) {
const carac = combatant.actor.system.carac[competence.system.defaut_carac].value;
const niveau = competence.system.niveau;
const bonusEcaille = (armeCombat?.system.magique) ? armeCombat.system.ecaille_efficacite : 0;
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, bonusEcaille);
const carac = combatant.actor.data.data.carac[competence.data.defaut_carac].value;
const niveau = competence.data.niveau;
const bonusEcaille = (armeCombat?.data.magique) ? armeCombat.data.ecaille_efficacite : 0;
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, bonusEcaille);
}
}
}
//console.log("Combatat", c);
const roll = combatant.getInitiativeRoll(rollFormula);
if ( !roll.total) {
roll.evaluate( {async: false});
if (!roll.total) {
roll.evaluate({ async: false });
}
if (roll.total <= 0) roll.total = 0.00;
console.log("Compute init for", rollFormula, roll.total, combatant);
@ -155,69 +155,68 @@ export class RdDCombatManager extends Combat {
// Gestion des armes 1/2 mains
let actionsArme = [];
for (const arme of armes) {
let action = duplicate(arme)
if (action.system.equipe) {
let compData = competences.find(c => c.name == action.system.competence)
let action = duplicate(Misc.data(arme));
if (action.data.equipe) {
let compData = competences.map(c => Misc.data(c)).find(c => c.name == action.data.competence);
actionsArme.push(action);
action.action = 'attaque';
action.system.dommagesReels = Number(action.system.dommages);
action.system.niveau = compData.system.niveau;
action.system.initiative = RdDCombatManager.calculInitiative(compData.system.niveau, carac[compData.system.defaut_carac].value);
action.data.dommagesReels = Number(action.data.dommages);
action.data.niveau = compData.data.niveau;
action.data.initiative = RdDCombatManager.calculInitiative(compData.data.niveau, carac[compData.data.defaut_carac].value);
// Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence
if (action.system.unemain && !action.system.deuxmains) {
action.system.mainInfo = "(1m)";
} else if (!action.system.unemain && action.system.deuxmains) {
action.system.mainInfo = "(2m)";
} else if (action.system.unemain && action.system.deuxmains) {
action.system.mainInfo = "(1m)";
if (action.data.unemain && !action.data.deuxmains) {
action.data.mainInfo = "(1m)";
} else if (!action.data.unemain && action.data.deuxmains) {
action.data.mainInfo = "(2m)";
} else if (action.data.unemain && action.data.deuxmains) {
action.data.mainInfo = "(1m)";
const comp2m = action.system.competence.replace(" 1 main", " 2 mains"); // Replace !
const comp = competences.find(c => c.name == comp2m)
const comp2m = action.data.competence.replace(" 1 main", " 2 mains"); // Replace !
const comp = Misc.data(competences.find(c => c.name == comp2m));
const arme2main = duplicate(action);
arme2main.system.mainInfo = "(2m)";
arme2main.system.niveau = comp.system.niveau;
arme2main.system.competence = comp2m;
arme2main.system.initiative = RdDCombatManager.calculInitiative(arme2main.system.niveau, carac[comp.system.defaut_carac].value);
arme2main.data.mainInfo = "(2m)";
arme2main.data.niveau = comp.data.niveau;
arme2main.data.competence = comp2m;
arme2main.data.initiative = RdDCombatManager.calculInitiative(arme2main.data.niveau, carac[comp.data.defaut_carac].value);
actionsArme.push(arme2main);
const containsSlash = action.system.dommages.includes("/");
const containsSlash = action.data.dommages.includes("/");
if (containsSlash) {
const tableauDegats = action.system.dommages.split("/");
action.system.dommagesReels = Number(tableauDegats[0]);
arme2main.system.dommagesReels = Number(tableauDegats[1]);
const tableauDegats = action.data.dommages.split("/");
action.data.dommagesReels = Number(tableauDegats[0]);
arme2main.data.dommagesReels = Number(tableauDegats[1]);
}
else{
else {
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + action.name + " ne sont pas corrects (ie sous la forme X/Y)");
}
}
}
}
return actionsArme.sort(Misc.ascending(armeData => armeData.name + (armeData.system.mainInfo ?? '')));
return actionsArme.sort(Misc.ascending(armeData => armeData.name + (armeData.data.mainInfo ?? '')));
}
static listActionsPossessions(actor) {
return RdDCombatManager._indexActions(actor.getPossessions().map(p =>
{
return {
name: p.name,
action: 'conjurer',
system: {
competence: p.name,
possessionid: p.system.possessionid,
}
return RdDCombatManager._indexActions(actor.getPossessions().map(p => {
return {
name: p.name,
action: 'conjurer',
data: {
competence: p.name,
possessionid: p.data.data.possessionid,
}
}));
}
}));
}
/* -------------------------------------------- */
static listActionsCombat(combatant) {
const actor = combatant.actor;
let actions = RdDCombatManager.listActionsPossessions(actor);
if (actions.length>0) {
if (actions.length > 0) {
return actions;
}
let items = actor.items;
let items = actor.data.items;
if (actor.isCreature()) {
actions = actions.concat(items.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
.map(competence => RdDItemCompetenceCreature.toActionArme(competence)));
@ -228,10 +227,10 @@ export class RdDCombatManager extends Combat {
.concat(RdDItemArme.mainsNues());
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) {
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
if (actor.data.data.attributs.hautrevant.value) {
actions.push({ name: "Draconic", action: 'haut-reve', data: { initOnly: true, competence: "Draconic" } });
}
}
@ -249,14 +248,14 @@ export class RdDCombatManager extends Combat {
static processPremierRoundInit() {
// Check if we have the whole init !
if (Misc.isUniqueConnectedGM() && game.combat.current.round == 1) {
let initMissing = game.combat.combatants.find(it => !it.initiative);
let initMissing = game.combat.data.combatants.find(it => !it.initiative);
if (!initMissing) { // Premier round !
for (let combatant of game.combat.combatants) {
for (let combatant of game.combat.data.combatants) {
let action = combatant.initiativeData?.arme;
//console.log("Parsed !!!", combatant, initDone, game.combat.current, arme);
if (action && action.type == "arme") {
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>
<hr>
<div>
@ -327,21 +326,21 @@ export class RdDCombatManager extends Combat {
initOffset = 9;
initInfo = "Draconic"
} else {
compData = RdDItemCompetence.findCompetence(combatant.actor.items, arme.system.competence);
compNiveau = compData.system.niveau;
initInfo = action.name + " / " + action.system.competence;
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
caracForInit = compData.system.carac_value;
if (compData.system.categorie == "lancer") {
initOffset = 7;
}
else {
initOffset = 5;
}
} else {
caracForInit = combatant.actor.system.carac[compData.system.defaut_carac].value;
initOffset = RdDCombatManager._baseInitOffset(compData.system.categorie, action);
compData = Misc.data(RdDItemCompetence.findCompetence(combatant.actor.data.items, action.data.competence));
compNiveau = compData.data.niveau;
initInfo = action.name + " / " + action.data.competence;
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
caracForInit = compData.data.carac_value;
if (compData.data.categorie == "lancer") {
initOffset = 7;
}
else {
initOffset = 5;
}
} else {
caracForInit = Misc.data(combatant.actor).data.carac[compData.data.defaut_carac].value;
initOffset = RdDCombatManager._baseInitOffset(compData.data.categorie, action);
}
}
@ -361,7 +360,7 @@ export class RdDCombatManager extends Combat {
return 7;
}
// Offset de principe pour les armes de jet
switch (arme.system.cac) {
switch (arme.data.cac) {
case "empoignade": return 3;
case "pugilat": return 4;
}
@ -372,7 +371,7 @@ export class RdDCombatManager extends Combat {
static displayInitiativeMenu(html, combatantId) {
console.log("Combatant ; ", combatantId);
const combatant = game.combat.combatants.get(combatantId);
if (! (combatant?.actor) ) {
if (!(combatant?.actor)) {
ui.notifications.warn(`Le combatant ${combatant.name ?? combatantId} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
return;
}
@ -384,7 +383,7 @@ export class RdDCombatManager extends Combat {
let menuItems = [];
for (let action of actions) {
menuItems.push({
name: action.system.competence,
name: action.data.competence,
icon: "<i class='fas fa-dice-d6'></i>",
callback: target => { RdDCombatManager.rollInitiativeAction(combatantId, action) }
});
@ -415,7 +414,7 @@ export class RdDCombat {
/* -------------------------------------------- */
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);
}
}
@ -456,8 +455,8 @@ export class RdDCombat {
}
else {
const defender = target?.actor;
const defenderTokenId = target?.id;
if ( defender.type == 'entite' && defender.system.definition.typeentite == ENTITE_NONINCARNE) {
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)
@ -558,8 +557,8 @@ export class RdDCombat {
this.attacker = attacker;
this.defender = defender;
this.target = target;
this.attackerId = this.attacker.id;
this.defenderId = this.defender.id;
this.attackerId = this.attacker.data._id;
this.defenderId = this.defender.data._id;
this.defenderTokenId = defenderTokenId;
}
@ -567,7 +566,7 @@ export class RdDCombat {
async onEvent(button, event) {
const chatMessage = ChatUtility.getChatMessage(event);
const defenderRoll = ChatUtility.getMessageData(chatMessage, 'defender-roll');
const attackerRoll = defenderRoll?.attackerRoll ?? ChatUtility.getMessageData(chatMessage, 'attacker-roll') ;
const attackerRoll = defenderRoll?.attackerRoll ?? ChatUtility.getMessageData(chatMessage, 'attacker-roll');
console.log('RdDCombat', attackerRoll, defenderRoll);
const defenderTokenId = event.currentTarget.attributes['data-defenderTokenId']?.value;
@ -691,7 +690,7 @@ export class RdDCombat {
if (!await this.accorderEntite('avant-attaque')) {
return;
}
if (arme.system.cac == 'empoignade' && this.attacker.isCombatTouche()) {
if (arme.data.cac == 'empoignade' && this.attacker.isCombatTouche()) {
ChatMessage.create({
alias: this.attacker.name,
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
@ -734,7 +733,7 @@ export class RdDCombat {
_prepareAttaque(competence, arme) {
let rollData = {
passeArme: randomID(16),
mortalite: arme?.system.mortalite,
mortalite: arme?.data.mortalite,
coupsNonMortels: false,
competence: competence,
surprise: this.attacker.getSurprise(true),
@ -751,8 +750,8 @@ export class RdDCombat {
}
else {
// sans armes: à mains nues
const niveau = competence.system.niveau;
const init = RdDCombatManager.calculInitiative(niveau, this.attacker.system.carac['melee'].value);
const niveau = competence.data.niveau;
const init = RdDCombatManager.calculInitiative(niveau, Misc.templateData(this.attacker).carac['melee'].value);
rollData.arme = RdDItemArme.mainsNues({ niveau: niveau, initiative: init });
}
return rollData;
@ -760,14 +759,14 @@ export class RdDCombat {
/* -------------------------------------------- */
async _onAttaqueParticuliere(rollData) {
const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0;
// force toujours, sauf empoignade
// finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum
// rapidité seulement en mêlée, si l'arme le permet, et si la difficulté libre est de -1 minimum
const isForce = !rollData.arme.system.empoignade;
const isFinesse = rollData.arme.system.empoignade || isMeleeDiffNegative;
const isRapide = !rollData.arme.system.empoignade && isMeleeDiffNegative && rollData.arme.system.rapide;
const isForce = !rollData.arme.data.empoignade;
const isFinesse = rollData.arme.data.empoignade || isMeleeDiffNegative;
const isRapide = !rollData.arme.data.empoignade && isMeleeDiffNegative && rollData.arme.data.rapide;
// si un seul choix possible, le prendre
if (isForce && !isFinesse && !isRapide) {
return await this.choixParticuliere(rollData, "force");
@ -778,7 +777,7 @@ export class RdDCombat {
else if (!isForce && !isFinesse && isRapide) {
return await this.choixParticuliere(rollData, "rapidite");
}
const choixParticuliere = await ChatMessage.create({
alias: this.attacker.name,
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
@ -802,7 +801,7 @@ export class RdDCombat {
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntite());
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
attackerRoll.show = {
cible: this.target ? this.defender.system.name : 'la cible',
cible: this.target ? this.defender.data.name : 'la cible',
isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge')
}
await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html');
@ -817,13 +816,13 @@ export class RdDCombat {
}
/* -------------------------------------------- */
isPossession( attackerRoll) {
isPossession(attackerRoll) {
return attackerRoll.selectedCarac.label.toLowerCase() == 'possession';
}
/* -------------------------------------------- */
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);
if (essaisPrecedents) {
@ -831,16 +830,16 @@ export class RdDCombat {
}
// # utilisation esquive
const corpsACorps = this.defender.getCompetence("Corps à corps", { onMessage: it => console.info(it, this.defender) });
const esquives = duplicate(this.defender.getCompetences("esquive", { onMessage: it => console.info(it, this.defender) }))
const corpsACorps = Misc.data(this.defender.getCompetence("Corps à corps", { onMessage: it => console.info(it, this.defender) }));
const esquives = duplicate(this.defender.getCompetences("esquive", { onMessage: it => console.info(it, this.defender) }).map(c => Misc.data(c)));
esquives.forEach(e => e.usages = e?.id ? this.defender.getItemUse(e.id) : 0);
const paramChatDefense = {
passeArme: attackerRoll.passeArme,
essais: attackerRoll.essais,
isPossession: this.isPossession(attackerRoll),
defender: this.defender,
attacker: this.attacker,
defender: Misc.data(this.defender),
attacker: Misc.data(this.attacker),
attackerId: this.attackerId,
esquives: esquives,
defenderTokenId: this.defenderTokenId,
@ -848,7 +847,7 @@ export class RdDCombat {
armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme),
diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0,
attaqueParticuliere: attackerRoll.particuliere,
attaqueCategorie: attackerRoll.competence.system.categorie,
attaqueCategorie: attackerRoll.competence.data.categorie,
attaqueArme: attackerRoll.arme,
surprise: this.defender.getSurprise(true),
dmg: attackerRoll.dmg,
@ -880,8 +879,8 @@ export class RdDCombat {
// envoyer le message au destinataire
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_defense", data: {
attackerId: this.attacker?.id,
defenderId: this.defender?.id,
attackerId: this.attacker?.data._id,
defenderId: this.defender?.data._id,
defenderTokenId: this.defenderTokenId,
defenderRoll: defenderRoll,
paramChatDefense: paramChatDefense,
@ -892,11 +891,13 @@ export class RdDCombat {
/* -------------------------------------------- */
_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) {
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 'lancer':
return items.filter(item => RdDItemArme.getCategorieParade(item) == 'boucliers')
@ -915,7 +916,7 @@ export class RdDCombat {
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', {
attackerId: this.attackerId,
attacker: this.attacker,
attacker: Misc.data(this.attacker),
defenderTokenId: this.defenderTokenId,
essais: attackerRoll.essais
})
@ -928,7 +929,7 @@ export class RdDCombat {
console.log("RdDCombat._onEchecTotal >>>", rollData);
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");
ChatUtility.createChatWithRollMode(this.defender.name, {
content: `<strong>Maladresse à ${action}!</strong> ` + await RdDRollTables.getMaladresse({ arme: avecArme })
@ -947,7 +948,7 @@ export class RdDCombat {
console.log("RdDCombat.choixParticuliere >>>", rollData, choix);
if (choix != "rapidite") {
this.attacker.incDecItemUse(rollData.arme.id);
this.attacker.incDecItemUse(rollData.arme._id);
}
this.removeChatMessageActionsPasseArme(rollData.passeArme);
@ -959,10 +960,9 @@ export class RdDCombat {
async parade(attackerRoll, armeParadeId) {
const arme = this.defender.getArmeParade(armeParadeId);
console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme);
const competence = arme?.system?.competence;
if (competence == undefined)
{
console.error("Pas de compétence de parade associée à ", arme?.name, armeParadeId) ;
const competence = Misc.templateData(arme)?.competence;
if (competence == undefined) {
console.error("Pas de compétence de parade associée à ", arme);
return;
}
@ -994,12 +994,12 @@ export class RdDCombat {
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,
attackerRoll: attackerRoll,
competence: this.defender.getCompetence(competenceParade),
competence: Misc.data(this.defender.getCompetence(competenceParade)),
arme: armeParade,
surprise: this.defender.getSurprise(true),
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
needResist: RdDItemArme.needArmeResist(attackerRoll.arme, armeParade),
carac: this.defender.system.carac,
carac: Misc.templateData(this.defender).carac,
show: {}
};
@ -1043,7 +1043,7 @@ export class RdDCombat {
/* -------------------------------------------- */
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) {
ui.notifications.error(this.defender.name + " n'a pas de compétence " + compName);
return;
@ -1077,7 +1077,7 @@ export class RdDCombat {
competence: competence,
surprise: this.defender.getSurprise(true),
surpriseDefenseur: this.defender.getSurprise(true),
carac: this.defender.system.carac,
carac: Misc.templateData(this.defender).carac,
show: {}
};
@ -1127,11 +1127,11 @@ export class RdDCombat {
const dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor;
let arme = defenderRoll.arme;
let resistance = Misc.toInt(arme.system.resistance);
if (arme.system.magique) {
let resistance = Misc.toInt(arme.data.resistance);
if (arme.data.magique) {
defenderRoll.show.deteriorationArme = 'resiste'; // Par défaut
if (arme.system.resistance_magique == undefined) arme.system.resistance_magique = 0; // Quick fix
if (dmg > arme.system.resistance_magique) { // Jet uniquement si dommages supérieur à résistance magique (cf. 274)
if (arme.data.resistance_magique == undefined) arme.data.resistance_magique = 0; // Quick fix
if (dmg > arme.data.resistance_magique) { // Jet uniquement si dommages supérieur à résistance magique (cf. 274)
// Jet de résistance de l'arme de parade (p.132)
let resistRoll = await RdDResolutionTable.rollData({
caracValue: resistance,
@ -1139,11 +1139,11 @@ export class RdDCombat {
showDice: HIDE_DICE
});
if (!resistRoll.rolled.isSuccess) {
let perteResistance = (dmg - arme.system.resistance_magique)
let perteResistance = (dmg - arme.data.resistance_magique)
resistance -= perteResistance;
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
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 {
@ -1159,14 +1159,14 @@ export class RdDCombat {
resistance -= dmg;
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
defenderRoll.show.perteResistance = dmg;
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, '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)
if (ReglesOptionelles.isUsing('defenseurDesarme') && resistance > 0 && RdDItemArme.getCategorieParade(defenderRoll.arme) != 'boucliers') {
let desarme = await RdDResolutionTable.rollData({
caracValue: this.defender.getForce(),
finalLevel: Misc.toInt(defenderRoll.competence.system.niveau) - dmg,
finalLevel: Misc.toInt(defenderRoll.competence.data.niveau) - dmg,
showDice: HIDE_DICE
});
defenderRoll.show.desarme = desarme.rolled.isEchec;
@ -1209,7 +1209,7 @@ export class RdDCombat {
_computeImpactRecul(attaque) {
const taille = this.defender.getTaille();
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);
}
@ -1245,6 +1245,8 @@ export class RdDCombat {
/* -------------------------------------------- */
/* retourne true si on peut continuer, false si on ne peut pas continuer */
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")
|| this.defender == undefined
|| !this.defender.isEntite([ENTITE_INCARNE])
@ -1252,7 +1254,7 @@ export class RdDCombat {
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 = {
content: "Jet de points actuels de rêve à " + rolled.finalLevel + RdDResolutionTable.explain(rolled) + "<br>",
@ -1273,25 +1275,25 @@ export class RdDCombat {
/* -------------------------------------------- */
static async displayActorCombatStatus(combat, actor) {
let formData = {
let data = {
combatId: combat._id,
alias: actor.name,
etatGeneral: actor.getEtatGeneral(),
isSonne: actor.getSonne(),
blessuresStatus: actor.computeResumeBlessure(),
SConst: actor.getSConst(),
actorId: actor.id,
actorId: actor.data._id,
isGrave: false,
isCritique: false
}
if (actor.countBlessuresNonSoigneeByName("critiques") > 0) { // Pour éviter le cumul grave + critique
formData.isCritique = true;
data.isCritique = true;
} else if (actor.countBlessuresNonSoigneeByName("graves") > 0) {
formData.isGrave = true;
data.isGrave = true;
}
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)
});
}
}

View File

@ -358,7 +358,7 @@ export class RdDCommands {
async supprimerSignesDraconiquesEphemeres() {
game.actors.forEach(actor => {
const ephemeres = actor.items.find(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) {
actor.deleteEmbeddedDocuments("Item", ephemeres);

View File

@ -3,11 +3,11 @@ import { Misc } from "./misc.js";
export class RddCompendiumOrganiser {
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) {
console.log('onRenderCompendium', compendium, html, compendiumData);
static async onRenderCompendium(compendium, html, data) {
console.log('onRenderCompendium', compendium, html, data);
const pack = compendium.collection
if (pack.metadata.system === SYSTEM_RDD) {
html.find('.directory-item').each((i, element) => {

View File

@ -18,19 +18,18 @@ const tableGemmes = {
export class RdDGemme extends Item {
static getGemmeTypeOptionList() {
// TODO: look how to map object key-value pairs
let options = ""
for (let gemmeKey in tableGemmes) {
options += `<option value="${gemmeKey}">${tableGemmes[gemmeKey].label}</option>`
let gemmeData = tableGemmes[gemmeKey];
options += `<option value="${gemmeKey}">${gemmeData.label}</option>`
}
return options;
}
static calculDataDerivees(gemme) {
gemme.system.cout = (gemme.system.taille * gemme.system.purete) + gemme.system.qualite;
gemme.system.inertie = 7 - gemme.system.purete;
gemme.system.enchantabilite = gemme.system.taille - gemme.system.inertie;
static calculDataDerivees(data) {
data.cout = (data.taille * data.purete) + data.qualite;
data.inertie = 7 - data.purete;
data.enchantabilite = data.taille - data.inertie;
}
}

View File

@ -1,4 +1,6 @@
/* -------------------------------------------- */
import { RdDUtility } from "./rdd-utility.js";
import { Misc } from "./misc.js";
import { RdDCalendrier } from "./rdd-calendrier.js";
/* -------------------------------------------- */
@ -6,11 +8,11 @@ export class RdDHerbes extends Item {
/* -------------------------------------------- */
static isHerbeSoin( botaniqueItem ) {
return botaniqueItem.categorie == 'Soin';
return Misc.templateData(botaniqueItem).categorie == 'Soin';
}
/* -------------------------------------------- */
static isHerbeRepos( botaniqueItem ) {
return botaniqueItem.categorie == 'Repos';
return Misc.templateData(botaniqueItem).categorie == 'Repos';
}
/* -------------------------------------------- */
@ -20,11 +22,12 @@ export class RdDHerbes extends Item {
}
/* -------------------------------------------- */
static buildHerbesList(listeHerbes, max) {
static buildHerbesList(listHerbes, max) {
let list = {}
for ( let herbe of listeHerbes) {
let brins = max - herbe.system.niveau;
list[herbe.system.name] = `${herbe.system.name} (Bonus: ${herbe.system.niveau}, Brins: ${brins})`;
for ( let herbe of listHerbes) {
let herbeData = Misc.templateData(herbe);
let brins = max - herbeData.niveau;
list[herbe.data.name] = `${herbe.data.name} (Bonus: ${herbeData.niveau}, Brins: ${brins})`;
}
list['Autre'] = 'Autre (Bonus: variable, Brins: variable)'
return list;
@ -36,39 +39,36 @@ export class RdDHerbes extends Item {
formData.herbesRepos = this.buildHerbesList(this.herbesRepos, 7);
formData.jourMoisOptions = RdDCalendrier.buildJoursMois();
formData.dateActuelle = game.system.rdd.calendrier.getDateFromIndex();
formData.splitDate = game.system.rdd.calendrier.getNumericDateFromIndex(formData.system.prdate);
formData.splitDate = game.system.rdd.calendrier.getNumericDateFromIndex(formData.data.prdate);
if (formData.system.categorie.includes('Soin') ) {
if (formData.data.categorie.includes('Soin') ) {
formData.isHerbe = true;
this.computeHerbeBonus(formData, this.herbesSoins, 12);
} else if (formData.system.categorie.includes('Repos')) {
} else if (formData.data.categorie.includes('Repos')) {
formData.isRepos = true;
this.computeHerbeBonus(formData, this.herbesRepos, 7);
}
}
/* -------------------------------------------- */
static calculePuissancePotion( potion ) {
return potion.system.herbebonus * potion.system.pr;
static calculePointsRepos( data ) {
return data.herbebonus * data.pr;
}
/* -------------------------------------------- */
static calculePointsRepos( potion ) {
return potion.system.herbebonus * potion.system.pr;
}
/* -------------------------------------------- */
static calculePointsGuerison( potion ){
return potion.system.herbebonus * potion.system.pr;
static calculePointsGuerison( data ){
return data.herbebonus * data.pr;
}
/* -------------------------------------------- */
static computeHerbeBonus( formData, herbesList, max) {
if ( Number(formData.system.herbebrins) ) {
let herbe = herbesList.find(item => item.name.toLowerCase() == formData.system.herbe.toLowerCase() );
if ( Number(formData.data.herbebrins) ) {
let herbe = herbesList.find(item => item.name.toLowerCase() == formData.data.herbe.toLowerCase() );
if( herbe ) {
let brinsBase = max - herbe.system.niveau;
formData.system.herbebonus = Math.max(herbe.system.niveau - Math.max(brinsBase - formData.system.herbebrins, 0), 0);
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);
}
}
}

View File

@ -2,99 +2,83 @@ import { Misc } from "./misc.js";
export class RdDHotbar {
static async createMacro(item, command) {
let macro = await Macro.create({
name: item.name,
type: "script",
img: item.img,
command: command
}, { displaySheet: false })
return macro
}
/**
* Create a macro when dropping an entity on the hotbar
* Item - open roll dialog for item
* Actor - open actor sheet
* Journal - open journal sheet
*/
static initDropbar() {
static initDropbar( ) {
Hooks.on("hotbarDrop", (bar, documentData, slot) => {
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill
if (documentData.type == "Item") {
let item = fromUuidSync(documentData.uuid)
if (item == undefined) {
item = this.actor.items.get(documentData.uuid)
}
console.log("DROP", documentData, item)
if (!item || (item.type != "arme" && item.type != "competence")) {
return true
}
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 = this.createMacro(item, command)
}
game.user.assignHotbarMacro(macro, slot);
return false
Hooks.on("hotbarDrop", async (bar, documentData, slot) => {
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill
if (documentData.type == "Item") {
if (documentData.data.type != "arme" && documentData.data.type != "competence" )
return
let item = documentData.data
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}");`;
let macro = game.macros.contents.find(m => (m.name === item.name) && (m.command === command));
if (!macro) {
macro = await Macro.create({
name: item.name,
type: "script",
img: item.img,
command: command
}, { displaySheet: false })
}
// Create a macro to open the actor sheet of the actor dropped on the hotbar
/*else if (documentData.type == "Actor") {
game.user.assignHotbarMacro(macro, slot);
}
// Create a macro to open the actor sheet of the actor dropped on the hotbar
else if (documentData.type == "Actor") {
let actor = game.actors.get(documentData.id);
let command = `game.actors.get("${documentData.id}").sheet.render(true)`
let macro = game.macros.contents.find(m => (m.name === actor.name) && (m.command === command));
if (!macro) {
macro = await Macro.create({
name: actor.name,
name: actor.data.name,
type: "script",
img: actor.img,
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 = fromUuidSync(documentData.uuid)
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.name,
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 true;
}
return false;
});
}
}
/** Roll macro */
static rollMacro(itemName, itemType, bypassData) {
const speaker = ChatMessage.getSpeaker();
let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token];
if (!actor) actor = game.actors.get(speaker.actor);
const speaker = ChatMessage.getSpeaker();
let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token];
if (!actor) actor = game.actors.get(speaker.actor);
let item = actor?.items.find(it => it.name === itemName && it.type == itemType) ?? undefined;
if (!item) {
return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`);
let item = Misc.data(actor?.items.find(it => it.name === itemName && it.type == itemType));
if (!item) return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`);
// Trigger the item roll
switch (item.type) {
case "arme":
return actor.rollArme(item);
case "competence":
return actor.rollCompetence( itemName );
}
}
// Trigger the item roll
switch (item.type) {
case "arme":
return actor.rollArme(item);
case "competence":
return actor.rollCompetence(itemName);
}
}
}

View File

@ -221,20 +221,19 @@ function messageDeBienvenue() {
// Register world usage statistics
function registerUsageCount( registerKey ) {
if ( game.user.isGM ) {
game.settings.register("world", "world-key", {
game.settings.register(registerKey, "world-key", {
name: "Unique world key",
scope: "world",
config: false,
default: "NONE",
type: String
});
let worldKey = game.settings.get("world", "world-key")
let worldKey = game.settings.get(registerKey, "world-key")
if ( worldKey == undefined || worldKey == "" ) {
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)
/* -------------------------------------------- */
}
@ -292,8 +291,8 @@ async function migrationPngWebp_1_5_34() {
await Item.updateDocuments(itemsUpdates);
await Actor.updateDocuments(actorsUpdates);
game.actors.forEach(actor => {
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
if (actor.data.token?.img && actor.data.token.img.match(regexOldPngJpg)) {
actor.update({ "token.img": convertImgToWebp(actor.data.token.img) });
}
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);

View File

@ -19,9 +19,9 @@ export class RdDPossession {
/* -------------------------------------------- */
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) {
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;
}
@ -31,11 +31,11 @@ export class RdDPossession {
possession.ptsConjuration = 0
possession.ptsPossession = 0
console.log("Possession", possession)
if (possession.system.compteur > 0) {
possession.ptsPossession = possession.system.compteur
if (possession.data.compteur > 0) {
possession.ptsPossession = possession.data.compteur
}
if (possession.system.compteur < 0) {
possession.ptsConjuration = Math.abs(possession.system.compteur)
if (possession.data.compteur < 0) {
possession.ptsConjuration = Math.abs(possession.data.compteur)
}
possession.isPosseder = false
possession.isConjurer = false
@ -49,14 +49,14 @@ export class RdDPossession {
/* -------------------------------------------- */
static async resultConjuration(rollData) {
let actor = game.actors.get(rollData.possession.system.possedeid)
let actor = game.actors.get(rollData.possession.data.possedeid)
if (!rollData.rolled.isSuccess) {
if (rollData.isECNIDefender) {
rollData.possession.system.compteur--
rollData.possession.data.compteur--
} else {
rollData.possession.system.compteur++
rollData.possession.data.compteur++
}
let update = { _id: rollData.possession._id, "system.compteur": rollData.possession.system.compteur }
let update = { _id: rollData.possession._id, "data.compteur": rollData.possession.data.compteur }
await actor.updateEmbeddedDocuments('Item', [update])
}
@ -84,10 +84,10 @@ export class RdDPossession {
attacker: attacker,
defender: defender,
competence: defender.getDraconicOuPossession(),
selectedCarac: defender.system.carac.reve,
selectedCarac: defender.data.data.carac.reve,
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } }
}
rollData.competence.system.defaut_carac = 'reve-actuel'
rollData.competence.data.defaut_carac = 'reve-actuel'
const dialog = await RdDRoll.create(defender, rollData,
@ -159,7 +159,7 @@ export class RdDPossession {
let possessionData = {
name: "Possession en cours de " + attacker.name, type: 'possession',
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
system: { description: "", typepossession: attacker.name, possede: false, possessionid: randomID(16), possesseurid: attacker.id, possedeid: defender.id, date: 0, compteur: 0 }
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])

View File

@ -158,6 +158,7 @@ export class RdDResolutionTable {
if (difficulte < -10) {
return duplicate(levelDown.find(levelData => levelData.level == difficulte));
}
console.log("DATA :", caracValue, difficulte)
return duplicate(RdDResolutionTable.resolutionTable[caracValue][difficulte + 10]);
}
@ -166,7 +167,7 @@ export class RdDResolutionTable {
if (rollData.selectedCarac?.label.toLowerCase().includes('chance')) {
return true;
}
if (rollData.selectedSort?.system.isrituel) {
if (rollData.selectedSort?.data.isrituel) {
return true;
}
return false;

View File

@ -38,25 +38,25 @@ export class RdDRoll extends Dialog {
/* -------------------------------------------- */
static _setDefaultOptions(actor, rollData) {
const actorData = actor.system
const actorData = Misc.data(actor);
let defaultRollData = {
alias: actor.name,
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
difficultesLibres: CONFIG.RDD.difficultesLibres,
etat: actor.getEtatGeneral(),
moral: actor.getMoralTotal(), /* La valeur du moral pour les jets de volonté */
carac: actorData.carac,
carac: actorData.data.carac,
finalLevel: 0,
diffConditions: 0,
diffLibre: rollData.competence?.system.default_diffLibre ?? 0,
diffLibre: rollData.competence?.data.default_diffLibre ?? 0,
malusArmureValue: actor.getMalusArmure(),
surencMalusFlag: actor.isPersonnage() ? (actorData.compteurs.surenc.value < 0) : false,
surencMalusFlag: actor.isPersonnage() ? (actorData.data.compteurs.surenc.value < 0) : false,
surencMalusValue: actor.computeMalusSurEncombrement(),
useMalusSurenc: false,
useMoral: false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */
perteMoralEchec: false, /* Pour l'affichage dans le chat */
use: { libre: true, conditions: true, surenc: false, encTotal: false },
isMalusEncombrementTotal: rollData.competence ? RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) : 0,
isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
useMalusEncTotal: false,
encTotal: actor.getEncTotal(),
ajustementAstrologique: actor.ajustementAstrologique(),
@ -67,7 +67,7 @@ export class RdDRoll extends Dialog {
}
// Mini patch :Ajout du rêve actuel
if ( actorData.type == "personnage") {
defaultRollData.carac["reve-actuel"] = actorData.reve.reve
defaultRollData.carac["reve-actuel"] = actorData.data.reve.reve
}
mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });
@ -165,17 +165,17 @@ export class RdDRoll extends Dialog {
function onLoad() {
let rollData = dialog.rollData;
console.log('Ouverture RdDRoll', rollData);
// Update html, according to rollData
console.log(rollData);
// Update html, according to data
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
rollData.selectedCarac = rollData.carac[defaut_carac];
$("#carac").val(defaut_carac);
}
if (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);
$("#diffLibre").val(Misc.toInt(rollData.diffLibre));
@ -221,7 +221,7 @@ export class RdDRoll extends Dialog {
});
html.find('#ptreve-variable').change((event) => {
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);
this.updateRollResult();
});
@ -271,21 +271,21 @@ export class RdDRoll extends Dialog {
async setSelectedSort(sort) {
this.rollData.selectedSort = sort; // Update the selectedCarac
this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.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.diffLibre = RdDItemSort.getDifficulte(sort, -7);
RdDItemSort.setCoutReveReel(sort);
const htmlSortDescription = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html", { sort: sort });
$(".sort-ou-rituel").text(sort.system.isrituel ? "rituel" : "sort");
$(".sort-ou-rituel").text(sort.data.isrituel ? "rituel" : "sort");
$(".bonus-case").text(`${this.rollData.bonus}%`);
$(".details-sort").remove();
$(".description-sort").append(htmlSortDescription);
$(".roll-draconic").val(sort.system.listIndex);
$(".div-sort-difficulte-fixe").text(Misc.toSignedString(sort.system.difficulte));
$(".div-sort-ptreve-fixe").text(sort.system.ptreve);
$(".roll-draconic").val(sort.data.listIndex);
$(".div-sort-difficulte-fixe").text(Misc.toSignedString(sort.data.difficulte));
$(".div-sort-ptreve-fixe").text(sort.data.ptreve);
const diffVariable = RdDItemSort.isDifficulteVariable(sort);
const coutVariable = RdDItemSort.isCoutVariable(sort);
HtmlUtility._showControlWhen($(".div-sort-non-rituel"), !sort.system.isrituel);
HtmlUtility._showControlWhen($(".div-sort-non-rituel"), !sort.data.isrituel);
HtmlUtility._showControlWhen($(".div-sort-difficulte-var"), diffVariable);
HtmlUtility._showControlWhen($(".div-sort-difficulte-fixe"), !diffVariable);
HtmlUtility._showControlWhen($(".div-sort-ptreve-var"), coutVariable);
@ -294,7 +294,7 @@ export class RdDRoll extends Dialog {
async setSelectedSigneDraconique(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));
}
@ -348,10 +348,10 @@ export class RdDRoll extends Dialog {
/* -------------------------------------------- */
_computeDiffCompetence(rollData) {
if (rollData.competence) {
return Misc.toInt(rollData.competence.system.niveau);
return Misc.toInt(rollData.competence.data.niveau);
}
if (rollData.draconicList) {
return Misc.toInt(rollData.competence.system.niveau);
return Misc.toInt(rollData.competence.data.niveau);
}
return 0;
}
@ -388,7 +388,7 @@ export class RdDRoll extends Dialog {
return compName + " - " + rollData.selectedSort.name;
}
// If a weapon is there, add it in the title
const niveau = Misc.toSignedString(rollData.competence.system.niveau)
const niveau = Misc.toSignedString(rollData.competence.data.niveau);
if (compName == carac) {
// cas des créatures
return carac + " Niveau " + niveau

View File

@ -10,22 +10,21 @@ export class RdDRollTables {
table = await pack.getDocument(entry._id);
}
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll"});
//console.log("RdDRollTables", tableName, toChat, ":", draw);
console.log("RdDRollTables", tableName, toChat, ":", draw);
return draw.results.length > 0 ? draw.results[0] : undefined;
}
/* -------------------------------------------- */
static async drawItemFromRollTable(tableName, toChat = false) {
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
const pack = game.packs.get(drawResult.documentCollection)
let doc = await pack.getDocument(drawResult.documentId)
return doc
const pack = game.packs.get(drawResult.data.collection);
return await pack.getDocument(drawResult.data.resultId);
}
/* -------------------------------------------- */
static async drawTextFromRollTable(tableName, toChat) {
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
return drawResult.system.text;
return drawResult.data.text;
}
/* -------------------------------------------- */

View File

@ -21,14 +21,14 @@ export class RdDSheetUtility {
}
static prepareItemDropParameters(destItemId, actorId, dragData, objetVersConteneur) {
const item = fromUuidSync(dragData.uuid)
const itemId = dragData.id || dragData.data._id;
return {
destId: destItemId,
targetActorId: actorId,
itemId: item.id,
sourceActorId: item.actor?.id,
srcId: objetVersConteneur[item.id],
onEnleverConteneur: () => { delete objetVersConteneur[item.id]; },
itemId: itemId,
sourceActorId: dragData.actorId,
srcId: objetVersConteneur[itemId],
onEnleverConteneur: () => { delete objetVersConteneur[itemId]; },
onAjouterDansConteneur: (itemId, conteneurId) => { objetVersConteneur[itemId] = conteneurId; }
}
}
@ -42,12 +42,12 @@ export class RdDSheetUtility {
}
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);
const splitItem = duplicate(item);
const itemData = duplicate(Misc.data(item));
// todo: ajouter dans le même conteneur?
splitItem.system.quantite = split;
await actor.createEmbeddedDocuments('Item', [splitItem])
itemData.data.quantite = split;
await actor.createEmbeddedDocuments('Item', [itemData])
}
}
}

View File

@ -78,12 +78,12 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
loadCasesSpeciales() {
this.casesSpeciales = this.actor.items.filter(item => Draconique.isCaseTMR(item));
this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item));
}
/* -------------------------------------------- */
loadSortsReserve() {
this.sortsReserves = this.actor.system.reve.reserve.list;
this.sortsReserves = Misc.data(this.actor).data.reve.reserve.list;
}
/* -------------------------------------------- */
@ -144,16 +144,17 @@ export class RdDTMRDialog extends Dialog {
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord);
}
_tokenCaseSpeciale(casetmr) {
const caseData = casetmr;
const draconique = Draconique.get(caseData.system.specific);
return draconique?.token(this.pixiTMR, caseData, () => caseData.system.coord);
const caseData = Misc.data(casetmr);
const draconique = Draconique.get(caseData.data.specific);
return draconique?.token(this.pixiTMR, caseData, () => caseData.data.coord);
}
_tokenSortEnReserve(sortEnReserve) {
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortEnReserve.sort, () => sortEnReserve.coord);
}
_tokenDemiReve() {
return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor.system, () => 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() {
@ -162,7 +163,7 @@ export class RdDTMRDialog extends Dialog {
}
_getActorCoord() {
return this.actor.system.reve.tmrpos.coord;
return Misc.data(this.actor).data.reve.tmrpos.coord;
}
/* -------------------------------------------- */
@ -246,11 +247,12 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
async updateValuesDisplay() {
const coord = this._getActorCoord();
const actorData = Misc.data(this.actor);
HtmlUtility._showControlWhen($(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
let ptsreve = document.getElementById("tmr-pointsreve-value");
ptsreve.innerHTML = this.actor.system.reve.reve.value;
ptsreve.innerHTML = actorData.data.reve.reve.value;
let tmrpos = document.getElementById("tmr-pos");
if (this.isDemiReveCache()) {
@ -263,11 +265,12 @@ export class RdDTMRDialog extends Dialog {
etat.innerHTML = this.actor.getEtatGeneral();
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")) {
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>";
}
}
@ -511,7 +514,7 @@ export class RdDTMRDialog extends Dialog {
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
if (presentCite) {
this.minimize();
const caseData = presentCite;
const caseData = Misc.data(presentCite);
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (type => this._utiliserPresentCite(presentCite, type, tmr, postRencontre)));
}
return presentCite;
@ -593,7 +596,7 @@ export class RdDTMRDialog extends Dialog {
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
}
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined,
rollData.competence.system.defaut_carac = 'reve-actuel';
rollData.competence.data.defaut_carac = 'reve-actuel';
await this._rollMaitriseCaseHumide(rollData);
}
}
@ -718,7 +721,7 @@ export class RdDTMRDialog extends Dialog {
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } },
maitrise: { verbe: 'conquérir', action: options.action }
};
rollData.competence.system.defaut_carac = 'reve-actuel';
rollData.competence.data.defaut_carac = 'reve-actuel';
await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options));
}
@ -872,6 +875,7 @@ export class RdDTMRDialog extends Dialog {
if (this.viewOnly) {
return;
}
let clickOddq = RdDTMRDialog._computeEventOddq(event.data.originalEvent);
await this._onClickTMRPos(clickOddq); // Vérifier l'état des compteurs reve/fatigue/vie
}

View File

@ -8,7 +8,7 @@ export class RdDTokenHud {
static init() {
// 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 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) ) {
ui.notifications.warn(`Le combatant ${token.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
return;
@ -63,7 +63,7 @@ export class RdDTokenHud {
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
const action = actionsCombat[actionIndex];
if (action.action == 'conjurer') {
actor.conjurerPossession(actor.getPossession(action.system.possessionid));
actor.conjurerPossession(actor.getPossession(action.data.possessionid));
}
else {
actor.rollArme(action);
@ -76,7 +76,7 @@ export class RdDTokenHud {
case 'inc': return RdDCombatManager.incDecInit(combatantId, 0.01);
case 'dec': return RdDCombatManager.incDecInit(combatantId, -0.01);
case 'autre': return RdDCombatManager.rollInitiativeAction(combatantId,
{ name: "Autre action", action: 'autre', system: { initOnly: true, competence: "Autre action" } });
{ name: "Autre action", action: 'autre', data: { initOnly: true, competence: "Autre action" } });
}
}

View File

@ -104,7 +104,7 @@ export class RdDUtility {
/* -------------------------------------------- */
static async init() {
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));
}
/* -------------------------------------------- */
@ -130,7 +130,6 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-liens-vehicules.html',
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-editor-notes-mj.html',
//Items
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-arme-sheet.html',
@ -240,7 +239,7 @@ export class RdDUtility {
Handlebars.registerHelper('typeTmr-name', coord => TMRUtility.typeTmrName(coord));
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
Handlebars.registerHelper('filtreTriCompetences', competences => competences.filter(it => it.system.isVisible)
Handlebars.registerHelper('filtreTriCompetences', competences => competences.filter(it => it.visible)
.sort((a, b) => {
if (a.name.startsWith("Survie") && b.name.startsWith("Survie")) {
if (a.name.includes("Cité")) return -1;
@ -249,7 +248,7 @@ export class RdDUtility {
if (b.name.includes("Extérieur")) return 1;
return a.name.localeCompare(b.name);
}
if (a.system.categorie.startsWith("melee") && b.system.categorie.startsWith("melee")) {
if (a.data.categorie.startsWith("melee") && b.data.categorie.startsWith("melee")) {
if (a.name.includes("Corps")) return -1;
if (b.name.includes("Corps")) return 1;
if (a.name.includes("Dague")) return -1;
@ -429,7 +428,7 @@ export class RdDUtility {
// Attribution des objets aux conteneurs
for (let conteneur of conteneurs) {
conteneur.subItems = [];
for (let id of conteneur.system.contenu ?? []) {
for (let id of conteneur.data.contenu ?? []) {
let objet = objets.find(objet => (id == objet._id));
if (objet) {
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template
@ -439,26 +438,27 @@ export class RdDUtility {
}
}
for (let conteneur of conteneurs) {
conteneur.system.encTotal = RdDUtility.calculEncContenu(conteneur, objets);
conteneur.data.encTotal = RdDUtility.calculEncContenu(conteneur, objets);
}
return objetVersConteneur;
}
/* -------------------------------------------- */
static calculEncContenu(conteneur, objets) {
const contenus = (conteneur.system.contenu ?? []).filter(id => id != undefined)
.map(id => objets.find(it => (id == it.id)))
const itemData = Misc.data(conteneur);
const contenuDatas = (itemData.data.contenu ?? []).filter(id => id != undefined)
.map(id => Misc.data(objets.find(it => (id == it._id))))
.filter(it => it);
let enc = Number(conteneur.system.encombrement ?? 0) * Number(conteneur.system.quantite ?? 1);
for (let contenu of contenus) {
if (contenu.type == 'conteneur') {
enc += RdDUtility.calculEncContenu(contenu, objets);
let enc = Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
for (let itemData of contenuDatas) {
if (itemData.type == 'conteneur') {
enc += RdDUtility.calculEncContenu(itemData, objets);
}
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;
}
/* -------------------------------------------- */
@ -476,7 +476,7 @@ export class RdDUtility {
objet.niveau = profondeur;
const isConteneur = objet.type == 'conteneur';
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-sheet-inventaire-item.html']({
item: objet,
vide: isVide,
@ -654,9 +654,9 @@ export class RdDUtility {
}
/* -------------------------------------------- */
static async responseNombreAstral(callData) {
let actor = game.actors.get(callData.id);
actor.ajouteNombreAstral(callData);
static async responseNombreAstral(data) {
let actor = game.actors.get(data.id);
actor.ajouteNombreAstral(data);
}
/* -------------------------------------------- */
@ -754,7 +754,7 @@ export class RdDUtility {
static getSelectedActor(msgPlayer = undefined) {
if (canvas.tokens.controlled.length == 1) {
let token = canvas.tokens.controlled[0];
if (token.actor) {
if (token.actor && token.data.actorLink) {
return token.actor;
}
if (msgPlayer != undefined) {
@ -777,7 +777,7 @@ export class RdDUtility {
static createMonnaie(name, valeur_deniers, img = "", enc = 0.01) {
let piece = {
name: name, type: 'monnaie', img: img, _id: randomID(16),
dasystemta: {
data: {
quantite: 0,
valeur_deniers: valeur_deniers,
encombrement: enc,
@ -832,7 +832,7 @@ export class RdDUtility {
static confirmerSuppressionSubacteur(actorSheet, li) {
let actorId = li.data("actor-id");
let actor = game.actors.get(actorId);
let msgTxt = "<p>Etes vous certain de vouloir supprimer le lien vers ce véhicule/monture/suivant : " + actor.name + " ?</p>";
let msgTxt = "<p>Etes vous certain de vouloir supprimer le lien vers ce véhicule/monture/suivant : " + actor.data.name + " ?</p>";
let d = new Dialog({
title: "Confirmer la suppression du lien",
content: msgTxt,
@ -861,7 +861,7 @@ export class RdDUtility {
let itemId = li.data("item-id");
let objet = actorSheet.actor.getObjet(itemId);
if (Monnaie.isSystemMonnaie(objet, actorSheet.actor.items)) {
if (objet.type == 'monnaie' && Monnaie.isSystemMonnaie(objet)) {
ui.notifications.warn("Suppression des monnaies de base impossible");
return;
}
@ -882,7 +882,8 @@ export class RdDUtility {
label: "Annuler"
}
}
if (objet.type == 'conteneur' && objet.system.contenu.length > 0) {
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>',

View File

@ -19,9 +19,9 @@ import { ReglesOptionelles } from "./regles-optionelles.js";
*/
export const referenceAjustements = {
competence: {
isUsed: (rollData, actor) => rollData.competence,
getLabel: (rollData, actor) => rollData.competence?.name,
getValue: (rollData, actor) => rollData.competence?.system?.niveau,
isUsed: (rollData, actor) => Misc.data(rollData.competence),
getLabel: (rollData, actor) => Misc.data(rollData.competence)?.name,
getValue: (rollData, actor) => Misc.data(rollData.competence)?.data?.niveau,
},
meditation: {
isUsed: (rollData, actor) => rollData.meditation,
@ -33,7 +33,7 @@ export const referenceAjustements = {
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ? 'Imposée' : 'Libre',
getValue: (rollData, actor) => rollData.selectedSort
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
: rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0
: rollData.diffLibre ?? Misc.data(rollData.competence)?.data.default_diffLibre ?? 0
},
diffConditions: {
isUsed: (rollData, actor) => rollData.diffConditions != undefined,
@ -95,10 +95,10 @@ export const referenceAjustements = {
getDescr: (rollData, actor) => rollData.diviseurSignificative > 1 ? `Facteur significative <span class="rdd-diviseur">&times;${Misc.getFractionHtml(rollData.diviseurSignificative)}</span>` : ''
},
isEcaille: {
isVisible: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
isUsed: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
isVisible: (rollData, actor) => Misc.data(rollData.arme)?.data.magique && Number(Misc.data(rollData.arme)?.data.ecaille_efficacite) > 0,
isUsed: (rollData, actor) => Misc.data(rollData.arme)?.data.magique && Number(Misc.data(rollData.arme)?.data.ecaille_efficacite) > 0,
getLabel: (rollData, actor) => "Ecaille d'Efficacité: ",
getValue: (rollData, actor) => Math.max(Number(rollData.arme?.system.ecaille_efficacite), 0),
getValue: (rollData, actor) => Math.max(Number(Misc.data(rollData.arme)?.data.ecaille_efficacite), 0),
},
finesse: {
isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData),

View File

@ -433,7 +433,7 @@ export class TMRRencontres {
/* -------------------------------------------- */
static async msgEchecPasseurFou(tmrData) {
tmrData.sortReserve = tmrData.actor.system.reve.reserve.list[0];
tmrData.sortReserve = Misc.templateData(tmrData.actor).reve.reserve.list[0];
if (tmrData.sortReserve) {
// Passeur fou positionne sur la case d'un ort en réserve // TODO : Choisir le sort le plus loin ou au hasard
tmrData.newTMR = TMRUtility.getTMR(tmrData.sortReserve.coord);
@ -468,15 +468,15 @@ export class TMRRencontres {
}
/* -------------------------------------------- */
static async onPostEchecTourbillonRouge(tmrDialog, rencontre) {
await rencontre.actor.reveActuelIncDec(-2); // -2 pts de Reve a chaque itération
TMRRencontres._toubillonner(tmrDialog, rencontre.actor, 4);
await rencontre.actor.santeIncDec("vie", -1); // Et -1 PV
static async 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 = actor.system.reve.tmrpos.coord;
let coord = Misc.templateData(actor).reve.tmrpos.coord;
for (let i = 0; i < cases; i++) {
coord = await TMRUtility.deplaceTMRAleatoire(actor, coord).coord;
}
@ -486,7 +486,7 @@ export class TMRRencontres {
/* -------------------------------------------- */
static async onPostSuccessReveDeDragon(tmrDialog, tmrData) {
if (tmrData.rolled.isPart) {
await tmrData.actor.appliquerAjoutExperience(tmrData);
await tmrData.actor.appliquerAjoutExperience(tmrData, true);
}
await tmrData.actor.resultCombatReveDeDragon(tmrData);
}

View File

@ -32,14 +32,14 @@ export class Conquete extends Draconique {
}
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 conquete = await RdDDice.rollOneOf(possibles);
await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue.id);
}
async onActorDeleteCaseTmr(actor, casetmr) {
await actor.deleteEmbeddedDocuments('Item', [casetmr.system.sourceid]);
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
}
}

View File

@ -13,7 +13,7 @@ export class Debordement extends Draconique {
match(item) { return Draconique.isSouffleDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('debordement'); }
manualMessage() { return false }
async onActorCreateOwned(actor, souffle) {
const existants = actor.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)));
await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr, souffle.id);
}

View File

@ -22,7 +22,7 @@ export class Desorientation extends Draconique {
}
_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));
}
@ -42,7 +42,7 @@ export class Desorientation extends Draconique {
}
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));
for (let tmr of tmrs) {
await this.createCaseTmr(actor, 'Désorientation: ' + tmr.label, tmr, souffle.id);

View File

@ -9,13 +9,13 @@ const registeredEffects = [
* Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR
*/
export class Draconique {
static isCaseTMR(item) { return item.type == 'casetmr'; }
static isQueueDragon(item) { return item.type == 'queue' || item.type == 'ombre'; }
static isSouffleDragon(item) { return item.type == 'souffle'; }
static isTeteDragon(item) { return item.type == 'tete'; }
static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); }
static isCaseTMR(itemData) { return itemData.type == 'casetmr'; }
static isQueueDragon(itemData) { return itemData.type == 'queue' || itemData.type == 'ombre'; }
static isSouffleDragon(itemData) { return itemData.type == 'souffle'; }
static isTeteDragon(itemData) { return itemData.type == 'tete'; }
static isQueueSouffle(itemData) { return Draconique.isQueueDragon(itemData) || Draconique.isSouffleDragon(itemData); }
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.system.coord); }
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.data.coord); }
static register(draconique) {
registeredEffects[draconique.code()] = draconique;
@ -38,7 +38,8 @@ export class Draconique {
* @returns true si l'item correspond
*/
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,
*/
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) {
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) {
const casetmrData = {
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]);
}
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));
}
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) {
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));
for (let casetmr of existants) {
onRemoveToken(tmr, casetmr);

View File

@ -95,7 +95,7 @@ export class EffetsDraconiques {
/* -------------------------------------------- */
static isSortImpossible(actor) {
return actor.items.find(it =>
return actor.data.items.find(it =>
EffetsDraconiques.conquete.match(it) ||
EffetsDraconiques.periple.match(it) ||
EffetsDraconiques.urgenceDraconique.match(it) ||
@ -104,7 +104,7 @@ export class EffetsDraconiques {
}
static isSortReserveImpossible(actor) {
return actor.items.find(it =>
return actor.data.items.find(it =>
EffetsDraconiques.conquete.match(it) ||
EffetsDraconiques.periple.match(it) ||
EffetsDraconiques.pelerinage.match(it)
@ -112,7 +112,7 @@ export class EffetsDraconiques {
}
static filterItems(actor, filter, name) {
return actor.filterItems(filter)
return actor.data.items.filter(filter)
.filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
}
@ -150,11 +150,11 @@ export class EffetsDraconiques {
}
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) {
return actor.items.find(it => EffetsDraconiques.urgenceDraconique.match(it));
return actor.data.items.find(it => EffetsDraconiques.urgenceDraconique.match(it));
}
static isPeage(actor) {

View File

@ -30,7 +30,7 @@ export class FermetureCites extends Draconique {
}
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));
for (let tmr of ouvertes) {
await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr, souffle.id);

View File

@ -33,7 +33,7 @@ export class Pelerinage extends Draconique {
}
async onActorDeleteCaseTmr(actor, casetmr) {
await actor.deleteEmbeddedDocuments('Item', [casetmr.system.sourceid]);
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
}
}

View File

@ -25,7 +25,7 @@ export class PixiTMR {
for (const [name, img] of Object.entries(PixiTMR.textures)) {
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) => {
onLoad(loader, resources);
for (let onAnimate of this.callbacksOnAnimate) {

View File

@ -30,7 +30,7 @@ export class PresentCites extends Draconique {
}
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) {
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),

View File

@ -12,8 +12,8 @@ export class ReserveExtensible extends Draconique {
match(item) { return Draconique.isTeteDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes("reserve extensible"); }
manualMessage() { return "Vous pouvez re-configurer votre Réserve extensible" }
async onActorCreateOwned(actor, tete) {
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
const tmr = await TMRUtility.getTMRAleatoire(it => !(it.type == 'fleuve' || existants.includes(it.system.coord)));
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
const tmr = await TMRUtility.getTMRAleatoire(it => !(it.type == 'fleuve' || existants.includes(it.coord)));
await this.createCaseTmr(actor, "Nouvelle Réserve extensible", tmr, tete.id);
}

View File

@ -13,8 +13,8 @@ export class TrouNoir extends Draconique {
manualMessage() { return false }
async onActorCreateOwned(actor, souffle) {
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
const tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.system.coord)));
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)));
await this.createCaseTmr(actor, 'Trou noir: ' + tmr.label, tmr, souffle.id);
}

View File

@ -16,7 +16,7 @@ export class UrgenceDraconique extends Draconique {
match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
manualMessage() { return false }
async onActorCreateOwned(actor, queue) {
const coordSortsReserve = (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) {
// La queue se transforme en idée fixe
const ideeFixe = await RdDRollTables.getIdeeFixe();
@ -37,7 +37,7 @@ export class UrgenceDraconique extends Draconique {
}
async onActorDeleteCaseTmr(actor, casetmr) {
await actor.deleteEmbeddedDocuments('Item', [casetmr.system.sourceid]);
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
}
code() { return 'urgence' }

View File

@ -23,7 +23,7 @@
{"_id":"UQYy9WjsKqqrjLc7","name":"Guerrier Sorde","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"sort","data":{"description":"<p>@JournalEntry[vid6uJc66QFgHSUr]{Note sur les invocations de créatures}</p>\n<p>Le Guerrier Sorde a lapparence dun humanoïde entièrement revêtu dune armure de plaques, visière du heaume toujours baissée, dissimulant son visage. Il est armé dune épée sorde, dun bouclier moyen et dune dague. La seule tâche que lon puisse lui demander est de faire usage de ses armes. Une fois invoqué, il attaque toute créature que le haut-rêvant lui désigne expressément, et se bat contre elle jusquà ce quil lextermine ou reçoive un contre-ordre. On peut alors lui ordonner de commencer un autre combat, à condition que le délai entre deux combats nexcède pas 10 rounds, faute de quoi il considère sa tâche accomplie et se dématérialise. Sil est invoqué alors quil ny a pas de créature à combattre immédiatement, il ne patiente que jusquà la fin de lheure en cours, après quoi il sestime dérangé pour rien et se dématérialise. Durant le délai, il peut accompagner le haut-rêvant où quil aille, mais sans pouvoir séloigner de lui de plus de E1 mètres. Sa vitesse est limitée à 12 m/round, il ne court, nescalade ni ne nage jamais. Il nobéit quau haut-rêvant qui la invoqué. Le rituel peut être répété pour invoquer plusieurs Guerriers Sordes dans un même combat. Tous ont les mêmes caractéristiques. La PERCEPTION indiquée tient compte des malus dus au heaume. Les Guerriers Sordes sont normalement affectés par les suggestions et illusions dHypnos, avec un JR standard r-8, ainsi que par les sorts individuels de Thananatos.</p>\n<p>@JournalEntry[R3q4vUTEfyxYgmGr]{Communication avec les créatures invoquées}</p>","draconic":"hypnos","duree":"Tâche","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"special","caseTMRspeciale":"Cité Sordide D13","ptreve":"7","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[]}
{"_id":"VG89vfk7KsO01eJv","name":"Secouriste blanc","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"sort","data":{"description":"<p>@JournalEntry[vid6uJc66QFgHSUr]{Note sur les invocations de créatures}</p>\n<p>Le Secouriste blanc ne peut être invoqué que pendant un combat ou au terme de celui-ci. Sa tâche consiste à prendre les blessés en charge, premiers soins et soins complets, ce quil fait spontanément. En plein combat, il peut même sapprocher de la mêlée pour tirer en arrière déventuels tombés à terre. Quand il a plusieurs blessés à soigner, il commence par le plus proche de lui. Mais linvocateur peut lui désigner un blessé à soigner en priorité.</p>\n<p>Le Secouriste possède son propre matériel de chirurgie, mais il na aucun consommable (eau, chiffons) quil faut lui fournir.</p>\n<p>Pour la résolution des soins, le Secouriste ne joue pas de jet de Chirurgie. À la place, cest le blessé qui joue des jets de CHANCE, pour déterminer les points de tâche obtenus :</p>\n<table style=\"height: 102px; width: 260px;\" border=\"0\">\n<tbody>\n<tr style=\"height: 17px;\">\n<td style=\"height: 17px; width: 119px;\">Particulière :</td>\n<td style=\"height: 17px; width: 134px;\">4 points</td>\n</tr>\n<tr style=\"height: 17px;\">\n<td style=\"width: 119px; height: 17px;\">Significative :</td>\n<td style=\"width: 134px; height: 17px;\">3 points</td>\n</tr>\n<tr style=\"height: 17px;\">\n<td style=\"width: 119px; height: 17px;\">Normale :</td>\n<td style=\"width: 134px; height: 17px;\">2 points</td>\n</tr>\n<tr style=\"height: 17px;\">\n<td style=\"width: 119px; height: 17px;\">Échec :</td>\n<td style=\"width: 134px; height: 17px;\">1 pt</td>\n</tr>\n<tr style=\"height: 17px;\">\n<td style=\"width: 119px; height: 17px;\">Échec particulier :</td>\n<td style=\"width: 134px; height: 17px;\">0 pt</td>\n</tr>\n<tr style=\"height: 17px;\">\n<td style=\"width: 119px; height: 17px;\">Échec total :</td>\n<td style=\"width: 134px; height: 17px;\">0 pt (et sans malus)</td>\n</tr>\n</tbody>\n</table>\n<p>Le Secouriste disparaît dès que le combat est terminé ET que tous les blessés ont été soignés.</p>\n<p>@JournalEntry[R3q4vUTEfyxYgmGr]{Communication avec les créatures invoquées}</p>","draconic":"hypnos","duree":"Tâche ou fin HN","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire Blanc G4","ptreve":"7","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[]}
{"_id":"WvTkEYb216X0XiJc","name":"Voix d'Hypnos","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"sort","data":{"description":"<p>Les rituels de lecture dHypnos sont détonnantes démonstrations dauto-suggestion. Aidé par un support, le haut-rêvant se persuade quil peut voir ou entendre à distance, et il le fait. Couplé à lultime forme dillusion que sont les invocations, il peut pareillement projeter son image ou sa voix à distance. Tous obéissent aux règles usuelles dapplication des rituels. Si un rituel de lecture est paramétré sur une personne et que celle-ci est morte ou a changé de rêve, aucun effet ne se produit, mais les points de rêve sont tout de même dépensés.</p>\n<p>Le rituel de Voix dHypnos permet de détecter le mensonge. Il ny a pas de véritable ciblage, le rituel opère sur le haut-rêvant directement sans passer par un support. Lors du paramétrage, le haut-rêvant se reporte à une certaine conversation de son choix, datant au maximum de 12 heures. La conversation peut avoir eu plusieurs interlocuteurs, mais Voix dHypnos ne fonctionne que sur un seul dentre eux à la fois.</p>\n<p>Pour les détecter tous, il faut recommencer autant de fois le rituel. Puis, le sort étant ciblé sur lui-même, le haut-rêvant se plonge dans un état hypnotique dans lequel il réentend toute la conversation, comme si on repassait la bande. La durée de réécoute est dun round, quelle quait été la conversation, le temps mental du haut-rêvant devenant élastique. Tant que son interlocuteur dit la vérité, sa voix est mélodieuse ; dès quil ment <em>volontairement</em>, elle devient horrible et grinçante. On ne peut ainsi détecter que les mensonges volontaires, pas les mensonges inconscients ou par omission.</p>","draconic":"hypnos","duree":"1 round","JR":"Aucun","cible":"Soi-même","difficulte":"-4","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"4","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[]}
{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"<p>Les rituels de Lecture d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Ce rituel permet d&rsquo;approfondir les informations fournies par D&eacute;tection d&rsquo;Aura. Pratiquer Lecture d&rsquo;Aura quand il n&rsquo;y a pas d&rsquo;aura revient &agrave; demander une magie impossible et cr&eacute;e imm&eacute;diatement une d&eacute;chirure du r&ecirc;ve.</p>\n<p>Lecture d&rsquo;Aura est effectu&eacute;e en plusieurs &eacute;tapes, toutes &eacute;tant de difficult&eacute; R-3 et co&ucirc;tant 3 points de r&ecirc;ve. La premi&egrave;re a toujours lieu dans un sanctuaire et ne fait que r&eacute;v&eacute;ler dans quel(s) autre(s) genre(s) de case(s) le haut-r&ecirc;vant doit se rendre pour continuer sa lecture. L&agrave;, il apprend quel genre de magie a &eacute;t&eacute; produit ou &agrave; quel type de r&ecirc;ve il a affaire, de m&ecirc;me que les cases sp&eacute;cifiques concern&eacute;es. Enfin dans les cases sp&eacute;cifiques, le haut-r&ecirc;vant peut apprendre la force du r&ecirc;ve ou de la magie en cours, c&rsquo;est-&agrave;-dire pratiquement la difficult&eacute; et le nombre de points de r&ecirc;ve impliqu&eacute;s, information indispensable dans l&rsquo;optique d&rsquo;une annulation de magie.</p>\n<p>Lecture d&rsquo;Aura r&eacute;v&egrave;le &eacute;galement la couleur de l&rsquo;aura (fixe ou pulsative) comme D&eacute;tection d&rsquo;Aura. Pour les cr&eacute;atures vivantes, on peut donc sauter l&rsquo;&eacute;tape de D&eacute;tection d&rsquo;Aura et commencer directement par la lecture, puisqu&rsquo;on est s&ucirc;r de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la d&eacute;tection si, en l&rsquo;absence finale d&rsquo;une aura, on ne veut pas cr&eacute;er de magie impossible. Effectu&eacute;e sur une cr&eacute;ature non soumise &agrave; un effet magique ni sous l&rsquo;emprise d&rsquo;une entit&eacute;, Lecture d&rsquo;Aura indique toujours le Fleuve. L&agrave;, dans n&rsquo;importe quelle case du Fleuve, le haut-r&ecirc;vant se contente d&rsquo;apprendre qu&rsquo;il a affaire &agrave; une cr&eacute;ature vivante et dou&eacute;e de r&ecirc;ve.</p>","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[]}
{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","data":{"description":"<p>Les rituels de Lecture d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Ce rituel permet d&rsquo;approfondir les informations fournies par D&eacute;tection d&rsquo;Aura. Pratiquer Lecture d&rsquo;Aura quand il n&rsquo;y a pas d&rsquo;aura revient &agrave; demander une magie impossible et cr&eacute;e imm&eacute;diatement une d&eacute;chirure du r&ecirc;ve.</p>\n<p>Lecture d&rsquo;Aura est effectu&eacute;e en plusieurs &eacute;tapes, toutes &eacute;tant de difficult&eacute; R-3 et co&ucirc;tant 3 points de r&ecirc;ve. La premi&egrave;re a toujours lieu dans un sanctuaire et ne fait que r&eacute;v&eacute;ler dans quel(s) autre(s) genre(s) de case(s) le haut-r&ecirc;vant doit se rendre pour continuer sa lecture. L&agrave;, il apprend quel genre de magie a &eacute;t&eacute; produit ou &agrave; quel type de r&ecirc;ve il a affaire, de m&ecirc;me que les cases sp&eacute;cifiques concern&eacute;es. Enfin dans les cases sp&eacute;cifiques, le haut-r&ecirc;vant peut apprendre la force du r&ecirc;ve ou de la magie en cours, c&rsquo;est-&agrave;-dire pratiquement la difficult&eacute; et le nombre de points de r&ecirc;ve impliqu&eacute;s, information indispensable dans l&rsquo;optique d&rsquo;une annulation de magie.</p>\n<p>Lecture d&rsquo;Aura r&eacute;v&egrave;le &eacute;galement la couleur de l&rsquo;aura (fixe ou pulsative) comme D&eacute;tection d&rsquo;Aura. Pour les cr&eacute;atures vivantes, on peut donc sauter l&rsquo;&eacute;tape de D&eacute;tection d&rsquo;Aura et commencer directement par la lecture, puisqu&rsquo;on est s&ucirc;r de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la d&eacute;tection si, en l&rsquo;absence finale d&rsquo;une aura, on ne veut pas cr&eacute;er de magie impossible. Effectu&eacute;e sur une cr&eacute;ature non soumise &agrave; un effet magique ni sous l&rsquo;emprise d&rsquo;une entit&eacute;, Lecture d&rsquo;Aura indique toujours le Fleuve. L&agrave;, dans n&rsquo;importe quelle case du Fleuve, le haut-r&ecirc;vant se contente d&rsquo;apprendre qu&rsquo;il a affaire &agrave; une cr&eacute;ature vivante et dou&eacute;e de r&ecirc;ve.</p>","descriptionmj":"","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"flags":{}}
{"_id":"YOJsOLpHTQYreZ6i","name":"Soufflet","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","data":{"description":"<p>Le Soufflet peut être dirigé contre toute créature, humanoïde ou animale. Son effet, instantané, est celui dune gifle magistrale, causant ses dommages sur la table des Coups non mortels. Le +dom de lagression est égal au nombre de points de rêve dépensés. Sauf pour les animaux qui peuvent faire jouer entièrement leur protection naturelle, la protection applicable peut être au maximum de 2 points.</p>","descriptionmj":"","draconic":"hypnos","duree":"Instantanée","JR":"Humanoïde selon HN, animal r-8","cible":"Toutes créatures","difficulte":"-6","portée":"","caseTMR":"gouffre","caseTMRspeciale":"","ptreve":"1+","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"jOzRscDxoXZWpGS6":3},"flags":{}}
{"_id":"aYOfXEuDp6xGDO4N","name":"Égarement","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"sort","data":{"description":"<p>Leffet dÉgarement ne sapplique quaux humanoïdes. Lapport massif de pseudo-souvenirs, informulés et insaisissables, empêche lhumanoïde visé de se concentrer sur son activité intellectuelle, manuelle ou verbale. Il ne fait plus ou ne dit plus que des <em>bêtises</em>, en termes de jeu des échecs totaux. Un intellectuel devient incapable de lire ou décrire, un artisan se tape sur les doigts, un musicien rate tous ses accords, un orateur bafouille, etc. Létat dégarement dure jusquà la fin de lheure en cours + une heure complète, ou se dissipe de lui-même dès quil y a stress, par exemple une agression. Ce sort est donc totalement inutile et inefficace en combat.</p>","draconic":"hypnos","duree":"Une heure","JR":"Selon HN","cible":"Humanoïde","difficulte":"-4","portée":"","caseTMR":"desolation","caseTMRspeciale":"","ptreve":"4"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[]}
{"_id":"cghxHRstw7cXLEm4","name":"Invoquer son image","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","data":{"description":"<p>Les rituels de lecture dHypnos sont détonnantes démonstrations dauto-suggestion. Aidé par un support, le haut-rêvant se persuade quil peut voir ou entendre à distance, et il le fait. Couplé à lultime forme dillusion que sont les invocations, il peut pareillement projeter son image ou sa voix à distance. Tous obéissent aux règles usuelles dapplication des rituels. Si un rituel de lecture est paramétré sur une personne et que celle-ci est morte ou a changé de rêve, aucun effet ne se produit, mais les points de rêve sont tout de même dépensés.</p>\n<p>Ce rituel est comme le négatif de @Item[Ew5JzQ2lzcpGoF11]{Miroir d'Hypnos}. Les conditions de ciblage et de paramétrage en sont exactement les mêmes. Lorsquun mouvement apparaît au centre du miroir, provoquant létat hypnotique, le haut-rêvant peut commencer à effectuer des gestes, des mimiques, ou montrer ostensiblement un objet quil tient sur lui, mais sans pouvoir se déplacer. Dans linstant même, un hologramme de lui-même, grandeur nature et fidèle jusquau moindre geste, prend naissance près de la personne ou au centre du lieu choisi.</p>\n<p>Les spectateurs peuvent se déplacer à travers lhologramme, ce nest quune illusion sans substance. Par ce rituel, le haut-rêvant ne peut communiquer aucun son, et lui-même nentend ni ne voit rien. Il ne peut pas savoir comment est accueillie sa \"visite\". La communication est de 1 round par point de rêve dépensé.</p>","descriptionmj":"","draconic":"hypnos","duree":"Selon r dépensé","JR":"Aucun","cible":"Un miroir","difficulte":"-6","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1+","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"jOzRscDxoXZWpGS6":3},"flags":{}}
@ -39,7 +39,7 @@
{"_id":"qqcLydulFkL25Ipc","name":"Conjurer l'oubli","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"sort","data":{"description":"<p>Ce rituel permet de faire renaître chez la cible un souvenir oublié, la cause de loubli pouvant être magique ou naturelle. Le souvenir oublié peut appartenir à une précédente incarnation si le gardien des rêves lestime possible ou pertinent. Dans tous les cas, le souvenir ne peut revenir que sous la forme dune <em>réponse </em>à une <em>question </em>précise. Et laccomplissement du rituel ne permet quune seule question-réponse.</p>","draconic":"hypnos","duree":"Une question","JR":"Aucun","cible":"Humanoïde","difficulte":"-4","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"4","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[]}
{"_id":"rrSE9c7KKsqcKueo","name":"Nonechalepasse","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"sort","data":{"description":"<p>@JournalEntry[vid6uJc66QFgHSUr]{Note sur les invocations de créatures}</p>\n<p>Le Nonechalepasse a la même apparence physique et le même armement que le Guerrier Sorde. Cest en fait une variante de ce dernier. Il est invoqué pour garder ou veiller sur quelque chose : une porte, un coffre, un pont, etc. Layant invoqué, le haut-rêvant doit lui indiquer expressément sur quoi il doit veiller, et le Nonechalepasse ne laissera personne dautre que linvocateur franchir la limite indiquée, cest-à-dire pas même ses compagnons. La garde peut avoir lieu en la présence du haut-rêvant, ou en son absence sil désire vaquer à dautres affaires, et dure jusquà la fin de son heure de naissance. Dès quune créature est en voie denfreindre la consigne donnée, le Nonechalepasse len prévient en clamant son propre nom à plusieurs reprises ; et si la créature insiste, il la combat jusquà ce quil lextermine ou quelle recule et senfuie. Les Nonechalepasses ont tous les mêmes caractéristiques que les Guerriers Sordes et sont comme eux affectés par les sorts.</p>\n<p>@JournalEntry[R3q4vUTEfyxYgmGr]{Communication avec les créatures invoquées}</p>","draconic":"hypnos","duree":"Tâche","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"special","caseTMRspeciale":"Cité Jalouse M1","ptreve":"7","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[]}
{"_id":"sVA94h9Reimmfw5B","name":"Suggestion","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","data":{"description":"<p>Leffet de Suggestion ne sapplique quaux humanoïdes. Comme lindique le titre, cest la suggestion à létat pur. Il permet de donner un ordre bref à la victime, et cette dernière ne pourra pas sempêcher dy obéir machinalement. Il est impératif que la victime puisse obéir à lordre de façon <em>immédiate</em>, dans la seconde qui suit lordre, et que laction soit uniquement <em>physique</em>, ni mentale ni réfléchie. Si la Suggestion est telle quelle oblige la victime à une autre action préalable ou si laction demandée ne peut être quune action réfléchie, pensée, la Suggestion avorte automatiquement.</p>\n<p>Un passant a sa bourse accrochée à la ceinture. On lui donne lordre de suggestion : \"donne ta bourse !\" Leffet avorte automatiquement. En effet, le passant doit dabord en dénouer les cordons, action préalable, et qui plus est réfléchie. Si le passant avait déjà sa bourse à la main, lordre : \"donne ta bourse !\" ou \"donne\"! tout court, pouvant être obéi de façon <em>immédiate</em>, aurait été accepté.</p>\n<p>Des ordres tels que \"réponds à la question \" ou \" dis la vérité\" sont pareillement inacceptables (actions mentales). Si la victime est au bord dun gouffre, et quon lui suggère : \" saute dans le gouffre !\", elle saute. Si elle est à trois mètres du gouffre, la suggestion avorte. Il faut dabord quelle y coure. Des ordres tels que : \"Fuis, saute, plonge, assieds-toi, agenouille-toi, lève les bras, ferme les yeux, hurle, donne (ce que la victime a déjà en main), mange ou bois (ce que la victime a déjà à portée de ses lèvres), lâche (ce quelle tient en main), etc.\" sont possibles. Des ordres tels que : \"endors-toi, suicide-toi, va faire ceci, déshabille-toi (actions multiples), écris ceci, avoue, lance tel sort, etc.\" sont impossibles.</p>\n<p>Lordre donné dans la suggestion doit être unique, cest-à-dire pratiquement ne comporter quun seul verbe. \"Cours et saute !\" est impossible. Quand laction implique une durée, elle est obéie pendant un round. Si par exemple lordre donné est \"cours !\" ou \"fuis !\", la victime courra, fuira, pendant un round. À ce moment, toutefois, lordre pourra être donné une seconde fois, et la victime obéira pour la durée dun nouveau round.</p>\n<p>Lordre contenu dans la suggestion doit être paramétré lors du lancer. Mais le ciblage de la victime ne le déclenche pas aussitôt. La victime étant maintenant sous leffet du sort, il faut que lordre soit donné réellement, <em>verbalement</em>. La victime doit pouvoir lentendre et le comprendre (parler la même langue). Peu importe qui donne lordre verbal, le haut-rêvant ou quelquun dautre. Chaque 3r dépensés permet verbalement de réitérer lordre une fois. Si par exemple 9 points de rêve ont été dépensés, lordre \"cours !\" pourra être donné trois fois. Il ny a aucune limite de temps entre le ciblage et le moment où le premier ordre est donné verbalement, ni non plus entre chaque ordre. Tant que le dernier ordre na pas été donné, la victime est sous linfluence du sort, influence qui peut être détectée et lue par Lecture dAura. Le libellé de lordre est également révélé dans la case spécifique par Lecture dAura, et le sort peut être annulé dans cette même case. Dès que le dernier ordre est donné, leffet se dissipe totalement.</p>","descriptionmj":"","draconic":"hypnos","duree":"Spéciale","JR":"Selon HN","cible":"Humanoïde","difficulte":"-9","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"3+","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"jOzRscDxoXZWpGS6":3},"flags":{}}
{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"<p>Les rituels de D&eacute;tection d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Toutes les cr&eacute;atures vivantes anim&eacute;es (humains, humano&iuml;des, animaux) ont une caract&eacute;ristique R&Ecirc;VE. Les objets enchant&eacute;s poss&egrave;dent des points de r&ecirc;ve, de m&ecirc;me que les produits de magie naturelle, comme certaines pierres de chance. Les entit&eacute;s de cauchemar, incarn&eacute;es ou non, en ont &eacute;galement. Quelle qu&rsquo;elle soit, la pr&eacute;sence de r&ecirc;ve &eacute;met une aura, laquelle est d&eacute;tectable par D&eacute;tection d&rsquo;Aura. Parall&egrave;lement, toute cible d&rsquo;un sort ou d&rsquo;un rituel, &eacute;met une aura propre, quand bien m&ecirc;me ladite cible ne poss&egrave;de pas de points de r&ecirc;ve (centre de zone, objet ou plante soumis &agrave; une illusion d&rsquo;Hypnos). Cette aura est &eacute;galement d&eacute;tectable par D&eacute;tection d&rsquo;Aura.</p>\n<p>L&rsquo;aura de pr&eacute;sence de r&ecirc;ve se traduit par un halo bleut&eacute; constant ; l&rsquo;aura r&eacute;sultant d&rsquo;un effet magique par un halo parcouru de pulsations. Quand les deux auras sont pr&eacute;sentes conjointement, le halo est pulsatif et d&rsquo;un bleu plus fonc&eacute;. On peut toujours effectuer D&eacute;tection d&rsquo;Aura sans aucun risque, il y a toujours une r&eacute;ponse. Soit une aura est per&ccedil;ue, constante ou pulsative, et l&rsquo;on peut tenter une Lecture d&rsquo;Aura pour en savoir plus ; soit aucune aura n&rsquo;est per&ccedil;ue et il s&rsquo;agit de mati&egrave;re inerte, sans r&ecirc;ve, non soumise &agrave; un sort.</p>","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[]}
{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","data":{"description":"<p>Les rituels de D&eacute;tection d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Toutes les cr&eacute;atures vivantes anim&eacute;es (humains, humano&iuml;des, animaux) ont une caract&eacute;ristique R&Ecirc;VE. Les objets enchant&eacute;s poss&egrave;dent des points de r&ecirc;ve, de m&ecirc;me que les produits de magie naturelle, comme certaines pierres de chance. Les entit&eacute;s de cauchemar, incarn&eacute;es ou non, en ont &eacute;galement. Quelle qu&rsquo;elle soit, la pr&eacute;sence de r&ecirc;ve &eacute;met une aura, laquelle est d&eacute;tectable par D&eacute;tection d&rsquo;Aura. Parall&egrave;lement, toute cible d&rsquo;un sort ou d&rsquo;un rituel, &eacute;met une aura propre, quand bien m&ecirc;me ladite cible ne poss&egrave;de pas de points de r&ecirc;ve (centre de zone, objet ou plante soumis &agrave; une illusion d&rsquo;Hypnos). Cette aura est &eacute;galement d&eacute;tectable par D&eacute;tection d&rsquo;Aura.</p>\n<p>L&rsquo;aura de pr&eacute;sence de r&ecirc;ve se traduit par un halo bleut&eacute; constant ; l&rsquo;aura r&eacute;sultant d&rsquo;un effet magique par un halo parcouru de pulsations. Quand les deux auras sont pr&eacute;sentes conjointement, le halo est pulsatif et d&rsquo;un bleu plus fonc&eacute;. On peut toujours effectuer D&eacute;tection d&rsquo;Aura sans aucun risque, il y a toujours une r&eacute;ponse. Soit une aura est per&ccedil;ue, constante ou pulsative, et l&rsquo;on peut tenter une Lecture d&rsquo;Aura pour en savoir plus ; soit aucune aura n&rsquo;est per&ccedil;ue et il s&rsquo;agit de mati&egrave;re inerte, sans r&ecirc;ve, non soumise &agrave; un sort.</p>","descriptionmj":"","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"flags":{}}
{"_id":"yNMa8DlBaZyTGFSr","name":"Oubli","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","data":{"description":"<p>Leffet dOubli ne sapplique quaux humanoïdes. Cest une des plus puissantes suggestions hypnotiques. Leffet damnésie ne survient pas aussitôt le sort ciblé, mais intervient à la fin de lheure en cours. À ce moment la victime perd tout souvenir de ce quelle a vécu, de ce quelle a pu dire ou faire, entre le moment présent et celui où le sort a été ciblé. Pratiquement, cette période est comme un grand trou noir dans sa tête, et aucun moyen normal ne peut lui restituer ses souvenirs. Chaque point de rêve dépensé en plus des 6 de base augmente la durée dune heure. Soit un haut-rêvant lançant ce sort au cours de lheure du Dragon et dépensant 8 points : à la fin de lheure de la Lyre, la victime se retrouve brusquement amnésique de ce quelle a pu faire depuis la mi-Dragon jusquà maintenant, sans comprendre comment elle est arrivée dans le lieu où elle se trouve actuellement, comme si elle venait de se réveiller dune période de sommeil noir, encore plus opaque que le gris rêve. Une Lecture dAura révèle la présence dun sort dOubli en train dœuvrer, et Annulation de Magie peut lannuler selon les règles normales. À défaut, le rituel de Conjurer lOubli peut être utilisé, mais ne restitue les souvenirs que sélectivement, en réponse à une question précise. Quand cest un personnage de joueur qui lance ce sort sur un PNJ, sa mise en œuvre est sans problème. Linverse est plus délicat. Le mieux est alors de faire sortir de la salle le joueur du personnage victime, et de le faire rentrer au moment où lamnésie opère. De cette façon, il ne se souvient effectivement de rien. Entre temps, si besoin est par rapport aux autres joueurs, jouer ce personnage comme un PNJ.</p>","descriptionmj":"","draconic":"hypnos","duree":"Selo n r dépensé","JR":"Selon HN","cible":"Humanoïde","difficulte":"-8","portée":"","caseTMR":"fleuve","caseTMRspeciale":"","ptreve":"6+","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"jOzRscDxoXZWpGS6":3},"flags":{}}
{"_id":"yhw8f7HKrmfzAxmj","name":"Sérénité","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","data":{"description":"<p>L&rsquo;effet de s&eacute;r&eacute;nit&eacute; ne s&rsquo;applique qu&rsquo;aux humano&iuml;des. La suggestion d&rsquo;une intense satisfaction est source d&rsquo;une s&eacute;r&eacute;nit&eacute; r&eacute;elle. Pour chaque 3r d&eacute;pens&eacute;s, le personnage vis&eacute; regagne 1 point de moral jusqu&rsquo;&agrave; concurrence de z&eacute;ro. Neuf points de r&ecirc;ve permettent ainsi de remonter un moral de -3 &agrave; z&eacute;ro. Si trop de points sont d&eacute;pens&eacute;s, l&rsquo;exc&eacute;dent est perdu, le moral ne pouvant d&eacute;passer z&eacute;ro par l&rsquo;influence de ce sort.</p>","descriptionmj":"","draconic":"hypnos","duree":"Instantanée","JR":"Selon HN","cible":"Humanoïde","difficulte":"-3","portée":"","caseTMR":"collines","caseTMRspeciale":"","ptreve":"3+","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"jOzRscDxoXZWpGS6":3},"flags":{}}
{"_id":"ze53LdwhuqUFMvqw","name":"Fou-rire","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"sort","data":{"description":"<p>L&rsquo;effet de Fou-Rire ne s&rsquo;applique qu&rsquo;aux humano&iuml;des. La suggestion d&rsquo;une id&eacute;e drolatique plonge la cible dans un irr&eacute;pressible fou-rire, automatique le premier round. Puis pour les rounds suivants, la cible doit r&eacute;ussir un jet de VOLONT&Eacute;/ <em>moins </em>moral &agrave; -5, ou continuer &agrave; rire. Tant que la cible rit, elle est consid&eacute;r&eacute;e en <em>demi-surprise</em>.</p>","draconic":"hypnos","duree":"Instantanée","JR":"Selon HN","cible":"Humanoïde","difficulte":"-5","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"5"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[]}

View File

@ -4,7 +4,7 @@
{"_id":"5NZnTt0mvfPorSHG","name":"Écailles de Protection contre le venin *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Chaque écaille de protection confère un bons de +1 au jet de CONSTITUTION contre toutes les sortes de venin et de poison, augmentant ainsi les chances de leur résister.</p>\n<p>Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.</p>\n<p><em>Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7&nbsp; &nbsp;x 4 = 28).</em></p>\n<p>Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.</p>\n<p>&nbsp;</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"foret","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"74XSU8DqNBXGFn3R","name":"Dragonne Lame","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"<p>M&ecirc;me principe que la@Item[r9onPANmiK5E5Jnw]{Fl&egrave;che de Feu} et la @Item[8BJ9kn3AWLFDwvez]{Dague de Force}, y compris la d&eacute;t&eacute;rioration automatique de 1 point de r&eacute;sistance. Une &eacute;p&eacute;e dragonne ainsi modifi&eacute;e a un +dom de +6.</p>","draconic":"narcos","duree":"HN","JR":"Il ny a aucun JR pour les objets ordinaires. Les objets magiques (enchantés) résistent automatiquement, le sort se dissipant sans effet, les points de rêve étant néanmoins dépensés","cible":"Une épée Dragonne (exclusivement)","difficulte":"6","portée":"","caseTMR":"desolation","caseTMRspeciale":"","ptreve":"4","xp":0,"isrituel":false,"portee":"","bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"AIBLH8EduhfUQscn","name":"Écaille d'Efficacité *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Les écailles d'efficacité servent à rendre un objet plus efficace, mais uniquement dans sa fonction normale. Une arme magiquement efficace permettra de toucher plus facilement un adversaire ; un bouclier de mieux parer ; un instrument de musique de jouer mieux à moindre effort ; mais un balai magique permettre de mieux balayer et non de voler. Les écailles d'efficacité n'ont de pertinence que sur les objets pouvant être utilisés activement, armes, instruments, outils. Les objets passifs, meubles, contenants, vêtements, armures, ne peuvent pas être rendus plus efficaces.</p>\n<p>En terme de jeu, chaque écaille d'efficacité possédée par l'objet confère un bonus de +1 sur la table de Résolution lors de son utilisation. S'il s'agit d'une arme, chaque écaille d'efficacité augmente également de 1 le facteur d'initiative, ainsi que le +dom de l'arme, mais jusqu'au maximum du double normal de ce dernier. Soit une épée dragonne (+dom +3) possédant 5 écailles d'efficacité. Son utilisateur bénéficie d'un bonus de +5 à l'initiative, de +5 à l'attaque et à la parade, mais d'un +dom de +6 seulement (le double du +dom normal) et non pas de +8. Ne pas oublier néanmoins de rajouter le +dom personnel dû à la taille et à la force. Cette règle s'applique également aux armes de jet (dague, javelot, fouet). En ce qui concerne les armes de tir (arbalète, arc et fronde), l'efficacité ne s'applique qu'aux dommages&nbsp; (toujours pour un maximum du double du +dom normal) et non au toucher. Pour qu'un archer bénéficie d'un bonus d'efficacité au toucher <em>et</em> aux dommages, il doit avoir à la fois un arc magique et une flèche magique.</p>\n<p>Le nombre maximum d'écailles d'efficacité pouvant être posées sur un objet est égal à l'enchantabilité de sa gemme, mais avec un maximum de 7 quelle que soit cette dernière. Pour obtenir des armes magiques d'un bonus supérieur à +7, il faut avoir recours à une éventuelle Grande Écaille de Narcos spécifique.</p>\n<p>La pose de chaque écaille d'efficacité coûte un point de seuil. Mais il n'y a aucune limite de temps entre la pose de chacune, l'objet pouvant être utilisé dans l'intervalle. Par exemple, on peut se contenter provisoirement d'une épée +1 (une écaille), s'en servir plusieurs fois en combat, et plus tard, rajouter une se conde écaille pour obtenir une épée +2. Toutefois, si entretemps l'objet a été maîtrisé par quelqu'un d'autre, il faut effectuer une Lecture d'Aura complète avant de pouvoir reposer une écaille. Si cette précaution est négligée, on aboutit à un cas de <em>magie impossible</em>. L'utilisation d'un objet magiquement efficace coûte un point de rêve par heure quel que soit le nombre d'écailles.</p>\n<p>Si plusieurs gemmes sont alliées à un même objet grâce à Individualité et reçoivent toutes des écailles d'efficacité, leurs bonus <em>ne s'ajoutent pas</em>, on ne considère que le meilleur. Des gemmes différentes sont faites pour des pouvoirs entièrement différents.</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"monts","caseTMRspeciale":"","ptreve":"7","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"BibuJdKmaQJm3kFw","name":"Annulation de magie","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"<p>Ce rituel permet d&rsquo;annuler un effet magique, que celui-ci ait &eacute;t&eacute; accompli par soi-m&ecirc;me ou par un autre haut-r&ecirc;vant. On peut annuler l&rsquo;effet d&rsquo;un sort, de zone ou individuel, d&rsquo;un rituel d&rsquo;enchantement, d&rsquo;une invocation, etc.</p>\n<p>Le haut-r&ecirc;vant doit se trouver dans la case <em>sp&eacute;cifique </em>des TMR d&rsquo;o&ugrave; la magie a &eacute;t&eacute; accomplie. Le jet de R&Ecirc;VE qu&rsquo;il doit r&eacute;ussir a alors la m&ecirc;me difficult&eacute; que celui ayant permis la magie, avec une d&eacute;pense de points de r&ecirc;ve pareillement identique.</p>\n<p>Pour annuler une invocation, le rituel d&rsquo;Annulation doit &ecirc;tre cibl&eacute; sur la cr&eacute;ature invoqu&eacute;e. Quand la magie est le r&eacute;sultat conjoint de plusieurs rituels, ce qui est notamment le cas des objets magiques, chacun doit &ecirc;tre annul&eacute; tour &agrave; tour, en commen&ccedil;ant toujours par le dernier &agrave; avoir &eacute;t&eacute; accompli chronologiquement. D&rsquo;une mani&egrave;re g&eacute;n&eacute;rale, ce sont les m&ecirc;mes op&eacute;rations qui doivent &ecirc;tre r&eacute;p&eacute;t&eacute;es &agrave; l&rsquo;envers. Quand un rituel co&ucirc;te des points de seuil, son annulation en co&ucirc;te &eacute;galement (le m&ecirc;me nombre). Annulation de Magie sert &eacute;galement &agrave; exorciser les entit&eacute;s de cauchemar non incarn&eacute;es. La difficult&eacute; d&rsquo;un exorcisme est toujours R-7, et le co&ucirc;t en points de r&ecirc;ve &eacute;gal au R&Ecirc;VE de l&rsquo;entit&eacute;. Le ciblage doit &ecirc;tre fait sur la cr&eacute;ature poss&eacute;d&eacute;e.</p>\n<p>Avant d&rsquo;accomplir une Annulation de Magie, les param&egrave;tres de la magie &agrave; annuler (case des TMR, R-, r) peuvent &ecirc;tre d&eacute;couverts au moyen du rituel Lecture d&rsquo;Aura.</p>\n<p>Pour la synth&egrave;se d&rsquo;Annulation de Magie, consid&eacute;rer que ce rituel est de difficult&eacute; R-7. Il peut &ecirc;tre utilis&eacute; indiff&eacute;remment par Oniros, Hypnos ou Narcos (mais jamais Thanatos), quelle que soit la voie ayant servi &agrave; accomplir la magie &agrave; annuler.</p>","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"Effet magique","difficulte":"variable","portée":"","caseTMR":"special","caseTMRspeciale":"variable","ptreve":"variable","xp":0,"isrituel":true,"bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[]}
{"_id":"BibuJdKmaQJm3kFw","name":"Annulation de magie","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","data":{"description":"<p>Ce rituel permet d&rsquo;annuler un effet magique, que celui-ci ait &eacute;t&eacute; accompli par soi-m&ecirc;me ou par un autre haut-r&ecirc;vant. On peut annuler l&rsquo;effet d&rsquo;un sort, de zone ou individuel, d&rsquo;un rituel d&rsquo;enchantement, d&rsquo;une invocation, etc.</p>\n<p>Le haut-r&ecirc;vant doit se trouver dans la case <em>sp&eacute;cifique </em>des TMR d&rsquo;o&ugrave; la magie a &eacute;t&eacute; accomplie. Le jet de R&Ecirc;VE qu&rsquo;il doit r&eacute;ussir a alors la m&ecirc;me difficult&eacute; que celui ayant permis la magie, avec une d&eacute;pense de points de r&ecirc;ve pareillement identique.</p>\n<p>Pour annuler une invocation, le rituel d&rsquo;Annulation doit &ecirc;tre cibl&eacute; sur la cr&eacute;ature invoqu&eacute;e. Quand la magie est le r&eacute;sultat conjoint de plusieurs rituels, ce qui est notamment le cas des objets magiques, chacun doit &ecirc;tre annul&eacute; tour &agrave; tour, en commen&ccedil;ant toujours par le dernier &agrave; avoir &eacute;t&eacute; accompli chronologiquement. D&rsquo;une mani&egrave;re g&eacute;n&eacute;rale, ce sont les m&ecirc;mes op&eacute;rations qui doivent &ecirc;tre r&eacute;p&eacute;t&eacute;es &agrave; l&rsquo;envers. Quand un rituel co&ucirc;te des points de seuil, son annulation en co&ucirc;te &eacute;galement (le m&ecirc;me nombre). Annulation de Magie sert &eacute;galement &agrave; exorciser les entit&eacute;s de cauchemar non incarn&eacute;es. La difficult&eacute; d&rsquo;un exorcisme est toujours R-7, et le co&ucirc;t en points de r&ecirc;ve &eacute;gal au R&Ecirc;VE de l&rsquo;entit&eacute;. Le ciblage doit &ecirc;tre fait sur la cr&eacute;ature poss&eacute;d&eacute;e.</p>\n<p>Avant d&rsquo;accomplir une Annulation de Magie, les param&egrave;tres de la magie &agrave; annuler (case des TMR, R-, r) peuvent &ecirc;tre d&eacute;couverts au moyen du rituel Lecture d&rsquo;Aura.</p>\n<p>Pour la synth&egrave;se d&rsquo;Annulation de Magie, consid&eacute;rer que ce rituel est de difficult&eacute; R-7. Il peut &ecirc;tre utilis&eacute; indiff&eacute;remment par Oniros, Hypnos ou Narcos (mais jamais Thanatos), quelle que soit la voie ayant servi &agrave; accomplir la magie &agrave; annuler.</p>","descriptionmj":"","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"Effet magique","difficulte":"variable","portée":"","caseTMR":"special","caseTMRspeciale":"variable","ptreve":"variable","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"flags":{}}
{"_id":"FpwaK1qJxKGs9HgS","name":"Permanence *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>C'est par ce rituel que le haut-rêvant stabilise les points de rêve d'une potion ou d'un objet, afin d'en prévenir l'évaporation quotidienne. Facultatif pour les potions, le rituel de Permanence est obligatoire pour tous les autres objets magiques.&nbsp; Son accomplissement diminue de 1 point le seuil de rêve du haut-rêvant.</p>","draconic":"narcos","duree":"Instantanée","JR":"","cible":"","difficulte":"-5","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"5","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"KW2VZhuEGJGglGcW","name":"Restauration *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Restauration est un rituel secondaire nullement obligatoire. Son seul usage est de redonner des points de rêve actifs à une amulette de protection. Il est en effet impossible d'utiliser le simple Enchantement une fois le rituel de Permanence accompli. Restauration fonctionne de façon semblable à un Enchantement, sauf que son accomplissement coûte chaque fois un point de seuil. On peut&nbsp; restaurer les points de rêve d'une amulette en plusieurs fois en intercalant un rituel de Purifcation entre chaque rituel de Restauration (qui coûte chaque fois un point de seuil). Il est possible de redonner plus de points de rêve actifs à l'objet qu'il n'en avait au départ, jusqu'à concurrence du maximum possible. Le nombre maximum de points de rêve actifs qu'un objet puisse posséder est égal à 7 fois l'enchantabilité de sa gemme.</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"1+","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"P9jMT8pl4pgKEoEW","name":"Écailles de Protection contre le feu *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû au feu, jouant le rôle d'une \"armure ignifugée\". Soit un personnage possédant une telle amulette dotée de 5 écailles, et se retrouvant dans une zone d'Air en Feu. Au lieu de jouer un jet d'encaissement à +10, il ne la joue qu'à +5. La protection de l'amulette est <em>en plus </em>de la protection physique qu'il peut avoir, laquelle ne peut être - rappelons-le - que d'un maximum de 2 points.</p>\n<p>Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.</p>\n<p><em>Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7&nbsp; &nbsp;x 4 = 28).</em></p>\n<p>Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.</p>\n<p>&nbsp;</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
@ -13,7 +13,7 @@
{"_id":"TjhnUMh6UL04k0k8","name":"Purification","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Purification est un rituel secondaire, mais néanmoins obligatoire. A moins de disposer d'une énorme quantité de points de rêve, il est vain d'espérer enchanter l'objet en une seule fois. Purifcation doit toujours s'intercaler entre deux rituels identiques : entre deux Enchantements, mais également entre deux écailles, d'activité ou de protection. Sauter cette étape aboutit à un cas de <em>magie impossible</em>.</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"necropole","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"xp":0,"bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"WUYaL4yvr0wFRLjk","name":"Enchantement","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>C'est le rituel de base de tout enchantement, c'est par lui que le haut-r&ecirc;vant conf&egrave;re des points de r&ecirc;ve &agrave; la gemme ou &agrave; la potion. Le nombre de points conf&eacute;r&eacute;s, param&eacute;tr&eacute; au lancer du sort, est &agrave; son enti&egrave;re discr&eacute;tion. Entre deux Enchantements de la m&ecirc;me potion ou de la m&ecirc;me gemme doit &ecirc;tre accompli un rituel de Purificiation.</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"1+","portee":"","isrituel":true,"xp":0,"bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"X8yMNrnbFIwTB6oL","name":"Écailles de Protection contre griffes et crocs *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû aux armes naturelles des animaux, griffes, crocs, mais également piétinement, cornes, tentacules, etc. Elle protège également des dommages au corps à corps de pugilat, coups de poing, coups de pied, mais ne s'applique pas à l'empoignade. La protection est en plus de l'armure véritable du personnage.&nbsp;</p>\n<p>Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.</p>\n<p><em>Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7&nbsp; &nbsp;x 4 = 28).</em></p>\n<p>Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.</p>\n<p>&nbsp;</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-10","portée":"","caseTMR":"marais","caseTMRspeciale":"","ptreve":"8","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"<p>Les rituels de Lecture d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Ce rituel permet d&rsquo;approfondir les informations fournies par D&eacute;tection d&rsquo;Aura. Pratiquer Lecture d&rsquo;Aura quand il n&rsquo;y a pas d&rsquo;aura revient &agrave; demander une magie impossible et cr&eacute;e imm&eacute;diatement une d&eacute;chirure du r&ecirc;ve.</p>\n<p>Lecture d&rsquo;Aura est effectu&eacute;e en plusieurs &eacute;tapes, toutes &eacute;tant de difficult&eacute; R-3 et co&ucirc;tant 3 points de r&ecirc;ve. La premi&egrave;re a toujours lieu dans un sanctuaire et ne fait que r&eacute;v&eacute;ler dans quel(s) autre(s) genre(s) de case(s) le haut-r&ecirc;vant doit se rendre pour continuer sa lecture. L&agrave;, il apprend quel genre de magie a &eacute;t&eacute; produit ou &agrave; quel type de r&ecirc;ve il a affaire, de m&ecirc;me que les cases sp&eacute;cifiques concern&eacute;es. Enfin dans les cases sp&eacute;cifiques, le haut-r&ecirc;vant peut apprendre la force du r&ecirc;ve ou de la magie en cours, c&rsquo;est-&agrave;-dire pratiquement la difficult&eacute; et le nombre de points de r&ecirc;ve impliqu&eacute;s, information indispensable dans l&rsquo;optique d&rsquo;une annulation de magie.</p>\n<p>Lecture d&rsquo;Aura r&eacute;v&egrave;le &eacute;galement la couleur de l&rsquo;aura (fixe ou pulsative) comme D&eacute;tection d&rsquo;Aura. Pour les cr&eacute;atures vivantes, on peut donc sauter l&rsquo;&eacute;tape de D&eacute;tection d&rsquo;Aura et commencer directement par la lecture, puisqu&rsquo;on est s&ucirc;r de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la d&eacute;tection si, en l&rsquo;absence finale d&rsquo;une aura, on ne veut pas cr&eacute;er de magie impossible. Effectu&eacute;e sur une cr&eacute;ature non soumise &agrave; un effet magique ni sous l&rsquo;emprise d&rsquo;une entit&eacute;, Lecture d&rsquo;Aura indique toujours le Fleuve. L&agrave;, dans n&rsquo;importe quelle case du Fleuve, le haut-r&ecirc;vant se contente d&rsquo;apprendre qu&rsquo;il a affaire &agrave; une cr&eacute;ature vivante et dou&eacute;e de r&ecirc;ve.</p>","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[]}
{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","data":{"description":"<p>Les rituels de Lecture d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Ce rituel permet d&rsquo;approfondir les informations fournies par D&eacute;tection d&rsquo;Aura. Pratiquer Lecture d&rsquo;Aura quand il n&rsquo;y a pas d&rsquo;aura revient &agrave; demander une magie impossible et cr&eacute;e imm&eacute;diatement une d&eacute;chirure du r&ecirc;ve.</p>\n<p>Lecture d&rsquo;Aura est effectu&eacute;e en plusieurs &eacute;tapes, toutes &eacute;tant de difficult&eacute; R-3 et co&ucirc;tant 3 points de r&ecirc;ve. La premi&egrave;re a toujours lieu dans un sanctuaire et ne fait que r&eacute;v&eacute;ler dans quel(s) autre(s) genre(s) de case(s) le haut-r&ecirc;vant doit se rendre pour continuer sa lecture. L&agrave;, il apprend quel genre de magie a &eacute;t&eacute; produit ou &agrave; quel type de r&ecirc;ve il a affaire, de m&ecirc;me que les cases sp&eacute;cifiques concern&eacute;es. Enfin dans les cases sp&eacute;cifiques, le haut-r&ecirc;vant peut apprendre la force du r&ecirc;ve ou de la magie en cours, c&rsquo;est-&agrave;-dire pratiquement la difficult&eacute; et le nombre de points de r&ecirc;ve impliqu&eacute;s, information indispensable dans l&rsquo;optique d&rsquo;une annulation de magie.</p>\n<p>Lecture d&rsquo;Aura r&eacute;v&egrave;le &eacute;galement la couleur de l&rsquo;aura (fixe ou pulsative) comme D&eacute;tection d&rsquo;Aura. Pour les cr&eacute;atures vivantes, on peut donc sauter l&rsquo;&eacute;tape de D&eacute;tection d&rsquo;Aura et commencer directement par la lecture, puisqu&rsquo;on est s&ucirc;r de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la d&eacute;tection si, en l&rsquo;absence finale d&rsquo;une aura, on ne veut pas cr&eacute;er de magie impossible. Effectu&eacute;e sur une cr&eacute;ature non soumise &agrave; un effet magique ni sous l&rsquo;emprise d&rsquo;une entit&eacute;, Lecture d&rsquo;Aura indique toujours le Fleuve. L&agrave;, dans n&rsquo;importe quelle case du Fleuve, le haut-r&ecirc;vant se contente d&rsquo;apprendre qu&rsquo;il a affaire &agrave; une cr&eacute;ature vivante et dou&eacute;e de r&ecirc;ve.</p>","descriptionmj":"","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"flags":{}}
{"_id":"asVUMvyZ0OocReY6","name":"Individualité","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"<p>Rituel secondaire, Individualit&eacute; est n&eacute;anmoins obligatoire pour les objets poss&eacute;dant plusieurs pouvoirs distincts. Il doit &ecirc;tre accompli sur toute nouvelle gemme, enchant&eacute;e d&rsquo;au moins un point de r&ecirc;ve actif, avant le rituel d&rsquo;Alliance. Lors, c&rsquo;est uniquement &agrave; cette nouvelle gemme que s&rsquo;adresseront les points de r&ecirc;ve et les &eacute;cailles. Vis &agrave; vis d&rsquo;une nouvelle gemme, le mat&eacute;riau re-poss&egrave;de toute son inertie et doit &agrave; nouveau &ecirc;tre satur&eacute;. Quand un objet a plusieurs gemmes, toutes ont d&ucirc; recevoir Individualit&eacute; sauf la premi&egrave;re. Les pouvoirs d&rsquo;un objet doivent &ecirc;tre &eacute;labor&eacute;s l&rsquo;un apr&egrave;s l&rsquo;autre. D&egrave;s que l&rsquo;on a commenc&eacute; une nouvelle gemme, on ne peut plus revenir sur les pr&eacute;c&eacute;dentes.</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"4","xp":0,"isrituel":true,"portee":"","bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"ckH9xONcfsffpRVr","name":"Écailles de Protection contre la magie *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Chaque &eacute;caille de protection rajoute un +1 &agrave; tous les jets de r&eacute;sistance contre les sorts d'illusion-suggestion d'Hypnos ainsi que les rituels de Possession et les sorts et griffes de Thanatos. L'amulette n'est pas sp&eacute;cifique &agrave; un sort, elle prot&egrave;ge de tous. Soit un personnage poss&eacute;dant une amulette de 4 &eacute;cailles et devant jouer une JR r-8, il ne joue en r&eacute;alit&eacute; qu'un JR r-4, augmentant consid&eacute;rablement ses chances de r&eacute;sister &agrave; la magie. La protection ne s'applique qu'&agrave; la magie autorisant un JR.</p>\n<p>Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontan&eacute;ment en face du danger pour lequel elle est con&ccedil;ue, m&ecirc;me si le possesseur n'a aucune id&eacute;e de son pouvoir. Pour fonctionner, l'amulette a besoin de points de r&ecirc;ve actifs. Ces points doivent &ecirc;tre des points de r&ecirc;ve conf&eacute;r&eacute;s par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-r&ecirc;vant ne s'arr&ecirc;te pas d'enchanter quand il atteint un nombre de points de r&ecirc;ve &eacute;gal &agrave; l'inertie totale de l'objet, mais continue &agrave; en rajouter. Le nombre maximum de points actifs qu'une amulette puisse poss&eacute;der est &eacute;gal &agrave; 7 fois l'enchantabilit&eacute; de sa gemme ; et, comme pour les &eacute;cailles d'efficacit&eacute;, le nombre d'&eacute;cailles de protection qu'elle puisse poss&eacute;der est &eacute;gal &agrave; l'enchantabilit&eacute; de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient &ecirc;tre obtenues que par de sp&eacute;cifiques Grandes &Eacute;cailles de Narcos.</p>\n<p><em>Soit une gemme de taille 6 et de puret&eacute; 5, ayant donc une inertie de 2 et une enchantabilit&eacute; de 4. Elle peut poss&eacute;der jusqu'&agrave; 4 &eacute;cailles de protection (=enchantabilit&eacute;) et un maximum de 28 points de r&ecirc;ve actifs (7&nbsp; &nbsp;x 4 = 28).</em></p>\n<p>Chaque fois qu'une amulette de protection fonctionne, elle d&eacute;pense un de ses points de r&ecirc;ve actifs quel que soit le nombre d'&eacute;cailles. Le possesseur, lui, n'en d&eacute;pense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les &eacute;cailles de protection peuvent &ecirc;tre pos&eacute;es progressivement, comme celles d'efficacit&eacute;, m&ecirc;me si l'amulette fonctionne entre temps. M&ecirc;mes r&egrave;gles d'application. Une gemme donn&eacute;e ne peut recevoir que des &eacute;cailles de protection d'un m&ecirc;me type, mais gr&acirc;ce &agrave; Individualit&eacute;, plusieurs gemmes d'une m&ecirc;me amulette peuvent offrir des protections diff&eacute;rentes. La pose de chaque &eacute;caille de protection co&ucirc;te un point de seuil.</p>\n<p>&nbsp;</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"6","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"hWAoVheMfyLIMKZy","name":"Alliance","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"sort","data":{"description":"<p>Ce rituel unit magiquement la gemme, seul v&eacute;ritable r&eacute;ceptacle du r&ecirc;ve,au reste de l&rsquo;objet, en sorte que son pouvoir puisse s&rsquo;&eacute;tendre &agrave; lui. Ce qui s&rsquo;applique &agrave; la gemme s&rsquo;applique d&eacute;sormais &agrave; l&rsquo;objet, et inversement. La forme de l&rsquo;objet participe maintenant &agrave; la magie. C&rsquo;est pourquoi il doit &ecirc;tre utilis&eacute; comme l&rsquo;exige sa fonction normale (bague au doigt, etc.) et pourquoi sa forme doit &ecirc;tre en analogie avec le ciblage. Pratiquement, une gemme seule ne peut &ecirc;tre utilis&eacute;e que pour une &eacute;caille d&rsquo;activit&eacute; lan&ccedil;ant un sort sur l&rsquo;utilisateur lui-m&ecirc;me (la gemme ne lui permettant pas d&rsquo;autre ciblage). Une gemme&nbsp;seule pourrait &ecirc;tre une amulette de protection, mais il faudrait la tenir sans cesse&nbsp;dans le creux de la main (seule fa&ccedil;on d&rsquo;utiliser une gemme seule). En revanche, on&nbsp;peut s&rsquo;en contenter pour la Grande &Eacute;caille&nbsp;de Narcos Puits de r&ecirc;ve.</p>\n<p>&nbsp;</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"pont","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"xp":0,"bonuscase":"","coutseuil":0},"flags":{"core":{"sourceId":"Item.5UQMurs8lNa8eBr0"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
@ -22,5 +22,5 @@
{"_id":"mh9JjaKckzz1eAoe","name":"Écailles de Protection contre la maladie* ","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Chaque écaille de protection confère un bons de +1 au jet de CONSTITUTION contre toutes les maladies, augmentant ainsi les chances de leur résister.</p>\n<p>Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.</p>\n<p><em>Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7&nbsp; &nbsp;x 4 = 28).</em></p>\n<p>Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.</p>\n<p>&nbsp;</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"mzAV6EdQlGkVkWEN","name":"Écailles de Protection contre les lames *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû à une arme de mêlée (dague, épée, hache, lance, masse, fléeau, arme d'hast), mais ni les projectiles ni les dommages au corps à corps. La protection est en plus de l'armure véritable du personnage.&nbsp;</p>\n<p>Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.</p>\n<p><em>Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7&nbsp; &nbsp;x 4 = 28).</em></p>\n<p>Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.</p>\n<p>&nbsp;</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-10","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"8","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"sEBhR48HagKNbkob","name":"Écaille d'activité *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Le rituel d'Écaille d'Activité confère à l'objet magique le pouvoir de lancer un sort. Ce peut être un sort de zone d'Oniros, un sort d'illusion-suggestion ou d'illusion sensorielle d'Hypnos, ou un sort de Thanatos, mais ne peut en aucun cas être un rituel d'aucune des quatre voies. Ayant <em>posé</em> l'écaille d'activité sur l'objet (\"poser\" est le terme consacré à l'accomplissement des rituels d'Écaille), le Haut-Rêvant y lance le sort de son choix et l'objet devient capable de le lancer à son tour. Pratiquement, le haut-rêvant effectue toutes les opérations nécessaires au lancer d'un sort, y compris son paramétrage précis, puis le lance normalement en dépensant les points de rêve du coût. Toutefois, au lieu de cibler comme l'exige le ciblage normal du sort, il touche l'objet possédant l'écaille d'activité. En résultat, aucun effet ne se produit, mais le sort est maintenant <em>enregistré </em>dans la \"mémoire\" de la gemme. Il suffit ensuite à l'utilisateur de se concentrer mentalement sur l'effet voulu (dont il doit avoir une idée) pour que l'objet lance le sort. Il pourra le lancer indéfiniment.</p>\n<p>A la fin du round de concentration, l'utilisateur doit être capable de dépenser les points de rêve exigés par le coût du sort tel qu'il est paramétéré. S'il n'en a pas assez, il ne dépense rien, mais l'objet ne fonctionne pas. Puis cela étant fait, le sort opère au tout début du round suivant, selon le ciblage voulu par l'utilisateur, fonction de la forme de l'objet et de la façon dont il est utilisé. Pour que le sort puisse être ciblé ailleurs que sur l'utilisateur lui-même, l'objet doit avoir une forme oblongue, analogue au doigt pointé d'un haut-rêvant. Le sort enregistré dans la gemme est paramétré une fois pour toutes. Un objet lançant un sort de Sommeil de 5 rounds lancera toujours un sort de Sommeil de 5 rounds, ni plus ni moins. Un objet lançant une illusion visuelle ne lancera toujours que la même illusion au moindre détail près. La portée est celle de l'EMPATHIE du créateur de l'objet et non de l'utilisateur, et quand le sort a une durée HN, c'est également l'heure de naissance du créateur. Le seul paramétrage inutile est l'heure de naissance de la cible en prévision du jet de résistance. Quand un JR est possible, il est toujours r-8, quelle que soit la cible. S'il réussit, le sort se dissipe aussitôt sans revenir vers l'utilisateur.</p>\n<p>L'objet réussit son lancer, sans jet de dés. Lancer un sort via un objet magique n'est pas plus économique en points de rêve que de la lancer soi-même, mais évite la montée en TMR, les rencontres, et confère la certitude que le sort partira à coup sûr. L'effet d'un sort lancé par un objet peut être annulé par Annulatrion de Magie, mais pas par Annulation de ses Propres Zones ni Annulation de ses Propres Illusions.</p>\n<p>Chaque gemme d'un objet ne peut recevoir qu'une seule écaille d'activité, et la pose de cette dernière coûte un point de seuil. Une écaille d'activité ne peut enregistrer et lancer q'un seul sort. Mais un même objet peut avoir plusieurs gemmes, grâce à Individualité, chacune possédant une écaille d'activité pour lancer un sort différent.</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-9","portée":"","caseTMR":"desolation","caseTMRspeciale":"","ptreve":"7","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}
{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"<p>Les rituels de D&eacute;tection d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Toutes les cr&eacute;atures vivantes anim&eacute;es (humains, humano&iuml;des, animaux) ont une caract&eacute;ristique R&Ecirc;VE. Les objets enchant&eacute;s poss&egrave;dent des points de r&ecirc;ve, de m&ecirc;me que les produits de magie naturelle, comme certaines pierres de chance. Les entit&eacute;s de cauchemar, incarn&eacute;es ou non, en ont &eacute;galement. Quelle qu&rsquo;elle soit, la pr&eacute;sence de r&ecirc;ve &eacute;met une aura, laquelle est d&eacute;tectable par D&eacute;tection d&rsquo;Aura. Parall&egrave;lement, toute cible d&rsquo;un sort ou d&rsquo;un rituel, &eacute;met une aura propre, quand bien m&ecirc;me ladite cible ne poss&egrave;de pas de points de r&ecirc;ve (centre de zone, objet ou plante soumis &agrave; une illusion d&rsquo;Hypnos). Cette aura est &eacute;galement d&eacute;tectable par D&eacute;tection d&rsquo;Aura.</p>\n<p>L&rsquo;aura de pr&eacute;sence de r&ecirc;ve se traduit par un halo bleut&eacute; constant ; l&rsquo;aura r&eacute;sultant d&rsquo;un effet magique par un halo parcouru de pulsations. Quand les deux auras sont pr&eacute;sentes conjointement, le halo est pulsatif et d&rsquo;un bleu plus fonc&eacute;. On peut toujours effectuer D&eacute;tection d&rsquo;Aura sans aucun risque, il y a toujours une r&eacute;ponse. Soit une aura est per&ccedil;ue, constante ou pulsative, et l&rsquo;on peut tenter une Lecture d&rsquo;Aura pour en savoir plus ; soit aucune aura n&rsquo;est per&ccedil;ue et il s&rsquo;agit de mati&egrave;re inerte, sans r&ecirc;ve, non soumise &agrave; un sort.</p>","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[]}
{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","data":{"description":"<p>Les rituels de D&eacute;tection d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Toutes les cr&eacute;atures vivantes anim&eacute;es (humains, humano&iuml;des, animaux) ont une caract&eacute;ristique R&Ecirc;VE. Les objets enchant&eacute;s poss&egrave;dent des points de r&ecirc;ve, de m&ecirc;me que les produits de magie naturelle, comme certaines pierres de chance. Les entit&eacute;s de cauchemar, incarn&eacute;es ou non, en ont &eacute;galement. Quelle qu&rsquo;elle soit, la pr&eacute;sence de r&ecirc;ve &eacute;met une aura, laquelle est d&eacute;tectable par D&eacute;tection d&rsquo;Aura. Parall&egrave;lement, toute cible d&rsquo;un sort ou d&rsquo;un rituel, &eacute;met une aura propre, quand bien m&ecirc;me ladite cible ne poss&egrave;de pas de points de r&ecirc;ve (centre de zone, objet ou plante soumis &agrave; une illusion d&rsquo;Hypnos). Cette aura est &eacute;galement d&eacute;tectable par D&eacute;tection d&rsquo;Aura.</p>\n<p>L&rsquo;aura de pr&eacute;sence de r&ecirc;ve se traduit par un halo bleut&eacute; constant ; l&rsquo;aura r&eacute;sultant d&rsquo;un effet magique par un halo parcouru de pulsations. Quand les deux auras sont pr&eacute;sentes conjointement, le halo est pulsatif et d&rsquo;un bleu plus fonc&eacute;. On peut toujours effectuer D&eacute;tection d&rsquo;Aura sans aucun risque, il y a toujours une r&eacute;ponse. Soit une aura est per&ccedil;ue, constante ou pulsative, et l&rsquo;on peut tenter une Lecture d&rsquo;Aura pour en savoir plus ; soit aucune aura n&rsquo;est per&ccedil;ue et il s&rsquo;agit de mati&egrave;re inerte, sans r&ecirc;ve, non soumise &agrave; un sort.</p>","descriptionmj":"","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"flags":{}}
{"_id":"zT72qy3Xb8ye9YKb","name":"Bouilloire de Mélimnod *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>La Grande Écaille <em>Bouilloire de Mélimnod</em>, du nom d'un célèbre haut-rêvant du Second Âge, est un exemple abordable d'objet autonome. Elle doit être posée sur une bouilloire ou un petit chaudron intégralement fait d'argent, de cuivre ou d'étain, à l'exclusion de tout autre métal, d'une capacité de 2 mesures (40 centilitres). La gemme peut être incrustée dans le fond du récipient ou participer à son alliage. A la fin de l'enchantement, avant l'accomplissement de Permanence, elle doit posséder au minimum 1 point de rêve actif. (Le maximum étant comme toujours 7 fois son enchantabilité.) Puis, à la place de Maîtrise, il est obligatoire d'accomplir le rituel d'Autonomie (qui coûte 2 points de seuil). La Grande Écaille peut alors être posée. Il n'en est besoin que d'une seule.</p>\n<p>Dès que la bouilloire se retrouve pleine d'eau (2 mesures), ou d'un liquide appartenant à l'élément Eau, elle se met à chauffer spontanément et porte le liquide à ébullition ern l'espace d'un seul round. Au bout d'un second round, le liquide est réduit de moitié (une mesure). Puis la bouilloire le fait refroidir, et il se retrouve tout juste tiède au bout d'un troisième round. Il peut alors demeurer indéfiniment dans la bouilloire ou être transvasé, mais dès que la bouilloire se retrouve <em>intégralement</em> pleine, le processus recommence. Chaque chauffe lui coûte un de ses points de rêve actifs. Le rituel d'Autonomie les lui fait récupérer à raison de 3 par heure de complète non-utilisation.</p>\n<p>Il est bien entendu possible de mettre des herbes de soin dans la bouilloire avant d'y verser l'eau, de façon à obtenir une décoction en un temps record. Etant autonome, la Bouilloire de Mélimnod n'a pas être maîtrisée. La pose de la Grande Écaille coûte 1 point de seuil.</p>","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-9","portée":"","caseTMR":"special","caseTMRspeciale":"Monts Brûlants E5","ptreve":"9","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","effects":[]}

File diff suppressed because one or more lines are too long

View File

@ -11,7 +11,7 @@
{"_id":"O1QllxIvIkWxntmO","name":"Animer un squelette","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>En invoquant les forces du cauchemar à venir hanter un corps mort, le haut-rêvant de Thanatos crée un hideux simulacre de vie. Sous l'effet du rituel, le cadavre se décompose à vue d'oeil, se dépouillant de toute chair, jusqu'à ce qu'il n'en reste plus que les os, magiquement liés. Le squelette se redresse alors en position verticale, capable de se déplacer sur ses jambes en une parodie de vie réelle, utilisant se smains griffues pour attaquer. Ainsi créé, le squelette est en tout point semblable à l'entité de cauchemar incarnée du même nom, tant au niveau de ses caractéristiques que de ses compétences (voir livre III, page 225). Sa caractéristique TAILLE est celle du cadavre utilisé, sa caractéristique RÊVE est égale au nombre de points de rêve dépensés par le haut-rêvant, sachant que comme pour les zombis, et contrairement aux entités de cauchemar incarnées qui peuvent dépasser cette limite, la caractéristique RÊVE d'un squelette invoqué ne peut jamais dépasser sa caractéristique TAILLE. Sa hideur est telle que quiconque l'aperçoit doit réussir un jet de VOLONTÉ à -3 ou être en demi-surprise jusqu'à la fin du round suivant.</p>\n<p>Un squelette invoqué est aux ordres de son invocateur et n'agit qu'aux ordres reçus. Pour donner un nouvel ordre à son squelette, le haut-rêvant de Thanatos doit s'en trouver à une portée maximale égale à E1. A la mort de son invocateur, le squelette n'est pas détruit, mais devient une entité sauvage, se comportant librement comme l'entitéde cauchemar incarnée du même nom.</p>","draconic":"thanatos","duree":"Permanente","JR":"Aucun","cible":"Un cadavre","difficulte":"-9","portée":"","caseTMR":"necropole","caseTMRspeciale":"","ptreve":"1+","portee":"","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}
{"_id":"W0JXIoChz3IXuaCc","name":"Putrescence","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>L'effet de Putrescence ne peut être ciblé que sur un objet. L'effet est un vieilllissement instantané de plusieurs années, supposé s'être accompli dans les pires concditions, avec pour résultat un délabrement, une putrescence de l'objet. Le vieillissement est de 10 ans par point de rêve dépensé.</p>\n<p>Dans tous les cas, c'est au gardien des rêves de juger de l'état final de l'objet en se souvenant que les conditions de vieillissement sont censées avoir été très mauvaises : humidité, moisissure, chaud et froid, etc. Ainsi dix ans seront suffisants pour venir à bout du tissu et du papier, vingt ans pour du parchemin ou du cuir souple, trente pour du cuir épais et du bois léger. Quarante ans et plus auront presque entièrement dévoré de rouille le métal ferreux et corrompu le bois épais, tout dépendant de leur qualité initiale. Noter par contre que verre et céramique sont pratiquement imprutescibles. La putrescence étant instantanée et définitive, l'objet altéré ne dispense aucune aura.&nbsp;</p>","draconic":"thanatos","duree":"Permanente","JR":"Aucun","cible":"Un objet","difficulte":"-8","portée":"","caseTMR":"marais","caseTMRspeciale":"","ptreve":"1+","portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}
{"_id":"XldJiyXL4gSrfx4t","name":"Surdité","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Quand la victime est entièrement possédée de corps, le haut-rêvant de Thanatos peut commencer l'envoûtement de Surdité. Chaque ensemble de 2 points de rêve dépensés (2r), fait perdre 1 point de caractéristique OUÏE à la victime. A zéro point d'OUÏE, elle est totalement sourde. La surdité semble inexplicable, et aucune médecine ne peut la guérir. Annuler la possession brise en même temps l'envoûtement de Cécité, et la victime recouvre instantanément toute son OUÏE.</p>","draconic":"thanatos","duree":"Illimitée","JR":"Aucun","cible":"Relique","difficulte":"-6","portée":"","caseTMR":"gouffre","caseTMRspeciale":"","ptreve":"2+","portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}
{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"<p>Les rituels de Lecture d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Ce rituel permet d&rsquo;approfondir les informations fournies par D&eacute;tection d&rsquo;Aura. Pratiquer Lecture d&rsquo;Aura quand il n&rsquo;y a pas d&rsquo;aura revient &agrave; demander une magie impossible et cr&eacute;e imm&eacute;diatement une d&eacute;chirure du r&ecirc;ve.</p>\n<p>Lecture d&rsquo;Aura est effectu&eacute;e en plusieurs &eacute;tapes, toutes &eacute;tant de difficult&eacute; R-3 et co&ucirc;tant 3 points de r&ecirc;ve. La premi&egrave;re a toujours lieu dans un sanctuaire et ne fait que r&eacute;v&eacute;ler dans quel(s) autre(s) genre(s) de case(s) le haut-r&ecirc;vant doit se rendre pour continuer sa lecture. L&agrave;, il apprend quel genre de magie a &eacute;t&eacute; produit ou &agrave; quel type de r&ecirc;ve il a affaire, de m&ecirc;me que les cases sp&eacute;cifiques concern&eacute;es. Enfin dans les cases sp&eacute;cifiques, le haut-r&ecirc;vant peut apprendre la force du r&ecirc;ve ou de la magie en cours, c&rsquo;est-&agrave;-dire pratiquement la difficult&eacute; et le nombre de points de r&ecirc;ve impliqu&eacute;s, information indispensable dans l&rsquo;optique d&rsquo;une annulation de magie.</p>\n<p>Lecture d&rsquo;Aura r&eacute;v&egrave;le &eacute;galement la couleur de l&rsquo;aura (fixe ou pulsative) comme D&eacute;tection d&rsquo;Aura. Pour les cr&eacute;atures vivantes, on peut donc sauter l&rsquo;&eacute;tape de D&eacute;tection d&rsquo;Aura et commencer directement par la lecture, puisqu&rsquo;on est s&ucirc;r de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la d&eacute;tection si, en l&rsquo;absence finale d&rsquo;une aura, on ne veut pas cr&eacute;er de magie impossible. Effectu&eacute;e sur une cr&eacute;ature non soumise &agrave; un effet magique ni sous l&rsquo;emprise d&rsquo;une entit&eacute;, Lecture d&rsquo;Aura indique toujours le Fleuve. L&agrave;, dans n&rsquo;importe quelle case du Fleuve, le haut-r&ecirc;vant se contente d&rsquo;apprendre qu&rsquo;il a affaire &agrave; une cr&eacute;ature vivante et dou&eacute;e de r&ecirc;ve.</p>","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[]}
{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","data":{"description":"<p>Les rituels de Lecture d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Ce rituel permet d&rsquo;approfondir les informations fournies par D&eacute;tection d&rsquo;Aura. Pratiquer Lecture d&rsquo;Aura quand il n&rsquo;y a pas d&rsquo;aura revient &agrave; demander une magie impossible et cr&eacute;e imm&eacute;diatement une d&eacute;chirure du r&ecirc;ve.</p>\n<p>Lecture d&rsquo;Aura est effectu&eacute;e en plusieurs &eacute;tapes, toutes &eacute;tant de difficult&eacute; R-3 et co&ucirc;tant 3 points de r&ecirc;ve. La premi&egrave;re a toujours lieu dans un sanctuaire et ne fait que r&eacute;v&eacute;ler dans quel(s) autre(s) genre(s) de case(s) le haut-r&ecirc;vant doit se rendre pour continuer sa lecture. L&agrave;, il apprend quel genre de magie a &eacute;t&eacute; produit ou &agrave; quel type de r&ecirc;ve il a affaire, de m&ecirc;me que les cases sp&eacute;cifiques concern&eacute;es. Enfin dans les cases sp&eacute;cifiques, le haut-r&ecirc;vant peut apprendre la force du r&ecirc;ve ou de la magie en cours, c&rsquo;est-&agrave;-dire pratiquement la difficult&eacute; et le nombre de points de r&ecirc;ve impliqu&eacute;s, information indispensable dans l&rsquo;optique d&rsquo;une annulation de magie.</p>\n<p>Lecture d&rsquo;Aura r&eacute;v&egrave;le &eacute;galement la couleur de l&rsquo;aura (fixe ou pulsative) comme D&eacute;tection d&rsquo;Aura. Pour les cr&eacute;atures vivantes, on peut donc sauter l&rsquo;&eacute;tape de D&eacute;tection d&rsquo;Aura et commencer directement par la lecture, puisqu&rsquo;on est s&ucirc;r de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la d&eacute;tection si, en l&rsquo;absence finale d&rsquo;une aura, on ne veut pas cr&eacute;er de magie impossible. Effectu&eacute;e sur une cr&eacute;ature non soumise &agrave; un effet magique ni sous l&rsquo;emprise d&rsquo;une entit&eacute;, Lecture d&rsquo;Aura indique toujours le Fleuve. L&agrave;, dans n&rsquo;importe quelle case du Fleuve, le haut-r&ecirc;vant se contente d&rsquo;apprendre qu&rsquo;il a affaire &agrave; une cr&eacute;ature vivante et dou&eacute;e de r&ecirc;ve.</p>","descriptionmj":"","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"flags":{}}
{"_id":"cM9eo2VuJSCkIZvd","name":"Cécité","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Quand la victime est entièrement possédée de corps, le haut-rêvant de Thanatos peut commencer l'envoûtement de Cécité. Chaque ensemble de 2 points de rêve dépensés (2r), fait perdre 1 point de caractéristique VUE à la victime. A zéro point de VUE, elle est aveugle. La cécité semble inexplicable, et aucune médecine ne peut la guérir. Annuler la possession brise en même temps l'envoûtement de Cécité, et la victime recouvre instantanément toute sa VUE.</p>","draconic":"thanatos","duree":"Illimitée","JR":"Aucun","cible":"Relique","difficulte":"-8","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"2+","portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}
{"_id":"dK54iZkb7ypIuKwn","name":"Peur thanataire","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Le sort de Peur Thanataire doit être ciblé sur un objet, lequel, et jusqu'à la fin de l'heure de naissance du haut-rêvant, distillera ensuite une peur intense. Toute personne apercevant l'objet en question et manquant un jet de résistance standard r-8, sera contrainte de s'en détourner, ne pouvant supporter de le regarder ni de s'en approcher ou le regarder le(s) round(s) suivant(s), il faudra réussir unjet de VOLONTÉ ajusté négativement aux points de rêve dépensés. Même chose pour le toucher, le prendre, le frapper. Ce jet de VOLONTÉ doit être renouvelé de round en round jusqu'à ce qui réussisse.</p>\n<p>Le haut-rêvant de Thanatos est lui-même immunisé contre les effets de sa peur thanataire. Par ailleurs, comme c'est la seule vue de l'objet qui déclenche la peur, il n'y a aucun effet tant que l'objet est dissimulé, dans une poche par exemple.</p>","draconic":"thanatos","duree":"HN","JR":"r-8","cible":"Un objet","difficulte":"-9","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"1+","portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}
{"_id":"gZHrkEnR88mEv67I","name":"Griffe de Thanatos *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Placée en guise d'écaille de pouvoir sur un objet enchanté, la griffe de Thanatos n'est qu'un piège. Son fonctionnement intervient au moment de la maîtrise. Cette dernière est automatique, comme avec les écailles de Narcos, mais au lieu de coûter des points de rêve, elle coûte un nombre de <em>points de vie</em> égal au nombre de griffes, chaque point de vie perdu s'accompagnant d'une perte d'1d6 points d'endurance. Il n'y a pas de jet de résistance. La maîtrise (et la perte de points de vie) a lieu au moment où l'objet contenant la griffe est utilisé selon sa fonction : arme frappant, bague au doigt, bracelet au poignet, etc. Si l'objet n'a pas de fonction évidente, statuette, bibelot, ou s'il n'est qu'une gemme seule, la maîtrise a lieu dès que l'objet est pris dasn la main&nbsp; nue.</p>\n<p>Un objet peut n'avoir qu'une gemme contenant une ou plusieurs griffes de Thanatos, ce n'est alors qu'un piège en soi ; il peut avoir avoir plusieurs gemmes, grâce à Individualité, certaines possédant des pouvoirs réels (écailles de Narcos), et l'une d'entre elles ne possédant que des griffes de Thanatos. La maîtrise de la grifef (perte de points de vie) accompagne alors la maîtrise de chacun des vrais pouvoirs. Le créateur de l'objet, le maîtrisant tacitement, n'a pas à subir de perte de points de vie, mais si l'objet est maîtrisé par quelqu'un d'autre et lui revient, il en subit les conséquences. Les points de vie perdus sont regagnés selon la règle normale.</p>","draconic":"thanatos","duree":"Permanente","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"necropole","caseTMRspeciale":"","ptreve":"8","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}
@ -20,6 +20,6 @@
{"_id":"wGXeubRhLPScDkNF","name":"Possession d'Esprit","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Pour posséder d'esprit une victime, le haut-rêvant de Thanatos doit prendre son entière volonté sous son contrôle. Le ciblage du rituel doit s'effectuer en touchant la relique. Pour chaque ensemble de 2 points de rêve dépensés (2r), le haut-rêvant contrôle 1 point de VOLONTÉ de sa victime. Dès qu'il la contrôle entièrement, elle est possédée d'esprit. Pour posséder une victime ayant une VOLONTÉ de 14, il faut ainsi dépenser 28 points de rêve. Le haut-rêvant peut s'y prendre en plusieurs fois, mais la victime a droit à un JR à chaque fois, et il suffit qu'un seul d'entre eux réussisse pour annuler toute la possessions précédemment accomplie ; simultanément, le haut-rêvant de Thanataos doit lui-même réussir un JR r0 (points de rêve à zéro) ou être frappé en retour par un souffle de Dragon.&nbsp;</p>\n<p><em>Note</em>. Le haut-rêvant ne fait que&nbsp;<em>contrôler</em>&nbsp;la VOLONTÉ de sa victime, celle-ci n'en perd aucun point. Tant qu'aucun envoûtement n'est à l'oeuvre, il n'y a aucun effet mental, et la victime ne se rend même compte de rien.</p>","draconic":"thanatos","duree":"Illimitée","JR":"Avec HN r-9, sans HN r-8","cible":"Relique","difficulte":"-9","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"2+","portee":"","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}
{"_id":"wuqqLld48IagimXp","name":"Poing de Thanatos","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Le Poing de Thanatos peut être dirigé contre toute créature, humanoïde ou animal. Son effet, instantané, est celui d'un violent coup de poing en pleine tête, ne causant toutefois ses dommages que sur la table des Coups non mortels. Le +dom de l'agression est égal au nombre de points de rêve dépensés. Sauf pour les animaux qui peuvent faire jouer entièrement leur protection naturelle ainsi que pour les humanoïdes de grande TAILLE qui en possèdent, la protection applicable peut être au maximum de 2 points. Si la victime réussit son JR standard r-8, le haut-rêvant de Thanatos doit jouer un JR r0 (points de rêve à zéro) ou subir l'effet de son sort en retour.</p>","draconic":"thanatos","duree":"Instantanée","JR":"r-8","cible":"Toutes créatures","difficulte":"-6","portée":"","caseTMR":"plaines","caseTMRspeciale":"","ptreve":"1+","portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}
{"_id":"xFkdsI0FnhCCszDR","name":"Métamorphose en bête","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>L'envoûtement de Métamorphose en bête peut être accompli sur une possession de corps ou d'esprit. Il s'agit de deux métamorphoses différentes devant faire l'objet d'envoûtements séparés.</p>\n<p>L'accomplissant sur une victime possédée d'esprit, le haut-rêvant de Thanatos transforme le mental de cette dernière en celui d'un animal de son choix. Le corps physique de la victime reste inchangé, mais son esprit, son comportement, ses instincts deviennent ceux de l'animal. La victime perd le sens de la parole et de la compréhension du langage pour ne plus s'exprimer que par des cris : aboiements, miaulements, sifflements, caquètements, etc. Le tout dans un corps normal.</p>\n<p>Sur une victime possédée de corps, le haut-rêvant transforme réellement son corps en celui d'un animal de son choix, dont la TAILLE finale ne peut être supérieure à celle de la victime et doit être au minimum de 1 (souris). Il ne s'agit pas d'une illusion : la transformation est réelle. Le nouveau gosier de la victime l'empêche de parler, mais elle continue à comprendre le langage. Son intelligence et son mental restent inchangés, mais dans un corps d'animal. Un haut-rêvant métamorphosé peut continuer à monter en TMR mais doit posséder l'équivalent d'un doigt pour cibler des sorts ailleurs que sur lui-même.</p>\n<p>Si les deux métamorphoses, d'esprit ou de corps, sont effectuées conjointement, la victime devient en tout point un animal réel.</p>\n<p>Annuler l'une ou l'autre possession brise en même temps l'envoûtement de Métamorphose correspondant, et la victime recouvre une part de son identité.</p>","draconic":"thanatos","duree":"Illimitée","JR":"Aucun","cible":"Relique","difficulte":"-10","portée":"","caseTMR":"fleuve","caseTMRspeciale":"","ptreve":"10","portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}
{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"<p>Les rituels de D&eacute;tection d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Toutes les cr&eacute;atures vivantes anim&eacute;es (humains, humano&iuml;des, animaux) ont une caract&eacute;ristique R&Ecirc;VE. Les objets enchant&eacute;s poss&egrave;dent des points de r&ecirc;ve, de m&ecirc;me que les produits de magie naturelle, comme certaines pierres de chance. Les entit&eacute;s de cauchemar, incarn&eacute;es ou non, en ont &eacute;galement. Quelle qu&rsquo;elle soit, la pr&eacute;sence de r&ecirc;ve &eacute;met une aura, laquelle est d&eacute;tectable par D&eacute;tection d&rsquo;Aura. Parall&egrave;lement, toute cible d&rsquo;un sort ou d&rsquo;un rituel, &eacute;met une aura propre, quand bien m&ecirc;me ladite cible ne poss&egrave;de pas de points de r&ecirc;ve (centre de zone, objet ou plante soumis &agrave; une illusion d&rsquo;Hypnos). Cette aura est &eacute;galement d&eacute;tectable par D&eacute;tection d&rsquo;Aura.</p>\n<p>L&rsquo;aura de pr&eacute;sence de r&ecirc;ve se traduit par un halo bleut&eacute; constant ; l&rsquo;aura r&eacute;sultant d&rsquo;un effet magique par un halo parcouru de pulsations. Quand les deux auras sont pr&eacute;sentes conjointement, le halo est pulsatif et d&rsquo;un bleu plus fonc&eacute;. On peut toujours effectuer D&eacute;tection d&rsquo;Aura sans aucun risque, il y a toujours une r&eacute;ponse. Soit une aura est per&ccedil;ue, constante ou pulsative, et l&rsquo;on peut tenter une Lecture d&rsquo;Aura pour en savoir plus ; soit aucune aura n&rsquo;est per&ccedil;ue et il s&rsquo;agit de mati&egrave;re inerte, sans r&ecirc;ve, non soumise &agrave; un sort.</p>","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[]}
{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","data":{"description":"<p>Les rituels de D&eacute;tection d&rsquo;Aura peuvent indiff&eacute;remment &ecirc;tre accomplis par n&rsquo;importe laquelle des quatre voies.</p>\n<p>Toutes les cr&eacute;atures vivantes anim&eacute;es (humains, humano&iuml;des, animaux) ont une caract&eacute;ristique R&Ecirc;VE. Les objets enchant&eacute;s poss&egrave;dent des points de r&ecirc;ve, de m&ecirc;me que les produits de magie naturelle, comme certaines pierres de chance. Les entit&eacute;s de cauchemar, incarn&eacute;es ou non, en ont &eacute;galement. Quelle qu&rsquo;elle soit, la pr&eacute;sence de r&ecirc;ve &eacute;met une aura, laquelle est d&eacute;tectable par D&eacute;tection d&rsquo;Aura. Parall&egrave;lement, toute cible d&rsquo;un sort ou d&rsquo;un rituel, &eacute;met une aura propre, quand bien m&ecirc;me ladite cible ne poss&egrave;de pas de points de r&ecirc;ve (centre de zone, objet ou plante soumis &agrave; une illusion d&rsquo;Hypnos). Cette aura est &eacute;galement d&eacute;tectable par D&eacute;tection d&rsquo;Aura.</p>\n<p>L&rsquo;aura de pr&eacute;sence de r&ecirc;ve se traduit par un halo bleut&eacute; constant ; l&rsquo;aura r&eacute;sultant d&rsquo;un effet magique par un halo parcouru de pulsations. Quand les deux auras sont pr&eacute;sentes conjointement, le halo est pulsatif et d&rsquo;un bleu plus fonc&eacute;. On peut toujours effectuer D&eacute;tection d&rsquo;Aura sans aucun risque, il y a toujours une r&eacute;ponse. Soit une aura est per&ccedil;ue, constante ou pulsative, et l&rsquo;on peut tenter une Lecture d&rsquo;Aura pour en savoir plus ; soit aucune aura n&rsquo;est per&ccedil;ue et il s&rsquo;agit de mati&egrave;re inerte, sans r&ecirc;ve, non soumise &agrave; un sort.</p>","descriptionmj":"","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"flags":{}}
{"_id":"xdWVcaPvSH8tNZIZ","name":"Tâche","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Quand la victime est entièrement possédée d'esprit, le haut-rêvant de Thanatos peut l'obliger à accomplir une certaine tâche ou quête. Comem avec Interdiction, la tâche doit être possible par la VOLONTÉ normale de la victime : <em>dors !</em> ou <em>meurs !</em> sont impossibles. L'ordre doit être formulé de façon très précise, comme pour Interdiction, sauf que cette fois le seul verbe possible doit être à l'impératif affirmatif. C'est pareillement au gardien des rêves de juger des interprétations litigieuses. E<em>xemples : monte en haut de la tour ; brûle le livre noir, mets le feu au château, assassine le roi, etc. </em>La victime s'efforcera d'accomplir la tâche par les moyens les plus rapides et les plus efficaces. L'effet du sort prend fin dès que la tâche est accomplie ou que survient la fin de l'heure de la naissance de la victime. Le haut-rêvant peut renouveler la tâche de jour en jour ou en apporter une nouvelle, mais ne peut pas en faire coexister deux simultanément. Annuler la possession brise en même temps l'envoûtement de Tâche, et la victime recouvre instantanément toute sa liberté.</p>","draconic":"thanatos","duree":"HN de la victime","JR":"Aucun","cible":"Relique","difficulte":"-8","portée":"","caseTMR":"foret","caseTMRspeciale":"","ptreve":"8","portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}
{"_id":"yCrVicu7rLWmMwxe","name":"Animer un zombi","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"<p>Le principe d'animation du zombi est semblable à celui du squelette. Comme ce dernier, sa TAILLE est celle du cadavre utilisé, son RÊVE est égal aux points de rêve dépensés, avec un maximum égal à la TAILLE (voir le Livre III, page 225). Comme le squelette, le zombi n'obéit qu'aux ordres reçus, mêmes règles d'application.</p>\n<p>La différence esssentielle est que le rituel d'Animation de Zombi interrompt totalement le processus de putréfaction au lieu de l'accélérer. Une fois animé, un zombi reste dans l'état physique qui était le seien lors de l'accomplissement du rituel, sans plus jamais subir la moindre trace de décomposition. La conséquence est qu'un cadavre frais, dont la mort ne remonte qu'à quelques minutes ou quelques heures, une fois animé, ne se distingue des vivants que par une pâleur inhabituelle, un regard un peu fixe, et des lèvres un peu exsangues, mais pour peu qu'il ne fasse pas très clair ou que son maître l'ait bien emmitouflé, capable de passer pour un vivant. Pour cette raison, les zombis sont souvent préférés aux squelettes par les haut-rêvants de Thanatos plus circonspects et moins enclins au tape-à-l'oeil.</p>","draconic":"thanatos","duree":"Permanente","JR":"Aucun","cible":"Un cadavre","difficulte":"-7","portée":"","caseTMR":"necropole","caseTMRspeciale":"","ptreve":"1+","portee":"","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","effects":[]}

View File

@ -1,43 +1,38 @@
{
"id": "foundryvtt-reve-de-dragon",
"name": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"description": "Rêve de Dragon RPG for FoundryVTT",
"author": "LeRatierBretonnien",
"authors": [
{
"name": "LeRatierBretonnien",
"flags": {}
"name": "LeRatierBretonnien"
},
{
"name": "VincentVK",
"flags": {}
"name": "VincentVK"
},
{
"name": "Grendel",
"flags": {}
"name": "Grendel"
},
{
"name": "Michael Nonne",
"flags": {}
"name": "Michael Nonne"
},
{
"name": "Mandar",
"flags": {}
"name": "Mandar"
},
{
"name": "Fred",
"flags": {}
"name": "Fred"
},
{
"name": "Fab",
"flags": {}
"name": "Fab"
}
],
"url": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/",
"license": "LICENSE.txt",
"version": "10.0.14",
"compatibility": {
"minimum": "10"
},
"flags": {},
"version": "1.5.90",
"minimumCoreVersion": "0.8.0",
"compatibleCoreVersion": "9",
"scripts": [],
"esmodules": [
"module/rdd-main.js"
],
@ -49,13 +44,12 @@
"lang": "en",
"name": "English",
"path": "lang/fr.json",
"flags": {}
"unreal": "this is a trick"
},
{
"lang": "fr",
"name": "Français",
"path": "lang/fr.json",
"flags": {}
"path": "lang/fr.json"
}
],
"packs": [
@ -63,278 +57,453 @@
"name": "competences",
"label": "Compétences",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/competences.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/competences.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"compétences"
],
"entity": "Item",
"private": false
},
{
"name": "arts-et-divertissements",
"label": "Arts et Divertissements",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/arts-et-divertissements.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/arts-et-divertissements.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"recette",
"cuisine",
"danse",
"musique",
"chant",
"jeux"
],
"entity": "Item",
"private": false
},
{
"name": "competences-creatures",
"label": "Compétences de Créatures",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/competences-creatures.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/competences-creatures.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"compétences",
"créatures"
],
"entity": "Item",
"private": false
},
{
"name": "competences-entites",
"label": "Compétences des Entités",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/competences-entites.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/competences-entites.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"compétences",
"entités"
],
"entity": "Item",
"private": false
},
{
"name": "sorts-oniros",
"label": "Sorts d'Oniros",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/sorts-oniros.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/sorts-oniros.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"sorts"
],
"entity": "Item",
"private": false
},
{
"name": "sorts-hypnos",
"label": "Sorts d'Hypnos",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/sorts-hypnos.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/sorts-hypnos.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"sorts"
],
"entity": "Item",
"private": false
},
{
"name": "sorts-narcos",
"label": "Sorts de Narcos",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/sorts-narcos.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/sorts-narcos.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"sorts"
],
"entity": "Item",
"private": false
},
{
"name": "sorts-thanatos",
"label": "Sorts de Thanatos",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/sorts-thanatos.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/sorts-thanatos.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"sorts"
],
"entity": "Item",
"private": false
},
{
"name": "equipement",
"label": "Equipement",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/equipement.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/equipement.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"équipement",
"objet"
],
"entity": "Item",
"private": false
},
{
"name": "maladies-et-poisons",
"label": "Maladies & Poisons",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/maladies-et-poisons.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/maladies-et-poisons.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"maladie",
"poison"
],
"entity": "Item",
"private": false
},
{
"name": "rappel-des-regles",
"label": "Rappels des Règles",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/rappel-des-regles.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/rappel-des-regles.db",
"type": "JournalEntry",
"private": false,
"flags": {}
"tags": [
"journal",
"règles"
],
"entity": "JournalEntry",
"private": false
},
{
"name": "queues-de-dragon",
"label": "Queues de Dragon",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/queues-de-dragon.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/queues-de-dragon.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"queue"
],
"entity": "Item",
"private": false
},
{
"name": "ombres-de-thanatos",
"label": "Ombres de Thanatos",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/ombres-de-thanatos.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/ombres-de-thanatos.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"ombre"
],
"entity": "Item",
"private": false
},
{
"name": "souffles-de-dragon",
"label": "Souffles de Dragon",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/souffles-de-dragon.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/souffles-de-dragon.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"souffle"
],
"entity": "Item",
"private": false
},
{
"name": "tarot-draconique",
"label": "Tarot Draconique",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/tarot-draconique.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/tarot-draconique.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"tarot"
],
"entity": "Item",
"private": false
},
{
"name": "tetes-de-dragon-pour-haut-revants",
"label": "Têtes de Dragon (Hauts-Rêvants)",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/tetes-de-dragon-pour-haut-revants.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/tetes-de-dragon-pour-haut-revants.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"tête"
],
"entity": "Item",
"private": false
},
{
"name": "tetes-de-dragon-pour-tous-personnages",
"label": "Têtes de Dragon (Tous Personnages)",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/tetes-de-dragon-pour-tous-personnages.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/tetes-de-dragon-pour-tous-personnages.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"item",
"tête"
],
"entity": "Item",
"private": false
},
{
"name": "tables-diverses",
"label": "Tables Diverses",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/tables-diverses.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/tables-diverses.db",
"type": "RollTable",
"private": false,
"flags": {}
"tags": [
"table",
"tables"
],
"entity": "RollTable",
"private": false
},
{
"name": "animaux",
"label": "Animaux",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/animaux.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/animaux.db",
"type": "Actor",
"private": false,
"flags": {}
"tags": [
"animaux",
"creature"
],
"entity": "Actor",
"private": false
},
{
"name": "voyageurs",
"label": "Voyageurs",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/voyageurs.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/voyageurs.db",
"type": "Actor",
"private": false,
"flags": {}
"tags": [
"voyageur",
"profils"
],
"entity": "Actor",
"private": false
},
{
"name": "vehicules",
"label": "Véhicules",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/vehicules.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/vehicules.db",
"type": "Actor",
"private": false,
"flags": {}
"tags": [
"vehicule",
"bateau",
"charett",
"chariot",
"carriole",
"barque"
],
"entity": "Actor",
"private": false
},
{
"name": "archetypes",
"label": "Archetypes PNJs",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/archetypes.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/archetypes.db",
"type": "Actor",
"private": false,
"flags": {}
"tags": [
"archetype",
"pnj"
],
"entity": "Actor",
"private": false
},
{
"name": "humanoides",
"label": "Humanoïdes",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/humanoides.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/humanoides.db",
"type": "Actor",
"private": false,
"flags": {}
"tags": [
"humanoides",
"pnj"
],
"entity": "Actor",
"private": false
},
{
"name": "entites",
"label": "Entités de Cauchemar",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/entites-de-cauchemar.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/entites-de-cauchemar.db",
"type": "Actor",
"private": false,
"flags": {}
"tags": [
"entités",
"entite",
"cauchemar",
"ecni",
"eni"
],
"entity": "Actor",
"private": false
},
{
"name": "invocations",
"label": "Invocation d'Hypnos",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/invocations.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/invocations.db",
"type": "Actor",
"private": false,
"flags": {}
"tags": [
"hypnos",
"invocation"
],
"entity": "Actor",
"private": false
},
{
"name": "botanique",
"label": "Botanique",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/botanique.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/botanique.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"plantes",
"champignons",
"herbes"
],
"entity": "Item",
"private": false
},
{
"name": "taches-courantes",
"label": "Tâches courantes",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/taches-courantes.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/taches-courantes.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"taches"
],
"entity": "Item",
"private": false
},
{
"name": "meditations-et-ecrits",
"label": "Méditations et Ecrits",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/meditations-et-ecrits.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/meditations-et-ecrits.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"meditations",
"méditations",
"livres",
"livre",
"méditation",
"écrits",
"écrit"
],
"entity": "Item",
"private": false
},
{
"name": "recettes-alchimiques",
"label": "Recettes Alchimiques",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/recettes-alchimiques.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/recettes-alchimiques.db",
"type": "Item",
"private": false,
"flags": {}
"tags": [
"recettes",
"recette",
"alchimie",
"alchimique",
"potion"
],
"entity": "Item",
"private": false
},
{
"name": "scenes-rdd",
"label": "Scenes Reve de Dragon",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/scenes-rdd.db",
"module": "foundryvtt-reve-de-dragon",
"path": "./packs/scenes-rdd.db",
"type": "Scene",
"private": false,
"flags": {}
"tags": [
"ecran",
"scene"
],
"entity": "Scene",
"private": false
}
],
"system": [],
"dependencies": [],
"socket": true,
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.0.14.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v1.5/system.json",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-1.5.90.zip",
"protected": false,
"gridDistance": 1,
"gridUnits": "m",
"primaryTokenAttribute": "sante.vie",
"secondaryTokenAttribute": "sante.endurance"
}
}

View File

@ -41,15 +41,15 @@
<div class="grid grid-2col">
<div class="flex-group-left flexcol">
<ol class="carac-list alterne-list">
{{#each system.carac as |carac key|}}
{{#each data.carac as |carac key|}}
<li class="flexrow list-item" data-attribute="{{key}}">
{{#if (eq key 'taille')}}
<span class="carac-label flexrow" name="system.carac.{{key}}.label">{{carac.label}}</span>
<span class="carac-label flexrow" name="data.carac.{{key}}.label">{{carac.label}}</span>
{{else}}
<span class="carac-label flexrow" name="system.carac.{{key}}.label"><a
<span class="carac-label flexrow" name="data.carac.{{key}}.label"><a
name={{key}}>{{carac.label}}</a></span>
{{/if}}
<input class="competence-value flexrow" type="text" name="system.carac.{{key}}.value"
<input class="competence-value flexrow" type="text" name="data.carac.{{key}}.value"
value="{{carac.value}}" data-dtype="{{carac.type}}" />
</li>
{{/each}}
@ -61,29 +61,29 @@
</div>
<div class="flex-group-left flexcol">
<ol class="carac-list alterne-list">
{{#each system.attributs as |attr key|}}
{{#each data.attributs as |attr key|}}
<li class="flexrow list-item" data-attribute="{{key}}">
<span class="carac-label" name="system.attributs.{{key}}.label">{{attr.label}}</span>
<input type="text" name="system.attributs.{{key}}.value" value="{{attr.value}}" data-dtype="{{attr.type}}" />
<span class="carac-label" name="data.attributs.{{key}}.label">{{attr.label}}</span>
<input type="text" name="data.attributs.{{key}}.value" value="{{attr.value}}" data-dtype="{{attr.type}}" />
</li>
{{/each}}
<li class="flexrow list-item" data-attribute="vie">
<span class="competence-label" name="system.sante.vie.label">Vie</span>
<span class="competence-label" name="data.sante.vie.label">Vie</span>
<span class="flexrow" >
<input type="text" name="system.sante.vie.value" value="{{system.sante.vie.value}}" data-dtype="Number" /> /
<input type="text" name="system.sante.vie.max" value="{{system.sante.vie.max}}" data-dtype="Number" />
<input type="text" name="data.sante.vie.value" value="{{data.sante.vie.value}}" data-dtype="Number" /> /
<input type="text" name="data.sante.vie.max" value="{{data.sante.vie.max}}" data-dtype="Number" />
</span>
</li>
<li class="flexrow list-item" data-attribute="endurance">
<span class="competence-label" name="system.sante.endurance.label">Endurance</span>
<span class="competence-label" name="data.sante.endurance.label">Endurance</span>
<span class="flexrow" >
<input type="text" name="system.sante.endurance.value" value="{{system.sante.endurance.value}}" data-dtype="Number" /> /
<input type="text" name="system.sante.endurance.max" value="{{system.sante.endurance.max}}" data-dtype="Number" />
<input type="text" name="data.sante.endurance.value" value="{{data.sante.endurance.value}}" data-dtype="Number" /> /
<input type="text" name="data.sante.endurance.max" value="{{data.sante.endurance.max}}" data-dtype="Number" />
</span>
</li>
<li class="flexrow list-item" data-attribute="etat">
<span class="competence-label" name="system.compteurs.etat.label">Etat Général</span>
<input type="text" value="{{system.compteurs.etat.value}}" disabled />
<span class="competence-label" name="data.compteurs.etat.label">Etat Général</span>
<input type="text" value="{{data.compteurs.etat.value}}" disabled />
</li>
</ol>
</div>
@ -102,11 +102,11 @@
<span class="competence-label">{{comp.name}}</span>
</a>
<input class="competence-value creature-carac" type="text" compname="{{comp.name}}"
value="{{comp.system.carac_value}}" data-dtype="number" />
value="{{comp.data.carac_value}}" data-dtype="number" />
<input class="competence-value creature-niveau" type="text" compname="{{comp.name}}"
value="{{numberFormat comp.system.niveau decimals=0 sign=true}}" data-dtype="number" />
value="{{numberFormat comp.data.niveau decimals=0 sign=true}}" data-dtype="number" />
<input class="competence-value creature-dommages" type="text" compname="{{comp.name}}"
value="{{numberFormat comp.system.dommages decimals=0 sign=true}}" data-dtype="number" />
value="{{numberFormat comp.data.dommages decimals=0 sign=true}}" data-dtype="number" />
<div class="item-controls">
<a class="item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
@ -134,12 +134,12 @@
<div class="form-group">
<span class="item-name"><h4>Race</h4></span>
<input type="text" name="system.race" value="{{system.race}}" data-dtype="String" />
<input type="text" name="data.race" value="{{data.race}}" data-dtype="String" />
</div>
<div class="form-group editor">
<div class="form-group editor">
<span class="item-name"><h4>Description</h4>
{{editor system.description target="system.description" button=true owner=owner editable=true}}
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
</div>
{{>"systems/foundryvtt-reve-de-dragon/templates/actor-sheet-editor-notes-mj.html"}}

View File

@ -32,15 +32,15 @@
<div class="grid grid-2col">
<div class="flex-group-left flexcol">
<ol class="carac-list alterne-list">
{{#each system.carac as |carac key|}}
{{#each data.carac as |carac key|}}
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
{{#if (eq key 'taille')}}
<span class="carac-label flexrow" name="system.carac.{{key}}.label">{{carac.label}}</span>
<span class="carac-label flexrow" name="data.carac.{{key}}.label">{{carac.label}}</span>
{{else}}
<span class="carac-label flexrow" name="system.carac.{{key}}.label"><a
<span class="carac-label flexrow" name="data.carac.{{key}}.label"><a
name={{key}}>{{carac.label}}</a></span>
{{/if}}
<input class="competence-value flexrow" type="text" name="system.carac.{{key}}.value"
<input class="competence-value flexrow" type="text" name="data.carac.{{key}}.value"
value="{{carac.value}}" data-dtype="{{carac.type}}" />
</li>
{{/each}}
@ -52,8 +52,8 @@
<ol class="carac-list alterne-list">
<li class="caracteristique flexrow list-item">
<span class="carac-label flexrow" name="catEntite">Catégorie : </span>
<select name="system.definition.categorieentite" value="{{system.definition.categorieentite}}" data-dtype="String">
{{#select system.definition.categorieentite}}
<select name="data.definition.categorieentite" value="{{data.definition.categorieentite}}" data-dtype="String">
{{#select data.definition.categorieentite}}
<option value="cauchemar">Cauchemar</option>
<option value="reve">Rêve</option>
{{/select}}
@ -61,27 +61,27 @@
</li>
<li class="caracteristique flexrow list-item">
<span class="carac-label flexrow" name="typeEntite">Type d'entité : </span>
<select name="system.definition.typeentite" value="{{system.definition.typeentite}}" data-dtype="String">
{{#select system.definition.typeentite}}
<select name="data.definition.typeentite" value="{{data.definition.typeentite}}" data-dtype="String">
{{#select data.definition.typeentite}}
<option value="incarne">Incarnée</option>
<option value="nonincarne">Non Incarnée</option>
<option value="blurette">Blurette</option>
<option value="blurette">Blurete</option>
{{/select}}
</select>
</li>
{{#each system.attributs as |attr key|}}
{{#each data.attributs as |attr key|}}
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
<span class="carac-label flexrow" name="system.attributs.{{key}}.label">{{attr.label}} : </span>
<span><input class="attribut-value flexrow" type="text" name="system.attributs.{{key}}.value"
<span class="carac-label flexrow" name="data.attributs.{{key}}.label">{{attr.label}} : </span>
<span><input class="attribut-value flexrow" type="text" name="data.attributs.{{key}}.value"
value="{{attr.value}}" data-dtype="{{attr.type}}" /></span>
</li>
{{/each}}
<li class="caracteristique flexrow list-item" data-attribute="endurance">
<span class="competence-label flexrow" name="system.sante.endurance.label">Endurance : </span>
<span><input class="sante-value flexrow" type="text" name="system.sante.endurance.value"
value="{{system.sante.endurance.value}}" data-dtype="Number" /></span><span>/ </span>
<span><input class="sante-value flexrow" type="text" name="system.sante.endurance.max"
value="{{system.sante.endurance.max}}" data-dtype="Number" /></span>
<span class="competence-label flexrow" name="data.sante.endurance.label">Endurance : </span>
<span><input class="sante-value flexrow" type="text" name="data.sante.endurance.value"
value="{{data.sante.endurance.value}}" data-dtype="Number" /></span><span>/ </span>
<span><input class="sante-value flexrow" type="text" name="data.sante.endurance.max"
value="{{data.sante.endurance.max}}" data-dtype="Number" /></span>
</li>
</ol>
</div>
@ -98,11 +98,11 @@
<img class="sheet-competence-img" src="{{comp.img}}" />
<span class="competence-label"><a>{{comp.name}}</a></span>
<input class="competence-value creature-carac" type="text" compname="{{comp.name}}"
value="{{comp.system.carac_value}}" data-dtype="number" />
value="{{comp.data.carac_value}}" data-dtype="number" />
<input class="competence-value creature-niveau" type="text" compname="{{comp.name}}"
value="{{numberFormat comp.system.niveau decimals=0 sign=true}}" data-dtype="number" />
value="{{numberFormat comp.data.niveau decimals=0 sign=true}}" data-dtype="number" />
<input class="competence-value creature-dommages" type="text" compname="{{comp.name}}"
value="{{numberFormat comp.system.dommages decimals=0 sign=true}}" data-dtype="number" />
value="{{numberFormat comp.data.dommages decimals=0 sign=true}}" data-dtype="number" />
<div class="item-controls">
<a class="item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
@ -131,7 +131,7 @@
{{!-- Biography Tab --}}
<div class="tab description" data-group="primary" data-tab="description">
<div class="form-group editor">
{{editor system.description target="system.description" button=true owner=owner editable=true}}
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
</div>
{{>"systems/foundryvtt-reve-de-dragon/templates/actor-sheet-editor-notes-mj.html"}}
</div>

View File

@ -13,15 +13,15 @@
</thead>
<tbody>
<tr class="table-row alterne-row" ><td/><td colspan="4">Légères</td></tr>
{{#each system.blessures.legeres.liste as |bless key|}}
{{#each data.blessures.legeres.liste as |bless key|}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html" bless=bless key=key gravite="legere" title="Légère"}}
{{/each}}
<tr class="table-row alterne-row"><td/><td colspan="4">Graves</td></tr>
{{#each system.blessures.graves.liste as |bless key|}}
{{#each data.blessures.graves.liste as |bless key|}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html" bless=bless key=key gravite="grave" title="Grave"}}
{{/each}}
<tr class="table-row alterne-row"><td/><td colspan="4">Critiques</td></tr>
{{#each system.blessures.critiques.liste as |bless key|}}
{{#each data.blessures.critiques.liste as |bless key|}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html" bless=bless key=key gravite="critique" title="Critique"}}
{{/each}}
</tbody>

View File

@ -1,45 +1,45 @@
{{#if system.isVisible}}
<li class="item flexrow list-item {{#if system.isLevelUp}}xp-level-up tooltip{{/if}}" data-item-id="{{_id}}">
{{#if visible}}
<li class="item flexrow list-item {{#if data.isLevelUp}}xp-level-up tooltip{{/if}}" data-item-id="{{_id}}">
<a class="competence-label" name="{{name}}">
<img class="sheet-competence-img" src="{{img}}"/>
<span class="competence-label">{{name}}</span>
</a>
{{#if system.isLevelUp}}
<span class="tooltiptext ttt-xp">Vous pouvez dépenser {{system.xpNext}} points d'Experience pour augmenter de 1 votre compétence {{name}}</span>
{{#if data.isLevelUp}}
<span class="tooltiptext ttt-xp">Vous pouvez dépenser {{data.xpNext}} points d'Experience pour augmenter de 1 votre compétence {{name}}</span>
<a class="competence-xp-augmenter" compname="{{name}}" title="Augmenter">
<i class="fas fa-arrow-alt-circle-up"></i>
</a>
{{/if}}
<input class="competence-value" type="text" compname="{{name}}" name="comp-value-{{name}}"
value="{{numberFormat system.niveau decimals=0 sign=true}}" data-dtype="number"
value="{{numberFormat data.niveau decimals=0 sign=true}}" data-dtype="number"
{{#unless @root.options.editCaracComp}}disabled{{/unless}} />
<span class="competence-xp tooltip">
<input class="competence-xp " type="text" compname="{{name}}" name="comp-xp-{{name}}"
value="{{numberFormat system.xp decimals=0 sign=false}}" data-dtype="number"
value="{{numberFormat data.xp decimals=0 sign=false}}" data-dtype="number"
{{#unless @root.options.editCaracComp}}disabled{{/unless}} />
<span class="tooltiptext left-competence ttt-xp">Vous devez acquérir {{system.xpNext}} points d'Experience pour augmenter de 1 votre compétence {{name}}</span>
<span class="tooltiptext left-competence ttt-xp">Vous devez acquérir {{data.xpNext}} points d'Experience pour augmenter de 1 votre compétence {{name}}</span>
</span>
{{#if (eq system.categorie 'draconic')}}
{{#if (eq data.categorie 'draconic')}}
<input class="competence-xp-sort" type="text" compname="{{name}}" name="comp-xp-sort-{{name}}"
value="{{numberFormat system.xp_sort decimals=0 sign=false}}" data-dtype="number"
value="{{numberFormat data.xp_sort decimals=0 sign=false}}" data-dtype="number"
{{#unless @root.options.editCaracComp}}disabled{{/unless}}/>
{{/if}}
{{#if @root.options.vueDetaillee}}
<div class="item-controls">
{{#if system.stressXpMax}}
{{#if data.stressXpMax}}
<a class="competence-stress-augmenter" compname="{{name}}"
title="Dépenser {{system.stressXpMax}} points de stress {{#if system.isStressLevelUp}} pour augmenter d'un niveau {{/if}}">
<i class="fas fa-arrow-alt-circle-up allouer-stress{{#if system.isStressLevelUp}}-level-up{{/if}}"></i>
title="Dépenser {{data.stressXpMax}} points de stress {{#if data.isStressLevelUp}} pour augmenter d'un niveau {{/if}}">
<i class="fas fa-arrow-alt-circle-up allouer-stress {{#if data.isStressLevelUp}}level-up{{/if}}"></i>
</a>
{{else}}
<i class="far fa-circle"></i>
{{/if}}
<input class="competence-archetype niveau-archetype" type="text" compname="{{name}}" name="comp-archetype-{{name}}"
value="{{numberFormat system.niveau_archetype decimals=0 sign=true}}" data-dtype="number"
value="{{numberFormat data.niveau_archetype decimals=0 sign=true}}" data-dtype="number"
{{#unless @root.options.editCaracComp}}disabled{{/unless}} />
<a class="item-edit" title="Modifier"><i class="fas fa-edit"></i></a>
{{#if @root.options.isGM}}

View File

@ -1,6 +1,6 @@
{{#if options.isGM}}
<h3>Notes du MJ : </h3>
<div class="form-group editor">
{{editor system.notesmj target="system.notesmj" button=true owner=owner editable=editable}}
{{editor content=data.notesmj target="data.notesmj" button=true owner=owner editable=editable}}
</div>
{{/if}}

View File

@ -1,52 +0,0 @@
<li class="item flexrow list-item" data-item-id="{{item._id}}" draggable="true">
{{#if (eq item.type 'conteneur')}}
<span class="sheet-competence-img conteneur-name">
{{#if vide}}
<i class="far fa-square"></i>
{{else}}
<a data-item-id="{{item._id}}">
{{#if ouvert}}
<i class="far fa-minus-square"></i>
<!-- <i class="far fa-caret-square-down"></i> -->
{{else}}
<i class="far fa-plus-square"></i>
<!-- <i class="fas fa-caret-square-right"></i> -->
{{/if}}
</a>
{{/if}}
</span>
<span class="item-name conteneur-name flex-grow">
<a data-item-id="{{item._id}}">
<img class="sheet-competence-img" src="{{item.img}}" title="{{item.name}}"/>
{{item.name}}
</a>
</span>
{{else}}
<img class="sheet-competence-img" src="{{item.img}}" title="{{item.name}}"/>
<span class="item-name flex-grow">{{item.name}}</span>
{{/if}}
<span class="item-quantite">{{item.system.quantite}}
{{#if (gt item.system.quantite 1)}}
<a class="item-control item-split" title="Séparer"><i class="fas fa-unlink"></i></a>
{{/if}}
</span>
<span class="item-quantite">{{numberFormat item.system.encTotal decimals=2}}</span>
<div class="item-controls flex-grow">
{{#unless item.estContenu}}
{{#if (ne item.type 'conteneur')}}
<a class="item-control item-equip" title="Equiper">{{#if item.system.equipe}}<i class="fas fa-hand-rock"></i>{{else}}<i class="far fa-hand-paper"></i>{{/if}}</a>
{{/if}}
{{/unless}}
<a class="item-control item-edit" title="Editer"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
{{#if (or (eq item.type 'arme') (eq item.type 'conteneur') item.system.quantite)}}
&nbsp;
<a class="item-control item-vendre" title="Vendre ou donner"><i class="fas fa-comments-dollar"></i></a>
{{/if}}
<a class="item-control item-montrer" title="Montrer"><i class="fas fa-comment"></i></a>
{{#if item.system.actionPrincipale}}
<a class="item-name item-action">{{item.system.actionPrincipale}}</a>
{{/if}}
</div>
</li>

View File

@ -21,27 +21,27 @@
<span>{{item.name}}</span>
{{/if}}
</span>
<span class="equipement-detail">{{item.system.quantite}}
{{#if (gt item.system.quantite 1)}}
<span class="equipement-detail">{{item.data.quantite}}
{{#if (gt item.data.quantite 1)}}
<a class="item-split" title="Séparer"><i class="fas fa-unlink"></i></a>
{{/if}}
</span>
<span class="equipement-detail">{{numberFormat item.system.encTotal decimals=2}}</span>
<span class="equipement-detail">{{numberFormat item.data.encTotal decimals=2}}</span>
<span class="equipement-actions item-controls">
{{#unless item.estContenu}}
{{#if (ne item.type 'conteneur')}}
<a class="item-equip" title="Equiper">{{#if item.system.equipe}}<i class="fas fa-hand-rock"></i>{{else}}<i class="far fa-hand-paper"></i>{{/if}}</a>
<a class="item-equip" title="Equiper">{{#if item.data.equipe}}<i class="fas fa-hand-rock"></i>{{else}}<i class="far fa-hand-paper"></i>{{/if}}</a>
{{/if}}
{{/unless}}
<a class="item-edit" title="Editer"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
&nbsp;
{{#if (or (eq item.type 'arme') (eq item.type 'conteneur') item.system.quantite)}}
{{#if (or (eq item.type 'arme') (eq item.type 'conteneur') item.data.quantite)}}
<a class="item-vendre" title="Vendre ou donner"><i class="fas fa-comments-dollar"></i></a>
{{/if}}
<a class="item-montrer" title="Montrer"><i class="fas fa-comment"></i></a>
{{#if item.actionPrincipale}}
<a class="item-action">{{item.actionPrincipale}}</a>
{{#if item.data.actionPrincipale}}
<a class="item-action">{{item.data.actionPrincipale}}</a>
{{/if}}
</span>
</li>

View File

@ -8,7 +8,7 @@
<a class="monnaie-moins"><i class="fas fa-minus-square"></i></a>
</span>
<span class="equipement-detail">
<span>{{piece.system.quantite}}</span>
<span>{{piece.data.quantite}}</span>
</span>
<span class="equipement-detail item-controls">
<a class="monnaie-plus"><i class="fas fa-plus-square"></i></a>
@ -16,7 +16,7 @@
<!-- <span class="equipement-detail">
<span class="flex-shrink"><a class="monnaie-moins"><i class="fas fa-minus-square"></i></a></span>
<span>{{piece.system.quantite}}</span>
<span>{{piece.data.quantite}}</span>
<span class="flex-shrink"><a class="monnaie-plus"><i class="fas fa-plus-square"></i></a></span>
</span> -->
<span class="equipement-actions item-controls">

View File

@ -1,7 +1,7 @@
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-monnaie.html" monnaie=monnaie}}
<span class="item-name"><h4>Equipement</h4></span>
<span class="item-name">Encombrement total/max : {{numberFormat calc.encTotal decimals=2}} / {{system.attributs.encombrement.value}} <b>{{calc.surEncombrementMessage}}</b></span> -
<span class="item-name">Encombrement total/max : {{numberFormat calc.encTotal decimals=2}} / {{data.attributs.encombrement.value}} <b>{{calc.surEncombrementMessage}}</b></span> -
<span class="item-name"><a class="creer-un-objet">Créer un objet</a></span>
{{#if options.isGM}}
<span class="item-name"> - <a id="nettoyer-conteneurs">Vider tout les conteneurs</a></span>

View File

@ -1,7 +1,7 @@
<li class="item flexrow list-item" data-item-id="{{oeuvre._id}}">
<span>{{upperFirst typeOeuvre}}</span>
<span class="competence-title {{classOeuvre}}">
<a>{{oeuvre.name}} (niveau {{oeuvre.system.niveau}})</a>
<a>{{oeuvre.name}} (niveau {{oeuvre.data.niveau}})</a>
</span>
<div class="item-controls">
<a class="item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>

View File

@ -13,8 +13,8 @@
<label class="compteur">
<a class="jet-vie">Vie</a>
<a class="vie-moins"><i class="fas fa-minus-square"></i></a>
<input class="resource-content" type="text" name="system.sante.vie.value" value="{{system.sante.vie.value}}" data-dtype="Number"/>
<span>/ {{system.sante.vie.max}}</span>
<input class="resource-content" type="text" name="data.sante.vie.value" value="{{data.sante.vie.value}}" data-dtype="Number"/>
<span>/ {{data.sante.vie.max}}</span>
<a class="vie-plus"><i class="fas fa-plus-square"></i></a>
</label>
</li>
@ -22,8 +22,8 @@
<label class="compteur">
<a class="jet-endurance">Endurance</a>
<a class="endurance-moins"><i class="fas fa-minus-square"></i></a>
<input class="resource-content" type="text" name="system.sante.endurance.value" value="{{system.sante.endurance.value}}" data-dtype="Number"/>
<span>/ {{system.sante.endurance.max}}</span>
<input class="resource-content" type="text" name="data.sante.endurance.value" value="{{data.sante.endurance.value}}" data-dtype="Number"/>
<span>/ {{data.sante.endurance.max}}</span>
<a class="endurance-plus"><i class="fas fa-plus-square"></i></a>
</label>
</li>
@ -32,8 +32,8 @@
<span class="tooltiptext ttt-fatigue">{{{calc.fatigue.html}}}</span>
Fatigue
<a class="fatigue-moins"><i class="fas fa-minus-square"></i></a>
<input class="resource-content" id="fatigue-value" type="text" name="system.sante.fatigue.value" value="{{system.sante.fatigue.value}}" data-dtype="Number" />
<span>/ {{system.sante.fatigue.max}}</span>
<input class="resource-content" id="fatigue-value" type="text" name="data.sante.fatigue.value" value="{{data.sante.fatigue.value}}" data-dtype="Number" />
<span>/ {{data.sante.fatigue.max}}</span>
<a class="fatigue-plus"><i class="fas fa-plus-square"></i></a>
</label>
</li>
@ -41,8 +41,8 @@
<label class="compteur">
<span class="ptreve-actuel"><a>Rêve</a></span>
<a class="ptreve-actuel-moins"><i class="fas fa-minus-square"></i></a>
<input class="resource-content" id="pointsreve-value" type="text" name="system.reve.reve.value" value="{{system.reve.reve.value}}" data-dtype="Number" />
<span>/ {{system.reve.seuil.value}}</span>
<input class="resource-content" id="pointsreve-value" type="text" name="data.reve.reve.value" value="{{data.reve.reve.value}}" data-dtype="Number" />
<span>/ {{data.reve.seuil.value}}</span>
<a class="ptreve-actuel-plus"><i class="fas fa-plus-square"></i></a>
</label>
</li>
@ -52,7 +52,7 @@
<span class="encaisser-direct"><a title="Encaisser des dommages"><img class="button-img" src="icons/svg/bones.svg" alt="Encaisser des dommages"/></a></span>
<span class="gm-only remise-a-neuf"><a title="Remise à neuf"><img class="button-img" src="icons/svg/regen.svg" alt="Remise à neuf"/></a></span>
<span class="repos"><a title="Repos"><img class="button-img" src="icons/svg/sleep.svg" alt="Se reposer"/></a></span>
{{#if system.attributs.hautrevant.value}}
{{#if data.attributs.hautrevant.value}}
<span class="monte-tmr"><a title="Montée dans les Terres M&eacute;dianes !" {{#if hautreve.isDemiReve}}disabled{{/if}}><img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/icon-tmr-normal.svg" alt="Montée dans les Terres M&eacute;dianes !"/></a></span>
<span class="monte-tmr-rapide"><a title="Montée accélérée dans les Terres M&eacute;dianes !"><img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/icon-tmr-rapide.svg" alt="Montée accélérée dans les Terres M&eacute;dianes !"/></a></span>
<span class="visu-tmr"><a title="Regarder les Terres M&eacute;dianes"><img class="button-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/icon-tmr-view.svg" alt="Regarder les Terres M&eacute;dianes"/></a></span>
@ -65,8 +65,8 @@
<span>{{calc.resumeBlessures}}</span>
</div>
<div class="flexrow">
<span>{{system.compteurs.etat.label}}: {{system.compteurs.etat.value}}</span>
<span>{{system.compteurs.surenc.label}}: {{system.compteurs.surenc.value}}</span>
<span>{{data.compteurs.etat.label}}: {{data.compteurs.etat.value}}</span>
<span>{{data.compteurs.surenc.label}}: {{data.compteurs.surenc.value}}</span>
</div>
<div class="flexrow">
{{>"systems/foundryvtt-reve-de-dragon/templates/actor-sheet-effects-partial.html"}}
@ -100,34 +100,34 @@
<div class="grid grid-2col">
<div class="flex-group-left flexcol">
<ul class="carac-list alterne-list">
{{#each system.carac as |carac key|}}
{{#each data.carac as |carac key|}}
{{#if carac.isLevelUp}}
<li class="caracteristique flexrow item-list xp-level-up" data-attribute="{{key}}">
{{else}}
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
{{/if}}
{{#if (eq key 'taille')}}
<span class="carac-label" name="system.carac.{{key}}.label">{{carac.label}}</span>
<input class="carac-value" type="text" name="system.carac.{{key}}.value" value="{{carac.value}}" data-dtype="{{carac.type}}" {{#unless @root.options.editCaracComp}}disabled{{/unless}} />
<span class="carac-label" name="data.carac.{{key}}.label">{{carac.label}}</span>
<input class="carac-value" type="text" name="data.carac.{{key}}.value" value="{{carac.value}}" data-dtype="{{carac.type}}" {{#unless @root.options.editCaracComp}}disabled{{/unless}} />
<label class="carac-xp"/>
{{else}}
{{#if carac.derivee}}
<span class="carac-label" name="system.carac.{{key}}.label"> <a name={{key}}>{{carac.label}}</a></span>
<span class="carac-label" name="data.carac.{{key}}.label"> <a name={{key}}>{{carac.label}}</a></span>
<label class="competence-value">{{carac.value}}</label>
<label class="carac-xp"/>
{{else}}
{{#if carac.isLevelUp}}
<span class="carac-label tooltip" name="system.carac.{{key}}.label">
<span class="carac-label tooltip" name="data.carac.{{key}}.label">
<span class="tooltiptext ttt-xp">
Vous pouvez dépenser {{carac.xpNext}} points d'Experience pour augmenter de 1 votre caractéristique {{carac.label}}
</span>
<a name={{key}}>{{carac.label}}</a></span>
{{else}}
<span class="carac-label tooltip" name="system.carac.{{key}}.label"><a name={{key}}>{{carac.label}}</a></span>
<span class="carac-label tooltip" name="data.carac.{{key}}.label"><a name={{key}}>{{carac.label}}</a></span>
{{/if}}
<input class="carac-value" type="text" name="system.carac.{{key}}.value" value="{{carac.value}}" data-dtype="{{carac.type}}" {{#unless @root.options.editCaracComp}}disabled{{/unless}} />
<input class="carac-value" type="text" name="data.carac.{{key}}.value" value="{{carac.value}}" data-dtype="{{carac.type}}" {{#unless @root.options.editCaracComp}}disabled{{/unless}} />
<span class="carac-xp tooltip">
<input class="carac-xp" type="text" name="system.carac.{{key}}.xp" value="{{carac.xp}}" data-dtype="number" {{#unless @root.options.editCaracComp}}disabled{{/unless}} />
<input class="carac-xp" type="text" name="data.carac.{{key}}.xp" value="{{carac.xp}}" data-dtype="number" {{#unless @root.options.editCaracComp}}disabled{{/unless}} />
<span class="tooltiptext ttt-xp">Vous devez acquérir {{carac.xpNext}} points d'Experience pour augmenter de 1 votre {{carac.label}}</span>
</span>
{{#if carac.isLevelUp}}
@ -149,17 +149,17 @@
<ul class="carac-list">
<li class="caracteristique flexrow list-item">
<span class="carac-label" name="beaute">Beauté&nbsp;:</span>
<input class="description-value" type="text" name="system.beaute" value="{{system.beaute}}" data-dtype="String" {{#unless @root.options.editCaracComp}}disabled{{/unless}}/>
<input class="description-value" type="text" name="data.beaute" value="{{data.beaute}}" data-dtype="String" {{#unless @root.options.editCaracComp}}disabled{{/unless}}/>
<label class="carac-xp"/>
</li>
{{#each system.attributs as |attr key|}}
{{#each data.attributs as |attr key|}}
{{#unless (eq key 'hautrevant')}}
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
<span class="carac-label" name="system.attributs.{{key}}.label">{{attr.label}}&nbsp;:</span>
<span class="carac-label" name="data.attributs.{{key}}.label">{{attr.label}}&nbsp;:</span>
{{#if (eq key 'protection')}}
<input class="description-value" id="attribut-protection-edit" type="text" name="{{key}}" value="{{attr.value}}" data-dtype="number"/>
{{else}}
<input class="description-value" type="text" disabled name="system.attributs.{{key}}." value="{{attr.value}}" data-dtype="number"/>
<input class="description-value" type="text" disabled name="data.attributs.{{key}}." value="{{attr.value}}" data-dtype="number"/>
{{/if}}
<label class="carac-xp"/>
</li>
@ -169,17 +169,17 @@
<ul class="carac-list alterne-list">
<li class="caracteristique flexrow list-item">
<span class="attribut-label chance-actuelle"><a>Chance actuelle</a></span>
<input class="description-value compteur-edit" type="text" name="chance" value="{{system.compteurs.chance.value}}" data-dtype="number"/>
<input class="description-value compteur-edit" type="text" name="chance" value="{{data.compteurs.chance.value}}" data-dtype="number"/>
<span class="utiliser-attribut" style="padding-left: 5px"><a class="chance-appel">Utiliser</a></span>
</li>
{{#each system.compteurs as |compteur key|}}
{{#each data.compteurs as |compteur key|}}
{{#if (eq compteur.label 'Chance')}}
{{else if (eq compteur.label 'Experience')}}
{{else if compteur.isInput}}
<li class="caracteristique flexrow list-item">
<span class="attribut-label">{{compteur.label}}</span>
{{#if (eq compteur.label 'Ethylisme')}}
<select class="description-value" name="system.compteurs.ethylisme.value" id="ethylisme" data-dtype="Number">
<select class="description-value" name="data.compteurs.ethylisme.value" id="ethylisme" data-dtype="Number">
{{#select compteur.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/niveau-ethylisme.html"}}
{{/select}}
@ -240,7 +240,7 @@
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-categorie-competences-partial.html" competences=(filtreTriCompetences competenceByCategory.tir) categorie="Compétences de Tir"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-categorie-competences-partial.html" competences=(filtreTriCompetences competenceByCategory.lancer) categorie="Compétences de Lancer"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-categorie-competences-partial.html" competences=(filtreTriCompetences competenceByCategory.connaissance) categorie="Connaissances"}}
{{#if (or system.attributs.hautrevant.value options.vueDetaillee)}}
{{#if (or data.attributs.hautrevant.value options.vueDetaillee)}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-categorie-competences-partial.html" competences=(filtreTriCompetences competenceByCategory.draconic) categorie="Draconic"}}
{{/if}}
@ -248,7 +248,7 @@
<ul class="item-list">
<li class="item flexrow">
<span class="generic-label">Stress transformé</span>
<input class="compteur-edit" type="text" name="experience" value="{{system.compteurs.experience.value}}" data-dtype="number" size="3"/>
<input class="compteur-edit" type="text" name="experience" value="{{data.compteurs.experience.value}}" data-dtype="number" size="3"/>
</li>
<li class="item flexrow">
@ -284,7 +284,7 @@
</li>
{{#each combat as |arme key|}}
<li class="item flexrow list-item" data-item-id="{{arme._id}}"
data-arme-name="{{arme.name}}" data-competence-name="{{arme.system.competence}}" >
data-arme-name="{{arme.name}}" data-competence-name="{{arme.data.competence}}" >
<span class="arme-label">
<a>
{{#if arme.img}}
@ -293,14 +293,14 @@
<span>{{arme.name}}</span>
</a>
</span>
<span class="arme-initiative"><a>{{arme.system.initiative}}</a></span>
<span class="competence-label">{{arme.system.competence}}</span>
<span class="competence-value">{{numberFormat arme.system.niveau decimals=0 sign=true}}</span>
<span class="competence-value">{{numberFormat arme.system.dommagesReels decimals=0 sign=true}}</span>
<span class="arme-initiative"><a>{{arme.data.initiative}}</a></span>
<span class="competence-label">{{arme.data.competence}}</span>
<span class="competence-value">{{numberFormat arme.data.niveau decimals=0 sign=true}}</span>
<span class="competence-value">{{numberFormat arme.data.dommagesReels decimals=0 sign=true}}</span>
</li>
{{/each}}
{{#each esquives as |esq key|}}
<li class="item flexrow list-item" data-item-id="{{esq._id}}">
<li class="item flexrow list-item">
<span class="competence-label">
<a class="competence-label" name="{{esq.name}}">
<img class="sheet-competence-img" src="{{esq.img}}"/>
@ -309,7 +309,7 @@
</span>
<span class="arme-initiative"></span>
<span class="competence-label"></span>
<span class="competence-value">{{numberFormat esq.system.niveau decimals=0 sign=true}}</span>
<span class="competence-value">{{numberFormat esq.data.niveau decimals=0 sign=true}}</span>
<span class="competence-value"></span>
</li>
{{/each}}
@ -332,7 +332,7 @@
{{#each maladiesPoisons as |maladie key|}}
<li class="item flexrow list-item" data-item-id="{{maladie._id}}">
<span class="competence-label">
{{#if (or @root.options.isGM maladie.system.identifie)}}
{{#if (or @root.options.isGM maladie.data.identifie)}}
{{maladie.name}}
{{else}}
Inconnue
@ -340,8 +340,8 @@
</span>
<span class="competence-label">{{maladie.type}}</span>
<span class="competence-label">
{{#if (or @root.options.isGM maladie.system.remedesconnus)}}
{{maladie.system.remedes}}
{{#if (or @root.options.isGM maladie.data.remedesconnus)}}
{{maladie.data.remedes}}
{{else}}
Remèdes Inconnus
{{/if}}
@ -368,7 +368,7 @@
<span class="competence-label">
<a class="sheet-possession-attack">{{possession.name}} (Conjurer)</a>
</span>
<span class="competence-label">{{possession.system.type}}</span>
<span class="competence-label">{{possession.data.type}}</span>
<div class="item-controls">
<a class="item-edit" title="Modifier"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
@ -385,9 +385,9 @@
<ul class="item-list alterne-list">
{{#each taches as |tache id|}}
<li class="item flexrow list-item" data-item-id="{{tache._id}}"><span class="competence-title tache-label"><a>{{tache.name}}
({{tache.system.points_de_tache_courant}}{{#if
(or @root.options.isGM (not tache.system.cacher_points_de_tache))
}}/{{tache.system.points_de_tache}}{{/if}})</a></span>
({{tache.data.points_de_tache_courant}}{{#if
(or @root.options.isGM (not tache.data.cacher_points_de_tache))
}}/{{tache.data.points_de_tache}}{{/if}})</a></span>
<div class="item-controls flex-shrink">
<a class="item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
@ -408,7 +408,7 @@
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-oeuvre-partial.html" oeuvre=danse typeOeuvre="Danse" classOeuvre="danse-label"}}
{{/each}}
{{#each oeuvres as |oeuvre id|}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-oeuvre-partial.html" oeuvre=oeuvre typeOeuvre=oeuvre.system.competence classOeuvre="oeuvre-label"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-oeuvre-partial.html" oeuvre=oeuvre typeOeuvre=oeuvre.data.competence classOeuvre="oeuvre-label"}}
{{/each}}
{{#each recettescuisine as |recette id|}}
{{> "systems/foundryvtt-reve-de-dragon/templates/actor-sheet-oeuvre-partial.html" oeuvre=recette typeOeuvre="Recette de cuisine" classOeuvre="recettecuisine-label"}}
@ -417,7 +417,7 @@
<h3>Jeux :</h3>
<ul class="item-list alterne-list">
{{#each jeux as |jeu id|}}
<li class="item flexrow list-item" data-item-id="{{jeu._id}}"><span class="competence-title jeu-label"><a>{{jeu.name}} (base {{jeu.system.base}})</a></span>
<li class="item flexrow list-item" data-item-id="{{jeu._id}}"><span class="competence-title jeu-label"><a>{{jeu.name}} (base {{jeu.data.base}})</a></span>
<div class="item-controls flex-shrink">
<a class="item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
@ -444,13 +444,13 @@
{{!-- hautreve Tab --}}
<div class="tab hautreve " data-group="primary" data-tab="hautreve" style="height:200px">
<div>
{{#if system.attributs.hautrevant.value}}
{{#if data.attributs.hautrevant.value}}
<h3>Haut rêvant</h3>
{{else}}
<h3>Vous n'avez pas le don de haut-rêve! Il faut attribuer la Tête de Dragon 'Don de Haut Rêve' si votre personnage est ou devient Haut-Rêvant.</h3>
{{/if}}
<ul class="item-list">
{{#if system.attributs.hautrevant.value}}
{{#if data.attributs.hautrevant.value}}
{{#if options.isGM}}
<li class="item flexrow">
<span>
@ -464,23 +464,23 @@
<li class="item flexrow">
{{#if options.isGM}}
<span class="competence-label flex-shrink">Demi rêve :
<span>{{caseTmr-label system.reve.tmrpos.coord}}</span>
<span>{{caseTmr-label data.reve.tmrpos.coord}}</span>
</span>
<span>
<input class="competence-value" type="text" name="system.reve.tmrpos.coord" value="{{system.reve.tmrpos.coord}}" data-dtype="String"/>
<input class="competence-value" type="text" name="data.reve.tmrpos.coord" value="{{data.reve.tmrpos.coord}}" data-dtype="String"/>
</span>
{{else}}
<span class="competence-label flex-shrink">Demi rêve :
{{#unless hautreve.cacheTMR}}
<span>{{caseTmr-label system.reve.tmrpos.coord}}</span>
<span>{{caseTmr-label data.reve.tmrpos.coord}}</span>
{{/unless}}
</span>
<span>
{{#if hautreve.cacheTMR}}
??
{{else}}
{{system.reve.tmrpos.coord}}
{{data.reve.tmrpos.coord}}
{{/if}}
</span>
{{/if}}
@ -490,9 +490,9 @@
<span class="competence-label">Seuil de Rêve :</span>
<span>
{{#if options.isGM}}
<input class="seuil-reve-value" type="text" name="system.reve.seuil.value" value="{{system.reve.seuil.value}}" data-dtype="Number"/>
<input class="seuil-reve-value" type="text" name="data.reve.seuil.value" value="{{data.reve.seuil.value}}" data-dtype="Number"/>
{{else}}
{{system.reve.seuil.value}}
{{data.reve.seuil.value}}
{{/if}}
</span>
</li>
@ -500,9 +500,9 @@
<span class="competence-label">Refoulement : </span>
<span>
{{#if options.isGM}}
<input class="competence-value" type="text" name="system.reve.refoulement.value" value="{{system.reve.refoulement.value}}" data-dtype="Number"/>
<input class="competence-value" type="text" name="data.reve.refoulement.value" value="{{data.reve.refoulement.value}}" data-dtype="Number"/>
{{else}}
{{system.reve.refoulement.value}}
{{data.reve.refoulement.value}}
{{/if}}
</span>
</li>
@ -562,14 +562,14 @@
{{/each}}
</ul>
{{/if}}
{{#if system.attributs.hautrevant.value}}
{{#if data.attributs.hautrevant.value}}
{{#if (and options.isGM signesdraconiques.length)}}
<h3>Signes draconiques</h3>
<ul class="item-list alterne-list">
{{#each signesdraconiques as |signe key|}}
<li class="item list-item flexrow" data-item-id="{{signe._id}}" data-attribute="{{key}}">
<span class="display-label flex-grow"> <a data-item-id="{{signe._id}}">{{signe.name}}</a></span>
<span class="flex-shrink">{{signe.system.difficulte}}</span>
<span class="flex-shrink">{{signe.data.difficulte}}</span>
<div class="item-controls flex-shrink">
<a class="item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
</div>
@ -601,7 +601,7 @@
{{#each hautreve.sortsReserve as |reserve key|}}
<li class="item list-item flexrow" data-item-id="{{reserve._id}}" data-attribute="{{key}}">
<img class="sheet-competence-img" src="{{reserve.sort.img}}" />
<span class="display-label">{{reserve.sort.name}} r{{reserve.sort.system.ptreve_reel}}</span>
<span class="display-label">{{reserve.sort.name}} r{{reserve.sort.data.ptreve_reel}}</span>
<span>{{reserve.coord}} - {{caseTmr-label reserve.coord}}</span>
<div class="item-controls flex-shrink">
<a class="item-delete flex-shrink" title="Supprimer"><i class="fas fa-trash"></i></a>
@ -619,10 +619,10 @@
<li class="item list-item flexrow" data-item-id="{{sort._id}}" data-attribute="{{key}}">
<span class="display-label flex-grow">
<a data-item-id="{{sort._id}}">{{sort.name}}
- {{#if sort.system.caseTMRspeciale}}{{sort.system.caseTMRspeciale}}{{else}}{{upperFirst sort.system.caseTMR}}{{/if}}
- {{#if sort.data.caseTMRspeciale}}{{sort.data.caseTMRspeciale}}{{else}}{{upperFirst sort.data.caseTMR}}{{/if}}
</a>
</span>
<span>{{sort.system.draconic}} / {{sort.system.difficulte}}</span>
<span>{{sort.data.draconic}} / {{sort.data.difficulte}}</span>
<div class="item-controls flex-shrink">
<a class="item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
</div>
@ -634,7 +634,7 @@
<ul class="item-list">
{{#each meditations as |meditation key|}}
<li class="item flexrow" data-item-id="{{meditation._id}}" data-attribute="{{key}}">
<span class="meditation-label flex-grow"><a data-item-id="{{meditation._id}}">{{meditation.name}} - {{meditation.system.competence}}</a></span>
<span class="meditation-label flex-grow"><a data-item-id="{{meditation._id}}">{{meditation.name}} - {{meditation.data.competence}}</a></span>
<div class="item-controls flex-shrink">
<a class="item-edit" title="Editer"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
@ -649,7 +649,7 @@
{{#each hautreve.casesTmr as |casetmr key|}}
<li class="item flexrow" data-item-id="{{casetmr._id}}" data-attribute="{{key}}">
<span class="display-label"><a data-item-id="{{casetmr._id}}">{{casetmr.name}}</a></span>
<span>{{casetmr.system.coord}} - {{caseTmr-label casetmr.system.coord}}</span>
<span>{{casetmr.data.coord}} - {{caseTmr-label casetmr.data.coord}}</span>
<div class="item-controls flex-shrink">
<a class="item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
</div>
@ -676,50 +676,50 @@
<article class="flexrow">
<ul class="item-list alterne-list">
<li class="item flexrow list-item">
<label for="system.race">Race :</label>
<input class="flex-grow" type="text" name="system.race" value="{{system.race}}" data-dtype="String"/>
<label for="data.race">Race :</label>
<input class="flex-grow" type="text" name="data.race" value="{{data.race}}" data-dtype="String"/>
</li>
<li class="item flexrow list-item">
<label for="system.sexe">Sexe :</label>
<input class="flex-grow" type="text" name="system.sexe" value="{{system.sexe}}" data-dtype="String"/>
<label for="data.sexe">Sexe :</label>
<input class="flex-grow" type="text" name="data.sexe" value="{{data.sexe}}" data-dtype="String"/>
</li>
<li class="item flexrow list-item">
<label for="system.age">Age :</label>
<input class="flex-grow" type="text" name="system.age" value="{{system.age}}" data-dtype="String"/>
<label for="data.age">Age :</label>
<input class="flex-grow" type="text" name="data.age" value="{{data.age}}" data-dtype="String"/>
</li>
<li class="item flexrow list-item">
<label for="system.poids">Poids :</label>
<input class="flex-grow" type="text" name="system.poids" value="{{system.poids}}" data-dtype="String"/>
<label for="data.poids">Poids :</label>
<input class="flex-grow" type="text" name="data.poids" value="{{data.poids}}" data-dtype="String"/>
</li>
<li class="item flexrow list-item">
<label for="system.taille">Taille :</label>
<input class="flex-grow" type="text" name="system.taille" value="{{system.taille}}" data-dtype="String"/>
<label for="data.taille">Taille :</label>
<input class="flex-grow" type="text" name="data.taille" value="{{data.taille}}" data-dtype="String"/>
</li>
</ul>
<ul class="item-list alterne-list">
<li class="item flexrow list-item">
<label for="system.main">Main directrice :</label>
<input type="text" name="system.main" value="{{system.main}}" data-dtype="String"/>
<label for="data.main">Main directrice :</label>
<input type="text" name="data.main" value="{{data.main}}" data-dtype="String"/>
</li>
<li class="item flexrow list-item">
<label for="system.heure">Heure de naissance :</label>
<select type="text" name="system.heure" value="{{system.heure}}" data-dtype="String">
{{#select system.heure}}
<label for="data.heure">Heure de naissance :</label>
<select type="text" name="data.heure" value="{{data.heure}}" data-dtype="String">
{{#select data.heure}}
{{>"systems/foundryvtt-reve-de-dragon/templates/heures-select-option.html"}}
{{/select}}
</select>
</li>
<li class="item flexrow list-item">
<label>Beauté :</label>
<input type="text" value="{{system.beaute}}" data-dtype="String" disabled/>
<input type="text" value="{{data.beaute}}" data-dtype="String" disabled/>
</li>
<li class="item flexrow list-item">
<label for="system.cheveux">Cheveux :</label>
<input class="flex-grow" type="text" name="system.cheveux" value="{{system.cheveux}}" data-dtype="String"/>
<label for="data.cheveux">Cheveux :</label>
<input class="flex-grow" type="text" name="data.cheveux" value="{{data.cheveux}}" data-dtype="String"/>
</li>
<li class="item flexrow list-item">
<label for="system.yeux">Yeux :</label>
<input class="flex-grow" type="text" name="system.yeux" value="{{system.yeux}}" data-dtype="String"/>
<label for="data.yeux">Yeux :</label>
<input class="flex-grow" type="text" name="data.yeux" value="{{data.yeux}}" data-dtype="String"/>
</li>
</ul>
</article>
@ -727,16 +727,16 @@
<article class="flexcol">
<h3>Biographie : </h3>
<div class="form-group editor">
{{editor system.biographie target="system.biographie" button=true owner=owner editable=editable}}
{{editor content=data.biographie target="data.biographie" button=true owner=owner editable=editable}}
</div>
<h3>Notes : </h3>
<div class="form-group editor">
{{editor system.notes target="system.notes" button=true owner=owner editable=editable}}
{{editor content=data.notes target="data.notes" button=true owner=owner editable=editable}}
</div>
<h3>Journal d'Experience</h3>
<div class="form-group editor">
<ul class="item-list alterne-list">
{{#each system.experiencelog as |xp key|}}
{{#each data.experiencelog as |xp key|}}
<li class="item flexrow list-item">
<label class="flex-shrink">{{xp.mode}} </label>
<label class="flex-grow">{{xp.valeur}} {{xp.raison}} </label>

View File

@ -27,39 +27,39 @@
<ol class="carac-list alterne-list">
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
<span class="carac-label flexrow" name="categorie">Catégorie</span>
<select name="system.categorie" class="categorie" data-dtype="String">
{{#select system.categorie}}
<select name="data.categorie" class="categorie" data-dtype="String">
{{#select data.categorie}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html"}}
{{/select}}
</select>
</li>
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
<span class="carac-label flexrow" name="categorie">Résistance</span>
<input class="competence-value flexrow" type="text" name="system.resistance" value="{{system.resistance}}" data-dtype="Number" />
<input class="competence-value flexrow" type="text" name="data.resistance" value="{{data.resistance}}" data-dtype="Number" />
</li>
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
<span class="carac-label flexrow" name="categorie">Structure</span>
<input class="competence-value flexrow" type="text" name="system.structure" value="{{system.structure}}" data-dtype="Number" />
<input class="competence-value flexrow" type="text" name="data.structure" value="{{data.structure}}" data-dtype="Number" />
</li>
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
<span class="carac-label flexrow" name="categorie">Vitesse</span>
<input class="competence-value flexrow" type="text" name="system.vitesse" value="{{system.vitesse}}" data-dtype="String" />
<input class="competence-value flexrow" type="text" name="data.vitesse" value="{{data.vitesse}}" data-dtype="String" />
</li>
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
<span class="carac-label flexrow" name="categorie">Bonus</span>
<input class="competence-value flexrow" type="text" name="system.bonus" value="{{system.bonus}}" data-dtype="String" />
<input class="competence-value flexrow" type="text" name="data.bonus" value="{{data.bonus}}" data-dtype="String" />
</li>
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
<span class="carac-label flexrow" name="categorie">Manoeuvrabilité</span>
<input class="competence-value flexrow" type="text" name="system.manoeuvrabilite" value="{{system.manoeuvrabilite}}" data-dtype="String" />
<input class="competence-value flexrow" type="text" name="data.manoeuvrabilite" value="{{data.manoeuvrabilite}}" data-dtype="String" />
</li>
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
<span class="carac-label flexrow" name="categorie">Equipage</span>
<input class="competence-value flexrow" type="text" name="system.equipage" value="{{system.equipage}}" data-dtype="Number" />
<input class="competence-value flexrow" type="text" name="data.equipage" value="{{data.equipage}}" data-dtype="Number" />
</li>
<li class="caracteristique flexrow list-item" data-attribute="{{key}}">
<span class="carac-label flexrow" name="categorie">Capacité d'Encombrement</span>
<input class="competence-value flexrow" type="text" name="system.capacite_encombrement" value="{{system.capacite_encombrement}}" data-dtype="Number" />
<input class="competence-value flexrow" type="text" name="data.capacite_encombrement" value="{{data.capacite_encombrement}}" data-dtype="Number" />
</li>
</ol>
</div>
@ -75,7 +75,7 @@
{{!-- Biography Tab --}}
<div class="tab description" data-group="primary" data-tab="description">
<div class="form-group editor">
{{editor content=system.description target="system.description" button=true owner=owner editable=editable}}
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
</div>
{{>"systems/foundryvtt-reve-de-dragon/templates/actor-sheet-editor-notes-mj.html"}}
</div>

View File

@ -6,4 +6,4 @@
{{#if vendeur}}à {{vendeur.name}}{{/if}}:
{{quantiteTotal}} {{item.name}} pour {{prixTotal}} sols.
</p>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" item.system}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" item.data}}

View File

@ -1,16 +1,16 @@
<img class="chat-icon" src="{{img}}" alt="potion de repos" />
<h4>
{{alias}} a bu une <strong>{{name}}{{#if system.magique}} enchantée{{/if}}</strong>
{{alias}} a bu une <strong>{{name}}{{#if data.magique}} enchantée{{/if}}</strong>
</h4>
<hr>
<div>
{{#if system.magique}}
{{#if data.magique}}
Le Jet de Résistance est {{#if rolled.isSuccess}}réussi{{else}}échoué{{/if}}.
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
{{/if}}
<br>Les effets de la potions sont à gérer manuellement, en fonction de sa nature
{{#if system.magique}}
{{#if rolled.isEchec}}et de son enchantement ({{system.pr}} Points de Rêve)
{{#if data.magique}}
{{#if rolled.isEchec}}et de son enchantement ({{data.pr}} Points de Rêve)
{{else}}son enchantement n'a pas d'effet
{{/if}}
{{/if}}.

View File

@ -1,27 +1,27 @@
<img class="chat-icon" src="{{img}}" alt="potion de repos" />
<h4>
{{alias}} a bu une <strong>{{name}}{{#if system.magique}} enchantée{{/if}}</strong>
{{alias}} a bu une <strong>{{name}}{{#if data.magique}} enchantée{{/if}}</strong>
</h4>
<hr>
<div>
{{#if system.magique}}
{{#if data.magique}}
Le Jet de Résistance est {{#if rolled.isSuccess}}réussi{{else}}échoué{{/if}}.
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
{{#if rolled.isEchec}}
<br>La potion fait effet !
{{alias}} a perdu 1 point de rêve et s'endort pour {{guerisonDureeValue}} {{guerisonDureeUnite}} et
se récupère {{caseFatigueReel}} cases de fatigue.<br>
{{#if system.reposalchimique}}
{{#if data.reposalchimique}}
De plus, la potion étant alchimique, {{alias}} est en aphasie pendant cette durée.
{{#if aphasiePermanente}}
Malheureusement, l'aphasie est permanente tant que {{alias}} ne réussit pas un jet de VOLONTE à 0 à Chateau Dormant (le moral compte).
{{/if}}
{{/if}}
{{else}}
<br>La potion ne fait pas effet ! Elle vous octroie tout de même un bonus de {{system.herbebonus}} segments de fatigue récupérés en plus à la fin de Chateau Dormant (à gérer manuellement).
<br>La potion ne fait pas effet ! Elle vous octroie tout de même un bonus de {{data.herbebonus}} segments de fatigue récupérés en plus à la fin de Chateau Dormant (à gérer manuellement).
{{/if}}
{{else}}
Une fois consommée (vers fin Lyre), elle vous octroie un bonus de {{system.herbebonus}} segments de fatigue récupérés en plus à la fin de Chateau Dormant (à gérer manuellement).
Une fois consommée (vers fin Lyre), elle vous octroie un bonus de {{data.herbebonus}} segments de fatigue récupérés en plus à la fin de Chateau Dormant (à gérer manuellement).
{{/if}}
<br>La potion a été supprimée de l'équipement.
</div>

View File

@ -1,10 +1,10 @@
<img class="chat-icon" src="{{img}}" alt="potion de soin" />
<h4>
{{alias}} a bu une <strong>{{name}}{{#if system.magique}} enchantée{{/if}}</strong>
{{alias}} a bu une <strong>{{name}}{{#if data.magique}} enchantée{{/if}}</strong>
</h4>
<hr>
<div>
{{#if system.magique}}
{{#if data.magique}}
Le Jet de Résistance est {{#if rolled.isSuccess}}réussi{{else}}échoué{{/if}}.
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
{{#if rolled.isEchec}}
@ -16,10 +16,10 @@
{{/each}}
</ul>
{{else}}
<br>La potion ne fait pas effet ! Lors de votre prochain jet de récupération à Chateau Dormant, vous bénéficierez d'un bonus de {{system.herbebonus}} (appliqué automatiquement).
<br>La potion ne fait pas effet ! Lors de votre prochain jet de récupération à Chateau Dormant, vous bénéficierez d'un bonus de {{data.herbebonus}} (appliqué automatiquement).
{{/if}}
{{else}}
Lors de votre prochain jet de récupération à Chateau Dormant, vous bénéficierez d'un bonus de {{system.herbebonus}} (appliqué automatiquement).
Lors de votre prochain jet de récupération à Chateau Dormant, vous bénéficierez d'un bonus de {{data.herbebonus}} (appliqué automatiquement).
{{/if}}
<br>La potion a été supprimée de l'équipement.
</div>

View File

@ -8,7 +8,7 @@
</a>
<br>
{{/unless}}
{{#if (gt attacker.system.compteurs.destinee.value 0)}}
{{#if (gt attacker.data.compteurs.destinee.value 0)}}
<a class='chat-card-button' id='appel-destinee-attaque' data-attackerId='{{attackerId}}'
data-defenderTokenId='{{defenderTokenId}}'>Utiliser la destinée</a>
</a>

View File

@ -26,7 +26,7 @@
<br>
{{/if}}
{{#if (eq defender.type 'personnage')}}
{{#if (gt defender.system.compteurs.destinee.value 0)}}
{{#if (gt defender.data.compteurs.destinee.value 0)}}
<a class='chat-card-button' id='appel-destinee-defense' data-attackerId='{{attackerId}}'
data-defenderTokenId='{{defenderTokenId}}'>Utiliser la destinée</a>
</a>
@ -38,14 +38,14 @@
{{#each armes as |arme key|}}
<a class='chat-card-button' id='parer-button' data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderTokenId}}'
data-armeid='{{arme._id}}'>
Parer avec {{arme.name}} à {{../diffLibre }}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}}
Parer avec {{arme.name}} à {{../diffLibre }}{{#if arme.data.nbUsage}} (Utilisations : {{arme.data.nbUsage}}){{/if}}
</a>
<br>
{{/each}}
{{#if mainsNues}}
<a class='chat-card-button' id='parer-button' data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderTokenId}}'
data-armeid='{{arme._id}}' data-competence='{{arme.system.competence}}'>
Parer à mains nues à {{diffLibre}}{{#if arme.system.nbUsage}} (Utilisations : {{arme.system.nbUsage}}){{/if}}
data-armeid='{{arme._id}}' data-competence='{{arme.data.competence}}'>
Parer à mains nues à {{diffLibre}}{{#if arme.data.nbUsage}} (Utilisations : {{arme.data.nbUsage}}){{/if}}
</a>
<br>
{{/if}}

View File

@ -1,6 +1,6 @@
<img class="chat-icon" src="{{herbe.img}}" alt="fabrication" />
<h4>
{{alias}} a fabriqué une potion de {{herbe.system.categorie}} de {{herbe.name}}, avec {{herbe.nbBrins}} brins.
{{alias}} a fabriqué une potion de {{herbe.data.categorie}} de {{herbe.name}}, avec {{herbe.nbBrins}} brins.
</h4>
<hr>
<div>

View File

@ -1,6 +1,6 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.data.competence}}" />
<h4>
{{alias}} tente de chanter : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} tente de chanter : {{oeuvre.name}} (niveau {{oeuvre.data.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
@ -12,4 +12,4 @@
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.system}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.data}}

View File

@ -1,6 +1,6 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.data.competence}}" />
<h4>
{{alias}} tente de danser : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} tente de danser : {{oeuvre.name}} (niveau {{oeuvre.data.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
@ -12,4 +12,4 @@
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.system}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.data}}

View File

@ -1,4 +1,4 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.data.competence}}" />
<h4>
{{alias}} joue à : {{oeuvre.name}}
</h4>
@ -12,4 +12,4 @@
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.system}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.data}}

View File

@ -6,7 +6,7 @@
<hr>
<div>
{{#if rolled.isSuccess}}
{{alias}} aperçoit un signe draconique éphémère, qu'il faut aller lire en <strong>{{typeTmr-name meditation.system.tmr}}</strong>.
{{alias}} aperçoit un signe draconique éphémère, qu'il faut aller lire en <strong>{{typeTmr-name meditation.data.tmr}}</strong>.
{{else}}
La méditation de {{alias}} ne porte pas ses fruits, il ne distingue aucun signe Draconique.
{{/if}}

View File

@ -1,6 +1,6 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.data.competence}}" />
<h4>
{{alias}} tente de jouer le morceau : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} tente de jouer le morceau : {{oeuvre.name}} (niveau {{oeuvre.data.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
@ -12,4 +12,4 @@
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.system}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.data}}

View File

@ -1,8 +1,8 @@
<h4><img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<h4><img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.data.competence}}" />
{{alias}} tente d'interpréter {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} tente d'interpréter {{oeuvre.name}} (niveau {{oeuvre.data.niveau}})
</h4>
<br>{{upperFirst oeuvre.system.default_carac}} / {{oeuvre.system.competence}}
<br>{{upperFirst oeuvre.data.default_carac}} / {{oeuvre.data.competence}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
<div>
@ -13,4 +13,4 @@
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.system}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.data}}

View File

@ -17,7 +17,7 @@
<a class='defense-possession chat-card-button'
data-attackerId='{{attacker.id}}'
data-defenderId='{{defender.id}}'
data-possessionId='{{possession.system.possessionid}}'>
data-possessionId='{{possession.data.possessionid}}'>
{{#if isECNIDefender}}
Résister à la conjuration
{{else}}
@ -39,9 +39,9 @@
<br>Points de Conjuration: {{possession.ptsConjuration}}
{{#if possession.isPosseder}}
<br><strong>Vous êtes été possédé par {{possession.system.typepossession}} ! La possession en cours a été supprimée.</strong>
<br><strong>Vous êtes été possédé par {{possession.data.typepossession}} ! La possession en cours a été supprimée.</strong>
{{/if}}
{{#if possession.isConjurer}}
<br><strong>Vous avez conjuré {{possession.system.typepossession}} ! La possession en cours a été supprimée.</strong>
<br><strong>Vous avez conjuré {{possession.data.typepossession}} ! La possession en cours a été supprimée.</strong>
{{/if}}
</div>

View File

@ -1,12 +1,12 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.data.competence}}" />
<h4>
{{alias}} tente de cuisiner la recette : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} tente de cuisiner la recette : {{oeuvre.name}} (niveau {{oeuvre.data.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
<span>
<img class="chat-icon" src="{{platCuisine.img}}" alt="{{platCuisine.name}}" />
<br>{{alias}} a préparé {{platCuisine.system.quantite}} portions de {{platCuisine.name}}
<br>{{alias}} a préparé {{platCuisine.data.quantite}} portions de {{platCuisine.name}}
{{~#if ajouterEquipement}}, qui ont été ajoutées à son équipement{{/if}}.
{{#if rolled.isSuccess}}
Il a réussi la recette, pour un plat de qualité {{qualiteFinale}}
@ -21,4 +21,4 @@
{{/if}}
</span>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.system}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-description.html" oeuvre.data}}

View File

@ -15,7 +15,7 @@
{{alias}} ne parvient pas à vaincre le Rêve de Dragon, et prend un violent coup de queue.
Il subit {{#if rolled.isETotal}}deux queues{{else}}une queue{{/if}} de dragon!
{{#each queues as | queue key|}}
<br>{{queue.name}}: {{{queue.system.description}}}
<br>{{queue.name}}: {{{queue.data.description}}}
{{/each}}
{{/if}}
</span>

View File

@ -1,10 +1,10 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{competence.name}}" />
<h4>
{{alias}} {{#if isSortReserve}}met en réserve{{else}}lance{{/if}}
le {{#if selectedSort.system.isrituel}}rituel{{else}}sort{{/if}}
le {{#if selectedSort.data.isrituel}}rituel{{else}}sort{{/if}}
{{selectedSort.name}}
</h4>
<div>Pour {{selectedSort.system.ptreve_reel}} point{{~#if (gt selectedSort.system.ptreve_reel 1)}}s{{/if}} de rêve en {{tmr.label}} ({{tmr.coord}}).
<div>Pour {{selectedSort.data.ptreve_reel}} point{{~#if (gt selectedSort.data.ptreve_reel 1)}}s{{/if}} de rêve en {{tmr.label}} ({{tmr.coord}}).
{{#if show.reveInsuffisant}}
<span>Pas assez de rêve!</span>
{{/if}}
@ -16,7 +16,7 @@
{{#if rolled.isETotal}}Echec TOTAL
{{else if rolled.isEchec}}Echec
{{else}}Réussite{{/if}}
du {{#if selectedSort.system.isrituel}}rituel{{else}}sort{{/if}},
du {{#if selectedSort.data.isrituel}}rituel{{else}}sort{{/if}},
{{#if (eq depenseReve 0)}}pas de dépense de rêve
{{else if (eq depenseReve 1)}}1 point de rêve a été dépensé
{{else}}{{depenseReve}} points de rêve ont été dépensés
@ -25,5 +25,5 @@
</div>
<hr>
<div class="poesie-extrait poesie-overflow">
{{{selectedSort.system.description}}}
{{{selectedSort.data.description}}}
</div>

View File

@ -8,11 +8,11 @@
<div>
{{alias}} a obtenu {{rolled.ptTache}} point{{~#unless (eq rolled.ptTache 1)}}s{{/unless}} de tâche,
son avancement est de
<span class="rdd-roll-{{#if (gt tache.system.points_de_tache_courant 0)}}norm{{else}}etotal{{/if}}">{{tache.system.points_de_tache_courant}}
{{#unless tache.system.cacher_points_de_tache}} sur {{tache.system.points_de_tache}}{{/unless}}</span>
point{{~#unless (eq tache.system.points_de_tache_courant 1)}}s{{/unless}} de tâche
({{~#unless (eq tache.system.tentatives 1)}}{{tache.system.tentatives}} tentatives{{else}}première tentative{{/unless~}}).
{{#if (and tache.system.fatigue appliquerFatigue)}}<br><span>Il s'est fatigué de {{tache.system.fatigue}} case{{~#if (gt tache.system.fatigue 1)}}s{{/if}}.</span>{{/if}}
<span class="rdd-roll-{{#if (gt tache.data.points_de_tache_courant 0)}}norm{{else}}etotal{{/if}}">{{tache.data.points_de_tache_courant}}
{{#unless tache.data.cacher_points_de_tache}} sur {{tache.data.points_de_tache}}{{/unless}}</span>
point{{~#unless (eq tache.data.points_de_tache_courant 1)}}s{{/unless}} de tâche
({{~#unless (eq tache.data.tentatives 1)}}{{tache.data.tentatives}} tentatives{{else}}première tentative{{/unless~}}).
{{#if (and tache.data.fatigue appliquerFatigue)}}<br><span>Il s'est fatigué de {{tache.data.fatigue}} case{{~#if (gt tache.data.fatigue 1)}}s{{/if}}.</span>{{/if}}
{{#if rolled.isETotal}}<br><span>Son échec total augmente de 1 la difficulté de la tâche!</span>{{/if~}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>

View File

@ -3,5 +3,5 @@
</h4>
<p>Pour le lire ce signe draconique, {{alias}} doit se rendre dans les
Terres Médianes du Rêve et trouvez une case de résonnance.
{{#if signe.system.ephemere}}C'est un signe éphémère, qui ne restera présent que pour {{signe.system.duree}}{{/if}}
{{#if signe.data.ephemere}}C'est un signe éphémère, qui ne restera présent que pour {{signe.data.duree}}{{/if}}
</p>

View File

@ -3,7 +3,7 @@
{{#if item.img}}
<img class="chat-icon" src="{{item.img}}" title="{{item.name}}" alt="{{item.name}}" />
{{/if}}
<div class="poesie-extrait poesie-overflow card-content">{{{item.system.description}}}</div>
<div class="poesie-extrait poesie-overflow card-content">{{{item.data.description}}}</div>
<p>
{{#each properties as |property p|}}
<span>{{{property}}}</span><br>

View File

@ -8,27 +8,27 @@
</h4>
</div>
<div class="form-group">
<label for="signe.system.difficulte">Difficulte</label>
<input type="number" name="signe.system.difficulte" value="{{signe.system.difficulte}}" data-dtype="Number" />
<label for="signe.data.difficulte">Difficulte</label>
<input type="number" name="signe.data.difficulte" value="{{signe.data.difficulte}}" data-dtype="Number" />
</div>
<div class="form-group">
<label for="signe.system.valeur.norm">Expérience en sorts</label>
<label for="signe.data.valeur.norm">Expérience en sorts</label>
<div class="flexrow">
<input class="signe-xp-sort" type="number" name="signe.system.valeur.norm" data-typereussite="norm"
value="{{signe.system.valeur.norm}}" min="1" max="100" data-dtype="Number" />
<input class="signe-xp-sort" type="number" name="signe.data.valeur.norm" data-typereussite="norm"
value="{{signe.data.valeur.norm}}" min="1" max="100" data-dtype="Number" />
<span>Sign.</span>
<input class="signe-xp-sort" type="number" name="signe.system.valeur.sign" data-typereussite="sign"
value="{{signe.system.valeur.sign}}" min="1" max="100" data-dtype="Number" />
<input class="signe-xp-sort" type="number" name="signe.data.valeur.sign" data-typereussite="sign"
value="{{signe.data.valeur.sign}}" min="1" max="100" data-dtype="Number" />
<span>Part.</span>
<input class="signe-xp-sort" type="number" name="signe.system.valeur.part" data-typereussite="part"
value="{{signe.system.valeur.part}}" min="1" max="100" data-dtype="Number" />
<input class="signe-xp-sort" type="number" name="signe.data.valeur.part" data-typereussite="part"
value="{{signe.data.valeur.part}}" min="1" max="100" data-dtype="Number" />
</div>
</div>
<div class="form-group flexrow">
<label for="signe.system.ephemere">Ephémère</label>
<input class="flex-shrink" type="checkbox" name="signe.system.ephemere" {{#if signe.system.ephemere}}checked{{/if}} />
<label for="signe.data.ephemere">Ephémère</label>
<input class="flex-shrink" type="checkbox" name="signe.data.ephemere" {{#if signe.data.ephemere}}checked{{/if}} />
<span>
<input type="text" name="signe.system.duree" value="{{signe.system.duree}}" data-dtype="String" />
<input type="text" name="signe.data.duree" value="{{signe.data.duree}}" data-dtype="String" />
</span>
</div>
<div class="form-group">

View File

@ -1,6 +1,6 @@
<form class="skill-roll-dialog">
<div class="form-group">
<label>Fabriquer une potion de {{system.categorie}} de {{name}}</label>
<label>Fabriquer une potion de {{data.categorie}} de {{name}}</label>
</div>
<div class="form-group">

Some files were not shown because too many files have changed in this diff Show More