Compare commits
163 Commits
foundryvtt
...
foundryvtt
Author | SHA1 | Date | |
---|---|---|---|
f08c8f93da | |||
d28362bf14 | |||
e506382d18 | |||
c1cecc76b3 | |||
f2a3e1db45 | |||
b69359a47d | |||
fe6c2e2ff2 | |||
9bd13a6021 | |||
a29630f9a2 | |||
c7fd9f7596 | |||
7b18fd25c3 | |||
5c256e2c49 | |||
1c475348d5 | |||
de5d32f88f | |||
76a02d60ca | |||
724c556b9e | |||
7dfba94a11 | |||
928c7bbcfe | |||
222a06a978 | |||
b4edaf8584 | |||
3c062afd56 | |||
6de4fff403 | |||
3543f081b2 | |||
56f14e12a2 | |||
e226af5ac5 | |||
d8be37a2ec | |||
ba2d9de7b6 | |||
6b8fb3267a | |||
05d6f64a31 | |||
c0570e58b4 | |||
8389d578bc | |||
f05ef79b97 | |||
d2a8bfae4f | |||
d54834fa71 | |||
c898bf5212 | |||
a118dc7334 | |||
46401e5d63 | |||
7eb1d9f838 | |||
1d8f4ebb88 | |||
145a92f462 | |||
5148d02314 | |||
000c89b11a | |||
5d4a18aac5 | |||
34b5df637f | |||
22572ca98c | |||
a6a1c1009e | |||
288cf9162c | |||
4b1381e535 | |||
78336a3f45 | |||
3001ae44de | |||
a43ceb3188 | |||
9e95a44efd | |||
179ea0c85b | |||
3821b5bea1 | |||
2739c650d9 | |||
b101d58bee | |||
0e3d721fc7 | |||
e1e45a83be | |||
3b14e54829 | |||
615a3f1315 | |||
ca72d088cc | |||
ac89b948ca | |||
f22c4d2ec8 | |||
ffd80394d3 | |||
0959d1b18e | |||
24e58abfcc | |||
7d292c009d | |||
4bf075786c | |||
a2a04ade4c | |||
2db6895c76 | |||
e46f35ef92 | |||
9e050d3e12 | |||
81492f2857 | |||
959e751e48 | |||
b6a124b57d | |||
db2ca945a8 | |||
667d764db1 | |||
4273f5f48f | |||
6c4a8eb70f | |||
eb029e8d66 | |||
9ee14b3b56 | |||
3203fae111 | |||
755301275b | |||
f6d5dc9d7c | |||
5e9b47af1f | |||
18dfb36a78 | |||
febccd508f | |||
b147f8937b | |||
55a93b317a | |||
02a630152d | |||
ad8ac0de77 | |||
dceb6f026f | |||
ad37ee1b8e | |||
4d40e2fe59 | |||
9d7e57d9fb | |||
717029e572 | |||
d6f8976298 | |||
92e93cbbea | |||
994eaad9a9 | |||
cfed7e2afa | |||
436f9e6fa4 | |||
18a50197cd | |||
b6910612f8 | |||
4ba1ec8a2e | |||
75a0f7c322 | |||
e2a9f55740 | |||
1e0788cde8 | |||
c10195f753 | |||
4d7317b964 | |||
7b1fa009bb | |||
71bb8a14e1 | |||
5444bc7fd8 | |||
debaf1da34 | |||
69e2ab9000 | |||
24218ed062 | |||
da4e18dc3c | |||
154a9b7a37 | |||
fb8189606b | |||
cfbfad27bd | |||
f541849306 | |||
d2d1891838 | |||
5580b6d59c | |||
40c45c30de | |||
1b6c5256cc | |||
c0e6759164 | |||
a096590a07 | |||
9883048fb5 | |||
7bec42c4cf | |||
6708dc0da9 | |||
96c2da0d05 | |||
2b19250e8b | |||
957eabcac7 | |||
285937c201 | |||
93965ce91a | |||
18aba9adff | |||
0a5662ff71 | |||
bf98e4eae2 | |||
e32a1d25f6 | |||
327943c4aa | |||
de56fa909a | |||
2aa62cffe9 | |||
c57f140c54 | |||
9cf14f8b75 | |||
b8e7b21e14 | |||
c1d02d9fda | |||
23af30a538 | |||
4e1b663dec | |||
c9d98c57da | |||
0aef139cf8 | |||
9c85293714 | |||
ab1c04ae17 | |||
a585e0faba | |||
50c730ba72 | |||
928a60f092 | |||
e5c2f52b0e | |||
f9391523f8 | |||
55434762f4 | |||
5e6ffc7846 | |||
3344e20936 | |||
5a66e4e741 | |||
d329724d63 | |||
8a5405c9f5 | |||
ea992aae46 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -8,3 +8,7 @@ todo.md
|
||||
/jsconfig.json
|
||||
/package.json
|
||||
/package-lock.json
|
||||
/packs/*/
|
||||
/packs/*/CURRENT
|
||||
/packs/*/LOG
|
||||
/packs/*/LOCK
|
||||
|
81
changelog.md
81
changelog.md
@ -1,10 +1,77 @@
|
||||
==================================================================
|
||||
v0.9.2 - 05/09/2020
|
||||
# v11.0
|
||||
## v11.0.24 - les couleurs de Khrachtchoum
|
||||
- nouvelle carte des TMRs
|
||||
|
||||
Erreur de calcul sur points de vie
|
||||
Gestion différente des compétences "troncs"
|
||||
## v11.0.23 - la lumière de Khrachtchoum
|
||||
- ajustement automatique de la luminosité selon l'heure pour les scènes:
|
||||
- avec une vision des tokens (sinon: ce n'est pas une scène de carte pour tokens)
|
||||
- avec illumination globale (correspondant à une illumination extérieure)
|
||||
- quand lampe "allumée" dans la fenêtre du calendrier
|
||||
|
||||
==================================================================
|
||||
v0.9.1 - 03/09/2020
|
||||
## v11.0.22 - les automatismes de Khrachtchoum le Problémeux
|
||||
- Macro pour attaquer avec les compétences de créatures
|
||||
|
||||
## v11.0.20
|
||||
- Macro pour attaquer avec les armes des personnages
|
||||
|
||||
## v11.0.17
|
||||
- Fix: les actions de commerce ne s'appliquait pas bien aux personnages des tokens non liés
|
||||
|
||||
## v11.0.15 - L'apprentissage de Khrachtchoum
|
||||
- Fix: l'expérience ne s'appliquait plus sur certaines réussites particulières (régression depuis la 11.0.7)
|
||||
|
||||
## v11.0.14 - Les pincettes de Khrachtchoum le Problémeux
|
||||
- Correction du calcul de la place restante lors de l'ajout dans un conteneur
|
||||
|
||||
## v11.0.13 - La multiplication de l'eau de Khrachtchoum le Problémeux
|
||||
- Correction de la vente depuis un commerce ayant des quantités illimitées
|
||||
|
||||
## v11.0.12 - Les poids de la mesure de Khrachtchoum le Problémeux
|
||||
- Correction des malus de surencombrement
|
||||
- Le malus armure est correctement affiché dans l'onglet des caractéristiques
|
||||
- Correction d'orthographe et amélioration des messages des oeuvres d'art
|
||||
|
||||
## v11.0.11 - Les bleus de Khrachtchoum le Problémeux
|
||||
- si le gardien configure le sommeil, les joueurs sont notifiés que chateau dormant vient de passer
|
||||
- possibilité de créer des armes et des compétences de créatures non-mortelles.
|
||||
|
||||
## v11.0.10 - Les Songes de Khrachtchoum le Problémeux
|
||||
- on peut de nouveau se déplacer dans les TMRs d'un clic sur la case à atteindre
|
||||
- Lire un livre depuis l'inventaire permet de nouveau de faire un jet de la tâche
|
||||
créée au lieu de créer toujours une nouvelle tâche
|
||||
- La sélection des TMR pour la création de signes draconiques ne cause plus d'erreurs
|
||||
- la récupération d'endurance en cas d'insomnie est limitée à la moitié
|
||||
- le résultat du sommeil lors d'un rêve de dragon à la première heure s'affiche normalement
|
||||
- lorsque le gardien gère la durée des nuits, en cas de rêve de dragon,
|
||||
les heures dormies sont déduites des heures restant à dormir
|
||||
|
||||
## v11.0.9 - Les Souvenirs de Khrachtchoum le Problémeux
|
||||
- mode de saisie de l'archétype en vue détaillée
|
||||
- création une nouvelle incarnation depuis l'archétype
|
||||
- réorganisation de la fenêtre de sélection des règles optionnelles
|
||||
- correction de l'affichage du type dans les fenêtres d'objets
|
||||
|
||||
## v11.0.8 - la poigne de Sémolosse
|
||||
- lien vers le changelog
|
||||
- organisation des compendiums du système
|
||||
- correction de l'empoignade
|
||||
- les items d'empoignade sont ajoutés par le MJ quand nécessaire
|
||||
- seul le joueur propriétaire du personnage peut effectuer ses choix et actions d'empoignade
|
||||
- les caractéristiques du défenseur sont utilisées pour la défense
|
||||
- la difficulté d'attaque est imposée au défenseur
|
||||
- les attaques particulières sont en finesse (p133)
|
||||
- on peut entraîner au sol dès 2 points d'empoignade
|
||||
- les actions liée à l'immobilisation sont proposées en fin de round
|
||||
|
||||
# v11.0.7
|
||||
|
||||
- les créatures ont maintenant le droit d'avoir des compétences de tir, lancer, mêlée, armes naturelles, parade.
|
||||
- les créatures armées utilisent la bonne phase d'initiative
|
||||
- correction des possessions
|
||||
- la difficulté de la défense est imposée par l'attaque
|
||||
- une attaque particulière de possession est en finesse
|
||||
- le rêve actuel des personnages est bien utilisé
|
||||
- correction des achats par le MJ sans acteur sélectionné
|
||||
|
||||
Cf branche v10 pour l'historique des versions 10
|
||||
|
||||
Initial official release
|
||||
|
102
lang/fr.json
102
lang/fr.json
@ -1,54 +1,56 @@
|
||||
{
|
||||
"ACTOR": {
|
||||
"TypePersonnage": "Personnage",
|
||||
"TypeCreature": "Créature",
|
||||
"TypeEntite": "Entité de cauchemar",
|
||||
"TypeCommerce": "Commerce",
|
||||
"TypeVehicule": "Véhicule"
|
||||
},
|
||||
"ITEM": {
|
||||
"TypeArme": "Arme",
|
||||
"TypeArmure": "Armure",
|
||||
"TypeBlessure": "Blessure",
|
||||
"TypeCasetmr": "TMR spéciale",
|
||||
"TypeChant": "Chant",
|
||||
"TypeCompetence": "Compétence",
|
||||
"TypeCompetencecreature": "Compétence de créature",
|
||||
"TypeConteneur": "Conteneur",
|
||||
"TypeDanse": "Danse",
|
||||
"TypeExtraitpoetique": "Extrait poetique",
|
||||
"TypeFaune": "Faune",
|
||||
"TypeGemme": "Gemme",
|
||||
"TypeHerbe": "Herbe",
|
||||
"TypeIngredient": "Ingrédient",
|
||||
"TypeJeu": "Jeu",
|
||||
"TypeLivre": "Livre",
|
||||
"TypeMaladie": "Maladie",
|
||||
"TypeMeditation": "Méditation",
|
||||
"TypeMonnaie": "Monnaie",
|
||||
"TypeMunition": "Munition",
|
||||
"TypeMusique": "Musique",
|
||||
"TypeNombreastral": "Nombre astral",
|
||||
"TypeNourritureboisson": "Nourriture & boisson",
|
||||
"TypeObjet": "Objet",
|
||||
"TypeOeuvre": "Oeuvre",
|
||||
"TypeOmbre": "Ombre de Thanatos",
|
||||
"TypePlante": "Plante",
|
||||
"TypePoison": "Poison",
|
||||
"TypePossession": "Possession",
|
||||
"TypePotion": "Potion",
|
||||
"TypeQueue": "Queue de Dragon",
|
||||
"TypeRecettealchimique": "Recette alchimique",
|
||||
"TypeRecettecuisine": "Recette de cuisine",
|
||||
"TypeRencontre": "Rencontre TMR",
|
||||
"TypeService": "Service",
|
||||
"TypeSignedraconique": "Signe draconique",
|
||||
"TypeSort": "Sort",
|
||||
"TypeSortreserve": "Sort en réserve",
|
||||
"TypeSouffle": "Souffle de Dragon",
|
||||
"TypeTache": "Tâche",
|
||||
"TypeTarot": "Carte de tarot",
|
||||
"TypeTete": "Tête de Dragon"
|
||||
"TYPES": {
|
||||
"Actor": {
|
||||
"Personnage": "Personnage",
|
||||
"Creature": "Créature",
|
||||
"Entite": "Entité de cauchemar",
|
||||
"Commerce": "Commerce",
|
||||
"Vehicule": "Véhicule"
|
||||
},
|
||||
"Item": {
|
||||
"Arme": "Arme",
|
||||
"Armure": "Armure",
|
||||
"Blessure": "Blessure",
|
||||
"Casetmr": "TMR spéciale",
|
||||
"Chant": "Chant",
|
||||
"Competence": "Compétence",
|
||||
"Competencecreature": "Compétence de créature",
|
||||
"Conteneur": "Conteneur",
|
||||
"Danse": "Danse",
|
||||
"Extraitpoetique": "Extrait poetique",
|
||||
"Faune": "Faune",
|
||||
"Gemme": "Gemme",
|
||||
"Herbe": "Herbe",
|
||||
"Ingredient": "Ingrédient",
|
||||
"Jeu": "Jeu",
|
||||
"Livre": "Livre",
|
||||
"Maladie": "Maladie",
|
||||
"Meditation": "Méditation",
|
||||
"Monnaie": "Monnaie",
|
||||
"Munition": "Munition",
|
||||
"Musique": "Musique",
|
||||
"Nombreastral": "Nombre astral",
|
||||
"Nourritureboisson": "Nourriture & boisson",
|
||||
"Objet": "Objet",
|
||||
"Oeuvre": "Oeuvre",
|
||||
"Ombre": "Ombre de Thanatos",
|
||||
"Plante": "Plante",
|
||||
"Poison": "Poison",
|
||||
"Possession": "Possession",
|
||||
"Potion": "Potion",
|
||||
"Queue": "Queue de Dragon",
|
||||
"Recettealchimique": "Recette alchimique",
|
||||
"Recettecuisine": "Recette de cuisine",
|
||||
"Rencontre": "Rencontre TMR",
|
||||
"Service": "Service",
|
||||
"Signedraconique": "Signe draconique",
|
||||
"Sort": "Sort",
|
||||
"Sortreserve": "Sort en réserve",
|
||||
"Souffle": "Souffle de Dragon",
|
||||
"Tache": "Tâche",
|
||||
"Tarot": "Carte de tarot",
|
||||
"Tete": "Tête de Dragon"
|
||||
}
|
||||
},
|
||||
"EFFECT": {
|
||||
"StatusStunned": "Sonné",
|
||||
|
@ -1,4 +1,6 @@
|
||||
import { RdDActorSheet } from "./actor-sheet.js";
|
||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
export class RdDActorEntiteSheet extends RdDActorSheet {
|
||||
|
||||
@ -13,6 +15,12 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
|
||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
||||
});
|
||||
}
|
||||
async getData() {
|
||||
let formData = await super.getData();
|
||||
formData.resonances = this.actor.system.sante.resonnance.actors.map(actorId => game.actors.get(actorId))
|
||||
.map(actor => { return { id: actor.id, name: actor.name, img: actor.img } })
|
||||
return formData
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
@ -35,6 +43,23 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
|
||||
let compName = event.currentTarget.attributes.compname.value;
|
||||
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
|
||||
});
|
||||
this.html.find('.resonance-delete').click(async event => {
|
||||
const li = RdDSheetUtility.getEventElement(event);
|
||||
const actorId = li.data("actor-id");
|
||||
if (actorId) {
|
||||
const actorResonance = game.actors.get(actorId);
|
||||
RdDUtility.confirmerSuppressionSubacteur(this, actorResonance, li, () => {
|
||||
console.log('Delete : ', actorId);
|
||||
this.removeSubacteur(actorId);
|
||||
RdDUtility.slideOnDelete(this, li);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async removeSubacteur(actorId) {
|
||||
let newResonances = this.actor.system.sante.resonnance.actors.filter(id => id != actorId);
|
||||
await this.actor.update({ 'system.sante.resonnance.actors': newResonances }, { renderSheet: false });
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,13 +7,14 @@ import { Misc } from "./misc.js";
|
||||
import { RdDCombatManager } from "./rdd-combat.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { DialogSplitItem } from "./dialog-split-item.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||
import { STATUSES } from "./settings/status-effects.js";
|
||||
import { MAINS_DIRECTRICES } from "./actor.js";
|
||||
import { RdDBaseActorSheet } from "./actor/base-actor-sheet.js";
|
||||
import { RdDItem } from "./item.js";
|
||||
import { RdDItemBlessure } from "./item/blessure.js";
|
||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/**
|
||||
@ -32,7 +33,8 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
|
||||
showCompNiveauBase: false,
|
||||
vueDetaillee: false
|
||||
vueDetaillee: false,
|
||||
vueArchetype: false,
|
||||
});
|
||||
}
|
||||
|
||||
@ -55,6 +57,7 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
|
||||
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
|
||||
surEncombrementMessage: this.actor.getMessageSurEncombrement(),
|
||||
malusArmure: this.actor.getMalusArmure()
|
||||
})
|
||||
|
||||
this.timerRecherche = undefined;
|
||||
@ -83,6 +86,7 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
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);
|
||||
formData.empoignades = this.actor.getEmpoignades();
|
||||
|
||||
this.armesList = formData.combat;
|
||||
|
||||
@ -112,19 +116,26 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue"));
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor));
|
||||
this.html.find('.item-action').click(async event => {
|
||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||
item?.actionPrincipale(this.actor, async () => this.render())
|
||||
});
|
||||
|
||||
this.html.find('.subacteur-delete').click(async event => {
|
||||
const li = RdDSheetUtility.getEventElement(event);
|
||||
const actorId = li.data("actor-id");
|
||||
if (actorId) {
|
||||
const subActor = game.actors.get(actorId);
|
||||
RdDUtility.confirmerSuppressionSubacteur(this, subActor, li);
|
||||
RdDUtility.confirmerSuppressionSubacteur(this, subActor, li, () => {
|
||||
console.log('Delete : ', subActor.id);
|
||||
this.actor.removeSubacteur(subActor.id);
|
||||
RdDUtility.slideOnDelete(this, li);
|
||||
});
|
||||
}
|
||||
});
|
||||
this.html.find('.experiencelog-delete').click(async event => {
|
||||
@ -137,6 +148,13 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
const key = Number(li.data("key") ?? -1);
|
||||
await this.actor.deleteExperienceLog(0, key + 1);
|
||||
});
|
||||
this.html.find("input.derivee-value[name='system.compteurs.stress.value']").change(async event => {
|
||||
this.actor.updateCompteurValue("stress", parseInt(event.target.value));
|
||||
});
|
||||
this.html.find("input.derivee-value[name='system.compteurs.experience.value']").change(async event => {
|
||||
this.actor.updateCompteurValue("experience", parseInt(event.target.value));
|
||||
});
|
||||
|
||||
this.html.find('.encaisser-direct').click(async event => {
|
||||
this.actor.encaisser();
|
||||
})
|
||||
@ -251,6 +269,11 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
this.actor.rollCarac('reve-actuel', true);
|
||||
});
|
||||
|
||||
// Suite empoignade
|
||||
this.html.find('.empoignade-label a').click(async event => {
|
||||
let emp = RdDSheetUtility.getItem(event, this.actor)
|
||||
RdDEmpoignade.onAttaqueEmpoignadeFromItem(emp)
|
||||
});
|
||||
// Roll Weapon1
|
||||
this.html.find('.arme-label a').click(async event => {
|
||||
let arme = this._getEventArmeCombat(event);
|
||||
@ -332,12 +355,19 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
let compName = event.currentTarget.attributes.compname.value;
|
||||
this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value));
|
||||
});
|
||||
this.html.find('.toggle-archetype').click(async event => {
|
||||
this.options.vueArchetype = !this.options.vueArchetype;
|
||||
this.render(true);
|
||||
});
|
||||
// On competence archetype change
|
||||
this.html.find('.competence-archetype').change(async event => {
|
||||
let compName = event.currentTarget.attributes.compname.value;
|
||||
this.actor.updateCompetenceArchetype(compName, parseInt(event.target.value));
|
||||
});
|
||||
}
|
||||
this.html.find('.nouvelle-incarnation').click(async event => {
|
||||
this.actor.nouvelleIncarnation();
|
||||
});
|
||||
|
||||
this.html.find('.show-hide-competences').click(async event => {
|
||||
this.options.showCompNiveauBase = !this.options.showCompNiveauBase;
|
||||
@ -435,9 +465,9 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async selectTypeOeuvreToCreate() {
|
||||
let typeObjets = RdDItem.getTypesOeuvres();
|
||||
let types = RdDItem.getTypesOeuvres();
|
||||
let content = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
|
||||
for (let typeName of typeObjets) {
|
||||
for (let typeName of types) {
|
||||
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
||||
}
|
||||
content += '</select>';
|
||||
|
621
module/actor.js
621
module/actor.js
File diff suppressed because it is too large
Load Diff
@ -3,7 +3,8 @@ import { Misc } from "../misc.js";
|
||||
import { DialogSplitItem } from "../dialog-split-item.js";
|
||||
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
||||
import { Monnaie } from "../item-monnaie.js";
|
||||
import { RdDItem } from "../item.js";
|
||||
import { RdDItem, TYPES } from "../item.js";
|
||||
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/**
|
||||
@ -50,16 +51,18 @@ export class RdDBaseActorSheet extends ActorSheet {
|
||||
encTotal: await this.actor.computeEncTotal(),
|
||||
}
|
||||
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||
this._appliquerRechercheObjets(formData.objets, formData.conteneurs);
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
|
||||
this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
|
||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||
formData.competences.filter(it => it.type == TYPES.competencecreature)
|
||||
.forEach(it => it.isdommages = RdDItemCompetenceCreature.isDommages(it))
|
||||
return formData;
|
||||
}
|
||||
|
||||
_appliquerRechercheObjets(objets, conteneurs) {
|
||||
_appliquerRechercheObjets(conteneurs, inventaires) {
|
||||
if (this.options.recherche?.text) {
|
||||
const recherche = this.options.recherche;
|
||||
const allVisible = objets.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id);
|
||||
const allVisible = inventaires.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id);
|
||||
let addVisible = conteneurs.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id)
|
||||
do {
|
||||
allVisible.push(...addVisible)
|
||||
@ -67,11 +70,11 @@ export class RdDBaseActorSheet extends ActorSheet {
|
||||
addVisible = parentsIds.filter(id => !allVisible.includes(id))
|
||||
}
|
||||
while (addVisible.length > 0)
|
||||
objets.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
||||
inventaires.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
||||
conteneurs.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
||||
}
|
||||
else {
|
||||
objets.forEach(it => it.system.isHidden = false)
|
||||
inventaires.forEach(it => it.system.isHidden = false)
|
||||
conteneurs.forEach(it => it.system.isHidden = false)
|
||||
}
|
||||
}
|
||||
@ -118,33 +121,34 @@ export class RdDBaseActorSheet extends ActorSheet {
|
||||
formData.herbes = Misc.arrayOrEmpty(itemTypes['herbe']);
|
||||
formData.nourritureboissons = Misc.arrayOrEmpty(itemTypes['nourritureboisson']);
|
||||
formData.gemmes = Misc.arrayOrEmpty(itemTypes['gemme']);
|
||||
formData.monnaie = Misc.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere());
|
||||
formData.monnaies = Misc.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere());
|
||||
formData.objets = Misc.arrayOrEmpty(itemTypes['objet'])
|
||||
|
||||
formData.objets = RdDItem.getItemTypesInventaire('all')
|
||||
formData.inventaires = RdDItem.getItemTypesInventaire('all')
|
||||
.map(t => Misc.arrayOrEmpty(itemTypes[t]))
|
||||
.reduce((a, b) => a.concat(b), [])
|
||||
.sort(Misc.ascending(it => it.name));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */ /** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
this.html = html;
|
||||
|
||||
this.html.find('.conteneur-name a').click(async event => {
|
||||
RdDUtility.toggleAfficheContenu(this.getItemId(event));
|
||||
this.render(true);
|
||||
});
|
||||
this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true))
|
||||
this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat());
|
||||
this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat());
|
||||
this.html.find('.recherche')
|
||||
.each((index, field) => {
|
||||
this._rechercheSelectArea(field);
|
||||
})
|
||||
.keyup(async event => this._rechercherKeyup(event))
|
||||
.change(async event => this._rechercherKeyup(event));
|
||||
this.html.find('.recherche').prop( "disabled", false );
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */ /** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
this.html = html;
|
||||
|
||||
this.html.find('.conteneur-name a').click(async event => {
|
||||
RdDUtility.toggleAfficheContenu(this.getItemId(event));
|
||||
this.render(true);
|
||||
});
|
||||
this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true))
|
||||
this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat());
|
||||
this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat());
|
||||
this.html.find('.recherche')
|
||||
.each((index, field) => {
|
||||
this._rechercheSelectArea(field);
|
||||
})
|
||||
.keyup(async event => this._rechercherKeyup(event))
|
||||
.change(async event => this._rechercherKeyup(event));
|
||||
this.html.find('.recherche').prop("disabled", false);
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
@ -152,6 +156,8 @@ export class RdDBaseActorSheet extends ActorSheet {
|
||||
const item = this.getItem(event);
|
||||
RdDSheetUtility.splitItem(item, this.actor);
|
||||
});
|
||||
this.html.find('.item-quantite-plus').click(async event => this.actor.itemQuantiteIncDec(this.getItemId(event), 1));
|
||||
this.html.find('.item-quantite-moins').click(async event => this.actor.itemQuantiteIncDec(this.getItemId(event), -1));
|
||||
this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, this.getItem(event)));
|
||||
this.html.find('.item-vendre').click(async event => this.vendre(this.getItem(event)));
|
||||
|
||||
@ -161,12 +167,6 @@ export class RdDBaseActorSheet extends ActorSheet {
|
||||
this.html.find('.nettoyer-conteneurs').click(async event => {
|
||||
this.actor.nettoyerConteneurs();
|
||||
});
|
||||
this.html.find('.monnaie-plus').click(async event => {
|
||||
this.actor.monnaieIncDec(this.getItemId(event), 1);
|
||||
});
|
||||
this.html.find('.monnaie-moins').click(async event => {
|
||||
this.actor.monnaieIncDec(this.getItemId(event), -1);
|
||||
});
|
||||
}
|
||||
|
||||
_rechercherKeyup(event) {
|
||||
@ -234,9 +234,9 @@ export class RdDBaseActorSheet extends ActorSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async selectObjetTypeToCreate() {
|
||||
let typeObjets = this.getTypesInventaire().sort(Misc.ascending(type => Misc.typeName('Item', type)));
|
||||
let types = this.getTypesInventaire().sort(Misc.ascending(type => Misc.typeName('Item', type)));
|
||||
let content = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
|
||||
for (let typeName of typeObjets) {
|
||||
for (let typeName of types) {
|
||||
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
||||
}
|
||||
content += '</select>';
|
||||
|
@ -3,6 +3,7 @@ import { SYSTEM_SOCKET_ID } from "../constants.js";
|
||||
import { Monnaie } from "../item-monnaie.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDAudio } from "../rdd-audio.js";
|
||||
import { RdDConfirm } from "../rdd-confirm.js";
|
||||
import { RdDUtility } from "../rdd-utility.js";
|
||||
import { SystemCompendiums } from "../settings/system-compendiums.js";
|
||||
import { APP_ASTROLOGIE_REFRESH } from "../sommeil/app-astrologie.js";
|
||||
@ -32,7 +33,7 @@ export class RdDBaseActor extends Actor {
|
||||
case "msg_refresh_nombre_astral":
|
||||
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static remoteActorCall(callData, userId = undefined) {
|
||||
@ -49,7 +50,13 @@ export class RdDBaseActor extends Actor {
|
||||
|
||||
static onRemoteActorCall(callData, userId) {
|
||||
if (userId == game.user.id) {
|
||||
const actor = game.actors.get(callData?.actorId);
|
||||
let actor = game.actors.get(callData?.actorId);
|
||||
if ( callData.tokenId) {
|
||||
let token = canvas.tokens.placeables.find(t => t.id == callData.tokenId)
|
||||
if (token) {
|
||||
actor = token.actor
|
||||
}
|
||||
}
|
||||
if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
|
||||
const args = callData.args;
|
||||
console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')');
|
||||
@ -109,7 +116,6 @@ export class RdDBaseActor extends Actor {
|
||||
isEntite() { return this.type == 'entite'; }
|
||||
isPersonnage() { return this.type == 'personnage'; }
|
||||
isVehicule() { return this.type == 'vehicule'; }
|
||||
|
||||
getItem(id, type = undefined) {
|
||||
const item = this.items.get(id);
|
||||
if (type == undefined || (item?.type == type)) {
|
||||
@ -119,7 +125,7 @@ export class RdDBaseActor extends Actor {
|
||||
}
|
||||
|
||||
listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); }
|
||||
filterItems(filter, type = undefined) { return this.listItems(type)?.filter(filter) ?? []; }
|
||||
filterItems(filter, type = undefined) { return (type ? this.itemTypes[type] : this.items)?.filter(filter) ?? []; }
|
||||
findItemLike(idOrName, type) {
|
||||
return this.getItem(idOrName, type)
|
||||
?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) });
|
||||
@ -144,17 +150,30 @@ export class RdDBaseActor extends Actor {
|
||||
.forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp))
|
||||
}
|
||||
|
||||
async creerObjetParMJ(object) {
|
||||
if (!Misc.isUniqueConnectedGM()) {
|
||||
RdDBaseActor.remoteActorCall({
|
||||
tokenId: this.token?.id,
|
||||
actorId: this.id,
|
||||
method: 'creerObjetParMJ',
|
||||
args: [object]
|
||||
});
|
||||
return;
|
||||
}
|
||||
await this.createEmbeddedDocuments('Item', [object])
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getFortune() {
|
||||
return Monnaie.getFortune(this.itemTypes['monnaie']);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async monnaieIncDec(id, value) {
|
||||
let monnaie = this.getMonnaie(id);
|
||||
if (monnaie) {
|
||||
const quantite = Math.max(0, monnaie.system.quantite + value);
|
||||
await this.updateEmbeddedDocuments('Item', [{ _id: monnaie.id, 'system.quantite': quantite }]);
|
||||
async itemQuantiteIncDec(id, value) {
|
||||
let item = this.getItem(id);
|
||||
if (item && item.isInventaire()) {
|
||||
const quantite = Math.max(0, item.system.quantite + value);
|
||||
await this.updateEmbeddedDocuments('Item', [{ _id: item.id, 'system.quantite': quantite }]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -208,6 +227,7 @@ export class RdDBaseActor extends Actor {
|
||||
if (fromActorId && !game.user.isGM) {
|
||||
RdDBaseActor.remoteActorCall({
|
||||
userId: Misc.connectedGMOrUser(),
|
||||
tokenId: this.token?.id,
|
||||
actorId: this.id,
|
||||
method: 'ajouterSols', args: [sols, fromActorId]
|
||||
});
|
||||
@ -244,14 +264,16 @@ export class RdDBaseActor extends Actor {
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const cout = Number(achat.prixTotal ?? 0);
|
||||
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
|
||||
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined;
|
||||
const vente = achat.vente;
|
||||
const quantite = (achat.choix.nombreLots ?? 1) * (vente.tailleLot);
|
||||
const itemVendu = vendeur?.getItem(vente.item._id);
|
||||
if (!this.verifierQuantite(vendeur, itemVendu, quantite)) {
|
||||
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
|
||||
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id);
|
||||
if (!itemVendu) {
|
||||
ChatUtility.notifyUser(achat.userId, 'warn', vendeur ? `Le vendeur n'a pas plus de ${achat.vente.item.name} !` : `Impossible de retrouver: ${achat.vente.item.name} !`);
|
||||
return;
|
||||
}
|
||||
if (vendeur && !vendeur.verifierQuantite(itemVendu, quantite)) {
|
||||
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
|
||||
return
|
||||
}
|
||||
@ -262,13 +284,13 @@ export class RdDBaseActor extends Actor {
|
||||
await this.decrementerVente(vendeur, itemVendu, quantite, cout);
|
||||
if (acheteur) {
|
||||
await acheteur.depenserSols(cout);
|
||||
const createdItemId = await acheteur.creerQuantiteItem(vente.item, quantite);
|
||||
await acheteur.consommerNourritureAchetee(achat, vente, createdItemId);
|
||||
const createdItemId = await acheteur.creerQuantiteItem(itemVendu, quantite);
|
||||
await acheteur.consommerNourritureAchetee(achat, achat.vente, createdItemId);
|
||||
}
|
||||
if (cout > 0) {
|
||||
RdDAudio.PlayContextAudio("argent");
|
||||
}
|
||||
const chatAchatItem = duplicate(vente);
|
||||
const chatAchatItem = duplicate(achat.vente);
|
||||
chatAchatItem.quantiteTotal = quantite;
|
||||
ChatMessage.create({
|
||||
user: achat.userId,
|
||||
@ -277,16 +299,16 @@ export class RdDBaseActor extends Actor {
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html', chatAchatItem)
|
||||
});
|
||||
|
||||
if (!vente.quantiteIllimite) {
|
||||
if (vente.quantiteNbLots <= achat.choix.nombreLots) {
|
||||
if (!achat.vente.quantiteIllimite) {
|
||||
if (achat.vente.quantiteNbLots <= achat.choix.nombreLots) {
|
||||
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
|
||||
}
|
||||
else if (achat.chatMessageIdVente) {
|
||||
vente["properties"] = itemVendu.getProprietes();
|
||||
vente.quantiteNbLots -= achat.choix.nombreLots;
|
||||
vente.jsondata = JSON.stringify(vente.item);
|
||||
achat.vente.properties = itemVendu.getProprietes();
|
||||
achat.vente.quantiteNbLots -= achat.choix.nombreLots;
|
||||
achat.vente.jsondata = JSON.stringify(achat.vente.item);
|
||||
const messageVente = game.messages.get(achat.chatMessageIdVente);
|
||||
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente) });
|
||||
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', achat.vente) });
|
||||
messageVente.render(true);
|
||||
}
|
||||
}
|
||||
@ -303,9 +325,9 @@ export class RdDBaseActor extends Actor {
|
||||
return this.getFortune() >= cout;
|
||||
}
|
||||
|
||||
verifierQuantite(vendeur, item, quantiteTotal) {
|
||||
const disponible = vendeur?.getQuantiteDisponible(item);
|
||||
return disponible == undefined || disponible >= quantiteTotal;
|
||||
verifierQuantite(item, quantiteDemande) {
|
||||
const disponible = this.getQuantiteDisponible(item);
|
||||
return disponible == undefined || disponible >= quantiteDemande;
|
||||
}
|
||||
|
||||
async consommerNourritureAchetee(achat, vente, createdItemId) {
|
||||
@ -433,62 +455,33 @@ export class RdDBaseActor extends Actor {
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
conteneurPeutContenir(dest, item) {
|
||||
conteneurPeutContenir(dest, moved) {
|
||||
if (!dest) {
|
||||
return true;
|
||||
}
|
||||
if (!dest.isConteneur()) {
|
||||
return false;
|
||||
}
|
||||
const destData = dest
|
||||
if (this._isConteneurContenu(item, dest)) {
|
||||
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${destData.name} !`);
|
||||
return false; // Loop detected !
|
||||
if (moved.isConteneurContenu(dest)) {
|
||||
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${moved.name}) dans un de ses contenus ${dest.name} !`);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculer le total actuel des contenus
|
||||
let encContenu = this.getRecursiveEnc(dest) - Number(destData.system.encombrement);
|
||||
let newEnc = this.getRecursiveEnc(item); // Calculer le total actuel du nouvel objet
|
||||
const encContenu = dest.getEncContenu();
|
||||
const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet
|
||||
const placeDisponible = Math.roundDecimals(dest.system.capacite - encContenu - newEnc, 4)
|
||||
|
||||
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
|
||||
if (Number(destData.system.capacite) < encContenu + newEnc) {
|
||||
if (placeDisponible < 0) {
|
||||
ui.notifications.warn(
|
||||
`Le conteneur ${dest.name} a une capacité de ${destData.system.capacite}, et contient déjà ${encContenu}.
|
||||
Impossible d'y ranger: ${item.name} d'encombrement ${newEnc}!`);
|
||||
`Le conteneur ${dest.name} a une capacité de ${dest.system.capacite}, et contient déjà ${encContenu}.
|
||||
Impossible d'y ranger: ${moved.name} d'encombrement ${newEnc}!`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_isConteneurContenu(item, conteneur) {
|
||||
if (item?.isConteneur()) { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant
|
||||
for (let id of item.system.contenu) {
|
||||
let subObjet = this.getItem(id);
|
||||
if (subObjet?.id == conteneur.id) {
|
||||
return true; // Loop detected !
|
||||
}
|
||||
if (subObjet?.isConteneur()) {
|
||||
return this._isConteneurContenu(subObjet, conteneur);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
getRecursiveEnc(objet) {
|
||||
if (!objet) {
|
||||
return 0;
|
||||
}
|
||||
const tplData = objet.system;
|
||||
if (objet.type != 'conteneur') {
|
||||
return Number(tplData.encombrement) * Number(tplData.quantite);
|
||||
}
|
||||
const encContenus = tplData.contenu.map(idContenu => this.getRecursiveEnc(this.getItem(idContenu)));
|
||||
return encContenus.reduce(Misc.sum(), 0)
|
||||
+ Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** Ajoute un item dans un conteneur, sur la base
|
||||
* de leurs ID */
|
||||
|
@ -22,12 +22,13 @@ export class RdDCommerce extends RdDBaseActor {
|
||||
}
|
||||
|
||||
getQuantiteDisponible(item) {
|
||||
return this.system.illimite || item.isService() ? undefined : item.getQuantite();
|
||||
return (this.system.illimite || item?.isService()) ? undefined : item.getQuantite();
|
||||
}
|
||||
|
||||
verifierFortune(cout) {
|
||||
return this.system.illimite || super.verifierFortune(cout);
|
||||
}
|
||||
|
||||
async depenserSols(cout) {
|
||||
if (this.system.illimite) {
|
||||
return
|
||||
|
39
module/actor/experience-log.js
Normal file
39
module/actor/experience-log.js
Normal file
@ -0,0 +1,39 @@
|
||||
|
||||
export const XP_TOPIC = {
|
||||
XP: { code: 'xp', label: 'xp' },
|
||||
XPSORT: { code: 'xpsort', label: 'xp sort' },
|
||||
NIVEAU: { code: 'niveau', label: 'Niveau' },
|
||||
XPCARAC: { code: 'xpcarac', label: 'xp carac' },
|
||||
CARAC: { code: 'carac', label: 'Carac' },
|
||||
STRESS: { code: 'stress', label: 'Stress' },
|
||||
TRANSFORM: { code: 'xps', label: 'Transformé' },
|
||||
}
|
||||
|
||||
export class ExperienceLog {
|
||||
|
||||
static async add(actor, topic, from, to, raison, manuel = false) {
|
||||
if (!actor.hasPlayerOwner || !actor.isPersonnage()) {
|
||||
return
|
||||
}
|
||||
if (from == to) {
|
||||
return
|
||||
}
|
||||
const newXpLog = {
|
||||
mode: topic?.code ?? topic,
|
||||
raison: (manuel ? '(manuel) ' : '') + raison,
|
||||
from: from,
|
||||
to: to,
|
||||
valeur: to - from,
|
||||
daterdd: game.system.rdd.calendrier.dateCourante(),
|
||||
datereel: game.system.rdd.calendrier.dateReel().replace('T', ' ')
|
||||
};
|
||||
console.log('ExperienceLog.add', newXpLog)
|
||||
const newExperienceLog = (actor.system.experiencelog ?? []).concat([newXpLog]);
|
||||
await actor.update({ [`system.experiencelog`]: newExperienceLog });
|
||||
}
|
||||
|
||||
static labelTopic(topic) {
|
||||
const xpt = Object.values(XP_TOPIC).find(it => it.code == topic);
|
||||
return xpt?.label ?? xpt?.code ?? topic;
|
||||
}
|
||||
}
|
@ -78,11 +78,7 @@ export class ChatUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createChatWithRollMode(name, chatOptions) {
|
||||
return await ChatUtility.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createChatMessage(name, rollMode, chatOptions) {
|
||||
let rollMode = game.settings.get("core", "rollMode")
|
||||
switch (rollMode) {
|
||||
case "blindroll": // GM only
|
||||
if (!game.user.isGM) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { SYSTEM_RDD } from "./constants.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
|
||||
|
||||
const LATEST_USED_JOURNAL_ID = "chronologie-dernier-journal";
|
||||
@ -25,23 +25,13 @@ export class DialogChronologie extends Dialog {
|
||||
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
|
||||
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
|
||||
timestamp: game.system.rdd.calendrier.timestamp,
|
||||
dateReel: DialogChronologie.getCurrentDateTime()
|
||||
dateReel: game.system.rdd.calendrier.dateReel()
|
||||
};
|
||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.html", dialogData);
|
||||
const dialog = new DialogChronologie(html, dialogData);
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
static getCurrentDateTime() {
|
||||
return new Date().toLocaleString("sv-SE", {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit"
|
||||
}).replace(" ", "T");
|
||||
}
|
||||
|
||||
constructor(html, dialogData) {
|
||||
const options = {
|
||||
classes: ["DialogChronologie"],
|
||||
|
@ -111,7 +111,7 @@ export class DialogCreateSigneDraconique extends Dialog {
|
||||
|
||||
onSelectTmr(event) {
|
||||
const tmrName = this.html.find(event.currentTarget)?.data("tmr-name");
|
||||
const onTmr = this.tmrs.find(it => it.name == tmrName);
|
||||
const onTmr = this.dialogData.tmrs.find(it => it.name == tmrName);
|
||||
if (onTmr){
|
||||
onTmr.selected = event.currentTarget.checked;
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import { RdDUtility } from "./rdd-utility.js";
|
||||
export class DialogFabriquerPotion extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async create(actor, item, dialogConfig) {
|
||||
static async create(actor, item, onActionItem) {
|
||||
const min = DialogFabriquerPotion.nombreBrinsMinimum(item);
|
||||
if (item.system.quantite < min) {
|
||||
ui.notifications.warn(`Vous avez ${item.system.quantite} brins de ${item.name}, il en faut au moins ${min} pour faire une potion!`);
|
||||
@ -13,12 +13,10 @@ export class DialogFabriquerPotion extends Dialog {
|
||||
}
|
||||
let potionData = DialogFabriquerPotion.prepareData(actor, item);
|
||||
|
||||
const html = await renderTemplate(dialogConfig.html, potionData);
|
||||
const html = await renderTemplate( 'systems/foundryvtt-reve-de-dragon/templates/dialog-fabriquer-potion-base.html', potionData);
|
||||
|
||||
let options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 };
|
||||
mergeObject(options, dialogConfig.options ?? {}, { overwrite: true })
|
||||
|
||||
new DialogFabriquerPotion(actor, potionData, html, options).render(true);
|
||||
new DialogFabriquerPotion(actor, potionData, onActionItem, html, options).render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -34,14 +32,14 @@ export class DialogFabriquerPotion extends Dialog {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(actor, potionData, html, options) {
|
||||
constructor(actor, potionData, onActionItem, html, options) {
|
||||
const conf = {
|
||||
title: `Fabriquer une potion de ${potionData.system.categorie}`,
|
||||
content: html,
|
||||
default: 'fabriquer',
|
||||
buttons: {
|
||||
'fabriquer': {
|
||||
label: potionData.buttonName, callback: it => this.onFabriquer(html)
|
||||
label: potionData.buttonName, callback: it => this.onFabriquer()
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -50,6 +48,7 @@ export class DialogFabriquerPotion extends Dialog {
|
||||
|
||||
this.actor = actor;
|
||||
this.potionData = potionData;
|
||||
this.onActionItem = onActionItem;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -64,10 +63,11 @@ export class DialogFabriquerPotion extends Dialog {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async onFabriquer(html) {
|
||||
async onFabriquer() {
|
||||
await this.html.find("[name='nbBrins']").change();
|
||||
this.actor.fabriquerPotion(this.potionData);
|
||||
await this.actor.fabriquerPotion(this.potionData);
|
||||
this.close();
|
||||
await this.onActionItem()
|
||||
}
|
||||
|
||||
static nombreBrinsMinimum(herbeData) {
|
||||
|
@ -18,7 +18,7 @@ export class DialogItemAchat extends Dialog {
|
||||
}
|
||||
|
||||
return {
|
||||
item: (json ? JSON.parse(json) : undefined),
|
||||
item: JSON.parse(json),
|
||||
vendeur,
|
||||
acheteur,
|
||||
nbLots: parseInt(chatButton.attributes['data-quantiteNbLots']?.value),
|
||||
@ -34,7 +34,6 @@ export class DialogItemAchat extends Dialog {
|
||||
const venteData = {
|
||||
item,
|
||||
actingUserId: game.user.id,
|
||||
vendeurId: vendeur?.id,
|
||||
vendeur,
|
||||
acheteur,
|
||||
tailleLot,
|
||||
|
@ -7,7 +7,7 @@ import { RdDUtility } from "./rdd-utility.js";
|
||||
*/
|
||||
export class DialogValidationEncaissement extends Dialog {
|
||||
|
||||
static async validerEncaissement(actor, rollData, armure, show, onEncaisser) {
|
||||
static async validerEncaissement(actor, rollData, armure, show, attackerId, onEncaisser) {
|
||||
let encaissement = await RdDUtility.jetEncaissement(rollData, armure, { showDice: HIDE_DICE });
|
||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', {
|
||||
actor: actor,
|
||||
@ -15,15 +15,15 @@ export class DialogValidationEncaissement extends Dialog {
|
||||
encaissement: encaissement,
|
||||
show: show
|
||||
});
|
||||
const dialog = new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, show, onEncaisser);
|
||||
const dialog = new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, show, attackerId, onEncaisser);
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, actor, rollData, armure, encaissement, show, onEncaisser) {
|
||||
constructor(html, actor, rollData, armure, encaissement, show, attackerId, onEncaisser) {
|
||||
// Common conf
|
||||
let buttons = {
|
||||
"valider": { label: "Valider", callback: html => this.validerEncaissement() },
|
||||
"valider": { label: "Valider", callback: html => this.onValider() },
|
||||
"annuler": { label: "Annuler", callback: html => { } },
|
||||
};
|
||||
|
||||
@ -48,6 +48,7 @@ export class DialogValidationEncaissement extends Dialog {
|
||||
this.armure = armure;
|
||||
this.encaissement = encaissement;
|
||||
this.show = show;
|
||||
this.attackerId = attackerId;
|
||||
this.onEncaisser = onEncaisser;
|
||||
this.forceDiceResult = {total: encaissement.roll.result };
|
||||
}
|
||||
@ -64,8 +65,8 @@ export class DialogValidationEncaissement extends Dialog {
|
||||
});
|
||||
}
|
||||
|
||||
async validerEncaissement() {
|
||||
async onValider() {
|
||||
this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: SHOW_DICE, forceDiceResult: this.forceDiceResult});
|
||||
this.onEncaisser(this.encaissement, this.show)
|
||||
this.onEncaisser(this.encaissement, this.show, this.attackerId)
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
|
||||
import { TYPES } from "./item.js";
|
||||
import { RdDCombatManager } from "./rdd-combat.js";
|
||||
|
||||
const nomCategorieParade = {
|
||||
@ -19,7 +20,7 @@ const nomCategorieParade = {
|
||||
export class RdDItemArme extends Item {
|
||||
|
||||
static isArme(item) {
|
||||
return (item.type == 'competencecreature' && item.system.iscombat) || item.type == 'arme';
|
||||
return RdDItemCompetenceCreature.getCategorieAttaque(item) || item.type == 'arme';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -27,7 +28,7 @@ export class RdDItemArme extends Item {
|
||||
switch (arme ? arme.type : '') {
|
||||
case 'arme': return arme;
|
||||
case 'competencecreature':
|
||||
return RdDItemCompetenceCreature.armeNaturelle(arme);
|
||||
return RdDItemCompetenceCreature.armeCreature(arme);
|
||||
}
|
||||
return RdDItemArme.mainsNues();
|
||||
}
|
||||
@ -165,7 +166,7 @@ export class RdDItemArme extends Item {
|
||||
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 }));
|
||||
armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
|
||||
}
|
||||
|
||||
static corpsACorps(mainsNuesActor) {
|
||||
|
@ -8,22 +8,22 @@ const xp_par_niveau = [5, 5, 5, 10, 10, 10, 10, 15, 15, 15, 15, 20, 20, 20, 20,
|
||||
const niveau_max = xp_par_niveau.length - 10;
|
||||
/* -------------------------------------------- */
|
||||
const limitesArchetypes = [
|
||||
{ "niveau": 0, "nombreMax": 100, "reste": 100 },
|
||||
{ "niveau": 1, "nombreMax": 10, "reste": 10 },
|
||||
{ "niveau": 2, "nombreMax": 9, "reste": 9 },
|
||||
{ "niveau": 3, "nombreMax": 8, "reste": 8 },
|
||||
{ "niveau": 4, "nombreMax": 7, "reste": 7 },
|
||||
{ "niveau": 5, "nombreMax": 6, "reste": 6 },
|
||||
{ "niveau": 6, "nombreMax": 5, "reste": 5 },
|
||||
{ "niveau": 7, "nombreMax": 4, "reste": 4 },
|
||||
{ "niveau": 8, "nombreMax": 3, "reste": 3 },
|
||||
{ "niveau": 9, "nombreMax": 2, "reste": 2 },
|
||||
{ "niveau": 10, "nombreMax": 1, "reste": 1 },
|
||||
{ "niveau": 11, "nombreMax": 1, "reste": 1 }
|
||||
{ niveau: 0, nombreMax: 100 },
|
||||
{ niveau: 1, nombreMax: 10 },
|
||||
{ niveau: 2, nombreMax: 9 },
|
||||
{ niveau: 3, nombreMax: 8 },
|
||||
{ niveau: 4, nombreMax: 7 },
|
||||
{ niveau: 5, nombreMax: 6 },
|
||||
{ niveau: 6, nombreMax: 5 },
|
||||
{ niveau: 7, nombreMax: 4 },
|
||||
{ niveau: 8, nombreMax: 3 },
|
||||
{ niveau: 9, nombreMax: 2 },
|
||||
{ niveau: 10, nombreMax: 1 },
|
||||
{ niveau: 11, nombreMax: 1 },
|
||||
];
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const categorieCompetences = {
|
||||
const categoriesCompetences = {
|
||||
"generale": { base: -4, label: "Générales" },
|
||||
"particuliere": { base: -8, label: "Particulières" },
|
||||
"specialisee": { base: -11, label: "Spécialisées" },
|
||||
@ -49,16 +49,16 @@ const competence_xp_cumul = _buildCumulXP();
|
||||
|
||||
export class RdDItemCompetence extends Item {
|
||||
/* -------------------------------------------- */
|
||||
static getCategorieCompetences() {
|
||||
return categorieCompetences;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getNiveauBase(category) {
|
||||
return categorieCompetences[category].base;
|
||||
static getCategories() {
|
||||
return categoriesCompetences;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getLabelCategorie(category) {
|
||||
return categorieCompetences[category].label;
|
||||
return categoriesCompetences[category].label;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getNiveauBase(category, categories = categoriesCompetences) {
|
||||
return categories[category]?.base ?? 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -192,7 +192,7 @@ export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isNiveauBase(item) {
|
||||
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie);
|
||||
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.getCategories());
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -259,13 +259,17 @@ export class RdDItemCompetence extends Item {
|
||||
/* -------------------------------------------- */
|
||||
static computeResumeArchetype(competences) {
|
||||
const computed = duplicate(limitesArchetypes);
|
||||
computed.forEach(it => { it.nombre = 0; it.reste = it.nombreMax; });
|
||||
|
||||
competences.map(it => Math.max(0, it.system.niveau_archetype))
|
||||
.filter(n => n > 0)
|
||||
.forEach(n => {
|
||||
computed[n] = computed[n] ?? { niveau: n, nombreMax: 0, reste: 0 };
|
||||
computed[n].reste = computed[n].reste - 1;
|
||||
computed[n] = computed[n] ?? { niveau: n, nombreMax: 0, reste: 0, nombre: 0 };
|
||||
computed[n].reste--;
|
||||
computed[n].nombre++;
|
||||
|
||||
});
|
||||
return computed.filter(it => it.reste > 0 && it.niveau > 0);
|
||||
return computed.filter(it => it.niveau > 0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -1,51 +1,97 @@
|
||||
|
||||
import { RdDItem, TYPES } from "./item.js";
|
||||
import { RdDCombatManager } from "./rdd-combat.js";
|
||||
|
||||
const categories = {
|
||||
"generale": { base: 0, label: "Générale" },
|
||||
"naturelle": { base: 0, label: "Arme naturelle" },
|
||||
"melee": { base: 0, label: "Mêlée" },
|
||||
"parade": { base: 0, label: "Parade" },
|
||||
"tir": { base: 0, label: "Tir" },
|
||||
"lancer": { base: 0, label: "Lancer" },
|
||||
"possession": { base: 0, label: "Possession" },
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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.selectedCarac = rollData.carac.carac_creature
|
||||
if (rollData.competence.system.iscombat) {
|
||||
rollData.arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence);
|
||||
}
|
||||
static getCategories() {
|
||||
return categories;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static armeNaturelle(competencecreature) {
|
||||
if (RdDItemCompetenceCreature.isCompetenceAttaque(competencecreature)) {
|
||||
// si c'est un Item compétence: cloner pour ne pas modifier lma compétence
|
||||
let arme = (competencecreature instanceof Item) ? competencecreature.clone(): competencecreature;
|
||||
mergeObject(arme.system,
|
||||
static setRollDataCreature(rollData) {
|
||||
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
|
||||
rollData.competence.system.defaut_carac = "carac_creature"
|
||||
rollData.selectedCarac = rollData.carac.carac_creature
|
||||
rollData.arme = RdDItemCompetenceCreature.armeCreature(rollData.competence);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static armeCreature(item) {
|
||||
const categorieAttaque = RdDItemCompetenceCreature.getCategorieAttaque(item)
|
||||
if (categorieAttaque != undefined) {
|
||||
// si c'est un Item compétence: cloner pour ne pas modifier la compétence
|
||||
let arme = item.clone();
|
||||
mergeObject(arme,
|
||||
{
|
||||
competence: arme.name,
|
||||
initiative: RdDCombatManager.calculInitiative(competencecreature.system.niveau, competencecreature.system.carac_value),
|
||||
niveau: competencecreature.system.niveau,
|
||||
equipe: true,
|
||||
resistance: 100,
|
||||
dommagesReels: arme.system.dommages,
|
||||
penetration: 0,
|
||||
force: 0,
|
||||
rapide: true,
|
||||
cac: competencecreature.system.isnaturelle ? "naturelle" : "",
|
||||
action: 'attaque'
|
||||
action: item.isCompetencePossession() ? 'possession' : 'attaque',
|
||||
system: {
|
||||
competence: arme.name,
|
||||
cac: categorieAttaque == "naturelle" ? "naturelle" : "",
|
||||
niveau: item.system.niveau,
|
||||
initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value),
|
||||
equipe: true,
|
||||
resistance: 100,
|
||||
dommagesReels: arme.system.dommages,
|
||||
penetration: 0,
|
||||
force: 0,
|
||||
rapide: true,
|
||||
}
|
||||
});
|
||||
return arme;
|
||||
}
|
||||
console.error("RdDItemCompetenceCreature.toActionArme(", competencecreature, ") : impossible de transformer l'Item en arme");
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCompetenceAttaque(item) {
|
||||
return item.type == 'competencecreature' && item.system.iscombat;
|
||||
static getCategorieAttaque(item) {
|
||||
if (item.type == TYPES.competencecreature) {
|
||||
switch (item.system.categorie) {
|
||||
case "melee":
|
||||
case "tir":
|
||||
case "lancer":
|
||||
case "naturelle":
|
||||
case "possession":
|
||||
return item.system.categorie
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
static isDommages(item) {
|
||||
if (item.type == TYPES.competencecreature) {
|
||||
switch (item.system.categorie) {
|
||||
case "melee":
|
||||
case "tir":
|
||||
case "lancer":
|
||||
case "naturelle":
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
static isParade(item) {
|
||||
if (item.type == TYPES.competencecreature) {
|
||||
switch (item.system.categorie) {
|
||||
case "melee":
|
||||
case "naturelle":
|
||||
case "parade":
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCompetenceParade(item) {
|
||||
return item.type == 'competencecreature' && item.system.categorie_parade !== "";
|
||||
|
@ -5,12 +5,14 @@ import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDHerbes } from "./rdd-herbes.js";
|
||||
import { RdDGemme } from "./rdd-gemme.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { SYSTEM_RDD } from "./constants.js";
|
||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||
import { TYPES } from "./item.js";
|
||||
|
||||
/**
|
||||
* Extend the basic ItemSheet for RdD specific items
|
||||
@ -98,9 +100,13 @@ export class RdDItemSheet extends ItemSheet {
|
||||
isComestible: this.item.getUtilisationCuisine(),
|
||||
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable)
|
||||
}
|
||||
if (this.item.type == TYPES.competencecreature) {
|
||||
formData.isparade = RdDItemCompetenceCreature.isParade(this.item)
|
||||
formData.isdommages = RdDItemCompetenceCreature.isDommages(this.item)
|
||||
}
|
||||
|
||||
const competences = await SystemCompendiums.getCompetences('personnage');
|
||||
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences()
|
||||
formData.categories = this.item.getCategories()
|
||||
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
|
||||
formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
|
||||
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve)
|
||||
@ -151,7 +157,7 @@ export class RdDItemSheet extends ItemSheet {
|
||||
super.activateListeners(html);
|
||||
this.html = html;
|
||||
|
||||
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs')
|
||||
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionnelles.isUsing('afficher-prix-joueurs')
|
||||
|| game.user.isGM
|
||||
|| !this.item.isOwned);
|
||||
HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
|
||||
@ -188,7 +194,7 @@ export class RdDItemSheet extends ItemSheet {
|
||||
});
|
||||
|
||||
this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item));
|
||||
this.html.find('.consommer-potion').click((event) => this._getEventActor(event).consommerPotion(this.item));
|
||||
this.html.find('.consommer-potion').click((event) => this._getEventActor(event).consommerPotion(this.item, this.getActionRenderItem()));
|
||||
this.html.find('.creer-potion-base').click((event) => this._getEventActor(event).dialogFabriquerPotion(this.item));
|
||||
|
||||
this.html.find('.alchimie-tache a').click((event) => {
|
||||
@ -203,12 +209,23 @@ export class RdDItemSheet extends ItemSheet {
|
||||
}
|
||||
});
|
||||
|
||||
this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, async () => this.render(true)));
|
||||
this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true));
|
||||
this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, RdDSheetUtility.getItem(event, this.actor)));
|
||||
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
|
||||
this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItemToChat());
|
||||
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, async () => this.render(true)));
|
||||
if (this.actor) {
|
||||
this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, this.getActionRenderItem()));
|
||||
this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true));
|
||||
this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, RdDSheetUtility.getItem(event, this.actor)));
|
||||
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
|
||||
this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItemToChat());
|
||||
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, this.getActionRenderItem()));
|
||||
|
||||
this.html.find('.item-quantite-plus').click(async event => {
|
||||
await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), 1)
|
||||
this.render();
|
||||
});
|
||||
this.html.find('.item-quantite-moins').click(async event => {
|
||||
await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), -1)
|
||||
this.render();
|
||||
});
|
||||
}
|
||||
|
||||
const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: duplicate(timestamp) })
|
||||
|
||||
@ -216,6 +233,16 @@ export class RdDItemSheet extends ItemSheet {
|
||||
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp);
|
||||
}
|
||||
|
||||
getActionRenderItem() {
|
||||
return async () => {
|
||||
let item = this.item;
|
||||
while (item) {
|
||||
await item.sheet?.render()
|
||||
item = this.actor.getContenant(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_getEventActor(event) {
|
||||
let actorId = event.currentTarget.attributes['data-actor-id'].value;
|
||||
let actor = game.actors.get(actorId);
|
||||
@ -228,7 +255,8 @@ export class RdDItemSheet extends ItemSheet {
|
||||
event.preventDefault();
|
||||
|
||||
if (this.item.isCompetence()) {
|
||||
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
|
||||
const categorie = event.currentTarget.value;
|
||||
const level = RdDItemCompetence.getNiveauBase(categorie, this.item.getCategories());
|
||||
this.item.system.base = level;
|
||||
this.html.find('[name="system.base"]').val(level);
|
||||
}
|
||||
@ -239,9 +267,8 @@ export class RdDItemSheet extends ItemSheet {
|
||||
_updateObject(event, formData) {
|
||||
if (this.item.type == 'sort') {
|
||||
// Données de bonus de cases ?
|
||||
formData['system.bonuscase'] = RdDItemSort.buildBonusCaseStringFromFormData(formData.bonusValue, formData.caseValue);
|
||||
formData['system.bonuscase'] = RdDItemSort.buildBonuscaseFromArrays(formData.bonusValue, formData.caseValue);
|
||||
}
|
||||
|
||||
return this.item.update(formData);
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* -------------------------------------------- */
|
||||
import { Misc } from "./misc.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
|
||||
@ -14,9 +13,9 @@ export class RdDItemSort extends Item {
|
||||
static isCoutVariable(sort) {
|
||||
return sort && (sort.system.ptreve.toLowerCase() == "variable" || sort.system.ptreve.indexOf("+") >= 0);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static setCoutReveReel(sort){
|
||||
static setCoutReveReel(sort) {
|
||||
if (sort) {
|
||||
sort.system.ptreve_reel = this.isCoutVariable(sort) ? 1 : sort.system.ptreve;
|
||||
}
|
||||
@ -25,94 +24,91 @@ export class RdDItemSort extends Item {
|
||||
/* -------------------------------------------- */
|
||||
static getDifficulte(sort, variable) {
|
||||
if (sort && !RdDItemSort.isDifficulteVariable(sort)) {
|
||||
return Misc.toInt(sort.system.difficulte);
|
||||
return Misc.toInt(sort.system.difficulte);
|
||||
}
|
||||
return variable;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static buildBonusCaseList( caseBonusString, newCase ) {
|
||||
if (caseBonusString == undefined) {
|
||||
return [];
|
||||
}
|
||||
let bonusCaseList = [];
|
||||
let bonusCaseArray = caseBonusString == undefined ? [] : caseBonusString.split(',');
|
||||
for( let bonusCase of bonusCaseArray) {
|
||||
let bonusSplit = bonusCase.split(':');
|
||||
bonusCaseList.push( { case: bonusSplit[0], bonus: bonusSplit[1] } );
|
||||
}
|
||||
if ( newCase )
|
||||
bonusCaseList.push( {case: "Nouvelle", bonus: 0} );
|
||||
return bonusCaseList;
|
||||
static buildBonusCaseList(bonuscase, newCase) {
|
||||
const list = RdDItemSort._bonuscaseStringToList(bonuscase)
|
||||
if (newCase) {
|
||||
return list.concat({ case: "Nouvelle", bonus: 0 });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retourne une liste de bonus/case pour un item-sheet
|
||||
* @param {} item
|
||||
*/
|
||||
static getBonusCaseList( item, newCase = false ) {
|
||||
static getBonusCaseList(item, newCase = false) {
|
||||
// Gestion spéciale case bonus
|
||||
if ( item.type == 'sort') {
|
||||
return this.buildBonusCaseList(item.system.bonuscase, newCase );
|
||||
if (item.type == 'sort') {
|
||||
return RdDItemSort.buildBonusCaseList(item.system.bonuscase, newCase);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** Met à jour les données de formulaire
|
||||
* si static des bonus de cases sont présents
|
||||
* */
|
||||
static buildBonusCaseStringFromFormData( bonuses, cases ) {
|
||||
if ( bonuses ) {
|
||||
let list = [];
|
||||
let caseCheck = {};
|
||||
for (let i=0; i<bonuses.length; i++) {
|
||||
let coord = cases[i]?.toUpperCase() || 'A1';
|
||||
let bonus = bonuses[i] || 0;
|
||||
if ( TMRUtility.verifyTMRCoord( coord ) && bonus > 0 && caseCheck[coord] == undefined ) {
|
||||
static buildBonuscaseFromArrays(bonuses, coords) {
|
||||
if (bonuses) {
|
||||
const list = [];
|
||||
const caseCheck = {};
|
||||
for (let i = 0; i < bonuses.length && i < coords.length; i++) {
|
||||
const coord = coords[i] == 'Fleuve' ? 'Fleuve' : (coords[i]?.toUpperCase() ?? 'A1');
|
||||
const bonus = bonuses[i] || 0;
|
||||
if (TMRUtility.verifyTMRCoord(coord) && bonus > 0 && caseCheck[coord] == undefined) {
|
||||
caseCheck[coord] = bonus;
|
||||
list.push( coord+":"+bonus );
|
||||
list.push({ case: coord, bonus: bonus });
|
||||
}
|
||||
}
|
||||
return list.toString();
|
||||
return RdDItemSort._bonuscaseListToString(list);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static incrementBonusCase( actor, sort, coord ) {
|
||||
let bonusCaseList = this.buildBonusCaseList(sort.system.bonuscase, false);
|
||||
//console.log("ITEMSORT", sort, bonusCaseList);
|
||||
|
||||
let found = false;
|
||||
let StringList = [];
|
||||
for( let bc of bonusCaseList) {
|
||||
if (bc.case == coord) { // Case existante
|
||||
found = true;
|
||||
bc.bonus = Number(bc.bonus) + 1;
|
||||
}
|
||||
StringList.push( bc.case+':'+bc.bonus );
|
||||
}
|
||||
if ( !found) { //Nouvelle case, bonus de 1
|
||||
StringList.push(coord+':1');
|
||||
}
|
||||
|
||||
// Sauvegarde/update
|
||||
let bonuscase = StringList.toString();
|
||||
//console.log("Bonus cae :", bonuscase);
|
||||
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }] );
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCaseBonus( sort, coord) {
|
||||
let bonusCaseList = this.buildBonusCaseList(sort.system.bonuscase, false);
|
||||
for( let bc of bonusCaseList) {
|
||||
if (bc.case == coord) { // Case existante
|
||||
return Number(bc.bonus);
|
||||
}
|
||||
static incrementBonusCase(actor, sort, coord) {
|
||||
if (TMRUtility.getTMR(coord).type == "fleuve") {
|
||||
coord = 'Fleuve';
|
||||
}
|
||||
return 0;
|
||||
const list = RdDItemSort.buildBonusCaseList(sort.system.bonuscase, false);
|
||||
const bonus = Number(list.find(it => it.case == coord)?.bonus ?? 0);
|
||||
const modified = { case: coord, bonus: bonus + 1 };
|
||||
|
||||
const bonuscase = RdDItemSort._bonuscaseListToString(
|
||||
list.filter(it => it.case != coord).concat(modified)
|
||||
);
|
||||
|
||||
// Sauvegarde/update
|
||||
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCaseBonus(sort, coord) {
|
||||
const isFleuve = TMRUtility.getTMR(coord).type == "fleuve";
|
||||
|
||||
let bc = RdDItemSort.buildBonusCaseList(sort.system.bonuscase, false)
|
||||
.filter(it => it.case == coord || (isFleuve && it.case == 'Fleuve'))
|
||||
.find(it => true)
|
||||
return Number(bc?.bonus ?? 0);
|
||||
}
|
||||
|
||||
static _bonuscaseListToString(list) {
|
||||
return list.map(it => `${it.case}:${it.bonus}`)
|
||||
.sort(Misc.ascending())
|
||||
.join(',');
|
||||
}
|
||||
static _bonuscaseStringToList(bonuscase) {
|
||||
return (bonuscase ?? '').split(',').map(it => {
|
||||
const b = it.split(':');
|
||||
return { case: b[0], bonus: b[1] };
|
||||
});
|
||||
}
|
||||
|
||||
}
|
208
module/item.js
208
module/item.js
@ -2,38 +2,87 @@ import { DialogItemVente } from "./dialog-item-vente.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDHerbes } from "./rdd-herbes.js";
|
||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||
import { RdDRaretes } from "./item/raretes.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||
|
||||
export const TYPES = {
|
||||
competence: 'competence',
|
||||
competencecreature: 'competencecreature',
|
||||
empoignade: 'empoignade',
|
||||
possession: 'possession',
|
||||
blessure: 'blessure',
|
||||
maladie: 'maladie',
|
||||
poison: 'poison',
|
||||
arme: 'arme',
|
||||
armure: 'armure',
|
||||
conteneur: 'conteneur',
|
||||
objet: 'objet',
|
||||
monnaie: 'monnaie',
|
||||
gemme: 'gemme',
|
||||
munition: 'munition',
|
||||
nourritureboisson: 'nourritureboisson',
|
||||
herbe: 'herbe',
|
||||
plante: 'plante',
|
||||
ingredient: 'ingredient',
|
||||
faune: 'faune',
|
||||
livre: 'livre',
|
||||
potion: 'potion',
|
||||
service: 'service',
|
||||
musique: 'musique',
|
||||
danse: 'danse',
|
||||
chant: 'chant',
|
||||
jeu: 'jeu',
|
||||
recettecuisine: 'recettecuisine',
|
||||
oeuvre: 'oeuvre',
|
||||
recettealchimique: 'recettealchimique',
|
||||
tache: 'tache',
|
||||
sort: 'sort',
|
||||
sortreserve: 'sortreserve',
|
||||
rencontre: 'rencontre',
|
||||
queue: 'queue',
|
||||
ombre: 'ombre',
|
||||
souffle: 'souffle',
|
||||
tete: 'tete',
|
||||
casetmr: 'casetmr',
|
||||
meditation: 'meditation',
|
||||
signedraconique: 'signedraconique',
|
||||
tarot: 'tarot',
|
||||
nombreastral: 'nombreastral',
|
||||
extraitpoetique: 'extraitpoetique',
|
||||
}
|
||||
|
||||
const typesInventaireMateriel = [
|
||||
"arme",
|
||||
"armure",
|
||||
"conteneur",
|
||||
"faune",
|
||||
"gemme",
|
||||
"herbe",
|
||||
"plante",
|
||||
"ingredient",
|
||||
"livre",
|
||||
"monnaie",
|
||||
"munition",
|
||||
"nourritureboisson",
|
||||
"objet",
|
||||
"potion",
|
||||
TYPES.arme,
|
||||
TYPES.armure,
|
||||
TYPES.conteneur,
|
||||
TYPES.faune,
|
||||
TYPES.gemme,
|
||||
TYPES.herbe,
|
||||
TYPES.plante,
|
||||
TYPES.ingredient,
|
||||
TYPES.livre,
|
||||
TYPES.monnaie,
|
||||
TYPES.munition,
|
||||
TYPES.nourritureboisson,
|
||||
TYPES.objet,
|
||||
TYPES.potion,
|
||||
]
|
||||
const typesInventaire = {
|
||||
materiel: typesInventaireMateriel,
|
||||
all: ['service'].concat(typesInventaireMateriel),
|
||||
}
|
||||
|
||||
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
|
||||
const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"]
|
||||
const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"]
|
||||
const typesObjetsEffet = ["possession", "poison", "maladie", "blessure"]
|
||||
const typesObjetsCompetence = ["competence", "competencecreature"]
|
||||
const typesObjetsTemporels = ["blessure", "poison", "maladie", "queue", "ombre", "souffle", "signedraconique", "rencontre"]
|
||||
const typesObjetsOeuvres = [TYPES.oeuvre, TYPES.recettecuisine, TYPES.musique, TYPES.chant, TYPES.danse, TYPES.jeu]
|
||||
const typesObjetsDraconiques = [TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.tete, TYPES.signedraconique, TYPES.sortreserve, TYPES.rencontre]
|
||||
const typesObjetsConnaissance = [TYPES.meditation, TYPES.recettealchimique, TYPES.sort]
|
||||
const typesObjetsEffet = [TYPES.possession, TYPES.poison, TYPES.maladie, TYPES.blessure]
|
||||
const typesObjetsCompetence = [TYPES.competence, TYPES.competencecreature]
|
||||
const typesObjetsTemporels = [TYPES.blessure, TYPES.poison, TYPES.maladie, TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.signedraconique, TYPES.rencontre]
|
||||
const typesObjetsEquipable = [TYPES.arme, TYPES.armure, TYPES.objet];
|
||||
const typesEnvironnement = typesInventaireMateriel;
|
||||
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
|
||||
const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc
|
||||
@ -75,11 +124,16 @@ export const defaultItemImg = {
|
||||
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
|
||||
extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
|
||||
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
|
||||
empoignade: "systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp"
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDItem extends Item {
|
||||
|
||||
static get defaultIcon() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
static getDefaultImg(itemType) {
|
||||
return game.system.rdd.itemClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
||||
}
|
||||
@ -87,12 +141,12 @@ export class RdDItem extends Item {
|
||||
static isFieldInventaireModifiable(type, field) {
|
||||
switch (field) {
|
||||
case 'quantite':
|
||||
if (['conteneur'].includes(type)) {
|
||||
if ([TYPES.conteneur].includes(type)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'cout':
|
||||
if (['monnaie'].includes(type)) {
|
||||
if ([TYPES.monnaie].includes(type)) {
|
||||
return game.user.isGM;
|
||||
}
|
||||
break;
|
||||
@ -138,49 +192,58 @@ export class RdDItem extends Item {
|
||||
super(docData, context);
|
||||
}
|
||||
|
||||
static get defaultIcon() {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
getUniteQuantite() {
|
||||
switch (this.type) {
|
||||
case "monnaie": return "(Pièces)"
|
||||
case "herbe":
|
||||
case TYPES.monnaie: return "(Pièces)"
|
||||
case TYPES.herbe:
|
||||
switch (this.system.categorie) {
|
||||
case 'Alchimie': case 'Repos': case 'Soin':
|
||||
return "(Brins)"
|
||||
case 'Cuisine': return '';
|
||||
}
|
||||
return '';
|
||||
case "ingredient": return "(Pépins ou Brins)"
|
||||
case TYPES.ingredient: return "(Pépins ou Brins)"
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
isCompetencePersonnage() { return this.type == 'competence' }
|
||||
isCompetenceCreature() { return this.type == 'competencecreature' }
|
||||
isConteneur() { return this.type == 'conteneur'; }
|
||||
isMonnaie() { return this.type == 'monnaie'; }
|
||||
isPotion() { return this.type == 'potion'; }
|
||||
isNourritureBoisson() { return this.type == 'nourritureboisson'; }
|
||||
isService() { return this.type == 'service'; }
|
||||
isEquipable() {
|
||||
return typesObjetsEquipable.includes(this.type)
|
||||
}
|
||||
|
||||
isCompetencePersonnage() { return this.type == TYPES.competence }
|
||||
isCompetenceCreature() { return this.type == TYPES.competencecreature }
|
||||
isConteneur() { return this.type == TYPES.conteneur; }
|
||||
isMonnaie() { return this.type == TYPES.monnaie; }
|
||||
isPotion() { return this.type == TYPES.potion; }
|
||||
isNourritureBoisson() { return this.type == TYPES.nourritureboisson; }
|
||||
isService() { return this.type == TYPES.service; }
|
||||
|
||||
isCompetence() { return typesObjetsCompetence.includes(this.type) }
|
||||
isCompetencePossession() { return TYPES.competencecreature == this.type && this.system.categorie == "possession" }
|
||||
isTemporel() { return typesObjetsTemporels.includes(this.type) }
|
||||
isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
|
||||
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
|
||||
isQueueDragon() { return [TYPES.queue, TYPES.ombre].includes(this.type) }
|
||||
isEffet() { return typesObjetsEffet.includes(this.type) }
|
||||
isConnaissance() { return typesObjetsConnaissance.includes(this.type) }
|
||||
|
||||
isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); }
|
||||
isBoisson() { return this.isNourritureBoisson() && this.system.boisson; }
|
||||
isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
|
||||
isHerbeAPotion() { return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
|
||||
isBlessure() { return this.type == 'blessure' }
|
||||
isHerbeAPotion() { return this.type == TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
|
||||
isBlessure() { return this.type == TYPES.blessure }
|
||||
|
||||
isPresentDansMilieux(milieux) {
|
||||
return this.getEnvironnements(milieux).length > 0
|
||||
}
|
||||
getCategories() {
|
||||
switch (this.type) {
|
||||
case TYPES.competence: return RdDItemCompetence.getCategories()
|
||||
case TYPES.competencecreature: return RdDItemCompetenceCreature.getCategories()
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
getEnvironnements(milieux = undefined) {
|
||||
const environnements = this.isInventaire() ? this.system.environnement : undefined;
|
||||
@ -261,15 +324,15 @@ export class RdDItem extends Item {
|
||||
|
||||
getUtilisation() {
|
||||
switch (this.type) {
|
||||
case 'potion':
|
||||
case TYPES.potion:
|
||||
switch (this.system.categorie) {
|
||||
case 'Alchimie': case 'AlchimieEnchante': case 'AlchimieAutre': return 'alchimie'
|
||||
case 'Cuisine': return 'cuisine'
|
||||
case 'Remede': case 'Repos': case 'ReposEnchante': case 'Soin': case 'SoinEnchante': return 'soins'
|
||||
}
|
||||
return '';
|
||||
case 'nourritureboisson': return 'cuisine';
|
||||
case 'herbe': case 'faune': case 'ingredient': case 'plante':
|
||||
case TYPES.nourritureboisson: return 'cuisine';
|
||||
case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante:
|
||||
switch (this.system.categorie) {
|
||||
case 'Cuisine': return 'cuisine';
|
||||
case 'Toxique': case 'Poison': return 'poison';
|
||||
@ -284,9 +347,9 @@ export class RdDItem extends Item {
|
||||
getUtilisationCuisine() {
|
||||
if (this.getUtilisation() == 'cuisine') {
|
||||
switch (this.type) {
|
||||
case 'nourritureboisson':
|
||||
case TYPES.nourritureboisson:
|
||||
return 'pret';
|
||||
case 'herbe': case 'faune': case 'ingredient': case 'plante':
|
||||
case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante:
|
||||
return 'brut';
|
||||
}
|
||||
}
|
||||
@ -294,7 +357,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
|
||||
isCristalAlchimique() {
|
||||
return this.type == 'objet' && Grammar.toLowerCaseNoAccent(this.name) == 'cristal alchimique' && this.system.quantite > 0;
|
||||
return this.type == TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0;
|
||||
}
|
||||
|
||||
isMagique() {
|
||||
@ -317,21 +380,31 @@ export class RdDItem extends Item {
|
||||
}
|
||||
|
||||
getEncTotal() {
|
||||
return (this.isService() ? 0 : this.getQuantite()) * this.getEnc();
|
||||
return (this.getQuantite() ?? 0) * this.getEnc();
|
||||
}
|
||||
|
||||
getEnc() {
|
||||
switch (this.type) {
|
||||
case 'service':
|
||||
case TYPES.service:
|
||||
return 0;
|
||||
case 'herbe':
|
||||
case TYPES.herbe:
|
||||
return this.getEncHerbe();
|
||||
case 'gemme':
|
||||
case TYPES.gemme:
|
||||
return encPepin * this.system.taille;
|
||||
}
|
||||
return Math.max(this.system.encombrement ?? 0, 0);
|
||||
}
|
||||
|
||||
getEncContenu() {
|
||||
return this.getContenu()
|
||||
.map(it => it.getRecursiveEnc())
|
||||
.reduce(Misc.sum(), 0);
|
||||
}
|
||||
|
||||
getRecursiveEnc() {
|
||||
return this.getEncTotal() + this.getEncContenu()
|
||||
}
|
||||
|
||||
getEncHerbe() {
|
||||
switch (this.system.categorie) {
|
||||
case 'Repos': case 'Soin': case 'Alchimie':
|
||||
@ -341,6 +414,18 @@ export class RdDItem extends Item {
|
||||
|
||||
}
|
||||
|
||||
getContenu() {
|
||||
if (this.isConteneur()) {
|
||||
return this.system.contenu.map(idContenu => this.actor.getItem(idContenu));
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
isConteneurContenu(conteneur) {
|
||||
return this.getContenu()
|
||||
.find(it => it.id == conteneur.id || it.isConteneurContenu(conteneur))
|
||||
}
|
||||
|
||||
valeurTotale() {
|
||||
return (this.isService() ? 1 : this.getQuantite()) * this.valeur()
|
||||
}
|
||||
@ -366,6 +451,7 @@ export class RdDItem extends Item {
|
||||
}
|
||||
this.system.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
|
||||
}
|
||||
this.equipable = this.isEquipable();
|
||||
}
|
||||
|
||||
prepareDataPotion() {
|
||||
@ -381,7 +467,7 @@ export class RdDItem extends Item {
|
||||
|
||||
getActionPrincipale(options = { warnIfNot: true }) {
|
||||
switch (this.type) {
|
||||
case 'conteneur': return 'Ouvrir';
|
||||
case TYPES.conteneur: return 'Ouvrir';
|
||||
}
|
||||
if (this.actor?.isPersonnage()) {
|
||||
const warn = options.warnIfNot;
|
||||
@ -389,11 +475,11 @@ export class RdDItem extends Item {
|
||||
return 'Utiliser';
|
||||
}
|
||||
switch (this.type) {
|
||||
case 'nourritureboisson': return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
|
||||
case 'potion': return this._actionOrWarnQuantiteZero('Boire', warn);
|
||||
case 'livre': return this._actionOrWarnQuantiteZero('Lire', warn);
|
||||
case 'herbe': return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
|
||||
case 'queue': case 'ombre': return this.system.refoulement > 0 ? 'Refouler' : undefined;
|
||||
case TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
|
||||
case TYPES.potion: return this._actionOrWarnQuantiteZero('Boire', warn);
|
||||
case TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn);
|
||||
case TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
|
||||
case TYPES.queue: case TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
@ -408,11 +494,11 @@ export class RdDItem extends Item {
|
||||
return;
|
||||
}
|
||||
switch (this.type) {
|
||||
case 'potion': return await actor.consommerPotion(this, onActionItem);
|
||||
case 'livre': return await actor.actionLire(this);
|
||||
case 'conteneur': return await this.sheet.render(true);
|
||||
case 'herbe': return await actor.actionHerbe(this);
|
||||
case 'queue': case 'ombre': return await actor.actionRefoulement(this);
|
||||
case TYPES.potion: return await actor.consommerPotion(this, onActionItem);
|
||||
case TYPES.livre: return await actor.actionLire(this);
|
||||
case TYPES.conteneur: return await this.sheet.render(true);
|
||||
case TYPES.herbe: return await actor.actionHerbe(this, onActionItem);
|
||||
case TYPES.queue: case TYPES.ombre: return await actor.actionRefoulement(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -611,7 +697,7 @@ export class RdDItem extends Item {
|
||||
_armeChatData() {
|
||||
return [
|
||||
`<b>Compétence</b>: ${this.system.competence}`,
|
||||
`<b>Dommages</b>: ${this.system.dommages}`,
|
||||
`<b>Dommages</b>: ${this.system.dommages} ${this.system.mortalite == 'non-mortel' ? '(Non mortel)' : ''}`,
|
||||
`<b>Force minimum</b>: ${this.system.force}`,
|
||||
`<b>Resistance</b>: ${this.system.resistance}`,
|
||||
...this._inventaireTemplateChatData()
|
||||
|
51
module/item/armure.js
Normal file
51
module/item/armure.js
Normal file
@ -0,0 +1,51 @@
|
||||
import { RdDItem } from "../item.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||
|
||||
export class RdDItemArmure extends RdDItem {
|
||||
|
||||
static get defaultIcon() {
|
||||
return "systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp";
|
||||
}
|
||||
|
||||
deteriorerArmure(dmg) {
|
||||
if (!ReglesOptionnelles.isUsing('deteriorationArmure') || this.system.protection == '0') {
|
||||
return;
|
||||
}
|
||||
let deterioration = (this.system.deterioration ?? 0) + dmg;
|
||||
let protection = this.system.protection;
|
||||
|
||||
if (deterioration >= 10) {
|
||||
deterioration -= 10;
|
||||
protection = this.calculProtectionDeterioree();
|
||||
ChatMessage.create({ content: `Votre armure ${this.name} s'est détériorée, elle protège maintenant de ${protection}` });
|
||||
}
|
||||
this.update({
|
||||
system: {
|
||||
deterioration: deterioration,
|
||||
protection: protection
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
calculProtectionDeterioree() {
|
||||
const protectionCourante = this.system.protection;
|
||||
let res = /(\d+)?d(\d+)(\-\d+)?/.exec(protectionCourante);
|
||||
if (res) {
|
||||
let protection = Misc.toInt(res[2]);
|
||||
let malus = Misc.toInt(res[3]) - 1;
|
||||
if (protection + malus <= 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return `1d${protection}${malus}`;
|
||||
}
|
||||
}
|
||||
else if (/\d+/.exec(protectionCourante)) {
|
||||
return `1d${protectionCourante}`;
|
||||
}
|
||||
else {
|
||||
ui.notifications.warn(`La valeur d'armure de votre ${this.name} est incorrecte`);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { RdDItem } from "../item.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDTimestamp } from "../rdd-timestamp.js";
|
||||
import { RdDTimestamp } from "../time/rdd-timestamp.js";
|
||||
|
||||
const BASE_TACHE_SOIN_BLESSURE = {
|
||||
type: "tache",
|
||||
@ -14,11 +14,11 @@ const TACHES_SOIN_BLESSURE = {
|
||||
}
|
||||
|
||||
const definitionsBlessures = [
|
||||
{ type: "contusion", gravite: 0, labelGravite: 'Contusion/éraflure', max: 100, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/eraflure.webp" },
|
||||
{ type: "legere", gravite: 2, labelGravite: 'Légère', max: 5, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
|
||||
{ type: "grave", gravite: 4, labelGravite: 'Grave', max: 2, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
|
||||
{ type: "critique", gravite: 6, labelGravite: 'Critique', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
|
||||
{ type: "mort", gravite: 8, labelGravite: 'Mort', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/mort.webp" }
|
||||
{ type: "contusion", gravite: 0, label: 'Contusion/éraflure', max: 100, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/eraflure.webp" },
|
||||
{ type: "legere", gravite: 2, label: 'Légère', max: 5, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
|
||||
{ type: "grave", gravite: 4, label: 'Grave', max: 2, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
|
||||
{ type: "critique", gravite: 6, label: 'Critique', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
|
||||
{ type: "mort", gravite: 8, label: 'Mort', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/mort.webp" }
|
||||
]
|
||||
|
||||
export class RdDItemBlessure extends RdDItem {
|
||||
@ -29,7 +29,7 @@ export class RdDItemBlessure extends RdDItem {
|
||||
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData();
|
||||
this.system.labelGravite = this.getLabelGravite()
|
||||
this.system.label = this.getLabelGravite()
|
||||
}
|
||||
|
||||
static prepareTacheSoin(gravite) {
|
||||
@ -40,19 +40,19 @@ export class RdDItemBlessure extends RdDItem {
|
||||
}
|
||||
return mergeObject(duplicate(BASE_TACHE_SOIN_BLESSURE), tache)
|
||||
}
|
||||
static async createBlessure(actor, gravite, localisation = '') {
|
||||
static async createBlessure(actor, gravite, localisation = '', attacker) {
|
||||
const definition = RdDItemBlessure.getDefinition(gravite)
|
||||
const blessure = {
|
||||
name: definition.labelGravite,
|
||||
name: definition.label,
|
||||
type: 'blessure',
|
||||
img: definition.icon,
|
||||
system: {
|
||||
gravite: gravite,
|
||||
difficulte: - gravite,
|
||||
localisation: localisation
|
||||
localisation: localisation,
|
||||
origine: attacker?.name ?? ""
|
||||
}
|
||||
}
|
||||
|
||||
const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
|
||||
return blessures[0]
|
||||
}
|
||||
@ -89,33 +89,37 @@ export class RdDItemBlessure extends RdDItem {
|
||||
|
||||
async recuperationBlessure({ actor, timestamp, message, isMaladeEmpoisonne, blessures }) {
|
||||
if (this.parent != actor || actor == undefined) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (new RdDTimestamp(this.system.fin).isAfterIndexDate(timestamp)) {
|
||||
if (new RdDTimestamp(this.system.temporel.fin).compare(timestamp) > 0) {
|
||||
// attente periode
|
||||
return
|
||||
}
|
||||
if (this.system.gravite > 0) {
|
||||
const update = { premierssoins: { bonus: 0 }, soinscomplets: { bonus: 0 } }
|
||||
const update = { system: { premierssoins: { bonus: 0 }, soinscomplets: { bonus: 0 } } }
|
||||
const gravite = this.system.gravite;
|
||||
const graviteMoindre = gravite - 2;
|
||||
const moindres = blessures.filter(it => it.system.gravite == graviteMoindre, 'blessures').length
|
||||
const labelGravite = RdDItemBlessure.getLabelGravite(gravite);
|
||||
const label = this.getLabelGravite();
|
||||
|
||||
let rolled = await actor.jetRecuperationConstitution(Misc.toInt(this.system.soinscomplets.bonus) + actor.system.sante.bonusPotion, message);
|
||||
let rolled = await actor.jetRecuperationConstitution(this.system.soinscomplets.bonus, message);
|
||||
|
||||
if (rolled.isETotal) {
|
||||
message.content += ` -- une blessure ${labelGravite} s'infecte (temps de guérison augmenté de ${definition.facteur} jours, perte de vie)`;
|
||||
mergeObject(update, { fin: { indexDate: timestamp.addJours(gravite).indexDate } });
|
||||
message.content += ` -- une blessure ${label} s'infecte (temps de guérison augmenté de ${gravite} jours, perte de vie)`;
|
||||
await actor.santeIncDec("vie", -1);
|
||||
mergeObject(update, {
|
||||
system: { fin: { indexDate: timestamp.addJours(gravite).indexDate } }
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (!isMaladeEmpoisonne && rolled.isSuccess && this.peutRetrograder(graviteMoindre, moindres)) {
|
||||
message.content += ` -- une blessure ${labelGravite} cicatrise`;
|
||||
mergeObject(update, { gravite: graviteMoindre, fin: { indexDate: timestamp.addJours(graviteMoindre).indexDate } });
|
||||
message.content += ` -- une blessure ${label} cicatrise`;
|
||||
mergeObject(update, {
|
||||
system: { gravite: graviteMoindre, fin: { indexDate: timestamp.addJours(graviteMoindre).indexDate } }
|
||||
});
|
||||
}
|
||||
else {
|
||||
message.content += ` -- une blessure ${labelGravite} reste stable`;
|
||||
message.content += ` -- une blessure ${label} reste stable`;
|
||||
}
|
||||
}
|
||||
await this.update(update);
|
||||
@ -148,7 +152,7 @@ export class RdDItemBlessure extends RdDItem {
|
||||
}
|
||||
|
||||
getLabelGravite() {
|
||||
return RdDItemBlessure.getDefinition(this.system.gravite).labelGravite
|
||||
return RdDItemBlessure.getDefinition(this.system.gravite).label
|
||||
}
|
||||
|
||||
static getDefinition(gravite) {
|
||||
@ -174,4 +178,22 @@ export class RdDItemBlessure extends RdDItem {
|
||||
isMort() {
|
||||
return this.system.gravite > 6
|
||||
}
|
||||
|
||||
getProprietes() {
|
||||
return [
|
||||
RdDItem.propertyIfDefined('Causée par', this.system.origine, this.system.origine),
|
||||
`<b>Heure et Date</b>: ${new RdDTimestamp(this.system.temporel.debut).formatDateHeure()}`,
|
||||
RdDItem.propertyIfDefined('Blessé', this.parent?.name, this.parent),
|
||||
`<b>Localisation</b>: ${this.system.localisation}`,
|
||||
`<b>Gravité</b>: ${RdDItemBlessure.getDefinition(this.system.gravite).label}`,
|
||||
`<b>Difficulté des soins</b>: ${this.system.difficulte}`,
|
||||
(this.system.soinscomplets.done ?
|
||||
`<b>Bonus soins complets</b>: ${this.system.soinscomplets.bonus}` :
|
||||
(this.system.premierssoins.done ?
|
||||
`<b>Bonus premiers soins</b>: ${this.system.premierssoins.bonus}` :
|
||||
`<b>Points de tâche</b>: ${this.system.premierssoins.tache}`
|
||||
)
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { RdDItem } from "../item.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDTimestamp } from "../rdd-timestamp.js";
|
||||
import { RdDTimestamp } from "../time/rdd-timestamp.js";
|
||||
|
||||
export class RdDItemMaladie extends RdDItem {
|
||||
|
||||
|
@ -29,7 +29,7 @@ export class RdDConteneurItemSheet extends RdDItemInventaireSheet {
|
||||
/* -------------------------------------------- */
|
||||
prepareConteneurData(formData) {
|
||||
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
|
||||
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ import { RdDItem, defaultItemImg } from "../item.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDDice } from "../rdd-dice.js";
|
||||
import { RdDRollTables } from "../rdd-rolltables.js";
|
||||
import { RdDTimestamp } from "../rdd-timestamp.js";
|
||||
import { RdDTimestamp } from "../time/rdd-timestamp.js";
|
||||
import { TMRType, TMRUtility } from "../tmr-utility.js";
|
||||
|
||||
const tableSignesIndicatifs = [
|
||||
|
@ -2,8 +2,8 @@ import { RdDBaseActor } from "./actor/base-actor.js";
|
||||
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Monnaie } from "./item-monnaie.js";
|
||||
import { RdDItem } from "./item.js";
|
||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||
import { RdDItem, TYPES } from "./item.js";
|
||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
import { RdDRaretes } from "./item/raretes.js";
|
||||
|
||||
class Migration {
|
||||
@ -13,7 +13,7 @@ class Migration {
|
||||
|
||||
async applyItemsUpdates(computeUpdates) {
|
||||
await game.actors.forEach(async (actor) => {
|
||||
const actorItemUpdates = computeUpdates(actor.items);
|
||||
const actorItemUpdates = computeUpdates(actor.items).filter(it => it != undefined);
|
||||
if (actorItemUpdates.length > 0) {
|
||||
console.log(
|
||||
this.code,
|
||||
@ -24,7 +24,7 @@ class Migration {
|
||||
}
|
||||
});
|
||||
|
||||
const itemUpdates = computeUpdates(game.items);
|
||||
const itemUpdates = computeUpdates(game.items).filter(it => it != undefined);
|
||||
if (itemUpdates.length > 0) {
|
||||
console.log(this.code, "Applying updates on items", itemUpdates);
|
||||
await Item.updateDocuments(itemUpdates);
|
||||
@ -65,7 +65,6 @@ class _1_5_34_migrationPngWebp {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class _10_0_16_MigrationSortsReserve extends Migration {
|
||||
get code() { return "creation-item-sort-reserve"; }
|
||||
get version() { return "10.0.16"; }
|
||||
@ -370,6 +369,7 @@ class _10_4_6_ServicesEnCommerces extends Migration {
|
||||
return itemToCreate;
|
||||
}
|
||||
}
|
||||
|
||||
class _10_5_0_UpdatePeriodicite extends Migration {
|
||||
get code() { return "migration-periodicite-poisons-maladies"; }
|
||||
get version() { return "10.5.0"; }
|
||||
@ -452,13 +452,68 @@ class _10_7_0_MigrationBlessures extends Migration {
|
||||
fin: { indexDate: datePremiereRecup.indexDate, indexMinute: 0 },
|
||||
premierssoins: { done: blessure.psdone, bonus: blessure.premiers_soins },
|
||||
soinscomplets: { done: blessure.scdone, bonus: blessure.soins_complets },
|
||||
localisation: blessure.localisation,
|
||||
jours: blessure.jours
|
||||
localisation: blessure.localisation
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _10_7_19_CategorieCompetenceCreature extends Migration {
|
||||
get code() { return "categorie-competence-creature"; }
|
||||
get version() { return "10.7.19"; }
|
||||
|
||||
async migrate() {
|
||||
await this.applyItemsUpdates(items => items
|
||||
.filter(it => TYPES.competencecreature == it.type)
|
||||
.map(it => this.migrateCompetenceCreature(it))
|
||||
);
|
||||
}
|
||||
|
||||
migrateCompetenceCreature(it) {
|
||||
const categorie = this.getCategorie(it)
|
||||
if (categorie == it.system.categorie) {
|
||||
return undefined
|
||||
}
|
||||
return { _id: it.id, 'system.categorie': categorie }
|
||||
}
|
||||
|
||||
getCategorie(it) {
|
||||
if (it.system.ispossession) {
|
||||
return 'possession'
|
||||
}
|
||||
switch (it.system.categorie) {
|
||||
case "melee":
|
||||
if (it.system.isnaturelle) {
|
||||
return 'naturelle'
|
||||
}
|
||||
return 'melee'
|
||||
case "particuliere": case "specialisee": case "connaissance":
|
||||
return "generale"
|
||||
default:
|
||||
return it.system.categorie
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class _10_7_19_PossessionsEntiteVictime extends Migration {
|
||||
get code() { return "possessions-entite-victime"; }
|
||||
get version() { return "10.7.19"; }
|
||||
|
||||
async migrate() {
|
||||
await this.applyItemsUpdates(items => items
|
||||
.filter(it => TYPES.possession == it.type)
|
||||
.map(it => this.migratePossession(it))
|
||||
);
|
||||
}
|
||||
|
||||
migratePossession(it) {
|
||||
return { _id: it.id,
|
||||
'system.entite.actorid': it.system.possesseurid,
|
||||
'system.victime.actorid': it.system.possedeid
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export class Migrations {
|
||||
static getMigrations() {
|
||||
return [
|
||||
@ -475,6 +530,8 @@ export class Migrations {
|
||||
new _10_4_6_ServicesEnCommerces(),
|
||||
new _10_5_0_UpdatePeriodicite(),
|
||||
new _10_7_0_MigrationBlessures(),
|
||||
new _10_7_19_CategorieCompetenceCreature(),
|
||||
new _10_7_19_PossessionsEntiteVictime(),
|
||||
];
|
||||
}
|
||||
|
||||
@ -491,7 +548,7 @@ export class Migrations {
|
||||
migrate() {
|
||||
const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion");
|
||||
if (isNewerVersion(game.system.version, currentVersion)) {
|
||||
//if (true) { /* comment previous and uncomment here to test before upgrade */
|
||||
// if (true) { /* comment previous and uncomment here to test before upgrade */
|
||||
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
|
||||
if (migrations.length > 0) {
|
||||
migrations.sort((a, b) => this.compareVersions(a, b));
|
||||
|
@ -42,7 +42,7 @@ export class Misc {
|
||||
}
|
||||
|
||||
static typeName(type, subType) {
|
||||
return subType ? game.i18n.localize(`${type.toUpperCase()}.Type${Misc.upperFirst(subType)}`)
|
||||
return subType ? game.i18n.localize(`TYPES.${type}.${Misc.upperFirst(subType)}`)
|
||||
: '';
|
||||
}
|
||||
|
||||
@ -239,4 +239,15 @@ export class Misc {
|
||||
}
|
||||
return subset;
|
||||
}
|
||||
|
||||
static cssRotation(angle) {
|
||||
const rotation = `rotate(${angle}deg)`;
|
||||
return {
|
||||
'transform': rotation,
|
||||
'-ms-transform': rotation,
|
||||
'-moz-transform': rotation,
|
||||
'-webkit-transform': rotation,
|
||||
'-o-transform': rotation
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { RdDPossession } from "./rdd-possession.js";
|
||||
|
||||
const conditionsTactiques = [
|
||||
{ type: '', descr: '', dmg: 0, attaque: 0, parade: 0, esquive: true },
|
||||
@ -24,6 +25,12 @@ export class RdDBonus {
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isDefenseAttaqueFinesse(rollData) {
|
||||
if (rollData.isEmpoignade && rollData.rolled?.isPart) {
|
||||
return true
|
||||
}
|
||||
if (RdDPossession.isDefensePossession(rollData)) {
|
||||
return RdDPossession.isPossessionFinesse(rollData)
|
||||
}
|
||||
return rollData.attackerRoll?.particuliere == 'finesse';
|
||||
}
|
||||
|
||||
@ -71,7 +78,7 @@ export class RdDBonus {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _dmgArme(rollData) {
|
||||
if ( rollData.arme) {
|
||||
if (rollData.arme) {
|
||||
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0);
|
||||
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
|
||||
return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0);
|
||||
|
@ -58,15 +58,6 @@ export class RdDCarac {
|
||||
selectedCarac?.label.match(/(Apparence|Force|Agilité|Dextérité|Vue|Ouïe|Odorat-Goût|Empathie|Dérobée|Mêlée|Tir|Lancer)/);
|
||||
}
|
||||
|
||||
static isIgnoreEtatGeneral(rollData) {
|
||||
const selectedCarac = rollData.selectedCarac;
|
||||
return !selectedCarac ||
|
||||
rollData.ethylisme ||
|
||||
RdDCarac.isChance(selectedCarac) ||
|
||||
(RdDCarac.isReve(selectedCarac) && !rollData.competence);
|
||||
}
|
||||
|
||||
|
||||
static computeTotal(carac, beaute = undefined) {
|
||||
const total = Object.values(carac ?? {}).filter(c => !c.derivee)
|
||||
.map(it => parseInt(it.value))
|
||||
|
@ -9,9 +9,10 @@ import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDRoll } from "./rdd-roll.js";
|
||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { STATUSES } from "./settings/status-effects.js";
|
||||
import { Targets } from "./targets.js";
|
||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const premierRoundInit = [
|
||||
@ -57,6 +58,7 @@ export class RdDCombatManager extends Combat {
|
||||
ChatUtility.removeChatMessageContaining(`<div data-combatid="${this.id}" data-combatmessage="actor-turn-summary">`)
|
||||
game.messages.filter(m => ChatUtility.getMessageData(m, 'attacker-roll') != undefined && ChatUtility.getMessageData(m, 'defender-roll') != undefined)
|
||||
.forEach(it => it.delete());
|
||||
RdDEmpoignade.deleteAllEmpoignades()
|
||||
}
|
||||
}
|
||||
|
||||
@ -85,19 +87,32 @@ export class RdDCombatManager extends Combat {
|
||||
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)
|
||||
const competence = combatant.actor.items.find(it => RdDItemCompetenceCreature.getCategorieAttaque(it))
|
||||
if (competence) {
|
||||
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, 0);
|
||||
}
|
||||
} else {
|
||||
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
|
||||
const compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.system.competence;
|
||||
let compName = "Corps à corps"
|
||||
if (armeCombat) {
|
||||
if (armeCombat.system.competence != "") {
|
||||
compName = armeCombat.system.competence
|
||||
}
|
||||
if (armeCombat.system.lancer != "") {
|
||||
compName = armeCombat.system.lancer
|
||||
}
|
||||
if (armeCombat.system.tir != "") {
|
||||
compName = armeCombat.system.tir
|
||||
}
|
||||
}
|
||||
const competence = RdDItemCompetence.findCompetence(combatant.actor.items, compName);
|
||||
if (competence) {
|
||||
if (competence && competence.system.defaut_carac) {
|
||||
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);
|
||||
} else {
|
||||
ui.notifications.warn(`Votre arme ${armeCombat.name} n'a pas de compétence renseignée`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -215,15 +230,15 @@ export class RdDCombatManager extends Combat {
|
||||
}
|
||||
|
||||
static listActionsCreature(competences) {
|
||||
return competences.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
|
||||
.map(it => RdDItemCompetenceCreature.armeNaturelle(it));
|
||||
return competences.map(it => RdDItemCompetenceCreature.armeCreature(it))
|
||||
.filter(it => it != undefined);
|
||||
}
|
||||
|
||||
static listActionsPossessions(actor) {
|
||||
return RdDCombatManager._indexActions(actor.getPossessions().map(p => {
|
||||
return {
|
||||
name: p.name,
|
||||
action: 'conjurer',
|
||||
action: 'possession',
|
||||
system: {
|
||||
competence: p.name,
|
||||
possessionid: p.system.possessionid,
|
||||
@ -240,15 +255,15 @@ export class RdDCombatManager extends Combat {
|
||||
return actions;
|
||||
}
|
||||
if (actor.isCreatureEntite()) {
|
||||
actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']));
|
||||
actions = RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']);
|
||||
} else if (actor.isPersonnage()) {
|
||||
// Recupération des items 'arme'
|
||||
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
|
||||
//.concat(RdDItemArme.empoignade())
|
||||
.concat(RdDItemArme.empoignade())
|
||||
.concat(RdDItemArme.mainsNues());
|
||||
|
||||
const competences = actor.itemTypes['competence'];
|
||||
actions = actions.concat(RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac));
|
||||
actions = RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac);
|
||||
|
||||
if (actor.system.attributs.hautrevant.value) {
|
||||
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
|
||||
@ -336,7 +351,7 @@ export class RdDCombatManager extends Combat {
|
||||
} else if (combatant.actor.getSurprise() == "demi") {
|
||||
initOffset = 0;
|
||||
initInfo = "Demi Surprise"
|
||||
} else if (action.action == 'conjurer') {
|
||||
} else if (action.action == 'possession') {
|
||||
initOffset = 10;
|
||||
caracForInit = combatant.actor.getReveActuel();
|
||||
initInfo = "Possession"
|
||||
@ -737,17 +752,11 @@ export class RdDCombat {
|
||||
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
|
||||
return;
|
||||
}
|
||||
if (arme.system.cac == 'empoignade' && this.attacker.isCombatTouche()) {
|
||||
ChatMessage.create({
|
||||
alias: this.attacker.name,
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-actor-perte-empoignade.html', {
|
||||
attacker: this.attacker,
|
||||
competence: competence
|
||||
})
|
||||
});
|
||||
if (arme.system.cac == 'empoignade') {
|
||||
RdDEmpoignade.onAttaqueEmpoignade(this.attacker, this.defender)
|
||||
return;
|
||||
}
|
||||
RdDEmpoignade.checkEmpoignadeEnCours(this.attacker)
|
||||
|
||||
let rollData = this._prepareAttaque(competence, arme);
|
||||
console.log("RdDCombat.attaque >>>", rollData);
|
||||
@ -780,7 +789,6 @@ export class RdDCombat {
|
||||
let rollData = {
|
||||
passeArme: randomID(16),
|
||||
mortalite: arme?.system.mortalite,
|
||||
coupsNonMortels: false,
|
||||
competence: competence,
|
||||
surprise: this.attacker.getSurprise(true),
|
||||
surpriseDefenseur: this.defender.getSurprise(true),
|
||||
@ -1039,7 +1047,7 @@ export class RdDCombat {
|
||||
competence: this.defender.getCompetence(competenceParade),
|
||||
arme: armeParade,
|
||||
surprise: this.defender.getSurprise(true),
|
||||
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
||||
needParadeSignificative: ReglesOptionnelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
||||
needResist: RdDItemArme.needArmeResist(attackerRoll.arme, armeParade),
|
||||
carac: this.defender.system.carac,
|
||||
show: {}
|
||||
@ -1157,7 +1165,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async computeDeteriorationArme(defenderRoll) {
|
||||
if (!ReglesOptionelles.isUsing('resistanceArmeParade')) {
|
||||
if (!ReglesOptionnelles.isUsing('resistanceArmeParade')) {
|
||||
return;
|
||||
}
|
||||
const attackerRoll = defenderRoll.attackerRoll;
|
||||
@ -1206,7 +1214,7 @@ export class RdDCombat {
|
||||
}
|
||||
}
|
||||
// Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
|
||||
if (ReglesOptionelles.isUsing('defenseurDesarme') && resistance > 0 && RdDItemArme.getCategorieParade(defenderRoll.arme) != 'boucliers') {
|
||||
if (ReglesOptionnelles.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,
|
||||
@ -1221,7 +1229,7 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
async computeRecul(defenderRoll) { // Calcul du recul (p. 132)
|
||||
const attackerRoll = defenderRoll.attackerRoll;
|
||||
if (ReglesOptionelles.isUsing('recul') && this._isForceOuCharge(attackerRoll)) {
|
||||
if (ReglesOptionnelles.isUsing('recul') && this._isForceOuCharge(attackerRoll)) {
|
||||
const impact = this._computeImpactRecul(attackerRoll);
|
||||
const rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impact });
|
||||
if (rollRecul.rolled.isSuccess) {
|
||||
@ -1295,7 +1303,7 @@ export class RdDCombat {
|
||||
blessuresStatus: actor.computeResumeBlessure(),
|
||||
SConst: actor.getSConst(),
|
||||
actorId: actor.id,
|
||||
isGrave: actor.countBlessures(it => it.isGraves()) > 0,
|
||||
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
|
||||
isCritique: actor.countBlessures(it => it.isCritique()) > 0
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
|
||||
export class RdDConfirm {
|
||||
/* -------------------------------------------- */
|
||||
static confirmer(options, autresActions) {
|
||||
options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionelles.isUsing(options.settingConfirmer));
|
||||
options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionnelles.isUsing(options.settingConfirmer));
|
||||
if (options.bypass) {
|
||||
options.onAction();
|
||||
}
|
||||
@ -47,7 +47,7 @@ export class RdDConfirm {
|
||||
icon: '<i class="fas fa-user-check"></i>',
|
||||
label: options.buttonLabel + "<br>et ne plus demander",
|
||||
callback: () => {
|
||||
ReglesOptionelles.set(options.settingConfirmer, false);
|
||||
ReglesOptionnelles.set(options.settingConfirmer, false);
|
||||
options.onAction();
|
||||
}
|
||||
}
|
||||
|
436
module/rdd-empoignade.js
Normal file
436
module/rdd-empoignade.js
Normal file
@ -0,0 +1,436 @@
|
||||
/* -------------------------------------------- */
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDRoll } from "./rdd-roll.js";
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { STATUSES } from "./settings/status-effects.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { TYPES } from "./item.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDEmpoignade {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static init() {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static registerChatCallbacks(html) {
|
||||
html.on("click", '.defense-empoignade-cac', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
|
||||
});
|
||||
html.on("click", '.defense-empoignade-esquive', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
|
||||
});
|
||||
html.on("click", '.empoignade-poursuivre', event => {
|
||||
let attackerId = event.currentTarget.attributes['data-attackerId'].value
|
||||
let defenderId = event.currentTarget.attributes['data-defenderId'].value
|
||||
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId))
|
||||
});
|
||||
html.on("click", '.empoignade-entrainer-sol', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
RdDEmpoignade.entrainerAuSol(rollData)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
});
|
||||
html.on("click", '.empoignade-projeter-sol', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
RdDEmpoignade.projeterAuSol(rollData)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
});
|
||||
html.on("change", '.empoignade-perte-endurance', event => {
|
||||
const chatMessage = ChatUtility.getChatMessage(event);
|
||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||
if (event.currentTarget.value && event.currentTarget.value != "none") {
|
||||
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
|
||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static checkEmpoignadeEnCours(actor) {
|
||||
// TODO: autoriser la perception? la comédie/séduction?
|
||||
if (RdDEmpoignade.isEmpoignadeEnCours(actor)) {
|
||||
ui.notifications.warn("Une empoignade est en cours ! Normalement, vous ne pouvez rien faire d'autre que continuer l'empoignade ou la rompre.")
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static $storeRollEmpoignade(msg, rollData) {
|
||||
RdDEmpoignade.$reduceActorToIds(rollData);
|
||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData);
|
||||
}
|
||||
|
||||
static $reduceActorToIds(rollData) {
|
||||
rollData.attacker = { id: rollData.attacker.id };
|
||||
rollData.defender = { id: rollData.defender.id };
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static $readRollEmpoignade(msg) {
|
||||
const rollData = ChatUtility.getMessageData(msg, 'empoignade-roll-data');
|
||||
RdDEmpoignade.$replaceIdsWithActors(rollData);
|
||||
return rollData
|
||||
}
|
||||
|
||||
static $replaceIdsWithActors(rollData) {
|
||||
rollData.attacker = game.actors.get(rollData.attacker.id);
|
||||
rollData.defender = game.actors.get(rollData.defender.id);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isEmpoignadeEnCours(actor) {
|
||||
return actor.itemTypes[TYPES.empoignade].find(it => it.system.pointsemp > 0)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getEmpoignadeById(actor, id) {
|
||||
let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id)
|
||||
return emp && duplicate(emp) || undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getEmpoignade(attacker, defender) {
|
||||
let emp = attacker.itemTypes[TYPES.empoignade].find(it =>
|
||||
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
|
||||
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
|
||||
)
|
||||
if (emp) {
|
||||
return duplicate(emp);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getMalusTaille(emp, attacker, defender) {
|
||||
// Si pas empoigné, alors 0
|
||||
if (emp.system.pointsemp == 0) {
|
||||
return 0
|
||||
}
|
||||
// p135: Malus de -1 par point de taille de différence de taille au delà de 1 (donc -2 pour une différence de 3, ...)
|
||||
const diffTaille = attacker.system.carac.taille.value - defender.system.carac.taille.value;
|
||||
const diffTailleAbs = Math.abs(diffTaille)
|
||||
const signDiff = diffTaille > 0 ? 1 : -1
|
||||
|
||||
if (diffTailleAbs > 2) {
|
||||
return signDiff * (diffTailleAbs - 1)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
static isActionAutorisee(mode, attacker, defender) {
|
||||
const acting = RdDEmpoignade.isActionDefenseur(mode) ? defender : attacker;
|
||||
if (acting.getUserLevel(game.user) < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) {
|
||||
ui.notifications.warn(`Vous n'êtes pas autorisé à choisir l'action de ${acting.name}`)
|
||||
return false;
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
static isActionDefenseur(mode) {
|
||||
switch (mode) {
|
||||
case "liberer":
|
||||
case "contrer-empoigner":
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onAttaqueEmpoignade(attacker, defender) {
|
||||
if (!RdDEmpoignade.isActionAutorisee("empoigner", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
const isNouvelle = empoignade == undefined;
|
||||
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
||||
//console.log("W.", empoignade, defender.hasArmeeMeleeEquipee())
|
||||
if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) {
|
||||
ChatUtility.createChatWithRollMode(attacker.name, {
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-valider.html`, { attacker: attacker, defender: defender })
|
||||
})
|
||||
} else {
|
||||
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onAttaqueEmpoignadeValidee(attacker, defender) {
|
||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||
const isNouvelle = empoignade == undefined;
|
||||
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
||||
|
||||
let mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
|
||||
|
||||
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
|
||||
return
|
||||
}
|
||||
|
||||
let rollData = {
|
||||
mode, empoignade, attacker, defender,
|
||||
isEmpoignade: true,
|
||||
competence: attacker.getCompetence("Corps à corps"),
|
||||
selectedCarac: attacker.system.carac.melee,
|
||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
|
||||
}
|
||||
if (attacker.isCreatureEntite()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||
}
|
||||
if (empoignade.system.pointsemp >= 2) {
|
||||
if (!empoignade.system.ausol) {
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.html');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
} else {
|
||||
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onAttaqueEmpoignadeFromItem(empoignade) {
|
||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
||||
}
|
||||
|
||||
static async onImmobilisation(attacker, defender, empoignade) {
|
||||
const rollData = {
|
||||
mode: "immobilise",
|
||||
empoignade, attacker, defender,
|
||||
isEmpoignade: true,
|
||||
competence: attacker.getCompetence("Corps à corps")
|
||||
}
|
||||
const msg = await ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(attacker.name),
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.html`, rollData)
|
||||
})
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) {
|
||||
const dialog = await RdDRoll.create(attacker, rollData,
|
||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
|
||||
{
|
||||
name: 'jet-empoignade',
|
||||
label: 'Empoigner',
|
||||
callbacks: [{ action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, isNouvelle) },]
|
||||
});
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $onRollEmpoignade(rollData, isNouvelle = false) {
|
||||
let attacker = game.actors.get(rollData.attacker.id)
|
||||
let defender = game.actors.get(rollData.defender.id)
|
||||
|
||||
|
||||
if (rollData.rolled.isSuccess && isNouvelle) {
|
||||
const objectEmpoignade = rollData.empoignade.toObject();
|
||||
// Creer l'empoignade sur attaquant/defenseur
|
||||
attacker.creerObjetParMJ(objectEmpoignade);
|
||||
defender.creerObjetParMJ(objectEmpoignade);
|
||||
}
|
||||
|
||||
rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
|
||||
if (rollData.rolled.isPart) {
|
||||
rollData.particuliere = "finesse";
|
||||
}
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onDefenseEmpoignade(attackerRoll, mode, competenceName = "Corps à corps", carac = "melee") {
|
||||
let attacker = game.actors.get(attackerRoll.attacker.id)
|
||||
let defender = game.actors.get(attackerRoll.defender.id)
|
||||
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
|
||||
return
|
||||
}
|
||||
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
if (!empoignade) {
|
||||
ui.notifications.warn("Une erreur s'est produite : Aucune empoignade trouvée !!")
|
||||
return
|
||||
}
|
||||
|
||||
empoignade = duplicate(empoignade)
|
||||
let defenderRoll = {
|
||||
mode, attacker, defender, empoignade, attackerRoll,
|
||||
diffLibre: attackerRoll.diffLibre,
|
||||
attaqueParticuliere: attackerRoll.particuliere,
|
||||
competence: defender.getCompetence(competenceName),
|
||||
surprise: defender.getSurprise(true),
|
||||
carac: defender.system.carac,
|
||||
selectedCarac: defender.system.carac[carac],
|
||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, defender, attacker),
|
||||
show: {}
|
||||
};
|
||||
await RdDEmpoignade.$rollDefenseEmpoignade(defender, defenderRoll);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $rollDefenseEmpoignade(defender, defenderRoll) {
|
||||
const dialog = await RdDRoll.create(defender, defenderRoll,
|
||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-empoignade.html' },
|
||||
{
|
||||
name: 'empoignade',
|
||||
label: 'Contrer',
|
||||
callbacks: [
|
||||
{ action: async (r) => await RdDEmpoignade.$onRollContrerLiberer(r) }
|
||||
]
|
||||
}
|
||||
);
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $onRollContrerLiberer(rollData) {
|
||||
let empoignade = rollData.empoignade
|
||||
|
||||
if (rollData.mode == "contrer-empoigner" && !rollData.rolled.isSuccess) {
|
||||
empoignade.system.pointsemp++
|
||||
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
||||
}
|
||||
if (rollData.mode == "contrer-liberer" && !rollData.rolled.isSuccess) {
|
||||
empoignade.system.pointsemp--
|
||||
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
||||
}
|
||||
|
||||
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-empoignade-resultat.html')
|
||||
if (empoignade.system.pointsemp >= 2) {
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-empoignade-entrainer.html');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $updateEtatEmpoignade(empoignade) {
|
||||
console.log("UPDATE Empoignade", empoignade)
|
||||
|
||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||
let update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
|
||||
await defender.updateEmbeddedDocuments('Item', [update])
|
||||
|
||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||
emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
|
||||
update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
|
||||
await attacker.updateEmbeddedDocuments('Item', [update])
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $deleteEmpoignade(empoignade) {
|
||||
console.log("DELETE Empoignade", empoignade)
|
||||
|
||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||
await defender.deleteEmbeddedDocuments('Item', [emp._id])
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async entrainerAuSol(rollData) {
|
||||
let attacker = game.actors.get(rollData.attacker.id)
|
||||
let defender = game.actors.get(rollData.defender.id)
|
||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
empoignade.system.ausol = true
|
||||
await this.$updateEtatEmpoignade(empoignade)
|
||||
|
||||
await attacker.setEffect(STATUSES.StatusProne, true);
|
||||
await defender.setEffect(STATUSES.StatusProne, true);
|
||||
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.html');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async projeterAuSol(rollData) {
|
||||
let attacker = game.actors.get(rollData.attacker.id)
|
||||
let defender = game.actors.get(rollData.defender.id)
|
||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
await defender.setEffect(STATUSES.StatusProne, true);
|
||||
await this.$deleteEmpoignade(empoignade)
|
||||
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-projeter-sol.html');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async perteEndurance(rollData, perteMode) {
|
||||
let attacker = game.actors.get(rollData.attacker.id)
|
||||
let defender = game.actors.get(rollData.defender.id)
|
||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||
return
|
||||
}
|
||||
let empoignade = this.getEmpoignade(attacker, defender)
|
||||
|
||||
//console.log("Perte d'endurance :!!!", perteMode)
|
||||
let endValue = defender.system.sante.endurance.value
|
||||
if (perteMode == "end0") {
|
||||
await defender.santeIncDec("endurance", -endValue);
|
||||
}
|
||||
if (perteMode == "end1") {
|
||||
await defender.santeIncDec("endurance", -(endValue - 1));
|
||||
}
|
||||
if (perteMode == "endmoitie") {
|
||||
await defender.santeIncDec("endurance", -Math.floor(endValue / 2));
|
||||
}
|
||||
if (perteMode == "endquart") {
|
||||
await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4)));
|
||||
}
|
||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.html');
|
||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async deleteAllEmpoignades() {
|
||||
for (let actor of game.actors) {
|
||||
let empIds = actor.itemTypes["empoignade"].map(it => it.id)
|
||||
await actor.deleteEmbeddedDocuments('Item', empIds)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async deleteLinkedEmpoignade(actorId, empoignade) {
|
||||
let actorDeleteId = (actorId == empoignade.system.empoigneurid) ? empoignade.system.empoigneid : empoignade.system.empoigneurid
|
||||
let actor = game.actors.get(actorDeleteId)
|
||||
let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
|
||||
if (emp) {
|
||||
await actor.deleteEmbeddedDocuments('Item', [emp._id])
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createEmpoignade(attacker, defender) {
|
||||
return await Item.create({
|
||||
name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name,
|
||||
type: 'empoignade',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
||||
system: { description: "", empoignadeid: randomID(16), compteempoigne: 0, empoigneurid: attacker.id, empoigneid: defender.id, ptsemp: 0, empoigneurname: attacker.name, empoignename: defender.name }
|
||||
},
|
||||
{
|
||||
temporary: true
|
||||
})
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDHerbes extends Item {
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { TYPES } from "./item.js";
|
||||
|
||||
export class RdDHotbar {
|
||||
|
||||
static async addToHotbar(item, slot) {
|
||||
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}");`;
|
||||
static async createItemMacro(item, slot, armeCompetence = undefined) {
|
||||
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}"` + ((armeCompetence) ? `, "${armeCompetence}");` : `);`);
|
||||
let macro = game.macros.contents.find(m => (m.name === item.name) && (m.command === command));
|
||||
if (!macro) {
|
||||
macro = await Macro.create({
|
||||
@ -15,6 +16,33 @@ export class RdDHotbar {
|
||||
await game.user.assignHotbarMacro(macro, slot);
|
||||
}
|
||||
|
||||
static async addToHotbar(item, slot) {
|
||||
switch (item?.type ?? "") {
|
||||
case TYPES.arme:
|
||||
{
|
||||
// Les armes peuvent avoir plusieurs usages
|
||||
if (item.system.competence != "") {
|
||||
await this.createItemMacro(item, slot, "competence")
|
||||
slot++
|
||||
}
|
||||
if (item.system.lancer != "") {
|
||||
await this.createItemMacro(item, slot, "lancer")
|
||||
slot++
|
||||
}
|
||||
if (item.system.tir != "") {
|
||||
await this.createItemMacro(item, slot, "lancer")
|
||||
slot++
|
||||
}
|
||||
}
|
||||
return
|
||||
case TYPES.competence:
|
||||
case TYPES.competencecreature:
|
||||
default:
|
||||
await this.createItemMacro(item, slot)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a macro when dropping an entity on the hotbar
|
||||
* Item - open roll dialog for item
|
||||
@ -27,16 +55,16 @@ export class RdDHotbar {
|
||||
|
||||
// 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)
|
||||
}
|
||||
const item = fromUuidSync(documentData.uuid) ?? this.actor.items.get(documentData.uuid)
|
||||
console.log("DROP", documentData, item)
|
||||
if (!item || (item.type != "arme" && item.type != "competence")) {
|
||||
return true
|
||||
switch (item?.type ?? "")
|
||||
{
|
||||
case TYPES.arme:
|
||||
case TYPES.competence:
|
||||
case TYPES.competencecreature:
|
||||
this.addToHotbar(item, slot)
|
||||
return false
|
||||
}
|
||||
this.addToHotbar(item, slot)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
@ -44,12 +72,14 @@ export class RdDHotbar {
|
||||
}
|
||||
|
||||
/** Roll macro */
|
||||
static rollMacro(itemName, itemType, bypassData) {
|
||||
static rollMacro(itemName, itemType, competenceName) {
|
||||
const speaker = ChatMessage.getSpeaker();
|
||||
let actor;
|
||||
if (speaker.token) actor = game.actors.tokens[speaker.token];
|
||||
if (!actor) actor = game.actors.get(speaker.actor);
|
||||
|
||||
if (!actor) {
|
||||
return ui.notifications.warn(`Impossible de trouver le personnage concerné`);
|
||||
}
|
||||
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`);
|
||||
@ -57,9 +87,10 @@ export class RdDHotbar {
|
||||
|
||||
// Trigger the item roll
|
||||
switch (item.type) {
|
||||
case "arme":
|
||||
return actor.rollArme(item);
|
||||
case "competence":
|
||||
case TYPES.arme:
|
||||
return actor.rollArme(item, competenceName);
|
||||
case TYPES.competence:
|
||||
case TYPES.competencecreature:
|
||||
return actor.rollCompetence(itemName);
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import { Migrations } from './migrations.js';
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||
import { RdDCalendrier } from "./time/rdd-calendrier.js";
|
||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
import { DialogChronologie } from "./dialog-chronologie.js";
|
||||
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
@ -15,7 +15,7 @@ import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { StatusEffects } from "./settings/status-effects.js";
|
||||
import { RdDCompendiumOrganiser } from "./rdd-compendium-organiser.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { RdDHotbar } from "./rdd-hotbar-drop.js"
|
||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||
import { RdDHerbes } from "./rdd-herbes.js";
|
||||
@ -58,6 +58,8 @@ import { RdDConteneurItemSheet } from "./item/sheet-conteneur.js";
|
||||
import { RdDSigneDraconiqueItemSheet } from "./item/sheet-signedraconique.js";
|
||||
import { RdDItemInventaireSheet } from "./item/sheet-base-inventaire.js";
|
||||
import { AppAstrologie } from "./sommeil/app-astrologie.js";
|
||||
import { RdDItemArmure } from "./item/armure.js";
|
||||
import { AutoAdjustDarkness as AutoAdjustDarkness } from "./time/auto-adjust-darkness.js";
|
||||
|
||||
/**
|
||||
* RdD system
|
||||
@ -76,6 +78,7 @@ export class SystemReveDeDragon {
|
||||
this.RdDUtility = RdDUtility;
|
||||
this.RdDHotbar = RdDHotbar;
|
||||
this.itemClasses = {
|
||||
armure: RdDItemArmure,
|
||||
blessure: RdDItemBlessure,
|
||||
maladie: RdDItemMaladie,
|
||||
ombre: RdDItemOmbre,
|
||||
@ -174,16 +177,18 @@ export class SystemReveDeDragon {
|
||||
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
|
||||
"meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
|
||||
"nombreastral", "tache", "maladie", "poison", "possession",
|
||||
"tarot", "extraitpoetique"
|
||||
"tarot", "extraitpoetique", "empoignade"
|
||||
], makeDefault: true
|
||||
});
|
||||
CONFIG.Combat.documentClass = RdDCombatManager;
|
||||
|
||||
// préparation des différents modules
|
||||
AutoAdjustDarkness.init();
|
||||
RdDTimestamp.init();
|
||||
RdDCalendrier.init();
|
||||
SystemCompendiums.init();
|
||||
DialogChronologie.init();
|
||||
ReglesOptionelles.init();
|
||||
ReglesOptionnelles.init();
|
||||
RdDUtility.init();
|
||||
RdDDice.init();
|
||||
RdDCommands.init();
|
||||
@ -216,25 +221,6 @@ export class SystemReveDeDragon {
|
||||
default: "avant-encaissement"
|
||||
});
|
||||
|
||||
/* -------------------------------------------- */
|
||||
game.settings.register(SYSTEM_RDD, "liste-nombre-astral", {
|
||||
name: "liste-nombre-astral",
|
||||
scope: "world",
|
||||
config: false,
|
||||
default: [],
|
||||
type: Object
|
||||
});
|
||||
|
||||
/* -------------------------------------------- */
|
||||
game.settings.register(SYSTEM_RDD, "calendrier-pos", {
|
||||
name: "calendrierPos",
|
||||
scope: "client",
|
||||
config: false,
|
||||
default: RdDCalendrier.createCalendrierPos(),
|
||||
type: Object
|
||||
});
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", {
|
||||
name: "Supprimer les dialogues de combat",
|
||||
@ -280,9 +266,11 @@ export class SystemReveDeDragon {
|
||||
let sidebar = document.getElementById("sidebar");
|
||||
sidebar.style.width = "min-content";
|
||||
}
|
||||
game.system.rdd.calendrier = new RdDCalendrier();
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
game.system.rdd.calendrier = new RdDCalendrier();
|
||||
new Migrations().migrate();
|
||||
this.messageDeBienvenue();
|
||||
this.registerUsageCount(SYSTEM_RDD);
|
||||
}
|
||||
|
||||
StatusEffects.onReady();
|
||||
@ -290,8 +278,7 @@ export class SystemReveDeDragon {
|
||||
RdDDice.onReady();
|
||||
/* -------------------------------------------- */
|
||||
/* Affiche/Init le calendrier */
|
||||
game.system.rdd.calendrier = new RdDCalendrier().display();
|
||||
|
||||
game.system.rdd.calendrier.display();
|
||||
// Avertissement si joueur sans personnage
|
||||
if (!game.user.isGM && game.user.character == undefined) {
|
||||
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !");
|
||||
@ -300,10 +287,6 @@ export class SystemReveDeDragon {
|
||||
user: game.user.id
|
||||
});
|
||||
}
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
this.messageDeBienvenue();
|
||||
this.registerUsageCount(SYSTEM_RDD);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -1,9 +1,9 @@
|
||||
/* -------------------------------------------- */
|
||||
import { RdDCombat } from "./rdd-combat.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDRoll } from "./rdd-roll.js";
|
||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||
import { Targets } from "./targets.js";
|
||||
import { TYPES } from "./item.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* On part du principe qu'une entité démarre tjs
|
||||
@ -20,9 +20,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.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id);
|
||||
if (!poss) {
|
||||
poss = defender.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
|
||||
poss = defender.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id);
|
||||
}
|
||||
return poss && duplicate(poss) || undefined;
|
||||
}
|
||||
@ -31,13 +31,13 @@ export class RdDPossession {
|
||||
static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) {
|
||||
const defender = target.actor;
|
||||
const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender);
|
||||
const isNouvelle = !suitePossession && ! fromEntite;
|
||||
const isNouvelle = !suitePossession && !fromEntite;
|
||||
const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender)));
|
||||
|
||||
|
||||
RdDPossession.$updateEtatPossession(possession)
|
||||
|
||||
let rollData = {
|
||||
mode: "possession",
|
||||
mode: "attaque",
|
||||
isECNIDefender: false,
|
||||
competence: competence,
|
||||
possession: possession,
|
||||
@ -45,25 +45,26 @@ export class RdDPossession {
|
||||
defender: defender,
|
||||
targetToken: Targets.extractTokenData(target)
|
||||
};
|
||||
if (attacker.isCreatureEntite()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||
}
|
||||
|
||||
RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker)
|
||||
|
||||
await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onConjurerPossession(attacker, competence, possession) {
|
||||
static async onConjurerPossession(attacker, possession) {
|
||||
possession = duplicate(possession);
|
||||
RdDPossession.$updateEtatPossession(possession)
|
||||
|
||||
const defender = game.actors.get(possession.system.entite.actorid);
|
||||
let rollData = {
|
||||
mode: "possession",
|
||||
mode: "attaque",
|
||||
isECNIDefender: true,
|
||||
competence: competence,
|
||||
possession: possession,
|
||||
attacker: attacker,
|
||||
defender: game.actors.get(possession.system.possesseurid)
|
||||
defender: defender,
|
||||
};
|
||||
RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker)
|
||||
|
||||
await RdDPossession.$rollAttaquePossession(attacker, rollData);
|
||||
}
|
||||
|
||||
@ -71,7 +72,7 @@ export class RdDPossession {
|
||||
static async onDefensePossession(attackerId, defenderId, possessionId) {
|
||||
let attacker = game.actors.get(attackerId)
|
||||
let possession = attacker?.getPossession(possessionId)
|
||||
defenderId = defenderId ?? possession?.system.possesseurid ?? undefined
|
||||
defenderId = defenderId ?? possession?.system.entite.actorid ?? undefined
|
||||
let defender = game.actors.get(defenderId)
|
||||
possession = possession ?? defender?.getPossession(possessionId) ?? undefined;
|
||||
|
||||
@ -82,19 +83,29 @@ export class RdDPossession {
|
||||
possession = duplicate(possession)
|
||||
// Update for draconic roll
|
||||
let rollData = {
|
||||
mode: "conjuration",
|
||||
mode: "defense",
|
||||
isECNIDefender: defender.type == "entite",
|
||||
possession: possession,
|
||||
attacker: attacker,
|
||||
defender: defender,
|
||||
competence: defender.getDraconicOuPossession(),
|
||||
selectedCarac: defender.system.carac.reve,
|
||||
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } }
|
||||
}
|
||||
rollData.competence.system.defaut_carac = 'reve-actuel'
|
||||
|
||||
RdDPossession.selectCompetenceDraconicOuPossession(rollData, defender)
|
||||
rollData.diffLibre = RdDPossession.getInfoAttaque(rollData).diffLibre
|
||||
|
||||
await RdDPossession.$rollDefensePossession(defender, rollData);
|
||||
}
|
||||
|
||||
static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
|
||||
rollData.competence = rollingActor.getDraconicOuPossession();
|
||||
if (rollingActor.isCreatureEntite()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||
}
|
||||
else {
|
||||
rollData.selectedCarac = rollingActor.system.carac.reve
|
||||
rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } }
|
||||
rollData.competence.system.defaut_carac = 'reve-actuel'
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) {
|
||||
@ -104,21 +115,22 @@ export class RdDPossession {
|
||||
name: 'jet-possession',
|
||||
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
|
||||
callbacks: [
|
||||
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDPossession.$onRollPossession(r, true, isNouvelle) },
|
||||
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDPossession.$onRollPossession(r, false, isNouvelle) },
|
||||
{ action: async (r) => await RdDPossession.$onRollPossession(r, isNouvelle) },
|
||||
]
|
||||
});
|
||||
dialog.render(true);
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $onRollPossession(rollData, isSuccess, isNouvelle = false) {
|
||||
rollData.possession.isSuccess = isSuccess;
|
||||
RdDPossession.$updateEtatPossession(rollData.possession);
|
||||
static async $onRollPossession(rollData, isNouvelle = false) {
|
||||
rollData.possession.isSuccess = rollData.rolled.isSuccess;
|
||||
RdDPossession.$updateEtatPossession(rollData.possession, rollData);
|
||||
if (isNouvelle) {
|
||||
// Creer la possession sur le defenseur
|
||||
rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()])
|
||||
await rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()])
|
||||
}
|
||||
const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid)
|
||||
RdDPossession.storePossessionAttaque(possession, rollData)
|
||||
await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html');
|
||||
}
|
||||
|
||||
@ -127,35 +139,42 @@ export class RdDPossession {
|
||||
const dialog = await RdDRoll.create(defender, rollData,
|
||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html' },
|
||||
{
|
||||
name: 'conjurer',
|
||||
name: 'possession',
|
||||
label: 'Conjurer une Possession',
|
||||
callbacks: [
|
||||
{ action: async (r) => await RdDPossession.$onRollConjuration(r) }
|
||||
]
|
||||
}
|
||||
);
|
||||
]
|
||||
}
|
||||
);
|
||||
dialog.render(true);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async $onRollConjuration(rollData) {
|
||||
let actor = game.actors.get(rollData.possession.system.possedeid)
|
||||
let victime = game.actors.get(rollData.possession.system.victime.actorid)
|
||||
let compteur = rollData.possession.system.compteur
|
||||
if (!rollData.rolled.isSuccess) {
|
||||
if (rollData.isECNIDefender) {
|
||||
rollData.possession.system.compteur--
|
||||
compteur--
|
||||
} else {
|
||||
rollData.possession.system.compteur++
|
||||
compteur++
|
||||
}
|
||||
let update = { _id: rollData.possession._id, "system.compteur": rollData.possession.system.compteur }
|
||||
await actor.updateEmbeddedDocuments('Item', [update])
|
||||
}
|
||||
|
||||
const possession = victime.getPossession(rollData.possession.system.possessionid)
|
||||
await possession.update({
|
||||
system: {
|
||||
compteur: compteur,
|
||||
entite: { diffLibre: 0, finesse: false },
|
||||
victime: { diffLibre: 0, finesse: false }
|
||||
}
|
||||
})
|
||||
rollData.possession = possession
|
||||
RdDPossession.$updateEtatPossession(rollData.possession)
|
||||
|
||||
await RdDResolutionTable.displayRollData(rollData,rollData.defender, 'chat-resultat-possession.html')
|
||||
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html')
|
||||
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
|
||||
// conjuration
|
||||
actor.deleteEmbeddedDocuments("Item", [rollData.possession._id])
|
||||
victime.deleteEmbeddedDocuments("Item", [rollData.possession._id])
|
||||
}
|
||||
}
|
||||
|
||||
@ -180,13 +199,43 @@ export class RdDPossession {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isPossessionFinesse(rollData) {
|
||||
return RdDPossession.getInfoAttaque(rollData).finesse
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getInfoAttaque(rollData) {
|
||||
return rollData.possession.system[rollData.isECNIDefender ? 'victime' : 'entite'];
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static isDefensePossession(rollData) {
|
||||
return rollData.possession && rollData.mode == "defense"
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static storePossessionAttaque(possession, rollData = undefined) {
|
||||
const attaquant = rollData?.isECNIDefender ? 'victime' : 'entite'
|
||||
possession.update({
|
||||
[`system.${attaquant}`]: {
|
||||
diffLibre: rollData?.diffLibre ?? 0,
|
||||
finesse: rollData?.rolled.isPart ?? false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createPossession(attacker, defender) {
|
||||
return await Item.create({
|
||||
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 }
|
||||
},
|
||||
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),
|
||||
entite: { actorid: attacker.id },
|
||||
victime: { actorid: defender.id },
|
||||
compteur: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
temporary: true
|
||||
})
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
|
||||
/**
|
||||
* difficultés au delà de -10
|
||||
@ -91,13 +91,17 @@ export class RdDResolutionTable {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.html') {
|
||||
return await ChatUtility.createChatWithRollMode(actor?.userName ?? game.user.name, {
|
||||
content: await RdDResolutionTable.buildRollDataHtml(rollData, actor, template)
|
||||
return await ChatUtility.createChatWithRollMode(RdDResolutionTable.actorChatName(actor), {
|
||||
content: await RdDResolutionTable.buildRollDataHtml(rollData, template)
|
||||
});
|
||||
}
|
||||
|
||||
static actorChatName(actor) {
|
||||
return actor?.userName ?? game.user.name;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async buildRollDataHtml(rollData, actor, template = 'chat-resultat-general.html') {
|
||||
static async buildRollDataHtml(rollData, template = 'chat-resultat-general.html') {
|
||||
rollData.show = rollData.show || {};
|
||||
return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData);
|
||||
}
|
||||
@ -122,7 +126,7 @@ export class RdDResolutionTable {
|
||||
rolled.bonus = rollData.bonus;
|
||||
rolled.factorHtml = Misc.getFractionHtml(rollData.diviseurSignificative);
|
||||
|
||||
if (ReglesOptionelles.isUsing("afficher-colonnes-reussite")) {
|
||||
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
|
||||
rolled.niveauNecessaire = this.findNiveauNecessaire(caracValue, rolled.roll);
|
||||
rolled.ajustementNecessaire = rolled.niveauNecessaire - finalLevel;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ export class RdDRollResolutionTable extends Dialog {
|
||||
async updateRollResult() {
|
||||
let rollData = this.rollData;
|
||||
rollData.caracValue = parseInt(rollData.selectedCarac.value)
|
||||
rollData.finalLevel = this._computeFinalLevel(rollData);
|
||||
rollData.finalLevel = Misc.toInt(rollData.diffConditions) + Misc.toInt(rollData.diffLibre);
|
||||
|
||||
const htmlTable = await RdDResolutionTable.buildHTMLTable({
|
||||
carac: rollData.caracValue,
|
||||
@ -129,12 +129,6 @@ export class RdDRollResolutionTable extends Dialog {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_computeFinalLevel(rollData) {
|
||||
const diffConditions = Misc.toInt(rollData.diffConditions);
|
||||
const diffLibre = Misc.toInt(rollData.diffLibre);
|
||||
|
||||
return diffLibre + diffConditions;
|
||||
}
|
||||
|
||||
async close() {
|
||||
await super.close();
|
||||
|
@ -6,7 +6,7 @@ import { Misc } from "./misc.js";
|
||||
import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
|
||||
/**
|
||||
* Extend the base Dialog entity to select roll parameters
|
||||
@ -85,7 +85,7 @@ export class RdDRoll extends Dialog {
|
||||
if (RdDBonus.isDefenseAttaqueFinesse(rollData)) {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (!ReglesOptionelles.isUsing('tripleSignificative')) {
|
||||
if (!ReglesOptionnelles.isUsing('tripleSignificative')) {
|
||||
facteurSign = Math.min(facteurSign, 4);
|
||||
}
|
||||
return facteurSign;
|
||||
@ -187,7 +187,7 @@ export class RdDRoll extends Dialog {
|
||||
console.log("RdDRollSelectDialog - Cout reve", ptreve);
|
||||
this.updateRollResult(html);
|
||||
});
|
||||
this.html.find("[name='coupsNonMortels']").change((event) => {
|
||||
this.html.find("[name='mortalite']").change((event) => {
|
||||
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
|
||||
this.updateRollResult(html);
|
||||
});
|
||||
@ -295,8 +295,7 @@ export class RdDRoll extends Dialog {
|
||||
|
||||
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat())
|
||||
rollData.caracValue = parseInt(rollData.selectedCarac.value)
|
||||
rollData.mortalite = rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite ?? 'mortel';
|
||||
rollData.coupsNonMortels = (rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite) == 'non-mortel';
|
||||
rollData.mortalite = rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite ?? rollData.mortalite ?? 'mortel';
|
||||
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);
|
||||
let dmgText = Misc.toSignedString(rollData.dmg.total);
|
||||
|
||||
@ -306,7 +305,6 @@ export class RdDRoll extends Dialog {
|
||||
}
|
||||
|
||||
RollDataAjustements.calcul(rollData, this.actor);
|
||||
rollData.finalLevel = this._computeFinalLevel(rollData);
|
||||
|
||||
const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel))
|
||||
const adjustements = await this.buildAjustements(rollData);
|
||||
@ -314,12 +312,12 @@ export class RdDRoll extends Dialog {
|
||||
HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac));
|
||||
HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
|
||||
HtmlUtility.showControlWhen(this.html.find(".utilisation-moral"), rollData.use.appelAuMoral);
|
||||
HtmlUtility.showControlWhen(this.html.find(".diffMoral"), rollData.ajustements.moralTotal.used);
|
||||
HtmlUtility.showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
||||
HtmlUtility.showControlWhen(this.html.find(".diffMoral"), rollData.ajustements.moralTotal.used);
|
||||
|
||||
// Mise à jour valeurs
|
||||
this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
|
||||
this.html.find("[name='coupsNonMortels']").prop('checked', rollData.mortalite == 'non-mortel');
|
||||
this.html.find("[name='mortalite']").prop('checked', rollData.mortalite == 'non-mortel');
|
||||
this.html.find(".dmg-arme-actor").text(dmgText);
|
||||
this.html.find("div.placeholder-ajustements").empty().append(adjustements);
|
||||
this.html.find("div.placeholder-resolution").empty().append(resolutionTable)
|
||||
@ -331,30 +329,6 @@ export class RdDRoll extends Dialog {
|
||||
return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html`, rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_computeFinalLevel(rollData) {
|
||||
return RollDataAjustements.sum(rollData.ajustements);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_computeDiffCompetence(rollData) {
|
||||
if (rollData.competence) {
|
||||
return Misc.toInt(rollData.competence.system.niveau);
|
||||
}
|
||||
if (rollData.draconicList) {
|
||||
return Misc.toInt(rollData.competence.system.niveau);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_computeMalusArmure(rollData) {
|
||||
let malusArmureValue = 0;
|
||||
if (rollData.malusArmureValue && (rollData.selectedCarac.label == "Agilité" || rollData.selectedCarac.label == "Dérobée")) {
|
||||
malusArmureValue = rollData.malusArmureValue;
|
||||
}
|
||||
return malusArmureValue;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_getTitle(rollData) {
|
||||
const carac = rollData.selectedCarac.label;
|
||||
|
@ -12,12 +12,11 @@ import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||
import { PixiTMR } from "./tmr/pixi-tmr.js";
|
||||
import { Draconique } from "./tmr/draconique.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { STATUSES } from "./settings/status-effects.js";
|
||||
import { RdDRencontre } from "./item/rencontre.js";
|
||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
@ -47,7 +46,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
const dialogOptions = {
|
||||
classes: ["tmrdialog"],
|
||||
width: 920, height: 980,
|
||||
width: 920, maxheight: 1024, height: 'fit-content',
|
||||
'z-index': 40
|
||||
}
|
||||
super(dialogConf, dialogOptions);
|
||||
@ -56,14 +55,13 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.actor = actor;
|
||||
this.actor.tmrApp = this; // reference this app in the actor structure
|
||||
this.viewOnly = tmrData.mode == "visu"
|
||||
this.fatigueParCase = this.viewOnly || !ReglesOptionelles.isUsing("appliquer-fatigue") ? 0 : this.actor.getTMRFatigue();
|
||||
this.fatigueParCase = this.viewOnly || !ReglesOptionnelles.isUsing("appliquer-fatigue") ? 0 : this.actor.getTMRFatigue();
|
||||
this.cumulFatigue = 0;
|
||||
this.loadRencontres();
|
||||
this.loadCasesSpeciales();
|
||||
this.allTokens = [];
|
||||
this.rencontreState = 'aucune';
|
||||
this.pixiApp = new PIXI.Application({ width: 720, height: 860 });
|
||||
|
||||
this.pixiTMR = new PixiTMR(this, this.pixiApp);
|
||||
|
||||
this.callbacksOnAnimate = [];
|
||||
@ -208,7 +206,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return;
|
||||
}
|
||||
|
||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue"));
|
||||
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord()));
|
||||
|
||||
// Roll Sort
|
||||
@ -228,7 +226,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
// Gestion du cout de montée en points de rêve
|
||||
let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse();
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
}
|
||||
await this.actor.reveActuelIncDec(reveCout);
|
||||
@ -264,7 +262,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
let refoulement = document.getElementById("tmr-refoulement-value");
|
||||
refoulement.innerHTML = this.actor.system.reve.refoulement.value;
|
||||
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.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>";
|
||||
}
|
||||
@ -286,7 +284,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async onActionRencontre(action, tmr, rencontre) {
|
||||
if (!this.currentRencontre){
|
||||
if (!this.currentRencontre) {
|
||||
ui.notifications.warn("#612 Rencontre perdue, récupération en cours. Vous pouvez contacter l'équipe avec les logs pour aider à résoudre ce problème")
|
||||
console.error("#612 Rencontre perdue", action, tmr, rencontre, this);
|
||||
this.currentRencontre = rencontre;
|
||||
@ -368,7 +366,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return true;
|
||||
}
|
||||
const resteAvantInconscience = this.actor.getFatigueMax() - this.actor.getFatigueActuelle() - this.cumulFatigue;
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue") && resteAvantInconscience <= 0) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && resteAvantInconscience <= 0) {
|
||||
this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !");
|
||||
this.quitterLesTMRInconscient();
|
||||
return true;
|
||||
@ -452,7 +450,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
setTimeout(() => {
|
||||
// TODO: remplacer par une boucle while(this.currentRencontre) ?
|
||||
rencData.nbRounds++;
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
}
|
||||
this._tentativeMaitrise(rencData);
|
||||
@ -805,19 +803,21 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async declencheSortEnReserve(coord) {
|
||||
let sorts = this.getSortsReserve(coord);
|
||||
const sorts = this.getSortsReserve(coord);
|
||||
if (sorts.length > 0) {
|
||||
if (EffetsDraconiques.isSortReserveImpossible(this.actor)) {
|
||||
ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!");
|
||||
return;
|
||||
}
|
||||
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) &&
|
||||
(EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord))) {
|
||||
let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête <strong>Reserve en Sécurité</strong> ou <strong>Réserve Exensible</strong>, vous pouvez contrôler le déclenchement. Cliquez si vous souhaitez le déclencher : <ul>";
|
||||
for (let sort of sorts) {
|
||||
msg += `<li><a class="chat-card-button declencher-sort-reserve" data-actor-id="${this.actor.id}" data-tmr-coord="${coord}" data-sort-id='${sort.id}">${sort.name}</a></li>`;
|
||||
}
|
||||
msg += "</ol>";
|
||||
const reserveSecurite = EffetsDraconiques.isReserveEnSecurite(this.actor);
|
||||
const reserveExtensible = this.isReserveExtensible(coord);
|
||||
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) && (reserveSecurite || reserveExtensible)) {
|
||||
const msg = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-demande-declencher-sort.hbs`, {
|
||||
actor: this.actor,
|
||||
sorts: sorts,
|
||||
coord: coord,
|
||||
tete: { reserveSecurite: reserveSecurite, reserveExtensible: reserveExtensible }
|
||||
})
|
||||
ChatMessage.create({
|
||||
content: msg,
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||
@ -905,15 +905,12 @@ export class RdDTMRDialog extends Dialog {
|
||||
if (this.viewOnly) {
|
||||
return;
|
||||
}
|
||||
let clickOddq = RdDTMRDialog._computeEventOddq(event.data.originalEvent);
|
||||
await this._onClickTMRPos(clickOddq); // Vérifier l'état des compteurs reve/fatigue/vie
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _onClickTMRPos(clickOddq) {
|
||||
let clickOddq = TMRUtility.computeEventOddq(event);
|
||||
let currentOddq = TMRUtility.coordTMRToOddq(this._getActorCoord());
|
||||
|
||||
let targetCoord = TMRUtility.oddqToCoordTMR(clickOddq);
|
||||
let currentCoord = TMRUtility.oddqToCoordTMR(currentOddq);
|
||||
|
||||
// Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter)
|
||||
let deplacementType = this._calculDeplacement(targetCoord, currentCoord, currentOddq, clickOddq);
|
||||
|
||||
@ -945,7 +942,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this._messagerDemiReve(targetCoord);
|
||||
break;
|
||||
default:
|
||||
ui.notifications.error("Vous ne pouvez pas vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
|
||||
ui.notifications.error("Vous ne pouvez vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
|
||||
console.log("STATUS :", this.rencontreState, this.currentRencontre);
|
||||
}
|
||||
|
||||
@ -1003,7 +1000,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this.actor.updateCoordTMR(tmr.coord);
|
||||
|
||||
this.forceDemiRevePositionView();
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
}
|
||||
this.updateValuesDisplay();
|
||||
@ -1048,18 +1045,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this.postRencontre(tmr);
|
||||
return tmr;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _computeEventOddq(origEvent) {
|
||||
let canvasRect = origEvent.target.getBoundingClientRect();
|
||||
let x = origEvent.clientX - canvasRect.left;
|
||||
let y = origEvent.clientY - canvasRect.top;
|
||||
let col = Math.floor(x / tmrConstants.cellw); // [From 0 -> 12]
|
||||
y -= col % 2 == 0 ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||
let row = Math.floor(y / tmrConstants.cellh); // [From 0 -> 14]
|
||||
return { col: col, row: row };
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** Retourne les coordonnées x, h, w, h du rectangle d'une case donnée */
|
||||
_getCaseRectangleCoord(coord) {
|
||||
|
@ -75,8 +75,8 @@ export class RdDTokenHud {
|
||||
(event) => {
|
||||
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
|
||||
const action = hudData.actions[actionIndex];
|
||||
if (action.action == 'conjurer') {
|
||||
const possession = combatant.actor.getPossession(action.system.possessionid);
|
||||
const possession = action.action == 'possession' ? combatant.actor.getPossession(action.system.possessionid) : undefined;
|
||||
if (possession) {
|
||||
combatant.actor.conjurerPossession(possession);
|
||||
}
|
||||
else {
|
||||
|
@ -5,7 +5,7 @@ import { Misc } from "./misc.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
import { DialogItemAchat } from "./dialog-item-achat.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { RdDItem } from "./item.js";
|
||||
import { RdDPossession } from "./rdd-possession.js";
|
||||
@ -13,8 +13,10 @@ import { RdDNameGen } from "./rdd-namegen.js";
|
||||
import { RdDConfirm } from "./rdd-confirm.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||
import { RdDRaretes } from "./item/raretes.js";
|
||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||
import { ExperienceLog } from "./actor/experience-log.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// This table starts at 0 -> niveau -10
|
||||
@ -119,6 +121,7 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/header-hautreve.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/archetype.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html',
|
||||
@ -135,6 +138,7 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/blessure.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/resonances.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html',
|
||||
@ -176,26 +180,28 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
|
||||
// partial enums
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-competence.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categories.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-mortalite.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-periode.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
|
||||
// Partials
|
||||
'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/time/horloge.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
|
||||
@ -231,9 +237,6 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-gardien.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-joueur.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-theme.hbs',
|
||||
// Calendrier
|
||||
'systems/foundryvtt-reve-de-dragon/templates/calendar-template.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html',
|
||||
// HUD
|
||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html',
|
||||
@ -242,20 +245,6 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-description.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-appelchance.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-attaque.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-parade.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-esquive.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-competence.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-general.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-tache.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-sort.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-alchimie.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-possession.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html',
|
||||
@ -291,13 +280,16 @@ export class RdDUtility {
|
||||
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
|
||||
|
||||
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
|
||||
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
|
||||
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionnelles.isUsing(option));
|
||||
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
|
||||
Handlebars.registerHelper('filtreTriCompetences', competences => RdDItemCompetence.triVisible(competences));
|
||||
Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
|
||||
Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite());
|
||||
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
|
||||
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
|
||||
|
||||
Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
|
||||
|
||||
return loadTemplates(templatePaths);
|
||||
}
|
||||
|
||||
@ -349,13 +341,13 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static buildArbreDeConteneurs(conteneurs, objets) {
|
||||
static buildArbreDeConteneurs(conteneurs, inventaires) {
|
||||
let objetVersConteneur = {};
|
||||
// Attribution des objets aux conteneurs
|
||||
for (let conteneur of conteneurs) {
|
||||
conteneur.subItems = [];
|
||||
for (let id of conteneur.system.contenu ?? []) {
|
||||
let objet = objets.find(objet => (id == objet._id));
|
||||
let objet = inventaires.find(objet => (id == objet._id));
|
||||
if (objet) {
|
||||
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template
|
||||
objetVersConteneur[id] = conteneur._id;
|
||||
@ -364,20 +356,20 @@ export class RdDUtility {
|
||||
}
|
||||
}
|
||||
for (let conteneur of conteneurs) {
|
||||
conteneur.system.encTotal = RdDUtility.calculEncContenu(conteneur, objets);
|
||||
conteneur.system.encTotal = RdDUtility.calculEncContenu(conteneur, inventaires);
|
||||
}
|
||||
return objetVersConteneur;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static calculEncContenu(conteneur, objets) {
|
||||
static calculEncContenu(conteneur, inventaires) {
|
||||
const contenus = (conteneur.system.contenu ?? []).filter(id => id != undefined)
|
||||
.map(id => objets.find(it => (id == it.id)))
|
||||
.map(id => inventaires.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);
|
||||
enc += RdDUtility.calculEncContenu(contenu, inventaires);
|
||||
}
|
||||
else {
|
||||
enc += Number(contenu.system.encombrement ?? 0) * Number(contenu.system.quantite ?? 1)
|
||||
@ -488,7 +480,7 @@ export class RdDUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static calculFatigueHtml(fatigue, endurance) {
|
||||
return ReglesOptionelles.isUsing("appliquer-fatigue") ? {
|
||||
return ReglesOptionnelles.isUsing("appliquer-fatigue") ? {
|
||||
malus: RdDUtility.calculMalusFatigue(fatigue, endurance),
|
||||
html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(fatigue, endurance).html() + "</table>"
|
||||
} : { malus: 0, html: '' };
|
||||
@ -564,14 +556,14 @@ export class RdDUtility {
|
||||
let formula = "2d10";
|
||||
|
||||
// Chaque dé fait au minmum la difficulté libre
|
||||
if (ReglesOptionelles.isUsing('degat-minimum-malus-libre')) {
|
||||
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre')) {
|
||||
if (rollData.diffLibre < 0) {
|
||||
let valeurMin = Math.abs(rollData.diffLibre);
|
||||
formula += "min" + valeurMin;
|
||||
}
|
||||
}
|
||||
// Chaque dé fait au minmum la difficulté libre
|
||||
if (ReglesOptionelles.isUsing('degat-ajout-malus-libre')) {
|
||||
if (ReglesOptionnelles.isUsing('degat-ajout-malus-libre')) {
|
||||
if (rollData.diffLibre < 0) {
|
||||
let valeurMin = Math.abs(rollData.diffLibre);
|
||||
formula += "+" + valeurMin;
|
||||
@ -581,7 +573,7 @@ export class RdDUtility {
|
||||
let roll = await RdDDice.roll(formula, options);
|
||||
|
||||
// 1 dé fait au minmum la difficulté libre
|
||||
if (ReglesOptionelles.isUsing('degat-minimum-malus-libre-simple')) {
|
||||
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre-simple')) {
|
||||
if (rollData.diffLibre < 0) {
|
||||
let valeurMin = Math.abs(rollData.diffLibre);
|
||||
if (roll.terms[0].results[0].result < valeurMin) {
|
||||
@ -634,7 +626,7 @@ export class RdDUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static currentFatigueMalus(value, max) {
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||
max = Math.max(1, Math.min(max, 60));
|
||||
value = Math.min(max * 2, Math.max(0, value));
|
||||
|
||||
@ -678,6 +670,7 @@ export class RdDUtility {
|
||||
/* -------------------------------------------- */
|
||||
static async chatListeners(html) {
|
||||
RdDCombat.registerChatCallbacks(html);
|
||||
RdDEmpoignade.registerChatCallbacks(html);
|
||||
|
||||
// Gestion spécifique message passeurs
|
||||
html.on("click", '.tmr-passeur-coord a', event => {
|
||||
@ -836,17 +829,13 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete) {
|
||||
static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete, onSuppression = ()=>{}) {
|
||||
RdDConfirm.confirmer({
|
||||
settingConfirmer: "confirmation-supprimer-lien-acteur",
|
||||
content: `<p>Etes vous certain de vouloir supprimer le lien vers ${subActor.name} ?</p>`,
|
||||
title: 'Confirmer la suppression',
|
||||
buttonLabel: 'Supprimer le lien',
|
||||
onAction: () => {
|
||||
console.log('Delete : ', subActor.id);
|
||||
sheet.actor.removeSubacteur(subActor.id);
|
||||
RdDUtility.slideOnDelete(sheet, htmlToDelete);
|
||||
}
|
||||
onAction: onSuppression
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,9 @@ import { RdDItemSort } from "./item-sort.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { RdDPossession } from "./rdd-possession.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||
|
||||
/**
|
||||
* tous les ajustements pouvant s'appliquer.
|
||||
@ -30,7 +31,7 @@ export const referenceAjustements = {
|
||||
},
|
||||
diffLibre: {
|
||||
isUsed: (rollData, actor) => rollData.diffLibre != undefined,
|
||||
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ? 'Imposée' : 'Libre',
|
||||
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ?? RdDPossession.isDefensePossession(rollData) ? 'Imposée' : 'Libre',
|
||||
getValue: (rollData, actor) => rollData.selectedSort
|
||||
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
|
||||
: rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0
|
||||
@ -51,7 +52,7 @@ export const referenceAjustements = {
|
||||
getValue: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).attaque,
|
||||
},
|
||||
etat: {
|
||||
isUsed: (rollData, actor) => !RdDCarac.isIgnoreEtatGeneral(rollData),
|
||||
isUsed: (rollData, actor) => !RollDataAjustements.isIgnoreEtatGeneral(rollData),
|
||||
getLabel: (rollData, actor) => 'Etat général',
|
||||
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined })
|
||||
},
|
||||
@ -85,7 +86,7 @@ export const referenceAjustements = {
|
||||
getValue: (rollData, actor) => actor.getMoralTotal()
|
||||
},
|
||||
astrologique: {
|
||||
isUsed: (rollData, actor) => ReglesOptionelles.isUsing("astrologie") && RdDBonus.isAjustementAstrologique(rollData),
|
||||
isUsed: (rollData, actor) => ReglesOptionnelles.isUsing("astrologie") && RdDBonus.isAjustementAstrologique(rollData),
|
||||
getLabel: (rollData, actor) => 'Astrologique',
|
||||
getValue: (rollData, actor) => actor.ajustementAstrologique()
|
||||
},
|
||||
@ -139,6 +140,12 @@ export const referenceAjustements = {
|
||||
isUsed: (rollData, actor) => rollData.ethylisme != undefined,
|
||||
getLabel: (rollData, actor) => "Ethylisme - " + RdDUtility.getNomEthylisme(rollData.ethylisme),
|
||||
getValue: (rollData, actor) => rollData.ethylisme,
|
||||
},
|
||||
tailleempoignade: {
|
||||
isVisible: (rollData, actor) => rollData.isEmpoignade,
|
||||
isUsed: (rollData, actor) => rollData.isEmpoignade,
|
||||
getLabel: (rollData, actor) => "Malus de taille",
|
||||
getValue: (rollData, actor) => rollData.malusTaille,
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,7 +164,7 @@ export class RollDataAjustements {
|
||||
descr: reference.getDescr && reference.getDescr(rollData, actor)
|
||||
}
|
||||
}
|
||||
rollData.finalLevel = RollDataAjustements.sum(rollData.ajustements);
|
||||
rollData.finalLevel = RollDataAjustements.sum(rollData.ajustements)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -171,4 +178,11 @@ export class RollDataAjustements {
|
||||
return sum;
|
||||
}
|
||||
|
||||
static isIgnoreEtatGeneral(rollData) {
|
||||
const selectedCarac = rollData.selectedCarac;
|
||||
return !selectedCarac ||
|
||||
rollData.ethylisme ||
|
||||
RdDCarac.isChance(selectedCarac) ||
|
||||
(RdDCarac.isReve(selectedCarac) && !rollData.competence);
|
||||
}
|
||||
}
|
||||
|
@ -1,119 +0,0 @@
|
||||
import { SYSTEM_RDD } from "../constants.js";
|
||||
import { Misc } from "../misc.js";
|
||||
|
||||
const listeReglesOptionelles = [
|
||||
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
|
||||
{ group: 'Règles de combat', name: 'resistanceArmeParade', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" },
|
||||
{ group: 'Règles de combat', name: 'deteriorationArmure', descr: "Tenir compte de la détérioration des armures" },
|
||||
{ group: 'Règles de combat', name: 'defenseurDesarme', descr: "Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier" },
|
||||
{ group: 'Règles de combat', name: 'categorieParade', descr: "Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes" },
|
||||
{ group: 'Règles de combat', name: 'tripleSignificative', descr: "En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès" },
|
||||
{ group: 'Règles de combat', name: 'degat-minimum-malus-libre-simple', descr: "Le malus libre d'attaque remplace une des valeurs de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, si le plus petit dé est inférieur à 4, alors il devient 4.", default: false },
|
||||
{ group: 'Règles de combat', name: 'degat-minimum-malus-libre', descr: "Le malus libre d'attaque remplace une valeur de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, tout résultat inférieur à 4 devient 4.", default: false },
|
||||
{ group: 'Règles de combat', name: 'degat-ajout-malus-libre', descr: "Le malus libre d'attaque s'ajoute au jet d'encaissement et aux autres bonus. Exemple : la difficulté libre de l'attaquant est de -4. Le jet d'encaissement est effectué à 2d10+4, plus les bonus de situation et d'armes.", default: false },
|
||||
{ group: 'Règles de combat', name: 'validation-encaissement-gr', descr: "Le Gardien des Rêves doit valider les jets d'encaissement et peut les changer.", default: false },
|
||||
|
||||
{ group: 'Règles générales', name: 'astrologie', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels"},
|
||||
{ group: 'Règles générales', name: 'afficher-prix-joueurs', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true},
|
||||
{ group: 'Règles générales', name: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"},
|
||||
{ group: 'Règles générales', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
|
||||
{ group: 'Règles générales', name: 'chateau-dormant-gardien', descr: "Saisie des heures de sommeil/jets de moral par le gardien des rêves", default: true },
|
||||
|
||||
{ group: 'Confirmations', name: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-equipement', descr: "Confirmer la suppression des équipements", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-oeuvre', descr: "Confirmer la suppression des oeuvres", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-connaissance', descr: "Confirmer la suppression des connaissances", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-draconique', descr: "Confirmer la suppression des queues, souffles, têtes", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-effet', descr: "Confirmer la suppression des effets", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-competence', descr: "Confirmer la suppression des compétences", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-autres', descr: "Confirmer la suppression des autres types d'Objets", scope: "client"},
|
||||
];
|
||||
|
||||
const uniquementJoueur = listeReglesOptionelles.filter(it => it.uniquementJoueur).map(it=>it.name);
|
||||
|
||||
export class ReglesOptionelles extends FormApplication {
|
||||
static init() {
|
||||
for (const regle of listeReglesOptionelles) {
|
||||
const name = regle.name;
|
||||
const id = ReglesOptionelles._getIdRegle(name);
|
||||
game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean });
|
||||
}
|
||||
|
||||
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
|
||||
name: "Choisir les règles optionelles",
|
||||
label: "Règles optionelles",
|
||||
hint: "Ouvre la fenêtre de sélection des règles optionelles",
|
||||
icon: "fas fa-bars",
|
||||
type: ReglesOptionelles
|
||||
});
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
static _getIdRegle(name) {
|
||||
return `rdd-option-${name}`;
|
||||
}
|
||||
|
||||
static get defaultOptions() {
|
||||
const options = super.defaultOptions;
|
||||
mergeObject(options, {
|
||||
id: "regles-optionelles",
|
||||
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionelles.html",
|
||||
height: 600,
|
||||
width: 450,
|
||||
minimizable: false,
|
||||
closeOnSubmit: true,
|
||||
title: "Règles optionnelles"
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
getData() {
|
||||
let formData = super.getData();
|
||||
const regles = listeReglesOptionelles.filter(it => game.user.isGM || it.scope == "client").map(it => {
|
||||
it = duplicate(it);
|
||||
it.id = ReglesOptionelles._getIdRegle(it.name);
|
||||
it.active = ReglesOptionelles.isSet(it.name);
|
||||
return it;
|
||||
});
|
||||
formData.regles = regles;
|
||||
formData.groups = Misc.classify(regles, it => it.group);
|
||||
return formData;
|
||||
}
|
||||
|
||||
static isUsing(name) {
|
||||
if (game.user.isGM && uniquementJoueur.includes(name)) {
|
||||
return true;
|
||||
}
|
||||
return ReglesOptionelles.isSet(name);
|
||||
}
|
||||
|
||||
static isSet(name) {
|
||||
return game.settings.get(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name));
|
||||
}
|
||||
|
||||
static set(name, value) {
|
||||
return game.settings.set(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name), value ? true: false);
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
html.find(".select-option").click((event) => {
|
||||
if (event.currentTarget.attributes.name) {
|
||||
let id = event.currentTarget.attributes.name.value;
|
||||
let isChecked = event.currentTarget.checked;
|
||||
game.settings.set(SYSTEM_RDD, id, isChecked);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async _updateObject(event, formData) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
122
module/settings/regles-optionnelles.js
Normal file
122
module/settings/regles-optionnelles.js
Normal file
@ -0,0 +1,122 @@
|
||||
import { SYSTEM_RDD } from "../constants.js";
|
||||
import { Misc } from "../misc.js";
|
||||
|
||||
const listeReglesOptionnelles = [
|
||||
{ group: 'Règles générales', name: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"},
|
||||
{ group: 'Règles générales', name: 'astrologie', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels"},
|
||||
|
||||
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
|
||||
{ group: 'Règles de combat', name: 'resistanceArmeParade', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" },
|
||||
{ group: 'Règles de combat', name: 'deteriorationArmure', descr: "Tenir compte de la détérioration des armures" },
|
||||
{ group: 'Règles de combat', name: 'defenseurDesarme', descr: "Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier" },
|
||||
{ group: 'Règles de combat', name: 'categorieParade', descr: "Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes" },
|
||||
{ group: 'Règles de combat', name: 'tripleSignificative', descr: "En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès" },
|
||||
{ group: 'Règles de combat', name: 'validation-encaissement-gr', descr: "Le Gardien des Rêves doit valider les jets d'encaissement et peut les changer.", default: false },
|
||||
|
||||
{ group: 'Automatisation', name: 'chateau-dormant-gardien', descr: "Saisie des heures de sommeil/jets de moral par le gardien des rêves", default: true },
|
||||
|
||||
{ group: 'Affichage', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
|
||||
{ group: 'Affichage', name: 'afficher-prix-joueurs', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true},
|
||||
|
||||
{ group: 'Confirmations', name: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-equipement', descr: "Confirmer la suppression des équipements", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-oeuvre', descr: "Confirmer la suppression des oeuvres", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-connaissance', descr: "Confirmer la suppression des connaissances", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-draconique', descr: "Confirmer la suppression des queues, souffles, têtes", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-effet', descr: "Confirmer la suppression des effets", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-competence', descr: "Confirmer la suppression des compétences", scope: "client"},
|
||||
{ group: 'Confirmations', name: 'confirmation-supprimer-autres', descr: "Confirmer la suppression des autres types d'Objets", scope: "client"},
|
||||
|
||||
{ group: 'Options alternatives', name: 'degat-minimum-malus-libre-simple', descr: "Le malus libre d'attaque remplace une des valeurs de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, si le plus petit dé est inférieur à 4, alors il devient 4.", default: false },
|
||||
{ group: 'Options alternatives', name: 'degat-minimum-malus-libre', descr: "Le malus libre d'attaque remplace une valeur de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, tout résultat inférieur à 4 devient 4.", default: false },
|
||||
{ group: 'Options alternatives', name: 'degat-ajout-malus-libre', descr: "Le malus libre d'attaque s'ajoute au jet d'encaissement et aux autres bonus. Exemple : la difficulté libre de l'attaquant est de -4. Le jet d'encaissement est effectué à 2d10+4, plus les bonus de situation et d'armes.", default: false },
|
||||
];
|
||||
|
||||
const uniquementJoueur = listeReglesOptionnelles.filter(it => it.uniquementJoueur).map(it=>it.name);
|
||||
|
||||
export class ReglesOptionnelles extends FormApplication {
|
||||
static init() {
|
||||
for (const regle of listeReglesOptionnelles) {
|
||||
const name = regle.name;
|
||||
const id = ReglesOptionnelles._getIdRegle(name);
|
||||
game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean });
|
||||
}
|
||||
|
||||
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
|
||||
name: "Choisir les règles optionnelles",
|
||||
label: "Règles optionnelles",
|
||||
hint: "Ouvre la fenêtre de sélection des règles optionnelles",
|
||||
icon: "fas fa-bars",
|
||||
type: ReglesOptionnelles
|
||||
});
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
}
|
||||
|
||||
static _getIdRegle(name) {
|
||||
return `rdd-option-${name}`;
|
||||
}
|
||||
|
||||
static get defaultOptions() {
|
||||
const options = super.defaultOptions;
|
||||
mergeObject(options, {
|
||||
id: "regles-optionnelles",
|
||||
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.html",
|
||||
height: 600,
|
||||
width: 450,
|
||||
minimizable: false,
|
||||
closeOnSubmit: true,
|
||||
title: "Règles optionnelles"
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
getData() {
|
||||
let formData = super.getData();
|
||||
const regles = listeReglesOptionnelles.filter(it => game.user.isGM || it.scope == "client").map(it => {
|
||||
it = duplicate(it);
|
||||
it.id = ReglesOptionnelles._getIdRegle(it.name);
|
||||
it.active = ReglesOptionnelles.isSet(it.name);
|
||||
return it;
|
||||
});
|
||||
formData.regles = regles;
|
||||
formData.groups = Misc.classify(regles, it => it.group);
|
||||
return formData;
|
||||
}
|
||||
|
||||
static isUsing(name) {
|
||||
if (game.user.isGM && uniquementJoueur.includes(name)) {
|
||||
return true;
|
||||
}
|
||||
return ReglesOptionnelles.isSet(name);
|
||||
}
|
||||
|
||||
static isSet(name) {
|
||||
return game.settings.get(SYSTEM_RDD, ReglesOptionnelles._getIdRegle(name));
|
||||
}
|
||||
|
||||
static set(name, value) {
|
||||
return game.settings.set(SYSTEM_RDD, ReglesOptionnelles._getIdRegle(name), value ? true: false);
|
||||
}
|
||||
|
||||
activateListeners(html) {
|
||||
html.find(".select-option").click((event) => {
|
||||
if (event.currentTarget.attributes.name) {
|
||||
let id = event.currentTarget.attributes.name.value;
|
||||
let isChecked = event.currentTarget.checked;
|
||||
game.settings.set(SYSTEM_RDD, id, isChecked);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async _updateObject(event, formData) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
@ -47,6 +47,7 @@ export class SystemCompendiums extends FormApplication {
|
||||
label: "Compendiums système",
|
||||
hint: "Ouvre la fenêtre de sélection des compendiums système",
|
||||
icon: "fas fa-bars",
|
||||
restricted: true,
|
||||
type: SystemCompendiums
|
||||
})
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { SYSTEM_RDD } from "../constants.js";
|
||||
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "../constants.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RDD_MINUTES_PAR_HEURES, RDD_MINUTES_PAR_JOUR, RdDTimestamp } from "../rdd-timestamp.js";
|
||||
import { RdDTimestamp } from "../time/rdd-timestamp.js";
|
||||
|
||||
export const APP_ASTROLOGIE_REFRESH = `${SYSTEM_RDD}-refresh-astrologie`
|
||||
|
||||
@ -22,6 +22,7 @@ export class AppAstrologie extends Application {
|
||||
title: "Astrologie",
|
||||
width: 'fit-content',
|
||||
height: 'fit-content',
|
||||
classes: ['calendar-astrologie'],
|
||||
popOut: true,
|
||||
resizable: false
|
||||
});
|
||||
@ -56,7 +57,7 @@ export class AppAstrologie extends Application {
|
||||
if (this.actor) {
|
||||
return {
|
||||
actor: this.actor,
|
||||
nombres: this._organizeNombresAstraux(this.actor.listItems('nombreastral')),
|
||||
nombres: this._organizeNombresAstraux(this.actor.itemTypes['nombreastral']),
|
||||
ajustements: CONFIG.RDD.difficultesLibres,
|
||||
etat: this.actor.getEtatGeneral(),
|
||||
astrologie: this.actor.getCompetence('Astrologie')
|
||||
@ -127,7 +128,7 @@ export class AppAstrologie extends Application {
|
||||
this.selectHeureNaissance(event.currentTarget.attributes['data-heure-naissance'].value);
|
||||
})
|
||||
this.html.find('[name="jet-astrologie"]').click(event => this.requestJetAstrologie());
|
||||
this.html.find('[name="rebuild-nombres-astraux"]').click(event => this.rebuildNombresAstraux());
|
||||
this.html.find('[name="rebuild-nombres-astraux"]').click(event => this.onRebuild());
|
||||
|
||||
this.onCalculThemeAstral();
|
||||
}
|
||||
@ -143,7 +144,7 @@ export class AppAstrologie extends Application {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rebuildNombresAstraux() {
|
||||
async onRebuild() {
|
||||
game.system.rdd.calendrier.resetNombresAstraux();
|
||||
|
||||
await game.system.rdd.calendrier.rebuildNombresAstraux();
|
||||
@ -155,30 +156,19 @@ export class AppAstrologie extends Application {
|
||||
RdDTimestamp.definitions().forEach(dh => {
|
||||
const ajustement = RdDTimestamp.ajustementAstrologiqueHeure(heureNaissance, chiffreAstral, dh.heure + 1);
|
||||
const txtAjustement = ajustement == 0 ? '' : Misc.toSignedString(ajustement);
|
||||
this.html.find(`div.astro-ajustement.heure-${dh.hh}`).text(txtAjustement)
|
||||
this.html.find(`div.horloge-ajustement.heure-${dh.hh}`).text(txtAjustement)
|
||||
});
|
||||
|
||||
this.html.find(`select[name="signe-astral"]`).val(this.appData.theme.signeAstral.key)
|
||||
this.html.find(`select[name="signe-naissance"]`).val(this.appData.theme.signeNaissance.key)
|
||||
|
||||
const angleAstrologie = ((chiffreAstral + heureNaissance) * 30) % 360 - 45;
|
||||
this.html.find(`div.astro-roue div.astro-disque img`).css(this.cssRotation(angleAstrologie));
|
||||
|
||||
this.html.find(`div.horloge-roue div.disque-astro img`).css(Misc.cssRotation(angleAstrologie));
|
||||
|
||||
const timestamp = game.system.rdd.calendrier.getTimestamp();
|
||||
|
||||
this.html.find(`div.astro-roue div.astro-horloge-heure img`).css(this.cssRotation(timestamp.angleHeure));
|
||||
this.html.find(`div.astro-roue div.astro-horloge-minute img`).css(this.cssRotation(timestamp.angleMinute));
|
||||
}
|
||||
|
||||
cssRotation(angleAstrologie) {
|
||||
const rotation = `rotate(${angleAstrologie}deg)`;
|
||||
return {
|
||||
'transform': rotation,
|
||||
'-ms-transform': rotation,
|
||||
'-moz-transform': rotation,
|
||||
'-webkit-transform': rotation,
|
||||
'-o-transform': rotation
|
||||
};
|
||||
this.html.find(`div.horloge-roue div.horloge-aiguille-heure img`).css(Misc.cssRotation(timestamp.angleHeure));
|
||||
this.html.find(`div.horloge-roue div.horloge-aiguille-minute img`).css(Misc.cssRotation(timestamp.angleMinute));
|
||||
}
|
||||
|
||||
requestJetAstrologie() {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
|
||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||
import { EffetsDraconiques } from "../tmr/effets-draconiques.js";
|
||||
|
||||
export class DialogRepos extends Dialog {
|
||||
@ -7,7 +7,7 @@ export class DialogRepos extends Dialog {
|
||||
if (!actor.isPersonnage()) {
|
||||
return
|
||||
}
|
||||
if (!ReglesOptionelles.isUsing("chateau-dormant-gardien") || !actor.hasPlayerOwner) {
|
||||
if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !actor.hasPlayerOwner) {
|
||||
actor.system.sommeil = {
|
||||
"nouveaujour": true,
|
||||
"insomnie": EffetsDraconiques.isSujetInsomnie(actor),
|
||||
|
34
module/time/auto-adjust-darkness.js
Normal file
34
module/time/auto-adjust-darkness.js
Normal file
@ -0,0 +1,34 @@
|
||||
import { SYSTEM_RDD } from "../constants.js";
|
||||
|
||||
export const AUTO_ADJUST_DARKNESS = "auto-adjust-darkness";
|
||||
|
||||
export class AutoAdjustDarkness {
|
||||
|
||||
static init() {
|
||||
game.settings.register(SYSTEM_RDD, AUTO_ADJUST_DARKNESS, {
|
||||
name: AUTO_ADJUST_DARKNESS,
|
||||
scope: "world",
|
||||
config: false,
|
||||
default: true,
|
||||
type: Boolean
|
||||
});
|
||||
}
|
||||
|
||||
static async adjust(darkness) {
|
||||
if (AutoAdjustDarkness.isAuto()) {
|
||||
const scene = game.scenes.viewed;
|
||||
if (scene.globalLight && scene.tokenVision) {
|
||||
await scene.update({ darkness });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static isAuto() {
|
||||
return game.settings.get(SYSTEM_RDD, AUTO_ADJUST_DARKNESS);
|
||||
}
|
||||
|
||||
static async toggle() {
|
||||
const previous = AutoAdjustDarkness.isAuto();
|
||||
await game.settings.set(SYSTEM_RDD, AUTO_ADJUST_DARKNESS, !previous)
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import { RdDTimestamp } from "./rdd-timestamp.js";
|
||||
* Extend the base Dialog entity by defining a custom window to perform roll.
|
||||
* @extends {Dialog}
|
||||
*/
|
||||
export class RdDCalendrierEditeur extends Dialog {
|
||||
export class RdDCalendrierEditor extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, calendrier, calendrierData) {
|
||||
@ -30,8 +30,8 @@ export class RdDCalendrierEditeur extends Dialog {
|
||||
this.html.find("input[name='calendar.annee']").val(this.calendrierData.annee);
|
||||
this.html.find("select[name='calendar.mois']").val(this.calendrierData.mois.key);
|
||||
this.html.find("select[name='calendar.heure']").val(this.calendrierData.heure.key);
|
||||
RdDCalendrierEditeur.setLimited(this.html.find("input[name='calendar.jourDuMois']"), this.calendrierData.jourDuMois, 1, 28);
|
||||
RdDCalendrierEditeur.setLimited(this.html.find("input[name='calendar.minute']"), this.calendrierData.minute, 0, 119);
|
||||
RdDCalendrierEditor.setLimited(this.html.find("input[name='calendar.jourDuMois']"), this.calendrierData.jourDuMois, 1, 28);
|
||||
RdDCalendrierEditor.setLimited(this.html.find("input[name='calendar.minute']"), this.calendrierData.minute, 0, 119);
|
||||
}
|
||||
|
||||
static setLimited(input, init, min, max) {
|
@ -1,78 +1,146 @@
|
||||
import { RdDCalendrierEditeur } from "./rdd-calendrier-editeur.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||
import { DialogChronologie } from "./dialog-chronologie.js";
|
||||
import { MAX_NOMBRE_ASTRAL, RdDTimestamp, WORLD_TIMESTAMP_SETTING } from "./rdd-timestamp.js";
|
||||
import { DialogChateauDormant } from "./sommeil/dialog-chateau-dormant.js";
|
||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||
import { APP_ASTROLOGIE_REFRESH, AppAstrologie } from "./sommeil/app-astrologie.js";
|
||||
import { RdDCalendrierEditor } from "./rdd-calendrier-editor.js";
|
||||
import { RdDResolutionTable } from "../rdd-resolution-table.js";
|
||||
import { RdDUtility } from "../rdd-utility.js";
|
||||
import { RdDDice } from "../rdd-dice.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { DialogChronologie } from "../dialog-chronologie.js";
|
||||
import { HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "../constants.js";
|
||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||
import { DialogChateauDormant } from "../sommeil/dialog-chateau-dormant.js";
|
||||
import { APP_ASTROLOGIE_REFRESH, AppAstrologie } from "../sommeil/app-astrologie.js";
|
||||
import { AutoAdjustDarkness } from "./auto-adjust-darkness.js";
|
||||
|
||||
const TEMPLATE_CALENDRIER = "systems/foundryvtt-reve-de-dragon/templates/time/calendar.hbs";
|
||||
|
||||
const INITIAL_CALENDAR_POS = { top: 200, left: 200, horlogeAnalogique: true };
|
||||
/* -------------------------------------------- */
|
||||
export class RdDCalendrier extends Application {
|
||||
static init() {
|
||||
game.settings.register(SYSTEM_RDD, "liste-nombre-astral", {
|
||||
name: "liste-nombre-astral",
|
||||
scope: "world",
|
||||
config: false,
|
||||
default: [],
|
||||
type: Object
|
||||
});
|
||||
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
template: "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html",
|
||||
popOut: false,
|
||||
resizable: false
|
||||
game.settings.register(SYSTEM_RDD, "calendrier-pos", {
|
||||
name: "calendrierPos",
|
||||
scope: "client",
|
||||
config: false,
|
||||
default: INITIAL_CALENDAR_POS,
|
||||
type: Object
|
||||
});
|
||||
}
|
||||
|
||||
static createCalendrierPos() {
|
||||
return { top: 200, left: 200 };
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
title: "Calendrier",
|
||||
template: TEMPLATE_CALENDRIER,
|
||||
classes: ["calendar"],
|
||||
popOut: true,
|
||||
resizable: false,
|
||||
width: 'fit-content',
|
||||
height: 'fit-content',
|
||||
});
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
// position
|
||||
this.calendrierPos = duplicate(game.settings.get(SYSTEM_RDD, "calendrier-pos"));
|
||||
if (this.calendrierPos == undefined || this.calendrierPos.top == undefined) {
|
||||
this.calendrierPos = RdDCalendrier.createCalendrierPos();
|
||||
game.settings.set(SYSTEM_RDD, "calendrier-pos", this.calendrierPos);
|
||||
}
|
||||
// Calendrier
|
||||
this.timestamp = RdDTimestamp.getWorldTime();
|
||||
|
||||
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
|
||||
RdDTimestamp.setWorldTime(this.timestamp);
|
||||
this.nombresAstraux = this.getNombresAstraux();
|
||||
this.rebuildNombresAstraux(HIDE_DICE); // Ensure always up-to-date
|
||||
this.rebuildNombresAstraux(); // Ensure always up-to-date
|
||||
}
|
||||
console.log('RdDCalendrier.constructor()', this.timestamp, this.timestamp.toCalendrier(), this.calendrierPos, this.nombresAstraux);
|
||||
Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id));
|
||||
}
|
||||
|
||||
display() {
|
||||
let templatePath = "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html";
|
||||
renderTemplate(templatePath, {}).then(html => {
|
||||
this.render(true);
|
||||
get title() {
|
||||
const calendrier = this.timestamp.toCalendrier();
|
||||
return `${calendrier.heure.label}, ${calendrier.jourDuMois} ${calendrier.mois.label} ${calendrier.annee} (${calendrier.mois.saison})`;
|
||||
}
|
||||
|
||||
savePosition() {
|
||||
game.settings.set(SYSTEM_RDD, "calendrier-pos", {
|
||||
top: this.position.top,
|
||||
left: this.position.left,
|
||||
horlogeAnalogique: this.horlogeAnalogique
|
||||
});
|
||||
}
|
||||
|
||||
getSavePosition() {
|
||||
const pos = game.settings.get(SYSTEM_RDD, "calendrier-pos");
|
||||
if (pos?.top == undefined) {
|
||||
return INITIAL_CALENDAR_POS;
|
||||
}
|
||||
this.horlogeAnalogique = pos.horlogeAnalogique;
|
||||
return pos
|
||||
}
|
||||
|
||||
setPosition(position) {
|
||||
super.setPosition(position)
|
||||
this.savePosition()
|
||||
}
|
||||
|
||||
display() {
|
||||
AutoAdjustDarkness.adjust(RdDTimestamp.getWorldTime().darkness);
|
||||
const pos = this.getSavePosition()
|
||||
this.render(true, { left: pos.left, top: pos.top });
|
||||
return this;
|
||||
}
|
||||
|
||||
_getHeaderButtons() {
|
||||
if (game.user.isGM) {
|
||||
return [
|
||||
{ class: "calendar-astrologie", icon: "fa-solid fa-moon-over-sun", onclick: ev => this.showAstrologieEditor() },
|
||||
{ class: "calendar-set-datetime", icon: "fa-solid fa-calendar-pen", onclick: ev => this.showCalendarEditor() },
|
||||
]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
async close() { }
|
||||
|
||||
async onUpdateSetting(setting, update, options, id) {
|
||||
if (setting.key == SYSTEM_RDD + '.' + WORLD_TIMESTAMP_SETTING) {
|
||||
this.timestamp = RdDTimestamp.getWorldTime();
|
||||
this.updateDisplay();
|
||||
this.positionAiguilles()
|
||||
this.render(false);
|
||||
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||
}
|
||||
}
|
||||
|
||||
getData() {
|
||||
const formData = super.getData();
|
||||
this.fillCalendrierData(formData);
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
fillCalendrierData(formData = {}) {
|
||||
mergeObject(formData, this.timestamp.toCalendrier());
|
||||
formData.isGM = game.user.isGM;
|
||||
formData.heures = RdDTimestamp.definitions()
|
||||
formData.horlogeAnalogique = this.horlogeAnalogique;
|
||||
formData.autoDarkness = AutoAdjustDarkness.isAuto()
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
async activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
this.html = html;
|
||||
|
||||
this.updateDisplay();
|
||||
|
||||
this.html.find('.ajout-chronologie').click(ev => DialogChronologie.create());
|
||||
|
||||
this.html.find('.toggle-horloge-analogique').click(ev => this.onToggleHorlogeAnalogique())
|
||||
this.html.find('.toggle-auto-darkness').click(ev => this.onToggleAutoDarkness())
|
||||
this.html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
|
||||
|
||||
this.html.find('.horloge-roue .horloge-heure').click(event => {
|
||||
const h = this.html.find(event.currentTarget)?.data('heure');
|
||||
this.positionnerHeure(Number(h));
|
||||
})
|
||||
this.html.find('.calendar-set-datetime').click(ev => {
|
||||
ev.preventDefault();
|
||||
this.showCalendarEditor();
|
||||
@ -82,77 +150,21 @@ export class RdDCalendrier extends Application {
|
||||
ev.preventDefault();
|
||||
this.showAstrologieEditor();
|
||||
});
|
||||
|
||||
this.html.find('.calendar-title').mousedown(ev => {
|
||||
ev.preventDefault();
|
||||
ev = ev || window.event;
|
||||
let isRightMB = false;
|
||||
if ("which" in ev) { // Gecko (Firefox), WebKit (Safari/Chrome) & Opera
|
||||
isRightMB = ev.which == 3;
|
||||
} else if ("button" in ev) { // IE, Opera
|
||||
isRightMB = ev.button == 2;
|
||||
}
|
||||
|
||||
if (!isRightMB) {
|
||||
dragElement(document.getElementById("calendar-time-container"));
|
||||
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
|
||||
|
||||
function dragElement(elmnt) {
|
||||
elmnt.onmousedown = dragMouseDown;
|
||||
function dragMouseDown(e) {
|
||||
e = e || window.event;
|
||||
e.preventDefault();
|
||||
pos3 = e.clientX;
|
||||
pos4 = e.clientY;
|
||||
|
||||
document.onmouseup = closeDragElement;
|
||||
document.onmousemove = elementDrag;
|
||||
}
|
||||
|
||||
function elementDrag(e) {
|
||||
e = e || window.event;
|
||||
e.preventDefault();
|
||||
// calculate the new cursor position:
|
||||
pos1 = pos3 - e.clientX;
|
||||
pos2 = pos4 - e.clientY;
|
||||
pos3 = e.clientX;
|
||||
pos4 = e.clientY;
|
||||
// set the element's new position:
|
||||
elmnt.style.bottom = undefined
|
||||
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
|
||||
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
|
||||
}
|
||||
|
||||
function closeDragElement() {
|
||||
// stop moving when mouse button is released:
|
||||
elmnt.onmousedown = undefined;
|
||||
document.onmouseup = undefined;
|
||||
document.onmousemove = undefined;
|
||||
let xPos = (elmnt.offsetLeft - pos1) > window.innerWidth ? window.innerWidth - 200 : (elmnt.offsetLeft - pos1);
|
||||
let yPos = (elmnt.offsetTop - pos2) > window.innerHeight - 20 ? window.innerHeight - 100 : (elmnt.offsetTop - pos2)
|
||||
xPos = xPos < 0 ? 0 : xPos;
|
||||
yPos = yPos < 0 ? 0 : yPos;
|
||||
if (xPos != (elmnt.offsetLeft - pos1) || yPos != (elmnt.offsetTop - pos2)) {
|
||||
elmnt.style.top = (yPos) + "px";
|
||||
elmnt.style.left = (xPos) + "px";
|
||||
}
|
||||
game.system.rdd.calendrier.calendrierPos.top = yPos;
|
||||
game.system.rdd.calendrier.calendrierPos.left = xPos;
|
||||
if (game.user.isGM) {
|
||||
game.settings.set(SYSTEM_RDD, "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (isRightMB) {
|
||||
game.system.rdd.calendrier.calendrierPos.top = 200;
|
||||
game.system.rdd.calendrier.calendrierPos.left = 200;
|
||||
if (game.user.isGM) {
|
||||
game.settings.set(SYSTEM_RDD, "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos));
|
||||
}
|
||||
this.setPos(game.system.rdd.calendrier.calendrierPos);
|
||||
}
|
||||
});
|
||||
this.positionAiguilles()
|
||||
}
|
||||
|
||||
positionAiguilles() {
|
||||
const timestamp = this.getTimestamp();
|
||||
this.html.find(`div.horloge-roue div.horloge-aiguille-heure img`).css(Misc.cssRotation(timestamp.angleHeure));
|
||||
this.html.find(`div.horloge-roue div.horloge-aiguille-minute img`).css(Misc.cssRotation(timestamp.angleMinute));
|
||||
}
|
||||
|
||||
onToggleHorlogeAnalogique() {
|
||||
this.horlogeAnalogique = !this.horlogeAnalogique;
|
||||
this.savePosition()
|
||||
this.display()
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getNombresAstraux() {
|
||||
return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? [];
|
||||
@ -163,6 +175,16 @@ export class RdDCalendrier extends Application {
|
||||
return this.timestamp.formatDate();
|
||||
}
|
||||
|
||||
dateReel() {
|
||||
return new Date().toLocaleString("sv-SE", {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "2-digit"
|
||||
});
|
||||
}
|
||||
|
||||
isAfterIndexDate(indexDate) {
|
||||
// TODO: standardize
|
||||
return indexDate < this.timestamp.indexDate;
|
||||
@ -199,15 +221,8 @@ export class RdDCalendrier extends Application {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async ajouterNombreAstral(indexDate, showDice = SHOW_DICE) {
|
||||
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: showDice, rollMode: "selfroll" });
|
||||
const dateFuture = RdDTimestamp.formatIndexDate(indexDate);
|
||||
if (showDice != HIDE_DICE) {
|
||||
ChatMessage.create({
|
||||
whisper: ChatMessage.getWhisperRecipients("GM"),
|
||||
content: `Le chiffre astrologique du ${dateFuture} sera le ${nombreAstral}`
|
||||
});
|
||||
}
|
||||
async ajouterNombreAstral(indexDate) {
|
||||
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: HIDE_DICE, rollMode: "selfroll" });
|
||||
return {
|
||||
nombreAstral: nombreAstral,
|
||||
valeursFausses: [],
|
||||
@ -226,7 +241,6 @@ export class RdDCalendrier extends Application {
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/**
|
||||
*
|
||||
* @param {*} indexDate la date pour laquelle obtenir le nombre astral. Si undefined, on prend la date du jour
|
||||
@ -243,7 +257,7 @@ export class RdDCalendrier extends Application {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rebuildNombresAstraux(showDice = HIDE_DICE) {
|
||||
async rebuildNombresAstraux() {
|
||||
if (Misc.isUniqueConnectedGM()) {
|
||||
let newList = [];
|
||||
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
||||
@ -252,7 +266,7 @@ export class RdDCalendrier extends Application {
|
||||
if (na) {
|
||||
newList[i] = na;
|
||||
} else {
|
||||
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice);
|
||||
newList[i] = await this.ajouterNombreAstral(dayIndex);
|
||||
}
|
||||
}
|
||||
this.nombresAstraux = newList;
|
||||
@ -275,12 +289,13 @@ export class RdDCalendrier extends Application {
|
||||
const oldTimestamp = this.timestamp;
|
||||
await Promise.all(game.actors.map(async actor => await actor.onTimeChanging(oldTimestamp, newTimestamp)));
|
||||
RdDTimestamp.setWorldTime(newTimestamp);
|
||||
if (oldTimestamp.indexDate + 1 == newTimestamp.indexDate && ReglesOptionelles.isUsing("chateau-dormant-gardien")) {
|
||||
if (oldTimestamp.indexDate + 1 == newTimestamp.indexDate && ReglesOptionnelles.isUsing("chateau-dormant-gardien")) {
|
||||
await DialogChateauDormant.create();
|
||||
}
|
||||
this.timestamp = newTimestamp;
|
||||
await this.rebuildNombresAstraux();
|
||||
this.updateDisplay();
|
||||
this.positionAiguilles()
|
||||
this.display();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -294,13 +309,15 @@ export class RdDCalendrier extends Application {
|
||||
else if (calendarSet) {
|
||||
this.positionnerHeure(Number(calendarSet.value));
|
||||
}
|
||||
this.updateDisplay();
|
||||
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||
this.positionAiguilles()
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async incrementTime(minutes = 0) {
|
||||
await this.setNewTimestamp(this.timestamp.addMinutes(minutes));
|
||||
if (game.user.isGM) {
|
||||
await this.setNewTimestamp(this.timestamp.addMinutes(minutes));
|
||||
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -310,17 +327,13 @@ export class RdDCalendrier extends Application {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async positionnerHeure(heure) {
|
||||
const indexDate = this.timestamp.indexDate;
|
||||
const addDay = this.timestamp.heure < heure ? 0 : 1;
|
||||
const newTimestamp = new RdDTimestamp({ indexDate: indexDate + addDay }).addHeures(heure);
|
||||
await this.setNewTimestamp(newTimestamp)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
fillCalendrierData(formData = {}) {
|
||||
mergeObject(formData, this.timestamp.toCalendrier());
|
||||
formData.isGM = game.user.isGM;
|
||||
return formData;
|
||||
if (game.user.isGM) {
|
||||
const indexDate = this.timestamp.indexDate;
|
||||
const addDay = this.timestamp.heure < heure ? 0 : 1;
|
||||
const newTimestamp = new RdDTimestamp({ indexDate: indexDate + addDay }).addHeures(heure);
|
||||
await this.setNewTimestamp(newTimestamp)
|
||||
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -376,14 +389,14 @@ export class RdDCalendrier extends Application {
|
||||
}
|
||||
|
||||
addNbAstralIncorect(actorId, date, nbAstral) {
|
||||
let astralData = this.nombresAstraux.find((nombreAstral, i) => nombreAstral.index == date);
|
||||
const astralData = this.nombresAstraux.find((nombreAstral, i) => nombreAstral.index == date);
|
||||
astralData.valeursFausses.push({ actorId: actorId, nombreAstral: nbAstral });
|
||||
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.nombresAstraux);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getAjustementAstrologique(heureNaissance, name = undefined) {
|
||||
let defHeure = RdDTimestamp.findHeure(heureNaissance);
|
||||
const defHeure = RdDTimestamp.findHeure(heureNaissance);
|
||||
if (defHeure) {
|
||||
return RdDTimestamp.ajustementAstrologiqueHeure(defHeure.heure, this.getNombreAstral(), this.timestamp.heure);
|
||||
}
|
||||
@ -396,56 +409,6 @@ export class RdDCalendrier extends Application {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getData() {
|
||||
let formData = super.getData();
|
||||
this.fillCalendrierData(formData);
|
||||
this.setPos(this.calendrierPos);
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
setPos(pos) {
|
||||
return new Promise(resolve => {
|
||||
function check() {
|
||||
let elmnt = document.getElementById("calendar-time-container");
|
||||
if (elmnt) {
|
||||
elmnt.style.bottom = undefined;
|
||||
let xPos = (pos.left) > window.innerWidth ? window.innerWidth - 200 : pos.left;
|
||||
let yPos = (pos.top) > window.innerHeight - 20 ? window.innerHeight - 100 : pos.top;
|
||||
elmnt.style.top = (yPos) + "px";
|
||||
elmnt.style.left = (xPos) + "px";
|
||||
resolve();
|
||||
} else {
|
||||
setTimeout(check, 30);
|
||||
}
|
||||
}
|
||||
check();
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateDisplay() {
|
||||
let calendrier = this.fillCalendrierData();
|
||||
// Rebuild text du calendrier
|
||||
let dateHTML = `${calendrier.jourDuMois} ${calendrier.mois.label} (${calendrier.mois.saison}) de l'année ${calendrier.annee}`
|
||||
if (game.user.isGM) {
|
||||
dateHTML = dateHTML + "<br>Nombre Astral: " + (this.getNombreAstral() ?? "?");
|
||||
}
|
||||
for (let handle of document.getElementsByClassName("calendar-title")) {
|
||||
handle.innerHTML = dateHTML;
|
||||
}
|
||||
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
|
||||
heure.innerHTML = calendrier.heure.label;
|
||||
}
|
||||
for (const minute of document.getElementsByClassName("calendar-minute-texte")) {
|
||||
minute.innerHTML = `${calendrier.minute} minutes`;
|
||||
}
|
||||
for (const heureImg of document.getElementsByClassName("calendar-heure-img")) {
|
||||
heureImg.src = calendrier.heure.icon;
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async saveEditeur(calendrierData) {
|
||||
const newTimestamp = RdDTimestamp.timestamp(
|
||||
@ -460,10 +423,10 @@ export class RdDCalendrier extends Application {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async showCalendarEditor() {
|
||||
let calendrierData = this.fillCalendrierData();
|
||||
const calendrierData = this.fillCalendrierData();
|
||||
if (this.editeur == undefined) {
|
||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', calendrierData);
|
||||
this.editeur = new RdDCalendrierEditeur(html, this, calendrierData)
|
||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/time/calendar-editor.hbs', calendrierData);
|
||||
this.editeur = new RdDCalendrierEditor(html, this, calendrierData)
|
||||
}
|
||||
this.editeur.updateData(calendrierData);
|
||||
this.editeur.render(true);
|
||||
@ -473,4 +436,9 @@ export class RdDCalendrier extends Application {
|
||||
async showAstrologieEditor() {
|
||||
await AppAstrologie.create();
|
||||
}
|
||||
}
|
||||
|
||||
async onToggleAutoDarkness() {
|
||||
await AutoAdjustDarkness.toggle()
|
||||
this.display()
|
||||
}
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import { SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { SHOW_DICE, SYSTEM_RDD } from "../constants.js";
|
||||
import { Grammar } from "../grammar.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDDice } from "../rdd-dice.js";
|
||||
import { AutoAdjustDarkness } from "./auto-adjust-darkness.js";
|
||||
|
||||
export const WORLD_TIMESTAMP_SETTING = "calendrier";
|
||||
|
||||
@ -15,18 +16,18 @@ export const RDD_MINUTES_PAR_JOUR = 1440; //RDD_HEURES_PAR_JOUR * RDD_MINUTES_PA
|
||||
const ROUNDS_PAR_MINUTE = 10;
|
||||
|
||||
const DEFINITION_HEURES = [
|
||||
{ key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "Printemps" },
|
||||
{ key: "sirene", label: "Sirène", lettreFont: 'i', saison: "Printemps" },
|
||||
{ key: "faucon", label: "Faucon", lettreFont: 'f', saison: "Printemps" },
|
||||
{ key: "couronne", label: "Couronne", lettreFont: '', saison: "Eté" },
|
||||
{ key: "dragon", label: "Dragon", lettreFont: 'd', saison: "Eté" },
|
||||
{ key: "epees", label: "Epées", lettreFont: 'e', saison: "Eté" },
|
||||
{ key: "lyre", label: "Lyre", lettreFont: 'l', saison: "Automne" },
|
||||
{ key: "serpent", label: "Serpent", lettreFont: 's', saison: "Automne" },
|
||||
{ key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne" },
|
||||
{ key: "araignee", label: "Araignée", lettreFont: 'a', saison: "Hiver" },
|
||||
{ key: "roseau", label: "Roseau", lettreFont: 'r', saison: "Hiver" },
|
||||
{ key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "Hiver" },
|
||||
{ key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "Printemps" , darkness: 0.7},
|
||||
{ key: "sirene", label: "Sirène", lettreFont: 'i', saison: "Printemps" , darkness: 0.4},
|
||||
{ key: "faucon", label: "Faucon", lettreFont: 'f', saison: "Printemps" , darkness: 0},
|
||||
{ key: "couronne", label: "Couronne", lettreFont: '', saison: "Eté" , darkness: 0},
|
||||
{ key: "dragon", label: "Dragon", lettreFont: 'd', saison: "Eté", darkness: 0 },
|
||||
{ key: "epees", label: "Epées", lettreFont: 'e', saison: "Eté", darkness: 0},
|
||||
{ key: "lyre", label: "Lyre", lettreFont: 'l', saison: "Automne", darkness: 0.4 },
|
||||
{ key: "serpent", label: "Serpent", lettreFont: 's', saison: "Automne", darkness: 0.7 },
|
||||
{ key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne", darkness: 1 },
|
||||
{ key: "araignee", label: "Araignée", lettreFont: 'a', saison: "Hiver", darkness: 1 },
|
||||
{ key: "roseau", label: "Roseau", lettreFont: 'r', saison: "Hiver", darkness: 1 },
|
||||
{ key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "Hiver", darkness: 1 },
|
||||
]
|
||||
|
||||
const FORMULES_DUREE = [
|
||||
@ -47,7 +48,6 @@ const FORMULES_PERIODE = [
|
||||
{ code: 'jour', label: "Jours", calcul: async (t, nombre) => t.addJours(nombre) },
|
||||
]
|
||||
|
||||
|
||||
export class RdDTimestamp {
|
||||
|
||||
static init() {
|
||||
@ -59,6 +59,7 @@ export class RdDTimestamp {
|
||||
type: Object
|
||||
});
|
||||
|
||||
|
||||
for (let i = 0; i < DEFINITION_HEURES.length; i++) {
|
||||
DEFINITION_HEURES[i].heure = i;
|
||||
DEFINITION_HEURES[i].hh = RdDTimestamp.hh(i);
|
||||
@ -67,7 +68,6 @@ export class RdDTimestamp {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static hh(heure) {
|
||||
return heure < 9 ? `0${heure + 1}` : `${heure + 1}`;
|
||||
}
|
||||
@ -157,7 +157,9 @@ export class RdDTimestamp {
|
||||
fields.minute.change(async (event) => await onChangeTimestamp(fields, path));
|
||||
}
|
||||
|
||||
|
||||
static defHeure(heure) {
|
||||
return DEFINITION_HEURES.find(it => (it.heure) == heure % RDD_HEURES_PAR_JOUR);
|
||||
}
|
||||
static findHeure(heure) {
|
||||
heure = Grammar.toLowerCaseNoAccentNoSpace(heure);
|
||||
let parHeureOuLabel = DEFINITION_HEURES.filter(it => (it.heure) == parseInt(heure) % RDD_HEURES_PAR_JOUR || Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure);
|
||||
@ -229,6 +231,21 @@ export class RdDTimestamp {
|
||||
this.indexMinute = indexMinute ?? 0
|
||||
}
|
||||
|
||||
get annee() { return Math.floor(this.indexDate / RDD_JOURS_PAR_AN) }
|
||||
get mois() { return Math.floor((this.indexDate % RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
|
||||
get jour() { return (this.indexDate % RDD_JOURS_PAR_AN) % RDD_JOURS_PAR_MOIS }
|
||||
get heure() { return Math.floor(this.indexMinute / RDD_MINUTES_PAR_HEURES) }
|
||||
get minute() { return this.indexMinute % RDD_MINUTES_PAR_HEURES }
|
||||
get round() { return ROUNDS_PAR_MINUTE * (this.indexMinute - Math.floor(this.indexMinute)) }
|
||||
get angleHeure() { return this.indexMinute / RDD_MINUTES_PAR_JOUR * 360 - 45 }
|
||||
get angleMinute() { return this.indexMinute / RDD_MINUTES_PAR_HEURES * 360 + 45 }
|
||||
|
||||
get darkness() {
|
||||
const darknessDebut = RdDTimestamp.definition(this.heure).darkness *100
|
||||
const darknessFin = RdDTimestamp.definition(this.heure + 1).darkness *100
|
||||
const darknessMinute = Math.round((darknessFin - darknessDebut) * this.minute / RDD_MINUTES_PAR_HEURES);
|
||||
return (darknessDebut + darknessMinute)/100
|
||||
}
|
||||
|
||||
/**
|
||||
* Convertit le timestamp en une structure avec les informations utiles
|
||||
@ -246,15 +263,6 @@ export class RdDTimestamp {
|
||||
};
|
||||
}
|
||||
|
||||
get annee() { return Math.floor(this.indexDate / RDD_JOURS_PAR_AN) }
|
||||
get mois() { return Math.floor((this.indexDate % RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
|
||||
get jour() { return (this.indexDate % RDD_JOURS_PAR_AN) % RDD_JOURS_PAR_MOIS }
|
||||
get heure() { return Math.floor(this.indexMinute / RDD_MINUTES_PAR_HEURES) }
|
||||
get minute() { return this.indexMinute % RDD_MINUTES_PAR_HEURES }
|
||||
get round() { return ROUNDS_PAR_MINUTE * (this.indexMinute - Math.floor(this.indexMinute)) }
|
||||
get angleHeure() { return this.indexMinute / RDD_MINUTES_PAR_JOUR * 360 - 60 }
|
||||
get angleMinute() { return this.indexMinute / RDD_MINUTES_PAR_HEURES * 360 + 45}
|
||||
|
||||
formatDate() {
|
||||
const jour = this.jour + 1;
|
||||
const mois = RdDTimestamp.definition(this.mois).label;
|
||||
@ -262,6 +270,10 @@ export class RdDTimestamp {
|
||||
return `${jour} ${mois}` + (annee ? ' ' + annee : '');
|
||||
}
|
||||
|
||||
formatDateHeure() {
|
||||
return `${RdDTimestamp.definition(this.heure).label}, ${this.formatDate()}`;
|
||||
}
|
||||
|
||||
nouveauJour() { return new RdDTimestamp({ indexDate: this.indexDate + 1, indexMinute: 0 }) }
|
||||
|
||||
nouvelleHeure() {
|
@ -1,6 +1,7 @@
|
||||
import { Misc } from "./misc.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { tmrConstants } from "./tmr-constants.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const TMRMapping = {
|
||||
@ -163,7 +164,7 @@ const TMRMapping = {
|
||||
C12: { type: "lac", label: "Lac de Fricassa" },
|
||||
D12: { type: "collines", label: "Collines d’Huaï" },
|
||||
E12: { type: "monts", label: "Monts Ajourés" },
|
||||
F12: { type: "necropole", label: "Nécropole de Troat" },
|
||||
F12: { type: "necropole", label: "Nécropole de Throat" },
|
||||
G12: { type: "plaines", label: "Plaines de Lufmil" },
|
||||
H12: { type: "collines", label: "Collines de Tooth" },
|
||||
I12: { type: "gouffre", label: "Gouffre Abimeux" },
|
||||
@ -199,7 +200,7 @@ const TMRMapping = {
|
||||
K14: { type: "necropole", label: "Nécropole d’Antinéar" },
|
||||
L14: { type: "plaines", label: "Plaines de Jislith" },
|
||||
M14: { type: "desolation", label: "Désolation d’Après" },
|
||||
|
||||
|
||||
A15: { type: "cite", label: "Cité de Mielh" },
|
||||
C15: { type: "plaines", label: "Plaines de Toué" },
|
||||
E15: { type: "foret", label: "Forêt des Furies" },
|
||||
@ -226,9 +227,6 @@ export const TMRType = {
|
||||
desolation: { name: "désolation", genre: "f" }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const caseSpecificModes = ["attache", "trounoir", "debordement", "reserve_extensible", "maitrisee"];
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const tmrRandomMovePatten =
|
||||
[{ name: 'top', col: 0, row: -1 },
|
||||
@ -239,8 +237,6 @@ const tmrRandomMovePatten =
|
||||
{ name: 'topleft', col: -1, row: -1 }
|
||||
]
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class TMRUtility {
|
||||
static init() {
|
||||
@ -258,39 +254,32 @@ export class TMRUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static verifyTMRCoord(coord) {
|
||||
let TMRregexp = new RegExp(/([A-M])(\d+)/g);
|
||||
let res = TMRregexp.exec(coord);
|
||||
if (res && res[1] && res[2]) {
|
||||
if (res[2] > 0 && res[2] < 16) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return Grammar.equalsInsensitive(coord, 'Fleuve') || TMRUtility.getTMR(coord);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getTMR(coord) {
|
||||
return TMRMapping[coord];
|
||||
return coord == 'Fleuve' ? TMRMapping['D1'] : TMRMapping[coord];
|
||||
}
|
||||
|
||||
static getTMRLabel(coord) {
|
||||
return TMRMapping[coord]?.label ?? (coord + ": case inconnue");
|
||||
return TMRUtility.getTMR(coord)?.label ?? (coord + ": case inconnue");
|
||||
}
|
||||
|
||||
static getTMRType(coord) {
|
||||
const tmr = TMRMapping[coord];
|
||||
const tmr = TMRUtility.getTMR(coord);
|
||||
return Misc.upperFirst(TMRType[tmr.type].name);
|
||||
}
|
||||
|
||||
static getTMRDescr(coord) {
|
||||
const tmr = TMRMapping[coord];
|
||||
const tmr = TMRUtility.getTMR(coord);
|
||||
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
|
||||
}
|
||||
|
||||
static findTMRLike(type, options = {inclusMauvaise:true}) {
|
||||
|
||||
static findTMRLike(type, options = { inclusMauvaise: true }) {
|
||||
const choix = [...Object.values(TMRType)]
|
||||
if (options.inclusMauvaise){
|
||||
choix.push({name: 'Mauvaise'});
|
||||
if (options.inclusMauvaise) {
|
||||
choix.push({ name: 'Mauvaise' });
|
||||
}
|
||||
const selection = Misc.findAllLike(type, choix).map(it => it.name);
|
||||
if (selection.length == 0) {
|
||||
@ -309,7 +298,7 @@ export class TMRUtility {
|
||||
}
|
||||
|
||||
static buildSelectionTypesTMR(typesTMR) {
|
||||
typesTMR = typesTMR?? [];
|
||||
typesTMR = typesTMR ?? [];
|
||||
return Object.values(TMRType).map(value => Misc.upperFirst(value.name))
|
||||
.sort()
|
||||
.map(name => { return { name: name, selected: typesTMR.includes(name) } });
|
||||
@ -387,6 +376,33 @@ export class TMRUtility {
|
||||
return caseList;
|
||||
}
|
||||
|
||||
// /* -------------------------------------------- */
|
||||
static computeEventPosition(event) {
|
||||
const canvasRect = event.nativeEvent.target.getBoundingClientRect();
|
||||
return {
|
||||
x: event.nativeEvent.clientX - canvasRect.left,
|
||||
y: event.nativeEvent.clientY - canvasRect.top
|
||||
};
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeEventOddq(event) {
|
||||
var { x, y } = TMRUtility.computeEventPosition(event);
|
||||
return TMRUtility.computeOddq(x, y);
|
||||
}
|
||||
|
||||
static computeOddq(x, y) {
|
||||
const col = Math.floor(x / tmrConstants.cellw); // [From 0 -> 12]
|
||||
const decallageColonne = col % 2 == 0 ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||
const row = Math.floor((y - decallageColonne) / tmrConstants.cellh); // [From 0 -> 14]
|
||||
return { col, row };
|
||||
}
|
||||
|
||||
static computeEventCoord(event) {
|
||||
const oddq = TMRUtility.computeEventOddq(event);
|
||||
return TMRUtility.oddqToCoordTMR(oddq);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// https://www.redblobgames.com/grids/hexagons/#distances
|
||||
// TMR Letter-row correspond to "odd-q" grid (letter => col, numeric => row )
|
||||
@ -412,7 +428,7 @@ export class TMRUtility {
|
||||
col >= 0 && col < 13 &&
|
||||
row >= 0 &&
|
||||
(row + col % 2 <= 14)
|
||||
);
|
||||
);
|
||||
// if (x >= 0 && x < 13 && y >= 0 && y < 14) return true;
|
||||
// if (x >= 0 && x < 13 && x % 2 == 0 && y == 14) return true;
|
||||
// return false;
|
||||
@ -456,7 +472,7 @@ export class TMRUtility {
|
||||
|
||||
static axial_subtract(a, b) {
|
||||
return {
|
||||
q: a.q- b.q,
|
||||
q: a.q - b.q,
|
||||
r: a.r - b.r
|
||||
};
|
||||
}
|
||||
@ -468,7 +484,7 @@ export class TMRUtility {
|
||||
// return Cube(q, r, s)
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// /* -------------------------------------------- */
|
||||
// static computeRealPictureCoordinates(coordOddq) {
|
||||
// let decallagePairImpair = (coordOddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Draconique } from "./draconique.js";
|
||||
import { PixiTMR } from "./pixi-tmr.js";
|
||||
|
||||
export class CarteTmr extends Draconique {
|
||||
|
||||
@ -12,9 +13,25 @@ export class CarteTmr extends Draconique {
|
||||
async onActorCreateOwned(actor, item) { }
|
||||
|
||||
code() { return 'tmr' }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/styles/img/ui/tmp_main_r1.webp' }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/styles/img/ui/tmr.webp' }
|
||||
|
||||
createSprite(pixiTMR) {
|
||||
return pixiTMR.carteTmr(this.code());
|
||||
|
||||
const img = PixiTMR.getImgFromCode(this.code())
|
||||
const sprite = new PIXI.Sprite(PIXI.utils.TextureCache[img]);
|
||||
// Setup the position of the TMR
|
||||
sprite.x = 0;
|
||||
sprite.y = 0;
|
||||
sprite.width = 722;
|
||||
sprite.height = 860;
|
||||
// Rotate around the center
|
||||
sprite.anchor.set(0);
|
||||
sprite.buttonMode = true;
|
||||
sprite.tmrObject = pixiTMR;
|
||||
|
||||
pixiTMR.addTooltip(sprite, (e,s) => this.computeTooltip(e,s));
|
||||
pixiTMR.pixiApp.stage.addChild(sprite);
|
||||
return sprite;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Misc } from "../misc.js";
|
||||
import { TYPES } from "../item.js";
|
||||
import { TMRUtility } from "../tmr-utility.js";
|
||||
import { PixiTMR } from "./pixi-tmr.js";
|
||||
|
||||
@ -9,10 +9,10 @@ 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 isCaseTMR(item) { return item.type == TYPES.casetmr; }
|
||||
static isQueueDragon(item) { return item.isQueueDragon(); }
|
||||
static isSouffleDragon(item) { return item.type == TYPES.souffle; }
|
||||
static isTeteDragon(item) { return item.type == TYPES.tete; }
|
||||
static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); }
|
||||
|
||||
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.system.coord); }
|
||||
@ -78,23 +78,45 @@ export class Draconique {
|
||||
/**
|
||||
* @param {*} img l'url du fichier image à utiliser pour le token. Si indéfini (et si createSprite n'est pas surchargé),
|
||||
* un disque est utilisé.
|
||||
*/
|
||||
*/
|
||||
img() { return undefined }
|
||||
|
||||
/**
|
||||
* factory d'élément graphique PIXI correpsondant à l'objet draconique
|
||||
* factory d'élément graphique PIXI correspondant à l'objet draconique
|
||||
* @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks.
|
||||
*/
|
||||
*/
|
||||
token(pixiTMR, linkData, coordTMR, type = undefined) {
|
||||
const token = {
|
||||
sprite: this.createSprite(pixiTMR),
|
||||
coordTMR: coordTMR
|
||||
};
|
||||
token[type ?? this.code()] = linkData;
|
||||
pixiTMR.addTooltip(token.sprite, this.tooltip(linkData));
|
||||
this.linkData = linkData;
|
||||
if (this.tooltip(linkData)) {
|
||||
pixiTMR.addTooltip(token.sprite, (e, s) => this.computeTooltip(e, s));
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* methode en charge de recalculer le tooltip lorsque la souris bouge
|
||||
* @param {*} event evenement contenant les coordonnées
|
||||
* @param {*} sprite sprite pour laquelle calculer le tooltip
|
||||
*/
|
||||
computeTooltip(event, sprite) {
|
||||
if (sprite.isOver) {
|
||||
const oddq = TMRUtility.computeEventOddq(event);
|
||||
const coord = TMRUtility.oddqToCoordTMR(oddq);
|
||||
const tmr = TMRUtility.getTMR(coord)
|
||||
if (tmr){
|
||||
const label = TMRUtility.getTMRLabel(coord);
|
||||
const text = this.tooltip(this.linkData);
|
||||
return text ? `${coord}: ${label}\n${text}` : `${coord}: ${label}`
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* factory d'élément graphique PIXI correpsondant à l'objet draconique
|
||||
* @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks.
|
||||
@ -116,11 +138,11 @@ export class Draconique {
|
||||
isCase(item, coord = undefined) {
|
||||
return Draconique.isCaseTMR(item) && item.system.specific == this.code() && (coord ? item.system.coord == coord : true);
|
||||
}
|
||||
|
||||
|
||||
find(list, coord = undefined) {
|
||||
return list.find(c => this.isCase(c, coord));
|
||||
}
|
||||
|
||||
|
||||
async createCaseTmr(actor, label, tmr, sourceId = undefined) {
|
||||
const casetmrData = {
|
||||
name: label, type: 'casetmr', img: this.img(),
|
||||
@ -128,12 +150,12 @@ export class Draconique {
|
||||
};
|
||||
await actor.createEmbeddedDocuments('Item', [casetmrData]);
|
||||
}
|
||||
|
||||
|
||||
async deleteCasesTmr(actor, draconique) {
|
||||
let caseTmrs = actor.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;
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import { Periple } from "./periple.js";
|
||||
import { UrgenceDraconique } from "./urgence-draconique.js";
|
||||
import { Grammar } from "../grammar.js";
|
||||
import { AugmentationSeuil } from "./augmentation-seuil.js";
|
||||
import { TYPES } from "../item.js";
|
||||
|
||||
|
||||
export class EffetsDraconiques {
|
||||
@ -114,46 +115,57 @@ export class EffetsDraconiques {
|
||||
);
|
||||
}
|
||||
|
||||
static filterItems(actor, filter, name) {
|
||||
return actor.filterItems(filter)
|
||||
.filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||
static tetesDragon(actor, name) {
|
||||
return actor.itemTypes[TYPES.tete].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||
}
|
||||
|
||||
static soufflesDragon(actor, name) {
|
||||
return actor.itemTypes[TYPES.souffle].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||
}
|
||||
|
||||
static queuesDragon(actor, name) {
|
||||
return actor.filterItems(it => it.isQueueDragon() && Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||
}
|
||||
|
||||
static queuesSoufflesDragon(actor, name) {
|
||||
return actor.filterItems(it => [TYPES.queue, TYPES.ombre, TYPES.souffle].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||
}
|
||||
|
||||
static countAugmentationSeuil(actor) {
|
||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Augmentation du seuil de rêve').length;
|
||||
return EffetsDraconiques.tetesDragon(actor, 'Augmentation du seuil de rêve').length;
|
||||
}
|
||||
|
||||
static isDonDoubleReve(actor) {
|
||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Don de double-rêve').length>0;
|
||||
return EffetsDraconiques.tetesDragon(actor, 'Don de double-rêve').length > 0;
|
||||
}
|
||||
|
||||
static isConnaissanceFleuve(actor) {
|
||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'connaissance du fleuve').length>0;
|
||||
return EffetsDraconiques.tetesDragon(actor, 'connaissance du fleuve').length > 0;
|
||||
}
|
||||
|
||||
static isReserveEnSecurite(actor) {
|
||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'réserve en sécurité').length>0;
|
||||
return EffetsDraconiques.tetesDragon(actor, 'réserve en sécurité').length > 0;
|
||||
}
|
||||
|
||||
static isDeplacementAccelere(actor) {
|
||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, ' déplacement accéléré').length>0;
|
||||
return EffetsDraconiques.tetesDragon(actor, 'déplacement accéléré').length > 0;
|
||||
}
|
||||
|
||||
static isDoubleResistanceFleuve(actor) {
|
||||
return EffetsDraconiques.filterItems(actor, Draconique.isSouffleDragon, 'résistance du fleuve').length>0;
|
||||
return EffetsDraconiques.soufflesDragon(actor, 'résistance du fleuve').length > 0;
|
||||
}
|
||||
|
||||
static countInertieDraconique(actor) {
|
||||
return EffetsDraconiques.filterItems(actor, Draconique.isQueueDragon, 'inertie draconique').length;
|
||||
return EffetsDraconiques.queuesDragon(actor, 'inertie draconique').length;
|
||||
}
|
||||
|
||||
static countMonteeLaborieuse(actor) {
|
||||
return EffetsDraconiques.filterItems(actor, Draconique.isQueueSouffle, 'montée laborieuse').length;
|
||||
return EffetsDraconiques.queuesSoufflesDragon(actor, 'montée laborieuse').length;
|
||||
}
|
||||
|
||||
static mauvaiseRencontre(actor) {
|
||||
const mauvaisesRencontres = EffetsDraconiques.filterItems(actor, Draconique.isQueueSouffle, 'mauvaise rencontre');
|
||||
return mauvaisesRencontres.length>0 ? mauvaisesRencontres[0] : undefined;
|
||||
const mauvaisesRencontres = EffetsDraconiques.queuesSoufflesDragon(actor, 'mauvaise rencontre');
|
||||
return mauvaisesRencontres.length > 0 ? mauvaisesRencontres[0] : undefined;
|
||||
}
|
||||
|
||||
static isPontImpraticable(actor) {
|
||||
@ -165,11 +177,11 @@ export class EffetsDraconiques {
|
||||
}
|
||||
|
||||
static isSujetInsomnie(actor) {
|
||||
return actor.items.find(it => ['queue', 'ombre'].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, 'Insomnie')) ? true : false;
|
||||
return EffetsDraconiques.queuesDragon(actor, 'Insomnie').length > 0 ? true : false;
|
||||
}
|
||||
|
||||
static isPeage(actor) {
|
||||
return EffetsDraconiques.filterItems(actor, Draconique.isSouffleDragon, 'péage').length > 0;
|
||||
return EffetsDraconiques.soufflesDragon(actor, 'péage').length > 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { ExperienceLog, XP_TOPIC } from "../actor/experience-log.js";
|
||||
import { ChatUtility } from "../chat-utility.js";
|
||||
import { Poetique } from "../poetique.js";
|
||||
import { RdDDice } from "../rdd-dice.js";
|
||||
@ -53,9 +54,10 @@ export class EffetsRencontre {
|
||||
static xp_sort_force = async (dialog, context) => {
|
||||
let competence = context.competence;
|
||||
if (competence) {
|
||||
const xpSort = Misc.toInt(competence.system.xp_sort) + context.rencontre.system.force;
|
||||
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': xpSort }]);
|
||||
await this.updateExperienceLog("XP Sort", xpSort, `Rencontre d'un ${context.rencontre.name} en TMR`);
|
||||
const fromXpSort = Number(competence.system.xp_sort);
|
||||
const toXpSort = fromXpSort + context.rencontre.system.force;
|
||||
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': toXpSort }]);
|
||||
await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXpSort, toXpSort, `${competence.name} - ${context.rencontre.name} en TMR`);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { RdDTMRDialog } from "../rdd-tmr-dialog.js";
|
||||
import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js";
|
||||
import { TMRUtility } from "../tmr-utility.js";
|
||||
|
||||
const tooltipStyle = new PIXI.TextStyle({
|
||||
export const tooltipStyle = new PIXI.TextStyle({
|
||||
fontFamily: 'CaslonAntique',
|
||||
fontSize: 18,
|
||||
fill: '#FFFFFF',
|
||||
@ -20,54 +22,37 @@ export class PixiTMR {
|
||||
this.callbacksOnAnimate = [];
|
||||
}
|
||||
|
||||
load( onLoad = (loader, resources) => {} ) {
|
||||
let loader = this.pixiApp.loader;
|
||||
async load(onLoad = (loader, resources) => { }) {
|
||||
// WIP - Deprecated since v7 : let loader = new PIXI.Loader();
|
||||
for (const [name, img] of Object.entries(PixiTMR.textures)) {
|
||||
loader = loader.add(name, img);
|
||||
const texture = await PIXI.Assets.load(img);
|
||||
let image = PIXI.Sprite.from(texture);
|
||||
}
|
||||
loader.onError.add((error, reason) => { console.log("ERROR", error, reason) });
|
||||
loader.load( (loader, resources) => {
|
||||
onLoad(loader, resources);
|
||||
for (let onAnimate of this.callbacksOnAnimate) {
|
||||
onAnimate();
|
||||
}
|
||||
});
|
||||
onLoad();
|
||||
for (let onAnimate of this.callbacksOnAnimate) {
|
||||
onAnimate();
|
||||
}
|
||||
}
|
||||
|
||||
static getImgFromCode(code) {
|
||||
return PixiTMR.textures[code]
|
||||
}
|
||||
|
||||
static register(name, img) {
|
||||
PixiTMR.textures[name] = img;
|
||||
}
|
||||
|
||||
animate(animation = pixiApp=>{})
|
||||
{
|
||||
animate(animation = pixiApp => { }) {
|
||||
this.callbacksOnAnimate.push(() => animation(this.pixiApp));
|
||||
}
|
||||
|
||||
carteTmr(code) {
|
||||
const carteTmr = new PIXI.Sprite(PIXI.utils.TextureCache[code]);
|
||||
// Setup the position of the TMR
|
||||
carteTmr.x = 0;
|
||||
carteTmr.y = 0;
|
||||
carteTmr.width = 720;
|
||||
carteTmr.height = 860;
|
||||
// Rotate around the center
|
||||
carteTmr.anchor.set(0);
|
||||
carteTmr.interactive = true;
|
||||
carteTmr.buttonMode = true;
|
||||
carteTmr.tmrObject = this;
|
||||
if (!this.tmrObject.viewOnly) {
|
||||
carteTmr.on('pointerdown', event => this.onClickBackground(event));
|
||||
}
|
||||
this.pixiApp.stage.addChild(carteTmr);
|
||||
return carteTmr;
|
||||
}
|
||||
|
||||
sprite(code, options = {}) {
|
||||
const texture = PIXI.utils.TextureCache[code];
|
||||
let img = PixiTMR.getImgFromCode(code)
|
||||
const texture = PIXI.utils.TextureCache[img];
|
||||
if (!texture) {
|
||||
console.error("Texture manquante", code)
|
||||
console.error("Texture manquante", code, PIXI.utils.TextureCache)
|
||||
return;
|
||||
}
|
||||
}
|
||||
let sprite = new PIXI.Sprite(texture);
|
||||
sprite.width = options.taille ?? tmrConstants.half;
|
||||
sprite.height = options.taille ?? tmrConstants.half;
|
||||
@ -75,13 +60,13 @@ export class PixiTMR {
|
||||
if (options.color) {
|
||||
sprite.tint = options.color;
|
||||
}
|
||||
sprite.zIndex = options.zIndex ?? tmrTokenZIndex.casehumide+1;
|
||||
sprite.zIndex = options.zIndex ?? tmrTokenZIndex.casehumide + 1;
|
||||
sprite.alpha = options.alpha ?? 0.75;
|
||||
sprite.decallage = options.decallage ?? tmrConstants.center;
|
||||
this.pixiApp.stage.addChild(sprite);
|
||||
return sprite;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
circle(name, options = {}) {
|
||||
let sprite = new PIXI.Graphics();
|
||||
sprite.beginFill(options.color, options.opacity);
|
||||
@ -92,26 +77,37 @@ export class PixiTMR {
|
||||
return sprite;
|
||||
}
|
||||
|
||||
addTooltip(sprite, text) {
|
||||
if (text) {
|
||||
sprite.tooltip = new PIXI.Text(text, tooltipStyle);
|
||||
sprite.tooltip.zIndex = tmrTokenZIndex.tooltip;
|
||||
sprite.isOver = false;
|
||||
sprite.interactive = true;
|
||||
sprite.on('pointerdown', event => this.onClickBackground(event))
|
||||
.on('pointerover', () => this.onShowTooltip(sprite))
|
||||
.on('pointerout', () => this.onHideTooltip(sprite));
|
||||
}
|
||||
addTooltip(sprite, computeTooltip) {
|
||||
sprite.tooltip = new PIXI.Text('', tooltipStyle);
|
||||
sprite.tooltip.zIndex = tmrTokenZIndex.tooltip;
|
||||
sprite.isOver = false;
|
||||
sprite.eventMode = 'dynamic'; // PIXI 7 To be checked
|
||||
sprite
|
||||
.on('pointermove', event => this.onPointerMove(event, sprite, computeTooltip))
|
||||
.on('pointerdown', event => this.onClickBackground(event))
|
||||
.on('pointerover', event => this.onShowTooltip(event, sprite))
|
||||
.on('pointerout', event => this.onHideTooltip(event, sprite));
|
||||
}
|
||||
|
||||
|
||||
onClickBackground(event) {
|
||||
this.tmrObject.onClickTMR(event)
|
||||
if (!this.viewOnly) {
|
||||
this.tmrObject.onClickTMR(event)
|
||||
}
|
||||
}
|
||||
|
||||
onShowTooltip(sprite) {
|
||||
if (sprite.tooltip) {
|
||||
onPointerMove(event, sprite, computeTooltip) {
|
||||
if (sprite.isOver && sprite.tooltip) {
|
||||
var { x, y } = TMRUtility.computeEventPosition(event);
|
||||
const oddq = TMRUtility.computeOddq(x, y);
|
||||
|
||||
sprite.tooltip.x = x + (oddq.col > 8 ? - 3 * tmrConstants.full : tmrConstants.half)
|
||||
sprite.tooltip.y = y + (oddq.row > 10 ? - tmrConstants.half : tmrConstants.half)
|
||||
sprite.tooltip.text = computeTooltip(event, sprite);
|
||||
}
|
||||
}
|
||||
|
||||
onShowTooltip(event, sprite) {
|
||||
if (sprite.tooltip) {
|
||||
if (!sprite.isOver) {
|
||||
sprite.tooltip.x = sprite.x;
|
||||
sprite.tooltip.y = sprite.y;
|
||||
@ -121,7 +117,7 @@ export class PixiTMR {
|
||||
}
|
||||
}
|
||||
|
||||
onHideTooltip(sprite) {
|
||||
onHideTooltip(event, sprite) {
|
||||
if (sprite.tooltip) {
|
||||
if (sprite.isOver) {
|
||||
this.pixiApp.stage.removeChild(sprite.tooltip);
|
||||
@ -130,7 +126,7 @@ export class PixiTMR {
|
||||
}
|
||||
}
|
||||
|
||||
setPosition( sprite, oddq) {
|
||||
setPosition(sprite, oddq) {
|
||||
let decallagePairImpair = (oddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||
let dx = (sprite.decallage == undefined) ? 0 : sprite.decallage.x;
|
||||
let dy = (sprite.decallage == undefined) ? 0 : sprite.decallage.y;
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,25 +1,25 @@
|
||||
{"_id":"2KM1yiEOE0ZdT2oL","name":"Désir d'escalade difficile","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.2KM1yiEOE0ZdT2oL"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Désir thanataire. Hauteur à grimper : 4d6 m, difficulté de l’escalade : 1d4-4.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":4,"hautrevant":false,"categorie":"lancinant","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017067,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"2KbzOC2aj98CiQbW","name":"Désir de blesser un enfant","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.2KbzOC2aj98CiQbW"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Désir thanataire. Causer au minimum une blessure légère.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":4,"hautrevant":false,"categorie":"lancinant","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017067,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"3dnmi4Fyh5eUQcyP","name":"Urgence draconique","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.3dnmi4Fyh5eUQcyP"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Le haut-rêvant est pris du besoin irrésistible de déclencher immédiatement son plus proche sort en réserve. À équidistance, prendre dans le sens des aiguilles d’une montre en commençant par le haut. En cas de rencontre dans les TMR, se dérober équivaut à refouler la queue de Dragon. Si aucun sort n’est en réserve, ou si il y a impossibilité de pratiquer la magie à cause d’une autre queue ou d’un souffle, tirer à la place une idée fixe.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"false","refoulement":4,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017067,"modifiedTime":1673118685215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"3dnmi4Fyh5eUQcyP","name":"Urgence draconique","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.3dnmi4Fyh5eUQcyP"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Le haut-rêvant est pris du besoin irrésistible de déclencher immédiatement son plus proche sort en réserve. À équidistance, prendre dans le sens des aiguilles d’une montre en commençant par le haut. En cas de rencontre dans les TMR, se dérober équivaut à refouler la queue de Dragon. Si aucun sort n’est en réserve, ou si il y a impossibilité de pratiquer la magie à cause d’une autre queue ou d’un souffle, tirer à la place une idée fixe.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"","refoulement":4,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478017067,"modifiedTime":1679614524362,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"6MUcjYfxfi45STvo","name":"Insomnie","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.6MUcjYfxfi45STvo"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Impossibilité totale de dormir, et donc de rêver, pendant un jour.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"","refoulement":0,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017067,"modifiedTime":1673118685215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"DnhuuGUEbOF95JlN","name":"Désir de boire du sang chaud","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.DnhuuGUEbOF95JlN"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Désir thanataire. Il s’agit de sang encore chaud de la chaleur naturelle de la victime.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":4,"hautrevant":false,"categorie":"lancinant","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017068,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"N9j8K6x89BdS7ZKN","name":"Conquête","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.N9j8K6x89BdS7ZKN"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Avant de pouvoir à nouveau faire usage du haut-rêve, y compris déclencher volontairement un sort mis en réserve, le haut-rêvant doit se rendre dans une certaine case des TMR déterminée aléatoirement et la <em>maîtriser</em>, difficulté -7. Ce peut être n’importe quelle case, sauf une case humide. En cas d’échec, la concentration est rompue ; il n’y a pas de souffle de Dragon en cas d’échec total.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"false","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017068,"modifiedTime":1673118685213,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"N9j8K6x89BdS7ZKN","name":"Conquête","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.N9j8K6x89BdS7ZKN"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Avant de pouvoir à nouveau faire usage du haut-rêve, y compris déclencher volontairement un sort mis en réserve, le haut-rêvant doit se rendre dans une certaine case des TMR déterminée aléatoirement et la <em>maîtriser</em>, difficulté -7. Ce peut être n’importe quelle case, sauf une case humide. En cas d’échec, la concentration est rompue ; il n’y a pas de souffle de Dragon en cas d’échec total.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478017068,"modifiedTime":1679614460613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"PMz7SaB6sRxhwrWw","name":"Coup de barre","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.PMz7SaB6sRxhwrWw"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Prise immédiate de 3d6 points de fatigue.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017068,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"PmEjVox3Q6SPF730","name":"Inertie draconique","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.PmEjVox3Q6SPF730"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant un jour, la fatigue en TMR est doublée. Chaque case ou round coûte 2 points au lieu d’un.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"","refoulement":0,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017068,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"RrPMV2HW2Rg8POK1","name":"Souvenir morbide de l'archétype","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.RrPMV2HW2Rg8POK1"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Les prochains points d’expérience dus au stress doivent être mis en Thanatos.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":5,"hautrevant":true,"categorie":"false","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017068,"modifiedTime":1673118685215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"S7se7qPnL6WDg5U5","name":"Mauvaise rencontre en perspective","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.S7se7qPnL6WDg5U5"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Tirer la prochaine rencontre dans les TMR sur la @Compendium[foundryvtt-reve-de-dragon.tables-diverses.66ye0OOxBO9LEjdd]{Table spéciale de rencontres}</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"false","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017068,"modifiedTime":1673118685215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"UmvGxA4cFSoRE82Z","name":"Dépouillement","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.UmvGxA4cFSoRE82Z"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Faire don de toute la monnaie actuellement possédée à la première personne inconnue rencontrée. En attendant, se garder d’aucune dépense.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"false","refoulement":4,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017069,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"RrPMV2HW2Rg8POK1","name":"Souvenir morbide de l'archétype","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.RrPMV2HW2Rg8POK1"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Les prochains points d’expérience dus au stress doivent être mis en Thanatos.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":5,"hautrevant":true,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478017068,"modifiedTime":1679614525067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"S7se7qPnL6WDg5U5","name":"Mauvaise rencontre en perspective","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.S7se7qPnL6WDg5U5"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Tirer la prochaine rencontre dans les TMR sur la @Compendium[foundryvtt-reve-de-dragon.tables-diverses.66ye0OOxBO9LEjdd]{Table spéciale de rencontres}</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478017068,"modifiedTime":1679614525873,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"UmvGxA4cFSoRE82Z","name":"Dépouillement","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.UmvGxA4cFSoRE82Z"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Faire don de toute la monnaie actuellement possédée à la première personne inconnue rencontrée. En attendant, se garder d’aucune dépense.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"","refoulement":4,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478017069,"modifiedTime":1679614470999,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"aZWuRmi8lplZQcdM","name":"Amnésie sélective","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.aZWuRmi8lplZQcdM"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant un jour, perte totale d’une compétence, à l’exclusion du Draconic. Déterminer aléatoirement la compétence visée qui, pratiquement, retourne au niveau de base. Si elle est déjà au niveau de base, en choisir une autre.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"","refoulement":0,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017069,"modifiedTime":1673118685213,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"cUkRSRz5DJYb3WM8","name":"Couardise irraisonnée","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.cUkRSRz5DJYb3WM8"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>la prochaine occasion de combat, obligation de fuir, de se cacher ou de se rendre. Impossibilité d’utiliser aucune magie, ni sur l’ennemi, ni sur soi-même.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"false","refoulement":4,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017069,"modifiedTime":1673118685213,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"cUkRSRz5DJYb3WM8","name":"Couardise irraisonnée","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.cUkRSRz5DJYb3WM8"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>la prochaine occasion de combat, obligation de fuir, de se cacher ou de se rendre. Impossibilité d’utiliser aucune magie, ni sur l’ennemi, ni sur soi-même.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"","refoulement":4,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478017069,"modifiedTime":1679614463556,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"dFf8jaC0RvidC1ZC","name":"Haine fatale","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.dFf8jaC0RvidC1ZC"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>On devient immédiatement haineux et jaloux envers la première personne inconnue de même sexe et de même espèce rencontrée. Traiter comme le Coup de foudre fatal. La satisfaction s’obtient en blessant gravement ou en infligeant une cuisante humiliation publique.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":10,"hautrevant":false,"categorie":"lancinant","refoulement":4,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017069,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"e67rXcuO236ioYAr","name":"Infarctus","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.e67rXcuO236ioYAr"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Perte immédiate de 4 points de vie (et 8 points d’endurance). Ces points pourront commencer à être regagnés au bout d’un jour complet.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":5,"hautrevant":false,"categorie":"false","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017069,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"e67rXcuO236ioYAr","name":"Infarctus","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.e67rXcuO236ioYAr"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Perte immédiate de 4 points de vie (et 8 points d’endurance). Ces points pourront commencer à être regagnés au bout d’un jour complet.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":5,"hautrevant":false,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478017069,"modifiedTime":1679614525870,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"fO1jjVlOb6faLv3T","name":"Désir de dormir dans un cercueil","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.fO1jjVlOb6faLv3T"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Désir thanataire.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":4,"hautrevant":false,"categorie":"lancinant","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017069,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"fUKNZ0uEG2y2PkOk","name":"Injurier le premier inconnu rencontré","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.fUKNZ0uEG2y2PkOk"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Désir d'injurier la première personne inconnue rencontrée</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"false","refoulement":4,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1673118685215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"fUKNZ0uEG2y2PkOk","name":"Injurier le premier inconnu rencontré","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.fUKNZ0uEG2y2PkOk"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Désir d'injurier la première personne inconnue rencontrée</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"","refoulement":4,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1679614525871,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"gT0PQAxlYrtITyut","name":"Désir de blesser une femme","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.gT0PQAxlYrtITyut"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Désir thanataire. Causer au minimum une blessure légère.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":4,"hautrevant":false,"categorie":"lancinant","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"lz3ghhJzkPRWJ2jz","name":"Désir de parler à un crâne (humain)","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.lz3ghhJzkPRWJ2jz"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Désir thanataire. La \"conversation\" doit durer un minimum de 15 minutes.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":4,"hautrevant":false,"categorie":"lancinant","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"spYuiInqbCoDsKvd","name":"Héroïsme forcené","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.spYuiInqbCoDsKvd"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>À la prochaine occasion de combat, obligation de foncer en tête en corps à corps ou avec une arme de mêlée. Impossibilité d’utiliser aucune magie, ni sur l’ennemi, ni sur soi-même.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":9,"hautrevant":false,"categorie":"false","refoulement":4,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"twUoR8ALYiabkfoE","name":"Désir d'entendre hurler de terreur","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.twUoR8ALYiabkfoE"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Désir thanataire. Il doit s’agir d’un hurlement humain.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":4,"hautrevant":false,"categorie":"lancinant","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"uQ4PwcwplvZarfn1","name":"Montée laborieuse","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.uQ4PwcwplvZarfn1"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant un jour, monter en TMR coûte 2 points de rêve au lieu d’un, et 3 points en déplacement accéléré.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"","refoulement":0,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1673118685215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"wqWkQQsAPVlFw4ft","name":"Désir d'assister à une pendaison","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.wqWkQQsAPVlFw4ft"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Désir thanataire.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":4,"hautrevant":false,"categorie":"lancinant","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1673118685214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"yEHdCabJYx0qvoL5","name":"Réinsertion aléatoire","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.yEHdCabJYx0qvoL5"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Comme après une sortie de la carte, le gardien des rêves réintroduit secrètement le demi-rêve du haut-rêvant dans les TMR.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"false","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1673118685215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"zIXgRwfB83DMaNX8","name":"Pèlerinage","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.zIXgRwfB83DMaNX8"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Avant de pouvoir à nouveau faire usage du haut-rêve, y compris déclencher volontairement un sort mis en réserve, le haut-rêvant doit se rendre dans une certaine case des TMR déterminée aléatoirement. Un Passeur peut l’y téléporter, mais un Messager ne peut s’y rendre à sa place. Dès que la case est atteinte, le pèlerinage est accompli.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"false","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1673118685215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"yEHdCabJYx0qvoL5","name":"Réinsertion aléatoire","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.yEHdCabJYx0qvoL5"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Comme après une sortie de la carte, le gardien des rêves réintroduit secrètement le demi-rêve du haut-rêvant dans les TMR.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1679614525586,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"zIXgRwfB83DMaNX8","name":"Pèlerinage","type":"ombre","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.ombres-de-thanatos.zIXgRwfB83DMaNX8"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Avant de pouvoir à nouveau faire usage du haut-rêve, y compris déclencher volontairement un sort mis en réserve, le haut-rêvant doit se rendre dans une certaine case des TMR déterminée aléatoirement. Un Passeur peut l’y téléporter, mais un Messager ne peut s’y rendre à sa place. Dès que la case est atteinte, le pèlerinage est accompli.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":true,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478017070,"modifiedTime":1679614525874,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{"_id":"0jrEZ62Q2Jz4kBGf","name":"Mauvaise rencontre en perspective","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.0jrEZ62Q2Jz4kBGf"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>La prochaine rencontre dans les TMR sera tirée de la @Compendium[foundryvtt-reve-de-dragon.tables-diverses.66ye0OOxBO9LEjdd]{Table spéciale de rencontres}</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025459,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"0uc2pMIGL03Hq2Hn","name":"Anorexie. Ne rien avaler, ni solide, ni liquide, pas même une potion","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.0uc2pMIGL03Hq2Hn"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025459,"modifiedTime":1673118700210,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"1gGVlZM0UyifL6RK","name":"Souvenir obsessionnel de l'archétype","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.1gGVlZM0UyifL6RK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Les prochains points d’expérience dus au stress doivent être mis dans une compétence déterminée aléatoirement par la table de @Compendium[foundryvtt-reve-de-dragon.tables-diverses.E0WLgjn6LA9WsvKJ]{Détermination aléatoire de compétence}.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":48,"hautrevant":false,"categorie":"","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025459,"modifiedTime":1673118700215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"1gGVlZM0UyifL6RK","name":"Souvenir obsessionnel de l'archétype","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.1gGVlZM0UyifL6RK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Les prochains points d’expérience dus au stress doivent être mis dans une compétence déterminée aléatoirement par la table de @Compendium[foundryvtt-reve-de-dragon.tables-diverses.E0WLgjn6LA9WsvKJ]{Détermination aléatoire de compétence}.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":48,"hautrevant":false,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478025459,"modifiedTime":1679614413217,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"1l59lWbtvYp74OTb","name":"Briser un objet de verre","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.1l59lWbtvYp74OTb"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025460,"modifiedTime":1673118700210,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"22EQLBJfHVYs96iC","name":"Cracher dans toute nourriture ou boisson aperçue","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.22EQLBJfHVYs96iC"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025460,"modifiedTime":1673118700211,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"2Rtm78bMKPy8eG4q","name":"Éteindre tout feu rencontré (feu de camp, torche, lanterne, etc.)","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.2Rtm78bMKPy8eG4q"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025460,"modifiedTime":1673118700211,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
@ -9,12 +9,12 @@
|
||||
{"_id":"32LbwxxokC9Tn370","name":"Coup de foudre fatal","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.32LbwxxokC9Tn370"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>On devient immédiatement amoureux fou de la première personne inconnue de sexe opposé et de même espèce rencontrée. Tant que satisfaction n’est pas obtenue, traiter comme un désir lancinant. </p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":20,"hautrevant":false,"categorie":"lancinant","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025460,"modifiedTime":1673118700211,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"3BcC8lSsP5WIyva7","name":"Gagner de l’argent (minimum 10 deniers)","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.3BcC8lSsP5WIyva7"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025460,"modifiedTime":1673118700211,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"3ZjwYyQRatCMnBCi","name":"Mégalomanie. Être acclamé par un minimum de 10 personnes","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.3ZjwYyQRatCMnBCi"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025460,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"5knw1NcnBsLIjHpr","name":"Montée laborieuse","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.5knw1NcnBsLIjHpr"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant un jour, monter en TMR coûte 2 points de rêve au lieu d’un, et 3 points en déplacement accéléré.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025460,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"5knw1NcnBsLIjHpr","name":"Montée laborieuse","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.5knw1NcnBsLIjHpr"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant un jour, monter en TMR coûte 2 points de rêve au lieu d’un, et 3 points en déplacement accéléré.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":0,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478025460,"modifiedTime":1679614361208,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"6G0lF06jSryTduAt","name":"Avoir le visage noirci à la cendre","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.6G0lF06jSryTduAt"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025460,"modifiedTime":1673118700210,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"7TKsit2Mv9mWGq3C","name":"Ne marcher qu’à quatre pattes","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.7TKsit2Mv9mWGq3C"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025461,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"8sLXQBqo8XwjAFG0","name":"Acquérir une chèvre","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.8sLXQBqo8XwjAFG0"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025461,"modifiedTime":1673118700209,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"E902EEYZHg3zFKq6","name":"Garder les yeux bandés","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.E902EEYZHg3zFKq6"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025461,"modifiedTime":1673118700211,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"EUrxQGd7FuW628NS","name":"Inertie draconique","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.EUrxQGd7FuW628NS"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant un jour, la fatigue en TMR est doublée. Chaque case ou round coûte 2 points au lieu d’un.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025461,"modifiedTime":1673118700213,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"EUrxQGd7FuW628NS","name":"Inertie draconique","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.EUrxQGd7FuW628NS"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant un jour, la fatigue en TMR est doublée. Chaque case ou round coûte 2 points au lieu d’un.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":0,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478025461,"modifiedTime":1679614313037,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"F6qL4d4g3qjh045R","name":"Danser nu sous la pluie","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.F6qL4d4g3qjh045R"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025461,"modifiedTime":1673118700211,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"F8G3rdU1nfJzYwYR","name":"Garder sur soi 3d6 kilos de cailloux","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.F8G3rdU1nfJzYwYR"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025461,"modifiedTime":1673118700211,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"HSNOvBR890dsEDw2","name":"Se faire raser la tête","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.HSNOvBR890dsEDw2"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025461,"modifiedTime":1673118700215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
@ -28,11 +28,11 @@
|
||||
{"_id":"OSV2b7bVWv2SCfUY","name":"Urgence draconique","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.OSV2b7bVWv2SCfUY"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Le haut-rêvant est pris du besoin irrésistible de déclencher immédiatement son plus proche sort en réserve. À équidistance, prendre dans le sens des aiguilles d’une montre en commençant par le haut. En cas de rencontre dans les TMR, se dérober équivaut à refouler la queue de Dragon. Si aucun sort n’est en réserve, ou si il y a impossibilité de pratiquer la magie à cause d’une autre queue ou d’un souffle, tirer à la place une idée fixe.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025463,"modifiedTime":1673118700215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"OjG8XRbeYtq2jcgB","name":"Casser 3d6 oeufs en les jetant à terre","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.OjG8XRbeYtq2jcgB"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025463,"modifiedTime":1673118700210,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"QHUOwjMR6AvepGPm","name":"Traire une vache","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.QHUOwjMR6AvepGPm"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025463,"modifiedTime":1673118700215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"Qgj5eSMpQ0IDHwZX","name":"Coup de barre","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.Qgj5eSMpQ0IDHwZX"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Prise immédiate de 3d6 points de fatigue.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":20,"hautrevant":false,"categorie":"","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025463,"modifiedTime":1673118700210,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"RVslW735GbPbXCpP","name":"Pèlerinage","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.RVslW735GbPbXCpP"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Avant de pouvoir à nouveau faire usage du haut-rêve, y compris déclencher volontairement un sort mis en réserve, le haut-rêvant doit se rendre dans une certaine case des TMR déterminée aléatoirement. Un Passeur peut l’y téléporter, mais un Messager ne peut s’y rendre à sa place. Dès que la case est atteinte, le pèlerinage est accompli.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025463,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"Qgj5eSMpQ0IDHwZX","name":"Coup de barre","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.Qgj5eSMpQ0IDHwZX"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Prise immédiate de 3d6 points de fatigue.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":20,"hautrevant":false,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478025463,"modifiedTime":1679614376913,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"RVslW735GbPbXCpP","name":"Pèlerinage","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.RVslW735GbPbXCpP"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Avant de pouvoir à nouveau faire usage du haut-rêve, y compris déclencher volontairement un sort mis en réserve, le haut-rêvant doit se rendre dans une certaine case des TMR déterminée aléatoirement. Un Passeur peut l’y téléporter, mais un Messager ne peut s’y rendre à sa place. Dès que la case est atteinte, le pèlerinage est accompli.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478025463,"modifiedTime":1679614238011,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"S8PVNgxb7TcFXq9g","name":"Pisser dans un violon (luth, mandoline, etc.)","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.S8PVNgxb7TcFXq9g"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025463,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"SY0SsWtZdxSodMcl","name":"Manger du poisson","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.SY0SsWtZdxSodMcl"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025464,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"TmEeikWOQt6NZGVY","name":"Masque de Narcos","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.TmEeikWOQt6NZGVY"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant 1d7 jours à compter du lendemain, la caractéristique APPARENCE baisse de 1d6 points, de même que la Beauté.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":20,"hautrevant":false,"categorie":"","refoulement":1,"duree":"1d7jours","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025464,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"TmEeikWOQt6NZGVY","name":"Masque de Narcos","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.TmEeikWOQt6NZGVY"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant 1d7 jours à compter du lendemain, la caractéristique APPARENCE baisse de 1d6 points, de même que la Beauté.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":20,"hautrevant":false,"categorie":"","refoulement":0,"duree":"1d7jours","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478025464,"modifiedTime":1679614425790,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"UUTbsktTcxsIe5L5","name":"Ne pas franchir de porte. (On peut franchir une fenêtre)","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.UUTbsktTcxsIe5L5"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025464,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"VChJbtGFtWoiFNky","name":"Refuser de se délester du moindre objet, ni donner ni prêter","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.VChJbtGFtWoiFNky"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025464,"modifiedTime":1673118700215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"YCHBbRLiMzTH7IBj","name":"Ne s’exprimer que par des cris d’animaux (meuh ! coin-coin ! etc.)","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.YCHBbRLiMzTH7IBj"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025464,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
@ -43,13 +43,13 @@
|
||||
{"_id":"gMmqdJ9I7Mt8Tg3f","name":"Ne dire que «non» ou négation analogue","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.gMmqdJ9I7Mt8Tg3f"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025465,"modifiedTime":1673118700214,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"gadh6aI5iCM82qpP","name":"Manger des champignons","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.gadh6aI5iCM82qpP"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025465,"modifiedTime":1673118700213,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"hghw6Cldrad1CIiJ","name":"Refuser de se déplacer autrement que porté","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.hghw6Cldrad1CIiJ"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025465,"modifiedTime":1673118700215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"iHuLw0I1Gc5mIucG","name":"Réinsertion aléatoire","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.iHuLw0I1Gc5mIucG"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Comme après une sortie de la carte, le gardien des rêves réintroduit secrètement le demi-rêve du haut-rêvant dans les TMR.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025465,"modifiedTime":1673118700215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"iJw6j7kuP1eAHIck","name":"Amnésie sélective","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.iJw6j7kuP1eAHIck"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant un jour, perte totale d’une compétence, à l’exclusion du Draconic. Déterminer aléatoirement la compétence visée qui, pratiquement, retourne au niveau de base. Si elle est déjà au niveau de base, en choisir une autre.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":20,"hautrevant":false,"categorie":"","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025465,"modifiedTime":1673118700209,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"iHuLw0I1Gc5mIucG","name":"Réinsertion aléatoire","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.iHuLw0I1Gc5mIucG"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Comme après une sortie de la carte, le gardien des rêves réintroduit secrètement le demi-rêve du haut-rêvant dans les TMR.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478025465,"modifiedTime":1679614348966,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"iJw6j7kuP1eAHIck","name":"Amnésie sélective","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.iJw6j7kuP1eAHIck"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Pendant un jour, perte totale d’une compétence, à l’exclusion du Draconic. Déterminer aléatoirement la compétence visée qui, pratiquement, retourne au niveau de base. Si elle est déjà au niveau de base, en choisir une autre.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":20,"hautrevant":false,"categorie":"","refoulement":0,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478025465,"modifiedTime":1679614403347,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"iPYPgxL2uUnphStc","name":"Garder une main sur la tête","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.iPYPgxL2uUnphStc"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025465,"modifiedTime":1673118700212,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"j2xIrFWYqhDM4TcN","name":"Appeler les hommes «madame» et les femmes «messire»","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/idee_fixe.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.j2xIrFWYqhDM4TcN"}},"system":{"description":"<p>Prend effet immédiatement et dure jusqu'à la <strong>fin de l'heure du Château Dormant </strong>du <strong>lendemain.<br /></strong>Si passé ce délai, l'occasion de la manifester ne s'est pas présentée, la queue prend fin.</p>\n<p>Si elle entre en contradiction avec une autre queue, retirer.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"ideefixe","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025465,"modifiedTime":1673118700210,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"jShpKV8mVcqWmYvp","name":"Se soûler (minimum pas frais)","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.jShpKV8mVcqWmYvp"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025465,"modifiedTime":1673118700215,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"kHWwwxA0alcpDYpf","name":"Insomnie","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.kHWwwxA0alcpDYpf"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Impossibilité totale de dormir, et donc de rêver, pendant un jour.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":20,"hautrevant":false,"categorie":"","refoulement":1,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025466,"modifiedTime":1673118700213,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"lBkO8FvFqXoKNhvk","name":"Conquête","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.lBkO8FvFqXoKNhvk"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Avant de pouvoir à nouveau faire usage du haut-rêve, y compris déclencher volontairement un sort mis en réserve, le haut-rêvant doit se rendre dans une certaine case des TMR déterminée aléatoirement et la <em>maîtriser</em>, difficulté -7. Ce peut être n’importe quelle case, sauf une case humide. En cas d’échec, la concentration est rompue ; il n’y a pas de souffle de Dragon en cas d’échec total.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025466,"modifiedTime":1673118700210,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"kHWwwxA0alcpDYpf","name":"Insomnie","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.kHWwwxA0alcpDYpf"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Impossibilité totale de dormir, et donc de rêver, pendant un jour.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":20,"hautrevant":false,"categorie":"","refoulement":0,"duree":"jour","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478025466,"modifiedTime":1679614392997,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"lBkO8FvFqXoKNhvk","name":"Conquête","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.lBkO8FvFqXoKNhvk"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Avant de pouvoir à nouveau faire usage du haut-rêve, y compris déclencher volontairement un sort mis en réserve, le haut-rêvant doit se rendre dans une certaine case des TMR déterminée aléatoirement et la <em>maîtriser</em>, difficulté -7. Ce peut être n’importe quelle case, sauf une case humide. En cas d’échec, la concentration est rompue ; il n’y a pas de souffle de Dragon en cas d’échec total.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":16,"hautrevant":true,"categorie":"","refoulement":0,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.3","coreVersion":"10.291","createdTime":1669478025466,"modifiedTime":1679614282249,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"mN0yghXkFfj2YctJ","name":"Construire une cabane","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.mN0yghXkFfj2YctJ"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025466,"modifiedTime":1673118700210,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"sjXBBr85OBk4Yg4t","name":"Embrasser un cochon sur le groin","type":"queue","img":"systems/foundryvtt-reve-de-dragon/icons/queues/desir_lancinant.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.sjXBBr85OBk4Yg4t"}},"system":{"description":"<p>Tant que satisfaction n'est pas obtenue, aucun point d'expérience ne peut plus être gagné par l'exercice en cas de particulière et d'ajustement final négatif.<br />Les points d'expérience dus au stress ne sont pas affectés.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":3,"hautrevant":false,"categorie":"lancinant","refoulement":1,"duree":"","restant":0},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025466,"modifiedTime":1673118700211,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"vft88ioHpGxMzdML","name":"Dépouillement","type":"queue","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.queues-de-dragon.vft88ioHpGxMzdML"}},"img":"systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp","effects":[],"system":{"description":"<p>Faire don de toute la monnaie actuellement possédée à la première personne inconnue rencontrée. En attendant, se garder d’aucune dépense.</p>","descriptionmj":"","temporel":{"debut":{"indexDate":0,"indexMinute":0},"fin":{"indexDate":0,"indexMinute":0}},"frequence":20,"hautrevant":false,"categorie":"","refoulement":2,"duree":"","restant":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.4.9","coreVersion":"10.291","createdTime":1669478025466,"modifiedTime":1673118700211,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
|
@ -23,7 +23,7 @@
|
||||
{"_id":"UQYy9WjsKqqrjLc7","name":"Guerrier Sorde","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.UQYy9WjsKqqrjLc7"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>@JournalEntry[vid6uJc66QFgHSUr]{Note sur les invocations de créatures}</p>\n<p>Le Guerrier Sorde a l’apparence d’un humanoïde entièrement revêtu d’une armure de plaques, visière du heaume toujours baissée, dissimulant son visage. Il est armé d’une épée sorde, d’un bouclier moyen et d’une dague. La seule tâche que l’on 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 qu’il l’extermine ou reçoive un contre-ordre. On peut alors lui ordonner de commencer un autre combat, à condition que le délai entre deux combats n’excède pas 10 rounds, faute de quoi il considère sa tâche accomplie et se dématérialise. S’il est invoqué alors qu’il n’y a pas de créature à combattre immédiatement, il ne patiente que jusqu’à la fin de l’heure en cours, après quoi il s’estime dérangé pour rien et se dématérialise. Durant le délai, il peut accompagner le haut-rêvant où qu’il 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, n’escalade ni ne nage jamais. Il n’obéit qu’au haut-rêvant qui l’a 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 d’Hypnos, 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>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Tâche","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"special","caseTMRspeciale":"Cité Sordide D13","ptreve":"7","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426561,"modifiedTime":1667260032848,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"VG89vfk7KsO01eJv","name":"Secouriste blanc","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.VG89vfk7KsO01eJv"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"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 qu’il fait spontanément. En plein combat, il peut même s’approcher 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 l’invocateur peut lui désigner un blessé à soigner en priorité.</p>\n<p>Le Secouriste possède son propre matériel de chirurgie, mais il n’a aucun consommable (eau, chiffons) qu’il faut lui fournir.</p>\n<p>Pour la résolution des soins, le Secouriste ne joue pas de jet de Chirurgie. À la place, c’est 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>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Tâche ou fin HN","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire Blanc G4","ptreve":"7","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426561,"modifiedTime":1667260032851,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"WvTkEYb216X0XiJc","name":"Voix d'Hypnos","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.WvTkEYb216X0XiJc"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>Les rituels de lecture d’Hypnos sont d’étonnantes démonstrations d’auto-suggestion. Aidé par un support, le haut-rêvant se persuade qu’il peut voir ou entendre à distance, et il le fait. Couplé à l’ultime forme d’illusion que sont les invocations, il peut pareillement projeter son image ou sa voix à distance. Tous obéissent aux règles usuelles d’application 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 d’Hypnos permet de détecter le mensonge. Il n’y 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 d’Hypnos ne fonctionne que sur un seul d’entre 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 d’un round, quelle qu’ait é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 qu’il 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>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"1 round","JR":"Aucun","cible":"Soi-même","difficulte":"-4","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"4","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426562,"modifiedTime":1667260032852,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.Y4r9kTN2brWC2N0n"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"description":"<p>Les rituels de Lecture d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.</p>\n<p>Ce rituel permet d’approfondir les informations fournies par Détection d’Aura. Pratiquer Lecture d’Aura quand il n’y a pas d’aura revient à demander une magie impossible et crée immédiatement une déchirure du rêve.</p>\n<p>Lecture d’Aura est effectuée en plusieurs étapes, toutes étant de difficulté R-3 et coûtant 3 points de rêve. La première a toujours lieu dans un sanctuaire et ne fait que révéler dans quel(s) autre(s) genre(s) de case(s) le haut-rêvant doit se rendre pour continuer sa lecture. Là, il apprend quel genre de magie a été produit ou à quel type de rêve il a affaire, de même que les cases spécifiques concernées. Enfin dans les cases spécifiques, le haut-rêvant peut apprendre la force du rêve ou de la magie en cours, c’est-à-dire pratiquement la difficulté et le nombre de points de rêve impliqués, information indispensable dans l’optique d’une annulation de magie.</p>\n<p>Lecture d’Aura révèle également la couleur de l’aura (fixe ou pulsative) comme Détection d’Aura. Pour les créatures vivantes, on peut donc sauter l’étape de Détection d’Aura et commencer directement par la lecture, puisqu’on est sûr de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la détection si, en l’absence finale d’une aura, on ne veut pas créer de magie impossible. Effectuée sur une créature non soumise à un effet magique ni sous l’emprise d’une entité, Lecture d’Aura indique toujours le Fleuve. Là, dans n’importe quelle case du Fleuve, le haut-rêvant se contente d’apprendre qu’il a affaire à une créature vivante et douée de rêve.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426562,"modifiedTime":1667260032849,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.Y4r9kTN2brWC2N0n"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"description":"<p>Les rituels de Lecture d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.</p>\n<p>Ce rituel permet d’approfondir les informations fournies par Détection d’Aura. Pratiquer Lecture d’Aura quand il n’y a pas d’aura revient à demander une magie impossible et crée immédiatement une déchirure du rêve.</p>\n<p>Lecture d’Aura est effectuée en plusieurs étapes, toutes étant de difficulté R-3 et coûtant 3 points de rêve. La première a toujours lieu dans un sanctuaire et ne fait que révéler dans quel(s) autre(s) genre(s) de case(s) le haut-rêvant doit se rendre pour continuer sa lecture. Là, il apprend quel genre de magie a été produit ou à quel type de rêve il a affaire, de même que les cases spécifiques concernées. Enfin dans les cases spécifiques, le haut-rêvant peut apprendre la force du rêve ou de la magie en cours, c’est-à-dire pratiquement la difficulté et le nombre de points de rêve impliqués, information indispensable dans l’optique d’une annulation de magie.</p>\n<p>Lecture d’Aura révèle également la couleur de l’aura (fixe ou pulsative) comme Détection d’Aura. Pour les créatures vivantes, on peut donc sauter l’étape de Détection d’Aura et commencer directement par la lecture, puisqu’on est sûr de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la détection si, en l’absence finale d’une aura, on ne veut pas créer de magie impossible. Effectuée sur une créature non soumise à un effet magique ni sous l’emprise d’une entité, Lecture d’Aura indique toujours le Fleuve. Là, dans n’importe quelle case du Fleuve, le haut-rêvant se contente d’apprendre qu’il a affaire à une créature vivante et douée de rêve.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","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":""},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.6","coreVersion":"10.291","createdTime":1667259426562,"modifiedTime":1681495249423,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"YOJsOLpHTQYreZ6i","name":"Soufflet","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.YOJsOLpHTQYreZ6i"}},"system":{"description":"<p>Le Soufflet peut être dirigé contre toute créature, humanoïde ou animale. Son effet, instantané, est celui d’une gifle magistrale, causant ses dommages 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, la protection applicable peut être au maximum de 2 points.</p>","descriptionmj":"","draconic":"Voie d'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":""},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426562,"modifiedTime":1667260032851,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"aYOfXEuDp6xGDO4N","name":"Égarement","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.aYOfXEuDp6xGDO4N"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>L’effet d’Égarement ne s’applique qu’aux humanoïdes. L’apport massif de pseudo-souvenirs, informulés et insaisissables, empêche l’humanoï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 l’heure en cours + une heure complète, ou se dissipe de lui-même dès qu’il y a stress, par exemple une agression. Ce sort est donc totalement inutile et inefficace en combat.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Une heure","JR":"Selon HN","cible":"Humanoïde","difficulte":"-4","portée":"","caseTMR":"desolation","caseTMRspeciale":"","ptreve":"4","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426562,"modifiedTime":1667260032847,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"cghxHRstw7cXLEm4","name":"Invoquer son image","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.cghxHRstw7cXLEm4"}},"system":{"description":"<p>Les rituels de lecture d’Hypnos sont d’étonnantes démonstrations d’auto-suggestion. Aidé par un support, le haut-rêvant se persuade qu’il peut voir ou entendre à distance, et il le fait. Couplé à l’ultime forme d’illusion que sont les invocations, il peut pareillement projeter son image ou sa voix à distance. Tous obéissent aux règles usuelles d’application 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. Lorsqu’un 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 qu’il tient sur lui, mais sans pouvoir se déplacer. Dans l’instant même, un hologramme de lui-même, grandeur nature et fidèle jusqu’au 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 l’hologramme, ce n’est qu’une illusion sans substance. Par ce rituel, le haut-rêvant ne peut communiquer aucun son, et lui-même n’entend 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":"Voie d'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":""},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426562,"modifiedTime":1667260032849,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
@ -39,7 +39,7 @@
|
||||
{"_id":"qqcLydulFkL25Ipc","name":"Conjurer l'oubli","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.qqcLydulFkL25Ipc"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>Ce rituel permet de faire renaître chez la cible un souvenir oublié, la cause de l’oubli pouvant être magique ou naturelle. Le souvenir oublié peut appartenir à une précédente incarnation si le gardien des rêves l’estime possible ou pertinent. Dans tous les cas, le souvenir ne peut revenir que sous la forme d’une <em>réponse </em>à une <em>question </em>précise. Et l’accomplissement du rituel ne permet qu’une seule question-réponse.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Une question","JR":"Aucun","cible":"Humanoïde","difficulte":"-4","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"4","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032846,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"rrSE9c7KKsqcKueo","name":"Nonechalepasse","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.rrSE9c7KKsqcKueo"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"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. C’est en fait une variante de ce dernier. Il est invoqué pour garder ou veiller sur quelque chose : une porte, un coffre, un pont, etc. L’ayant invoqué, le haut-rêvant doit lui indiquer expressément sur quoi il doit veiller, et le Nonechalepasse ne laissera personne d’autre que l’invocateur franchir la limite indiquée, c’est-à-dire pas même ses compagnons. La garde peut avoir lieu en la présence du haut-rêvant, ou en son absence s’il désire vaquer à d’autres affaires, et dure jusqu’à la fin de son heure de naissance. Dès qu’une créature est en voie d’enfreindre la consigne donnée, le Nonechalepasse l’en prévient en clamant son propre nom à plusieurs reprises ; et si la créature insiste, il la combat jusqu’à ce qu’il l’extermine ou qu’elle recule et s’enfuie. 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>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Tâche","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"special","caseTMRspeciale":"Cité Jalouse M1","ptreve":"7","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032850,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"sVA94h9Reimmfw5B","name":"Suggestion","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.sVA94h9Reimmfw5B"}},"system":{"description":"<p>L’effet de Suggestion ne s’applique qu’aux humanoïdes. Comme l’indique le titre, c’est la suggestion à l’état pur. Il permet de donner un ordre bref à la victime, et cette dernière ne pourra pas s’empêcher d’y obéir machinalement. Il est impératif que la victime puisse obéir à l’ordre de façon <em>immédiate</em>, dans la seconde qui suit l’ordre, et que l’action soit uniquement <em>physique</em>, ni mentale ni réfléchie. Si la Suggestion est telle qu’elle oblige la victime à une autre action préalable ou si l’action demandée ne peut être qu’une 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 l’ordre de suggestion : \"donne ta bourse !\" L’effet avorte automatiquement. En effet, le passant doit d’abord 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, l’ordre : \"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 d’un gouffre, et qu’on lui suggère : \" saute dans le gouffre !\", elle saute. Si elle est à trois mètres du gouffre, la suggestion avorte. Il faut d’abord qu’elle 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 qu’elle 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>L’ordre donné dans la suggestion doit être unique, c’est-à-dire pratiquement ne comporter qu’un seul verbe. \"Cours et saute !\" est impossible. Quand l’action implique une durée, elle est obéie pendant un round. Si par exemple l’ordre donné est \"cours !\" ou \"fuis !\", la victime courra, fuira, pendant un round. À ce moment, toutefois, l’ordre pourra être donné une seconde fois, et la victime obéira pour la durée d’un nouveau round.</p>\n<p>L’ordre 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 l’effet du sort, il faut que l’ordre soit donné réellement, <em>verbalement</em>. La victime doit pouvoir l’entendre et le comprendre (parler la même langue). Peu importe qui donne l’ordre verbal, le haut-rêvant ou quelqu’un d’autre. Chaque 3r dépensés permet verbalement de réitérer l’ordre une fois. Si par exemple 9 points de rêve ont été dépensés, l’ordre \"cours !\" pourra être donné trois fois. Il n’y 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 n’a pas été donné, la victime est sous l’influence du sort, influence qui peut être détectée et lue par Lecture d’Aura. Le libellé de l’ordre est également révélé dans la case spécifique par Lecture d’Aura, et le sort peut être annulé dans cette même case. Dès que le dernier ordre est donné, l’effet se dissipe totalement.</p>","descriptionmj":"","draconic":"Voie d'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":""},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032851,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.xOicgRMCUxJNmVzF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"description":"<p>Les rituels de Détection d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.</p>\n<p>Toutes les créatures vivantes animées (humains, humanoïdes, animaux) ont une caractéristique RÊVE. Les objets enchantés possèdent des points de rêve, de même que les produits de magie naturelle, comme certaines pierres de chance. Les entités de cauchemar, incarnées ou non, en ont également. Quelle qu’elle soit, la présence de rêve émet une aura, laquelle est détectable par Détection d’Aura. Parallèlement, toute cible d’un sort ou d’un rituel, émet une aura propre, quand bien même ladite cible ne possède pas de points de rêve (centre de zone, objet ou plante soumis à une illusion d’Hypnos). Cette aura est également détectable par Détection d’Aura.</p>\n<p>L’aura de présence de rêve se traduit par un halo bleuté constant ; l’aura résultant d’un effet magique par un halo parcouru de pulsations. Quand les deux auras sont présentes conjointement, le halo est pulsatif et d’un bleu plus foncé. On peut toujours effectuer Détection d’Aura sans aucun risque, il y a toujours une réponse. Soit une aura est perçue, constante ou pulsative, et l’on peut tenter une Lecture d’Aura pour en savoir plus ; soit aucune aura n’est perçue et il s’agit de matière inerte, sans rêve, non soumise à un sort.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0,"portee":""},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032847,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.xOicgRMCUxJNmVzF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"description":"<p>Les rituels de Détection d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.</p>\n<p>Toutes les créatures vivantes animées (humains, humanoïdes, animaux) ont une caractéristique RÊVE. Les objets enchantés possèdent des points de rêve, de même que les produits de magie naturelle, comme certaines pierres de chance. Les entités de cauchemar, incarnées ou non, en ont également. Quelle qu’elle soit, la présence de rêve émet une aura, laquelle est détectable par Détection d’Aura. Parallèlement, toute cible d’un sort ou d’un rituel, émet une aura propre, quand bien même ladite cible ne possède pas de points de rêve (centre de zone, objet ou plante soumis à une illusion d’Hypnos). Cette aura est également détectable par Détection d’Aura.</p>\n<p>L’aura de présence de rêve se traduit par un halo bleuté constant ; l’aura résultant d’un effet magique par un halo parcouru de pulsations. Quand les deux auras sont présentes conjointement, le halo est pulsatif et d’un bleu plus foncé. On peut toujours effectuer Détection d’Aura sans aucun risque, il y a toujours une réponse. Soit une aura est perçue, constante ou pulsative, et l’on peut tenter une Lecture d’Aura pour en savoir plus ; soit aucune aura n’est perçue et il s’agit de matière inerte, sans rêve, non soumise à un sort.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0,"bonuscase":"","isrituel":true,"coutseuil":0,"portee":""},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.7.6","coreVersion":"10.291","createdTime":1667259426564,"modifiedTime":1681495242408,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"yNMa8DlBaZyTGFSr","name":"Oubli","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.yNMa8DlBaZyTGFSr"}},"system":{"description":"<p>L’effet d’Oubli ne s’applique qu’aux humanoïdes. C’est une des plus puissantes suggestions hypnotiques. L’effet d’amnésie ne survient pas aussitôt le sort ciblé, mais intervient à la fin de l’heure en cours. À ce moment la victime perd tout souvenir de ce qu’elle a vécu, de ce qu’elle 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 d’une heure. Soit un haut-rêvant lançant ce sort au cours de l’heure du Dragon et dépensant 8 points : à la fin de l’heure de la Lyre, la victime se retrouve brusquement amnésique de ce qu’elle 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 d’une période de sommeil noir, encore plus opaque que le gris rêve. Une Lecture d’Aura révèle la présence d’un sort d’Oubli en train d’œuvrer, et Annulation de Magie peut l’annuler selon les règles normales. À défaut, le rituel de Conjurer l’Oubli peut être utilisé, mais ne restitue les souvenirs que sélectivement, en réponse à une question précise. Quand c’est un personnage de joueur qui lance ce sort sur un PNJ, sa mise en œuvre est sans problème. L’inverse 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ù l’amné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":"Voie d'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":""},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032850,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"yhw8f7HKrmfzAxmj","name":"Sérénité","type":"sort","img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.yhw8f7HKrmfzAxmj"}},"system":{"description":"<p>L’effet de sérénité ne s’applique qu’aux humanoïdes. La suggestion d’une intense satisfaction est source d’une sérénité réelle. Pour chaque 3r dépensés, le personnage visé regagne 1 point de moral jusqu’à concurrence de zéro. Neuf points de rêve permettent ainsi de remonter un moral de -3 à zéro. Si trop de points sont dépensés, l’excédent est perdu, le moral ne pouvant dépasser zéro par l’influence de ce sort.</p>","descriptionmj":"","draconic":"Voie d'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":""},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032851,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
{"_id":"ze53LdwhuqUFMvqw","name":"Fou-rire","type":"sort","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.sorts-hypnos.ze53LdwhuqUFMvqw"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","effects":[],"system":{"description":"<p>L’effet de Fou-Rire ne s’applique qu’aux humanoïdes. La suggestion d’une idée drolatique plonge la cible dans un irrépressible fou-rire, automatique le premier round. Puis pour les rounds suivants, la cible doit réussir un jet de VOLONTÉ/ <em>moins </em>moral à -5, ou continuer à rire. Tant que la cible rit, elle est considérée en <em>demi-surprise</em>.</p>","descriptionmj":"","draconic":"Voie d'Hypnos","duree":"Instantanée","JR":"Selon HN","cible":"Humanoïde","difficulte":"-5","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"5","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0},"ownership":{"default":0,"jOzRscDxoXZWpGS6":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.32","coreVersion":"10.288","createdTime":1667259426564,"modifiedTime":1667260032847,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 313 KiB |
BIN
styles/img/ui/tmr.webp
Normal file
BIN
styles/img/ui/tmr.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 637 KiB |
@ -79,13 +79,13 @@
|
||||
--gradient-silver-light: linear-gradient(30deg, rgba(61, 55, 93, 0.2), rgba(178, 179, 196, 0.1), rgba(59, 62, 63, 0.2), rgba(206, 204, 199, 0.1), rgba(61, 46, 49, 0.2));
|
||||
--gradient-daylight: conic-gradient(
|
||||
from 0deg,
|
||||
hsla(50, 50%, 80%, 0.7),
|
||||
hsla(50, 50%, 80%, 0.1) 25%,
|
||||
hsla(250, 50%, 20%, 0.1) 25%,
|
||||
hsla(250, 50%, 20%, 0.5) 50%,
|
||||
hsla(250, 50%, 20%, 0.1) 75%,
|
||||
hsla(50, 50%, 80%, 0.1) 75%,
|
||||
hsla(50, 50%, 80%, 0.7)
|
||||
hsla(50, 100%, 80%, 0.7),
|
||||
hsla(30, 30%, 40%, 0.1) 25%,
|
||||
hsla(250, 50%, 40%, 0.1) 25%,
|
||||
hsla(250, 30%, 30%, 0.7) 50%,
|
||||
hsla(250, 50%, 40%, 0.1) 75%,
|
||||
hsla(30, 30%, 40%, 0.1) 75%,
|
||||
hsla(50, 100%, 80%, 0.7)
|
||||
);
|
||||
|
||||
--background-custom-button: linear-gradient(to bottom, rgba(33, 55, 74, 0.988) 5%, rgba(21, 40, 51, 0.671) 100%);
|
||||
@ -171,6 +171,9 @@ i:is(.fas, .far) {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.tmr-dialog table {
|
||||
border: none;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .sheet-header div.tmr-buttons {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
@ -287,6 +290,16 @@ table {border: 1px solid #7a7971;}
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
.grid-competence-archetype {
|
||||
display: grid;
|
||||
grid-column: span 3 / span 3;
|
||||
grid-template-columns: 2fr 2fr 1fr;
|
||||
gap: 0.5rem;
|
||||
margin: 0.5rem 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.grid-3col {
|
||||
grid-column: span 3 / span 3;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
@ -876,120 +889,29 @@ form.rdddialogchrono input[type=datetime-local] {
|
||||
color: var(--color-text-dark-primary);
|
||||
border-radius: 3px;
|
||||
}
|
||||
div.theme-astral{
|
||||
.app-calendar-astrologie div.theme-astral{
|
||||
width: 14rem;
|
||||
margin: 0.4rem;
|
||||
}
|
||||
form.dialog-astro {
|
||||
width: 17rem;
|
||||
}
|
||||
div.astro-roue {
|
||||
|
||||
.app-calendar-astrologie div.horloge-roue {
|
||||
position: relative;
|
||||
left: calc(50% - 6.5rem);
|
||||
width: 13rem;
|
||||
height: 13rem;
|
||||
}
|
||||
div.astro-roue div.astro-heure {
|
||||
|
||||
.app-calendar-astrologie div.horloge-roue div.horloge-heure {
|
||||
position: absolute;
|
||||
width: 1.8rem;
|
||||
height: 1.8rem;
|
||||
}
|
||||
|
||||
div.astro-roue div.astro-cercle1 {
|
||||
position: absolute;
|
||||
background: var(--gradient-daylight);
|
||||
border: 0.2rem solid rgba(100, 45, 124, 0.6);
|
||||
border-radius: calc(6rem);
|
||||
top: calc(50% - 6rem);
|
||||
left: calc(50% - 6rem);
|
||||
width: calc(100% - 1rem);
|
||||
height: calc(100% - 1rem);
|
||||
}
|
||||
div.astro-roue div.astro-cercle2 {
|
||||
position: absolute;
|
||||
border: 0.1rem solid rgba(100, 45, 124, 0.4);
|
||||
border-radius: calc(6.1rem);
|
||||
top: calc(50% - 4.5rem);
|
||||
left: calc(50% - 4.5rem);
|
||||
width: calc(100% - 4rem);
|
||||
height: calc(100% - 4rem);
|
||||
}
|
||||
div.astro-roue div.astro-disque {
|
||||
position: absolute;
|
||||
border: none;
|
||||
top: calc(50% - 3.4rem);
|
||||
left: calc(50% - 3.4rem);
|
||||
width: calc(100% - 6.2rem);
|
||||
height: calc(100% - 6.2rem);
|
||||
}
|
||||
div.astro-roue div.astro-horloge-heure {
|
||||
position: absolute;
|
||||
border: none;
|
||||
top: calc(50% - 2.5rem);
|
||||
left: calc(50% - 2.5rem);
|
||||
width: calc(100% - 8rem);
|
||||
height: calc(100% - 8rem);
|
||||
}
|
||||
div.astro-roue div.astro-horloge-minute {
|
||||
position: absolute;
|
||||
border: none;
|
||||
top: calc(50% - 3.5rem);
|
||||
left: calc(50% - 3.5rem);
|
||||
width: calc(100% - 6rem);
|
||||
height: calc(100% - 6rem);
|
||||
}
|
||||
div.astro-roue div.astro-ajustement {
|
||||
position: absolute;
|
||||
width: 0.8rem;
|
||||
height: 0.8rem;
|
||||
color: hsl(120, 50%, 15%);
|
||||
font-size: 0.8rem;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-radius: 0.4rem;
|
||||
background-color: hsla(300, 100%, 95%, 0.3);
|
||||
}
|
||||
div.astro-roue div.astro-disque img { border: none; }
|
||||
div.astro-roue div:is(.astro-horloge-heure, .astro-horloge-minute) img {
|
||||
border: none;
|
||||
text-shadow: #403f3e;
|
||||
}
|
||||
div.astro-roue div.astro-heure img.astro-heure-img {
|
||||
.app-calendar-astrologie div.horloge-roue div.horloge-heure img.horloge-heure-img {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
flex-grow: 0;
|
||||
padding: 0.1rem;
|
||||
border: 0;
|
||||
opacity: 0.9;
|
||||
border: none;
|
||||
}
|
||||
|
||||
div.astro-roue div.astro-heure.heure-01 { top: calc(50% - 1rem + sin(-180deg) * 5rem); left: calc(50% - 1rem + cos(-180deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-02 { top: calc(50% - 1rem + sin(-150deg) * 5rem); left: calc(50% - 1rem + cos(-150deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-03 { top: calc(50% - 1rem + sin(-120deg) * 5rem); left: calc(50% - 1rem + cos(-120deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-04 { top: calc(50% - 1rem + sin(-90deg) * 5rem); left: calc(50% - 1rem + cos(-90deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-05 { top: calc(50% - 1rem + sin(-60deg) * 5rem); left: calc(50% - 1rem + cos(-60deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-06 { top: calc(50% - 1rem + sin(-30deg) * 5rem); left: calc(50% - 1rem + cos(-30deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-07 { top: calc(50% - 1rem + sin(-0deg) * 5rem); left: calc(50% - 1rem + cos(-0deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-08 { top: calc(50% - 1rem + sin(30deg) * 5rem); left: calc(50% - 1rem + cos(30deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-09 { top: calc(50% - 1rem + sin(60deg) * 5rem); left: calc(50% - 1rem + cos(60deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-10 { top: calc(50% - 1rem + sin(90deg) * 5rem); left: calc(50% - 1rem + cos(90deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-11 { top: calc(50% - 1rem + sin(120deg) * 5rem); left: calc(50% - 1rem + cos(120deg) * 5rem); }
|
||||
div.astro-roue div.astro-heure.heure-12 { top: calc(50% - 1rem + sin(150deg) * 5rem); left: calc(50% - 1rem + cos(150deg) * 5rem); }
|
||||
|
||||
div.astro-roue div.astro-ajustement.heure-01 { top: calc(50% - 0.4rem + sin(180deg) * 3.9rem); left: calc(50% - 0.4rem + cos(180deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-02 { top: calc(50% - 0.4rem + sin(-150deg) * 3.9rem); left: calc(50% - 0.4rem + cos(-150deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-03 { top: calc(50% - 0.4rem + sin(-120deg) * 3.9rem); left: calc(50% - 0.4rem + cos(-120deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-04 { top: calc(50% - 0.4rem + sin(-90deg) * 3.9rem); left: calc(50% - 0.4rem + cos(-90deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-05 { top: calc(50% - 0.4rem + sin(-60deg) * 3.9rem); left: calc(50% - 0.4rem + cos(-60deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-06 { top: calc(50% - 0.4rem + sin(-30deg) * 3.9rem); left: calc(50% - 0.4rem + cos(-30deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-07 { top: calc(50% - 0.4rem + sin(0deg) * 3.9rem); left: calc(50% - 0.4rem + cos(0deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-08 { top: calc(50% - 0.4rem + sin(30deg) * 3.9rem); left: calc(50% - 0.4rem + cos(30deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-09 { top: calc(50% - 0.4rem + sin(60deg) * 3.9rem); left: calc(50% - 0.4rem + cos(60deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-10 { top: calc(50% - 0.4rem + sin(90deg) * 3.9rem); left: calc(50% - 0.4rem + cos(90deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-11 { top: calc(50% - 0.4rem + sin(120deg) * 3.9rem); left: calc(50% - 0.4rem + cos(120deg) * 3.9rem); }
|
||||
div.astro-roue div.astro-ajustement.heure-12 { top: calc(50% - 0.4rem + sin(150deg) * 3.9rem); left: calc(50% - 0.4rem + cos(150deg) * 3.9rem); }
|
||||
|
||||
.window-app .window-content, .window-app.sheet .window-content .sheet-body{
|
||||
background: rgb(245,245,240) url(img/bg_left.webp) no-repeat left top;
|
||||
}
|
||||
@ -1698,178 +1620,219 @@ table.table-nombres-astraux tr:hover {
|
||||
border-image-outset: 0px;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
/* CALENDAR STUFF */
|
||||
#calendar-time-container{
|
||||
position: absolute;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.calendar {
|
||||
min-width: 250px;
|
||||
width: fit-content;
|
||||
|
||||
display: grid;
|
||||
grid-row: 2;
|
||||
grid-column: 9;
|
||||
|
||||
min-height: 5rem;
|
||||
height: fit-content;
|
||||
.window-app.calendar {
|
||||
display: inline-block;
|
||||
background: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-shadow: none;
|
||||
pointer-events: none;
|
||||
max-height: fit-content;
|
||||
}
|
||||
|
||||
.window-app.calendar header.window-header {
|
||||
min-width: fit-content;
|
||||
height: 1.4rem;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.window-app.calendar .window-content {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 1px solid #000;
|
||||
border-radius: 0.3rem;
|
||||
background: hsla(0, 0%, 0%, 0.5);
|
||||
font-family: "GoudyAcc";
|
||||
z-index: 100;
|
||||
flex-direction: column;
|
||||
min-width: 250px;
|
||||
height: fit-content;
|
||||
background: hsla(0, 0%, 0%, 0.0);
|
||||
font-family: "GoudyAcc";
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.calendar-title {
|
||||
grid-column: 1 / span 7;
|
||||
grid-row: 1;
|
||||
|
||||
color: #CCC;
|
||||
opacity: 90;
|
||||
font-size: 0.9rem;
|
||||
text-align: center;
|
||||
.window-app.calendar .window-content div:is(.calendar-boutons-heure, .horloge-digitale) {
|
||||
pointer-events: all;
|
||||
}
|
||||
.calendar-options {
|
||||
grid-column: 8 / span 2;
|
||||
}
|
||||
.calendar-title,.calendar-options{
|
||||
border-bottom: 1px solid hsla(0, 0%, 80%, 0.5);
|
||||
.window-app.calendar .window-content div.horloge-analogique {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.calendar-avance-heure {
|
||||
grid-column: 1 / span 3;
|
||||
.window-app.calendar .window-content div.horloge-analogique div.horloge-roue {
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
.calendar-change-heure {
|
||||
grid-column: 9 / span 1;
|
||||
.window-app.calendar div.horloge-roue {
|
||||
position: relative;
|
||||
margin-bottom: 7px;
|
||||
left: 0;
|
||||
width: 8rem;
|
||||
height: 8rem;
|
||||
}
|
||||
|
||||
.calendar-change-heure .calendar-change-heure-grid {
|
||||
.window-app.calendar div.horloge-roue div.horloge-heure {
|
||||
width: 1.4rem;
|
||||
height: 1.4rem;
|
||||
}
|
||||
.window-app.calendar div.horloge-roue div.horloge-heure img.horloge-heure-img {
|
||||
width: 1.4rem;
|
||||
height: 1.4rem;
|
||||
}
|
||||
|
||||
div.horloge-roue div {
|
||||
position: absolute;
|
||||
border: none;
|
||||
pointer-events: all;
|
||||
}
|
||||
|
||||
div.horloge-roue div.horloge-cercle {
|
||||
background: hsl(60, 20%, 95%) url(img/bg_left.webp) no-repeat left top;
|
||||
top: 2%; left: 2%; width: 96%; height: 96%; border-radius: 50%;
|
||||
}
|
||||
|
||||
div.horloge-roue div.horloge-cercle1 {
|
||||
background: var(--gradient-daylight);
|
||||
border: 0.2rem solid rgba(100, 45, 124, 0.6);
|
||||
top: 2%; left: 2%; width: 96%; height: 96%; border-radius: 50%;
|
||||
}
|
||||
|
||||
div.horloge-roue div.horloge-cercle2 {
|
||||
border: 0.1rem solid rgba(100, 45, 124, 0.4);
|
||||
top: 17%; left: 17%; width: 66%; height: 66%; border-radius: 50%;
|
||||
}
|
||||
div.horloge-roue div.disque-astro {
|
||||
top: 28%; left: 28%; width: 44%; height: 44%;
|
||||
}
|
||||
div.horloge-roue div.horloge-aiguille-heure {
|
||||
top: 25%; left: 25%; width: 50%; height: 50%;
|
||||
}
|
||||
div.horloge-roue div.horloge-aiguille-minute {
|
||||
top: 20%; left: 20%; width: 60%; height: 60%;
|
||||
}
|
||||
div.horloge-roue div.horloge-ajustement {
|
||||
width: 0.8rem;
|
||||
height: 0.8rem;
|
||||
color: hsl(120, 50%, 15%);
|
||||
background-color: hsla(300, 100%, 95%, 0.4);
|
||||
font-size: 0.8rem;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
border-radius: 0.3rem;
|
||||
}
|
||||
|
||||
div.horloge-roue div img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
.window-app.calendar div.horloge-heure.heure-01 { top: calc(50% - 0.7rem + sin(-180deg) *38%); left: calc(50% - 0.7rem + cos(-180deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-02 { top: calc(50% - 0.7rem + sin(-150deg) *38%); left: calc(50% - 0.7rem + cos(-150deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-03 { top: calc(50% - 0.7rem + sin(-120deg) *38%); left: calc(50% - 0.7rem + cos(-120deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-04 { top: calc(50% - 0.7rem + sin(-90deg) *38%); left: calc(50% - 0.7rem + cos(-90deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-05 { top: calc(50% - 0.7rem + sin(-60deg) *38%); left: calc(50% - 0.7rem + cos(-60deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-06 { top: calc(50% - 0.7rem + sin(-30deg) *38%); left: calc(50% - 0.7rem + cos(-30deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-07 { top: calc(50% - 0.7rem + sin(-0deg) *38%); left: calc(50% - 0.7rem + cos(-0deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-08 { top: calc(50% - 0.7rem + sin(30deg) *38%); left: calc(50% - 0.7rem + cos(30deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-09 { top: calc(50% - 0.7rem + sin(60deg) *38%); left: calc(50% - 0.7rem + cos(60deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-10 { top: calc(50% - 0.7rem + sin(90deg) *38%); left: calc(50% - 0.7rem + cos(90deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-11 { top: calc(50% - 0.7rem + sin(120deg) *38%); left: calc(50% - 0.7rem + cos(120deg) *38%); }
|
||||
.window-app.calendar div.horloge-heure.heure-12 { top: calc(50% - 0.7rem + sin(150deg) *38%); left: calc(50% - 0.7rem + cos(150deg) *41%); }
|
||||
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-01 { top: calc(50% - 1rem + sin(-180deg) *41%); left: calc(50% - 1rem + cos(-180deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-02 { top: calc(50% - 1rem + sin(-150deg) *41%); left: calc(50% - 1rem + cos(-150deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-03 { top: calc(50% - 1rem + sin(-120deg) *41%); left: calc(50% - 1rem + cos(-120deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-04 { top: calc(50% - 1rem + sin(-90deg) *41%); left: calc(50% - 1rem + cos(-90deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-05 { top: calc(50% - 1rem + sin(-60deg) *41%); left: calc(50% - 1rem + cos(-60deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-06 { top: calc(50% - 1rem + sin(-30deg) *41%); left: calc(50% - 1rem + cos(-30deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-07 { top: calc(50% - 1rem + sin(-0deg) *41%); left: calc(50% - 1rem + cos(-0deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-08 { top: calc(50% - 1rem + sin(30deg) *41%); left: calc(50% - 1rem + cos(30deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-09 { top: calc(50% - 1rem + sin(60deg) *41%); left: calc(50% - 1rem + cos(60deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-10 { top: calc(50% - 1rem + sin(90deg) *41%); left: calc(50% - 1rem + cos(90deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-11 { top: calc(50% - 1rem + sin(120deg) *41%); left: calc(50% - 1rem + cos(120deg) *41%); }
|
||||
.window-app.calendar-astrologie div.horloge-heure.heure-12 { top: calc(50% - 1rem + sin(150deg) *41%); left: calc(50% - 1rem + cos(150deg) *41%); }
|
||||
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-01 { top: calc(50% - 0.4rem + sin(180deg) * 28%); left: calc(50% - 0.4rem + cos(180deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-02 { top: calc(50% - 0.4rem + sin(-150deg) * 28%); left: calc(50% - 0.4rem + cos(-150deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-03 { top: calc(50% - 0.4rem + sin(-120deg) * 28%); left: calc(50% - 0.4rem + cos(-120deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-04 { top: calc(50% - 0.4rem + sin(-90deg) * 28%); left: calc(50% - 0.4rem + cos(-90deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-05 { top: calc(50% - 0.4rem + sin(-60deg) * 28%); left: calc(50% - 0.4rem + cos(-60deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-06 { top: calc(50% - 0.4rem + sin(-30deg) * 28%); left: calc(50% - 0.4rem + cos(-30deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-07 { top: calc(50% - 0.4rem + sin(0deg) * 28%); left: calc(50% - 0.4rem + cos(0deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-08 { top: calc(50% - 0.4rem + sin(30deg) * 28%); left: calc(50% - 0.4rem + cos(30deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-09 { top: calc(50% - 0.4rem + sin(60deg) * 28%); left: calc(50% - 0.4rem + cos(60deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-10 { top: calc(50% - 0.4rem + sin(90deg) * 28%); left: calc(50% - 0.4rem + cos(90deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-11 { top: calc(50% - 0.4rem + sin(120deg) * 28%); left: calc(50% - 0.4rem + cos(120deg) * 28%); }
|
||||
.window-app.calendar-astrologie div.horloge-ajustement.heure-12 { top: calc(50% - 0.4rem + sin(150deg) * 28%); left: calc(50% - 0.4rem + cos(150deg) * 28%); }
|
||||
|
||||
.window-app.calendar header.window-header h4 {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.window-app.calendar section.window-content div.calendar-boutons-heure {
|
||||
display: grid;
|
||||
grid-column: 1;
|
||||
grid-row: 2;
|
||||
|
||||
margin: 2px;
|
||||
grid-row-gap: 3px;
|
||||
color: hsla(0, 0%, 80%, 0.5);
|
||||
background: hsla(0, 0%, 20%, 1);
|
||||
color: hsla(0, 0%, 80%, 0.8);
|
||||
|
||||
grid-row: 1;
|
||||
grid-column: 10;
|
||||
}
|
||||
|
||||
.calendar-avance-heure .calendar-avance-heure-grid {
|
||||
display: grid;
|
||||
grid-column: 3;
|
||||
grid-row: 2;
|
||||
|
||||
margin: 2px;
|
||||
grid-row-gap: 3px;
|
||||
color: hsla(0, 0%, 80%, 0.5);
|
||||
}
|
||||
|
||||
.calendar-avance-heure .calendar-avance-heure-grid:hover {
|
||||
color: #FFF;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.calendar-affiche-heure {
|
||||
grid-column: 4 / span 4;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.calendar-affiche-heure .calendar-horloge {
|
||||
display: grid;
|
||||
max-width: 100px;
|
||||
float: left;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
margin: 0 0.3rem 0 0.3rem;
|
||||
color: #CCC;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.calendar-affiche-heure .calendar-horloge .calendar-heure-texte {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
.calendar-affiche-heure .calendar-horloge .calendar-minute-texte {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.calendar-affiche-heure .calendar-horloge .calendar-heure-img{
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
float: left;
|
||||
flex-grow: 0;
|
||||
padding: 0.1rem;
|
||||
border: 0;
|
||||
opacity: 0.9;
|
||||
.calendar-boutons-heure .calendar-btn:is(.calendar-lyre,.calendar-vaisseau) img {
|
||||
color: hsla(0, 0%, 100%, 0.5);
|
||||
border: none;
|
||||
vertical-align: bottom;
|
||||
max-width: 1.2em;
|
||||
max-height: 1.2em;
|
||||
margin: 1px;
|
||||
}
|
||||
|
||||
.calendar :is(.calendar-astrologie,.calendar-set-datetime) {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
}
|
||||
.calendar :is(.calendar-astrologie,.calendar-set-datetime,.calendar-btn) {
|
||||
color: hsla(0, 0%, 100%, 0.5);
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
}
|
||||
.calendar :is(.calendar-astrologie,.calendar-set-datetime,.calendar-btn):hover {
|
||||
color: var(--color-controls-hover);
|
||||
border: 1px solid var(--color-control-border-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
.calendar .calendar-affiche-heure .calendar-horloge a {
|
||||
.calendar-boutons-heure i {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
}
|
||||
.calendar .calendar-affiche-heure .calendar-horloge a:hover {
|
||||
.calendar-boutons-heure i:hover {
|
||||
color: var(--color-controls-hover);
|
||||
border: 1px solid var(--color-control-border-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.calendar-avance-heure .calendar-1min {
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
}
|
||||
.calendar-avance-heure .calendar-5min {
|
||||
grid-row: 1;
|
||||
grid-column: 2;
|
||||
}
|
||||
.calendar-avance-heure .calendar-15min {
|
||||
grid-row: 1;
|
||||
grid-column: 3;
|
||||
}
|
||||
.calendar-avance-heure .calendar-30min {
|
||||
grid-row: 2;
|
||||
grid-column: 1;
|
||||
}
|
||||
.calendar-avance-heure .calendar-60min {
|
||||
grid-row: 2;
|
||||
grid-column: 2;
|
||||
}
|
||||
.calendar-avance-heure .calendar-1heure {
|
||||
grid-row: 2;
|
||||
grid-column: 3;
|
||||
.calendar-1min { grid-column: 1;}
|
||||
.calendar-5min { grid-column: 2;}
|
||||
.calendar-15min { grid-column: 3;}
|
||||
.calendar-30min { grid-column: 4;}
|
||||
.calendar-60min { grid-column: 5;}
|
||||
.calendar-1heure { grid-column: 6;}
|
||||
.calendar-lyre { grid-column: 7;}
|
||||
.calendar-vaisseau { grid-column: 8;}
|
||||
.calendar-set-datetime { grid-column: 9;}
|
||||
.calendar-astrologie { grid-column: 10;}
|
||||
|
||||
div.horloge-analogique {
|
||||
border: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.calendar-lyre{
|
||||
grid-row: 1;
|
||||
grid-column: 1;
|
||||
div.horloge-analogique.horloge-analogique-hidden {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.calendar-vaisseau {
|
||||
grid-row: 2;
|
||||
grid-column: 1;
|
||||
div.horloge-digitale {
|
||||
color: #CCC;
|
||||
background: hsla(0, 0%, 20%, 1);
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.calendar-change-heure .calendar-btn:is(.calendar-lyre,.calendar-vaisseau) img {
|
||||
color: hsla(0, 0%, 100%, 0.5);
|
||||
vertical-align: bottom;
|
||||
max-width: 1.2em;
|
||||
max-height: 1.2em;
|
||||
border-width: 0;
|
||||
div.horloge-digitale :is(.calendar-heure-texte,.calendar-minute-texte) {
|
||||
font-size: 1rem;
|
||||
pointer-events: all;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
div.horloge-digitale a {
|
||||
border: 1px solid rgba(0, 0, 0, 0);
|
||||
}
|
||||
div.horloge-digitale a:hover {
|
||||
color: var(--color-controls-hover);
|
||||
border: 1px solid var(--color-control-border-hover);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.calendar-timestamp-edit select.calendar-signe-heure {
|
||||
@ -1948,34 +1911,51 @@ div.calendar-timestamp-edit select.calendar-signe-heure {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.chat-card-button {
|
||||
box-shadow: inset 0px 1px 0px 0px #a6827e;
|
||||
background: var(--background-custom-button);
|
||||
background-color: #7d5d3b00;
|
||||
border-radius: 3px;
|
||||
border: 2px ridge #846109;
|
||||
display: inline-block;
|
||||
.chat-card-button, .chat-card-button-pushed {
|
||||
border-radius: 0.2rem;
|
||||
cursor: pointer;
|
||||
color: #ffffff;
|
||||
font-family: CaslonPro;
|
||||
font-size: 0.9rem;
|
||||
padding: 4px 12px 0px 12px;
|
||||
padding: 0.2rem 0.4rem 0rem 0.4rem;
|
||||
text-decoration: none;
|
||||
text-shadow: 0px 1px 0px #4d3534;
|
||||
position: relative;
|
||||
margin:5px;
|
||||
margin: 0.3rem;
|
||||
|
||||
border: 2px ridge #846109;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.chat-card-button{
|
||||
text-shadow: 1px 1px #4d3534;
|
||||
box-shadow: inset 1x 1px #a6827e;
|
||||
color: var(--major-button-color);
|
||||
background: var(--background-custom-button);
|
||||
background-color: #7d5d3b00;
|
||||
}
|
||||
|
||||
.chat-card-button-pushed {
|
||||
text-shadow: 1px 1px hsla(202, 30%, 70%, 0.5);
|
||||
box-shadow: inset -1px -1px #a6827e;
|
||||
color: hsla(202, 42%, 14%, 0.7);
|
||||
background: var(--major-button-color);
|
||||
background-color: #7d5d3b00;
|
||||
}
|
||||
|
||||
.chat-card-button:hover {
|
||||
background: var(--background-custom-button-hover);
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.chat-card-button:active {
|
||||
.chat-card-button-pushed:hover {
|
||||
background: var(--background-custom-button-hover);
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.chat-card-button:active, .chat-card-button-pushed:active {
|
||||
position:relative;
|
||||
top:1px;
|
||||
}
|
||||
|
||||
/* Dropdown Content (Hidden by Default) */
|
||||
.button-dropdown-content {
|
||||
display: none;
|
||||
|
237
system.json
237
system.json
@ -1,12 +1,13 @@
|
||||
{
|
||||
"id": "foundryvtt-reve-de-dragon",
|
||||
"title": "Rêve de Dragon",
|
||||
"version": "10.7.1",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.7.1.zip",
|
||||
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json",
|
||||
"version": "11.0.24",
|
||||
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.24.zip",
|
||||
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json",
|
||||
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
|
||||
"compatibility": {
|
||||
"minimum": "10",
|
||||
"verified": "10"
|
||||
"minimum": "11",
|
||||
"verified": "11"
|
||||
},
|
||||
"description": "Rêve de Dragon RPG for FoundryVTT",
|
||||
"authors": [
|
||||
@ -68,7 +69,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/competences.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -77,7 +81,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/arts-et-divertissements.db",
|
||||
"type": "Item",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -86,7 +93,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/competences-creatures.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -95,7 +105,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/competences-entites.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -104,7 +117,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/sorts-oniros.db",
|
||||
"type": "Item",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -113,7 +129,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/sorts-hypnos.db",
|
||||
"type": "Item",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -122,7 +141,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/sorts-narcos.db",
|
||||
"type": "Item",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -131,7 +153,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/sorts-thanatos.db",
|
||||
"type": "Item",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -140,7 +165,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/equipement.db",
|
||||
"type": "Item",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -149,7 +177,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/maladies-et-poisons.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -158,7 +189,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/rappel-des-regles.db",
|
||||
"type": "JournalEntry",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OBSERVER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -167,7 +201,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/macros.db",
|
||||
"type": "Macro",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -176,7 +213,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/queues-de-dragon.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -185,7 +225,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/ombres-de-thanatos.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -194,7 +237,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/souffles-de-dragon.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -203,7 +249,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/tarot-draconique.db",
|
||||
"type": "Item",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -212,7 +261,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/extrait-poetique.db",
|
||||
"type": "Item",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "OBSERVER",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -221,7 +273,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/tetes-de-dragon-pour-haut-revants.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -230,7 +285,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/tetes-de-dragon-pour-tous-personnages.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -239,7 +297,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/rencontres.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -248,7 +309,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/tables-diverses.db",
|
||||
"type": "RollTable",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -257,7 +321,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/animaux.db",
|
||||
"type": "Actor",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -266,7 +333,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/voyageurs.db",
|
||||
"type": "Actor",
|
||||
"private": false,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -275,7 +345,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/vehicules.db",
|
||||
"type": "Actor",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -284,7 +357,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/archetypes.db",
|
||||
"type": "Actor",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -293,7 +369,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/humanoides.db",
|
||||
"type": "Actor",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -302,7 +381,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/entites-de-cauchemar.db",
|
||||
"type": "Actor",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -311,7 +393,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/invocations.db",
|
||||
"type": "Actor",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -320,7 +405,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/faune-flore-mineraux.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -329,7 +417,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/meditations-et-ecrits.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -338,7 +429,10 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/recettes-alchimiques.db",
|
||||
"type": "Item",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
},
|
||||
{
|
||||
@ -347,10 +441,79 @@
|
||||
"system": "foundryvtt-reve-de-dragon",
|
||||
"path": "packs/scenes-rdd.db",
|
||||
"type": "Scene",
|
||||
"private": true,
|
||||
"ownership": {
|
||||
"PLAYER": "NONE",
|
||||
"ASSISTANT": "OWNER"
|
||||
},
|
||||
"flags": {}
|
||||
}
|
||||
],
|
||||
"packFolders": [
|
||||
{
|
||||
"name": "Rêve de Dragon",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"rappel-des-regles"
|
||||
],
|
||||
"folders": [
|
||||
{
|
||||
"name": "Personnages",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"voyageurs",
|
||||
"archetypes",
|
||||
"humanoides",
|
||||
"equipement",
|
||||
"competences",
|
||||
"arts-et-divertissements",
|
||||
"meditations-et-ecrits",
|
||||
"recettes-alchimiques"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Le Haut-rêve",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"tetes-de-dragon-pour-tous-personnages",
|
||||
"sorts-oniros",
|
||||
"sorts-hypnos",
|
||||
"sorts-narcos",
|
||||
"sorts-thanatos",
|
||||
"invocations",
|
||||
"rencontres",
|
||||
"queues-de-dragon",
|
||||
"ombres-de-thanatos",
|
||||
"souffles-de-dragon",
|
||||
"tetes-de-dragon-pour-haut-revants"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Découverte du monde",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"animaux",
|
||||
"vehicules",
|
||||
"entites",
|
||||
"faune-flore-mineraux",
|
||||
"competences-creatures",
|
||||
"competences-entites",
|
||||
"maladies-et-poisons"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Outils du Gardien",
|
||||
"sorting": "m",
|
||||
"packs": [
|
||||
"scenes-rdd",
|
||||
"tables-diverses",
|
||||
"macros",
|
||||
"tarot-draconique",
|
||||
"extrait-poetique"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"socket": true,
|
||||
"gridDistance": 1,
|
||||
"gridUnits": "m",
|
||||
|
@ -393,12 +393,6 @@
|
||||
"label": "Encombrement",
|
||||
"derivee": true
|
||||
},
|
||||
"malusarmure": {
|
||||
"type": "number",
|
||||
"value": 0,
|
||||
"label": "Malus Armure",
|
||||
"derivee": true
|
||||
},
|
||||
"protection": {
|
||||
"type": "number",
|
||||
"value": 0,
|
||||
@ -538,7 +532,7 @@
|
||||
"service",
|
||||
"meditation", "rencontre", "queue", "ombre", "souffle", "tete", "casetmr", "signedraconique", "sort", "sortreserve",
|
||||
"nombreastral", "tache", "blessure", "maladie", "poison", "possession",
|
||||
"tarot", "extraitpoetique"
|
||||
"tarot", "extraitpoetique", "empoignade"
|
||||
],
|
||||
"templates": {
|
||||
"description": {
|
||||
@ -586,25 +580,43 @@
|
||||
},
|
||||
"competencecreature": {
|
||||
"templates": ["description"],
|
||||
"categorie_parade": "",
|
||||
"carac_value": 0,
|
||||
"niveau": 0,
|
||||
"default_diffLibre": 0,
|
||||
"categorie": "",
|
||||
"carac_value": 0,
|
||||
"categorie_parade": "",
|
||||
"iscombat": false,
|
||||
"isnaturelle": true,
|
||||
"ispossession": false,
|
||||
"dommages": 0
|
||||
"dommages": 0,
|
||||
"mortalite": "mortel"
|
||||
},
|
||||
"empoignade": {
|
||||
"templates": ["description"],
|
||||
"empoignadeid": "",
|
||||
"empoigneurid": "",
|
||||
"empoigneid": "",
|
||||
"pointsemp": 0,
|
||||
"empoigneurname": "",
|
||||
"empoignename": "",
|
||||
"ausol": false
|
||||
},
|
||||
"possession": {
|
||||
"templates": ["description"],
|
||||
"typepossession": "",
|
||||
"possede": false,
|
||||
"possessionid": "",
|
||||
"possesseurid": "",
|
||||
"possedeid": "",
|
||||
"compteur": 0,
|
||||
"date": 0
|
||||
"entite": {
|
||||
"actorid": "",
|
||||
"diffLibre": 0,
|
||||
"finesse": false
|
||||
},
|
||||
"victime": {
|
||||
"actorid": "",
|
||||
"diffLibre": 0,
|
||||
"finesse": false
|
||||
},
|
||||
"compteur": 0
|
||||
},
|
||||
"blessure": {
|
||||
"templates": ["temporel"],
|
||||
@ -620,7 +632,7 @@
|
||||
"bonus": 0
|
||||
},
|
||||
"localisation": "",
|
||||
"jours": 0
|
||||
"origine": ""
|
||||
},
|
||||
"maladie": {
|
||||
"templates": ["description", "temporel"],
|
||||
@ -654,6 +666,7 @@
|
||||
"resistance": 0,
|
||||
"categorie_parade": "",
|
||||
"dommages": "0",
|
||||
"mortalite": "mortel",
|
||||
"penetration": 0,
|
||||
"force": "0",
|
||||
"competence": "",
|
||||
@ -682,7 +695,7 @@
|
||||
"capacite": 0
|
||||
},
|
||||
"objet": {
|
||||
"templates": ["description", "inventaire"]
|
||||
"templates": ["description", "equipement", "inventaire"]
|
||||
},
|
||||
"monnaie": {
|
||||
"templates": ["description", "inventaire"]
|
||||
|
@ -41,6 +41,9 @@
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.html"}}
|
||||
</div>
|
||||
<div>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/resonances.hbs"}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group large-editor">
|
||||
|
@ -53,7 +53,9 @@
|
||||
{{#if options.isObserver}}{{!-- Compétences Tab --}}
|
||||
<div class="tab competences" data-group="primary" data-tab="competences">
|
||||
<div class="flexrow">
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html"}}
|
||||
<span>
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html"}}
|
||||
</span>
|
||||
<span class="flexrow"><a class="show-hide-competences">
|
||||
{{#if options.showCompNiveauBase}}
|
||||
<i class="fa-regular fa-filter-slash"></i> Montrer tout
|
||||
@ -65,9 +67,17 @@
|
||||
<input class="recherche flex-grow" type="text" value="{{options.recherche.text}}" name="recherche" size="8" data-dtype="String" placeholder=""/>
|
||||
</span>
|
||||
<span>
|
||||
{{#if options.vueDetaillee}}
|
||||
|
||||
{{#if @root.options.vueArchetype}}
|
||||
<a class="competence-archetype toggle-archetype chat-card-button-pushed"><i class="fa-solid fa-up-right-from-square"></i>Incarnation</a>
|
||||
{{else}}
|
||||
<a class="competence-archetype toggle-archetype chat-card-button"><i class="fa-solid fa-people-line"></i>Archétype</a>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="grid grid-2col">
|
||||
<div class="grid {{#if (and options.vueDetaillee options.vueArchetype)}}grid-competence-archetype{{else}}grid-2col{{/if}}">
|
||||
<div class="competence-column">
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.generale) categorie="Compétences générales"}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.particuliere) categorie="Compétences Particulières"}}
|
||||
@ -83,13 +93,17 @@
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html" competences=(filtreTriCompetences byCateg.draconic) categorie="Draconic"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if (and options.vueDetaillee options.vueArchetype)}}
|
||||
<div>
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/archetype.hbs"}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if options.isObserver}}{{!-- Combat Tab --}}
|
||||
<div class="tab combat" data-group="primary" data-tab="combat">
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/combat.html"}}<hr>
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.html"}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/blessures.html"}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html"}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html"}}
|
||||
@ -100,6 +114,7 @@
|
||||
<div class="tab connaissances" data-group="primary" data-tab="connaissances">
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html"}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/taches.html"}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.html"}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html"}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html"}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html"}}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{{#if recettesAlchimiques.length}}
|
||||
<h3>Recettes Alchimiques</h3>
|
||||
<ul class="item-list alterne-list">
|
||||
{{#each recettesAlchimiques as |recette id|}}
|
||||
{{#each (trier recettesAlchimiques) as |recette id|}}
|
||||
<li class="item flexrow list-item" data-item-id="{{recette._id}}"><span class="competence-title recette-label item-edit"><a>{{recette.name}}</a></span>
|
||||
<div class="item-controls flex-shrink">
|
||||
<a class="item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
|
||||
|
21
templates/actor/archetype.hbs
Normal file
21
templates/actor/archetype.hbs
Normal file
@ -0,0 +1,21 @@
|
||||
<div>
|
||||
<ul class="item-list">
|
||||
{{#if @root.options.isGM}}
|
||||
<li>
|
||||
<a class="nouvelle-incarnation chat-card-button"><i class="fa-solid fa-person-circle-plus"></i> Nouvelle incarnation</a>
|
||||
</li>
|
||||
{{/if}}
|
||||
<li><hr></li>
|
||||
<li>Niveaux d'archétype</li>
|
||||
{{#if calc.comptageArchetype}}
|
||||
{{#each calc.comptageArchetype as |archetype|}}
|
||||
|
||||
<li class="item flexrow">
|
||||
<label class="generic-label">
|
||||
Niveaux {{numberFormat archetype.niveau decimals=0 sign=true}} : {{archetype.nombre}} / {{archetype.nombreMax}}
|
||||
</label>
|
||||
</li>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
</ul>
|
||||
</div>
|
@ -1,8 +1,8 @@
|
||||
<li class="item item-blessure flexrow list-item blessure-active-{{lowercase system.labelGravite}}" data-item-id="{{id}}">
|
||||
<li class="item item-blessure flexrow list-item blessure-active-{{lowercase system.label}}" data-item-id="{{id}}">
|
||||
<span class="blessure-control">
|
||||
<img class="sheet-competence-img" src="{{img}}" />
|
||||
<i class="fas fa-skull-crossbones"></i>
|
||||
{{system.labelGravite}}
|
||||
{{system.label}}
|
||||
</span>
|
||||
{{#if (gt system.gravite 6)}}
|
||||
<span class="flexrow"></span>
|
||||
@ -11,7 +11,9 @@
|
||||
<span class="flexrow">
|
||||
<input type="checkbox" class="blessure-premierssoins-done" name="blessure.{{id}}.premierssoins.done" {{#if system.premierssoins.done}}checked{{/if}}/>
|
||||
{{#if system.premierssoins.done}}
|
||||
{{#unless system.soinscomplets.done}}
|
||||
<input type="text" class="blessure-premierssoins-bonus number-x2" name="blessure.{{id}}.premierssoins.bonus" data-dtype="number" value="{{system.premierssoins.bonus}}"/>
|
||||
{{/unless}}
|
||||
{{else}}
|
||||
<label>{{system.premierssoins.tache}} / {{system.gravite}}</label>
|
||||
{{/if}}
|
||||
@ -28,7 +30,8 @@
|
||||
</span>
|
||||
{{/if}}
|
||||
<span>
|
||||
{{system.localisation}}
|
||||
{{#if system.origine}}<span>Par {{system.origine}}</span>{{/if}}
|
||||
{{#if system.localisation}}<span>{{system.localisation}}</span>{{/if}}
|
||||
</span>
|
||||
<span class="item-controls">
|
||||
<a class="item-edit" title="Editer"><i class="fas fa-edit"></i></a>
|
||||
|
@ -72,7 +72,7 @@
|
||||
</li>
|
||||
<li class="caracteristique flexrow list-item" >
|
||||
<label class="carac-label">Malus armure</label>
|
||||
<input class="derivee-value" type="number" disabled value="{{system.attributs.malusarmure.value}}" data-dtype="number"/>
|
||||
<input class="derivee-value" type="number" disabled value="{{calc.malusArmure}}" data-dtype="number"/>
|
||||
</li>
|
||||
<li class="caracteristique flexrow list-item">
|
||||
<label class="carac-label" for="system.attributs.protection.value" >Protection naturelle</label>
|
||||
|
@ -40,4 +40,29 @@
|
||||
<span class="initiative-value"></span>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
||||
<ul class="item-list alterne-list">
|
||||
<li class="competence-header flexrow">
|
||||
<span class="competence-title competence-label">Empoignades</span>
|
||||
<span class="competence-title competence-value">Points d'Emp</span>
|
||||
</li>
|
||||
{{#each empoignades as |emp key|}}
|
||||
<li class="item flexrow list-item"
|
||||
data-item-id="{{emp._id}}" data-arme-name="{{emp.name}}">
|
||||
<span class="empoignade-label">
|
||||
<a>
|
||||
{{#if emp.img}}
|
||||
<img class="sheet-competence-img" src="{{emp.img}}"/>
|
||||
{{/if}}
|
||||
<span>{{emp.name}}</span>
|
||||
</a>
|
||||
</span>
|
||||
<span class="competence-value">{{emp.system.pointsemp}}</span>
|
||||
<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>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
@ -61,7 +61,7 @@
|
||||
{{/unless}}
|
||||
</label>
|
||||
</li>
|
||||
{{#each system.services as |service key|}}
|
||||
{{#each (trier system.services) as |service key|}}
|
||||
<li class="item flexrow list-item" data-key="{{key}}">
|
||||
<input {{@root.disabled}} type="text" name="services[{{key}}].name" value="{{service.name}}" data-dtype="String" />
|
||||
<input {{@root.disabled}} type="checkbox" name="services[{{key}}].system.moral" {{#if service.system.moral}}checked{{/if}} />
|
||||
|
@ -25,14 +25,14 @@
|
||||
<span class="equipement-detail">Prix (sols)</span>
|
||||
<span class="equipement-actions">Actions</span>
|
||||
</li>
|
||||
{{#each objets as |item id|}}
|
||||
{{#each (trier inventaires) as |item id|}}
|
||||
{{#unless item.estContenu}}
|
||||
{{#if (ne item.type 'conteneur')}}
|
||||
{{buildLigneInventaire item ../options}}
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
{{#each conteneurs as |conteneur id|}}
|
||||
{{#each (trier conteneurs) as |conteneur id|}}
|
||||
{{buildLigneInventaire conteneur ../options}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
@ -9,18 +9,24 @@
|
||||
<input class="competence-carac creature-carac" type="text" compname="{{comp.name}}" name="{{comp._id}}.carac"
|
||||
value="{{comp.system.carac_value}}" data-dtype="number"
|
||||
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}/>
|
||||
<input class="competence-value creature-niveau" type="text" compname="{{comp.name}}" name="{{comp._id}}.niveau"
|
||||
value="{{numberFormat comp.system.niveau decimals=0 sign=true}}" data-dtype="number"
|
||||
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}/>
|
||||
<input class="competence-damage creature-dommages" type="text" compname="{{comp.name}}" name="{{comp._id}}.dommages"
|
||||
value="{{numberFormat comp.system.dommages decimals=0 sign=true}}" data-dtype="number"
|
||||
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}/>
|
||||
{{#if @root.options.vueDetaillee}}
|
||||
<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>
|
||||
</div>
|
||||
{{/if}}
|
||||
<input class="competence-value creature-niveau" type="text" data-dtype="number"
|
||||
compname="{{comp.name}}" name="{{comp._id}}.niveau"
|
||||
value="{{numberFormat comp.system.niveau decimals=0 sign=true}}"
|
||||
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}
|
||||
/>
|
||||
<input class="competence-damage creature-dommages" type="text" data-dtype="number"
|
||||
{{#if comp.isdommages}}
|
||||
compname="{{comp.name}}" name="{{comp._id}}.dommages"
|
||||
value="{{numberFormat comp.system.dommages decimals=0 sign=true}}"
|
||||
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}
|
||||
{{else}}disabled{{/if}}
|
||||
/>
|
||||
{{#if @root.options.vueDetaillee}}
|
||||
<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>
|
||||
</div>
|
||||
{{/if}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
|
@ -14,12 +14,13 @@
|
||||
|
||||
<input class="competence-value" type="text" compname="{{name}}" name="comp-value-{{name}}"
|
||||
value="{{numberFormat system.niveau decimals=0 sign=true}}" data-dtype="number"
|
||||
{{#unless @root.options.vueDetaillee}}disabled{{/unless}} />
|
||||
{{#if (or (not @root.options.vueDetaillee) @root.options.vueArchetype)}}disabled{{/if}} />
|
||||
|
||||
{{#if @root.options.vueDetaillee}}
|
||||
<span class="competence-xp {{#unless system.isLevelUp}}tooltip{{/unless}}">
|
||||
<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 system.xp decimals=0 sign=false}}" data-dtype="number"
|
||||
{{#if (or (not @root.options.vueDetaillee) @root.options.vueArchetype)}}disabled{{/if}} />
|
||||
{{#unless system.isLevelUp}}
|
||||
<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>
|
||||
{{/unless}}
|
||||
@ -28,7 +29,7 @@
|
||||
{{#if (eq system.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"
|
||||
{{#unless @root.options.vueDetaillee}}disabled{{/unless}}/>
|
||||
{{#if (or (not @root.options.vueDetaillee) @root.options.vueArchetype)}}disabled{{/if}} />
|
||||
{{/if}}
|
||||
{{#if @root.options.vueDetaillee}}
|
||||
<div class="item-controls">
|
||||
@ -41,7 +42,8 @@
|
||||
<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 system.niveau_archetype decimals=0 sign=true}}" data-dtype="number"
|
||||
{{#if (not @root.options.vueArchetype)}}disabled{{/if}} />
|
||||
<a class="item-edit" title="Modifier"><i class="fas fa-edit"></i></a>
|
||||
{{#if @root.options.isGM}}
|
||||
<a class="item-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{{#if meditations.length}}
|
||||
<h3>Méditations</h3>
|
||||
<ul class="item-list">
|
||||
{{#each meditations as |meditation key|}}
|
||||
{{#each (trier meditations) as |meditation key|}}
|
||||
<li class="item flexrow" data-item-id="{{meditation._id}}" data-attribute="{{key}}">
|
||||
<img class="sheet-competence-img" src="{{meditation.img}}" />
|
||||
<span class="meditation-label flex-grow"><a data-item-id="{{meditation._id}}">{{meditation.name}} - {{meditation.system.competence}}</a></span>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{{#if sortsReserve.length}}
|
||||
<h3>Sorts en Réserve</h3>
|
||||
<ul class="item-list alterne-list">
|
||||
{{#each sortsReserve as |sort key|}}
|
||||
{{#each (trier sortsReserve) as |sort key|}}
|
||||
<li class="item list-item flexrow" data-item-id="{{sort._id}}" data-attribute="{{key}}">
|
||||
<img class="sheet-competence-img" src="{{sort.img}}" />
|
||||
<span class="item-edit"><a>{{#if sort.system.echectotal}}Echec total: {{/if}}{{sort.name}} r{{sort.system.ptreve}}</a></span>
|
||||
|
@ -1,7 +1,7 @@
|
||||
{{#if sorts.length}}
|
||||
<h3>Sorts</h3>
|
||||
<ul class="item-list alterne-list">
|
||||
{{#each sorts as |sort key|}}
|
||||
{{#each (trier sorts) as |sort key|}}
|
||||
<li class="item list-item flexrow" data-item-id="{{sort._id}}" data-attribute="{{key}}">
|
||||
<img class="sheet-competence-img" src="{{sort.img}}" />
|
||||
<span class="item-edit flex-grow-2">
|
||||
|
@ -15,7 +15,11 @@
|
||||
</a>
|
||||
{{/if}}
|
||||
</span>
|
||||
<span class="equipement-detail">{{item.system.quantite}}
|
||||
<span class="equipement-detail">
|
||||
{{#if (gt item.system.quantite 1)}}
|
||||
<a class="item-quantite-moins"><i class="fas fa-minus-square"></i></a>
|
||||
{{/if}}
|
||||
{{item.system.quantite}}
|
||||
{{#if (gt item.system.quantite 1)}}
|
||||
<a class="item-split" title="Séparer"><i class="fas fa-unlink"></i></a>
|
||||
{{/if}}
|
||||
@ -24,7 +28,7 @@
|
||||
<span class="equipement-actions item-controls">
|
||||
{{#if options.isOwner}}
|
||||
{{#unless item.estContenu}}
|
||||
{{#if (or (eq item.type 'arme') (eq item.type 'armure') )}}
|
||||
{{#if item.equipable}}
|
||||
<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>
|
||||
{{/if}}
|
||||
{{/unless}}
|
||||
|
@ -1,7 +1,7 @@
|
||||
{{#if @root.options.isObserver}}
|
||||
<span class="item-name"><h4>Argent et Monnaies (fortune: {{calc.fortune.sols}} sols {{calc.fortune.deniers}} deniers)</h4></span>
|
||||
<ul class="item-list alterne-list">
|
||||
{{#each monnaie as |piece id|}}
|
||||
{{#each monnaies as |piece id|}}
|
||||
<li class="item flexrow list-item" data-item-id="{{piece._id}}">
|
||||
<img class="sheet-competence-img" src="{{piece.img}}" title="{{piece.name}}"/>
|
||||
<span class="equipement-nom">{{piece.name}}</span>
|
||||
@ -10,7 +10,7 @@
|
||||
</span>
|
||||
{{#if @root.options.isOwner}}
|
||||
<span class="equipement-button item-controls">
|
||||
<a class="monnaie-moins"><i class="fas fa-minus-square"></i></a>
|
||||
<a class="item-quantite-moins"><i class="fas fa-minus-square"></i></a>
|
||||
</span>
|
||||
{{/if}}
|
||||
<span class="equipement-detail">
|
||||
@ -18,7 +18,7 @@
|
||||
</span>
|
||||
{{#if @root.options.isOwner}}
|
||||
<span class="equipement-button item-controls">
|
||||
<a class="monnaie-plus"><i class="fas fa-plus-square"></i></a>
|
||||
<a class="item-quantite-plus"><i class="fas fa-plus-square"></i></a>
|
||||
</span>
|
||||
{{/if}}
|
||||
<span class="equipement-actions item-controls">
|
||||
|
@ -22,7 +22,7 @@
|
||||
<span class="equipement-detail">Enc.</span>
|
||||
<span class="equipement-actions">Actions</span>
|
||||
</li>
|
||||
{{#each objets as |item id|}}
|
||||
{{#each inventaires as |item id|}}
|
||||
{{#unless item.estContenu}}
|
||||
{{#if (ne item.type 'conteneur')}}
|
||||
{{buildLigneInventaire item @root.options}}
|
||||
|
@ -1,18 +1,18 @@
|
||||
<h3>Oeuvres diverses</h3><a class="chat-card-button creer-une-oeuvre">Créer une oeuvre</a>
|
||||
<ul class="item-list alterne-list">
|
||||
{{#each chants as |chant id|}}
|
||||
{{#each (trier chants) as |chant id|}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.html" oeuvre=chant typeOeuvre="Chant" classOeuvre="chant-label"}}
|
||||
{{/each}}
|
||||
{{#each musiques as |musique id|}}
|
||||
{{#each (trier musiques) as |musique id|}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.html" oeuvre=musique typeOeuvre="Musique" classOeuvre="musique-label"}}
|
||||
{{/each}}
|
||||
{{#each danses as |danse id|}}
|
||||
{{#each (trier danses) as |danse id|}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.html" oeuvre=danse typeOeuvre="Danse" classOeuvre="danse-label"}}
|
||||
{{/each}}
|
||||
{{#each oeuvres as |oeuvre id|}}
|
||||
{{#each (trier oeuvres) as |oeuvre id|}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.html" oeuvre=oeuvre typeOeuvre=oeuvre.system.competence classOeuvre="oeuvre-label"}}
|
||||
{{/each}}
|
||||
{{#each recettescuisine as |recette id|}}
|
||||
{{#each (trier recettescuisine) as |recette id|}}
|
||||
{{> "systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.html" oeuvre=recette typeOeuvre="Recette de cuisine" classOeuvre="recettecuisine-label"}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
|
12
templates/actor/resonances.hbs
Normal file
12
templates/actor/resonances.hbs
Normal file
@ -0,0 +1,12 @@
|
||||
<span class="item-name"><h4>Personnages accordés</h4></span>
|
||||
<ul class="item-list alterne-list">
|
||||
{{#each resonances as |actor|}}
|
||||
<li class="item flexrow list-item" data-actor-id="{{actor.id}}">
|
||||
<img class="sheet-competence-img" src="{{actor.img}}" title="{{actor.name}}"/>
|
||||
<span class="subacteur-label"><a>{{actor.name}}</a></span>
|
||||
<div class="flex-shrink">
|
||||
<a class="resonance-delete" title="Supprimer"><i class="fas fa-trash"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
@ -3,7 +3,7 @@
|
||||
<li class="item flexrow">
|
||||
<label class="derivee-label" for="system.compteurs.experience.value">Stress transformé</label>
|
||||
{{#if options.vueDetaillee}}
|
||||
<input type="number" name="system.compteurs.experience.value" value="{{system.compteurs.experience.value}}" data-dtype="number" size="3"/>
|
||||
<input class="derivee-value" type="number" name="system.compteurs.experience.value" value="{{system.compteurs.experience.value}}" data-dtype="number" size="3"/>
|
||||
{{else}}
|
||||
<label name="system.compteurs.experience.value">{{system.compteurs.experience.value}}</label>
|
||||
{{/if}}
|
||||
@ -13,18 +13,7 @@
|
||||
<span class="generic-label">Total XP compétences</span>
|
||||
<span class="competence-value">{{calc.competenceXPTotal}}</span>
|
||||
</li>
|
||||
{{#if calc.comptageArchetype}}
|
||||
<li><hr></li>
|
||||
<li>Niveaux d'archétype à répartir</li>
|
||||
{{#each calc.comptageArchetype as |archetype key|}}
|
||||
{{#if (gt archetype.reste 0)}}
|
||||
<li class="item flexrow">
|
||||
<label class="generic-label">Reste {{archetype.reste}} niveaux {{numberFormat archetype.niveau decimals=0 sign=true}} sur {{archetype.nombreMax}}</label>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
<li> </li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -1,14 +1,18 @@
|
||||
<h3>Journal d'Experience</h3>
|
||||
<div class="form-group large-editor">
|
||||
<ul class="item-list alterne-list">
|
||||
{{#each system.experiencelog as |xp key|}}
|
||||
{{#each system.experiencelog as |xplog key|}}
|
||||
<li class="experiencelog flexrow list-item" data-key="{{key}}">
|
||||
<label class="flex-grow">{{xp.valeur}} {{xp.raison}}</label>
|
||||
<label class="flex-shrink">{{xp.mode}}</label>
|
||||
<label class="flex-shrink">{{xp.daterdd}}</label>
|
||||
<label class="flex-shrink">{{xp.datereel}}</label>
|
||||
<label class="flex-shrink">{{xplog.valeur}} {{experienceLog-topic xplog.mode}} </label>
|
||||
{{#if (or xplog.from xplog.to)}}
|
||||
<label class="flex-grow">{{xplog.raison}}: de {{xplog.from}} à {{xplog.to}}</label>
|
||||
{{else}}
|
||||
<label class="flex-grow">{{xplog.raison}}</label>
|
||||
{{/if}}
|
||||
<label class="flex-shrink">{{xplog.daterdd}}</label>
|
||||
<label class="flex-shrink">{{xplog.datereel}}</label>
|
||||
{{#if @root.options.isGM}}
|
||||
<span>
|
||||
<span class="flex-shrink">
|
||||
<a class="experiencelog-delete" title="Supprimer">
|
||||
<i class="fas fa-trash"></i>
|
||||
</a>
|
||||
|
@ -1,47 +0,0 @@
|
||||
<div id="calendar-time-container">
|
||||
<div class="calendar">
|
||||
<div class="calendar-title" title="Deplacer">{{jourDuMois}} {{mois.label}} ({{mois.saison}})</div>
|
||||
<div class="calendar-options">
|
||||
{{#if isGM}}
|
||||
<i class="calendar-set-datetime fa-solid fa-calendar-pen" title="Editer"></i>
|
||||
<i class="calendar-astrologie fa-solid fa-moon-over-sun" title="Astrologie"></i>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="calendar-avance-heure">
|
||||
<div class="calendar-avance-heure-grid">
|
||||
{{#if isGM}}
|
||||
<i class="calendar-btn calendar-1min" data-calendar-avance="1" title="Avancer de 1 minute">+1</i>
|
||||
<i class="calendar-btn calendar-5min" data-calendar-avance="5" title="Avancer de 5 minutes">+5</i>
|
||||
<i class="calendar-btn calendar-15min" data-calendar-avance="15" title="Avancer de 15 minutes">+15</i>
|
||||
<i class="calendar-btn calendar-30min" data-calendar-avance="30" title="Avancer de 30 minutes">+30</i>
|
||||
<i class="calendar-btn calendar-60min" data-calendar-avance="60" title="Avancer de 60 minutes" >+60</i>
|
||||
<i class="calendar-btn calendar-1heure" data-calendar-avance="120" title="Avancer d'1 heure" >+1h</i>
|
||||
{{else}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="calendar-affiche-heure">
|
||||
<div class="calendar-horloge">
|
||||
<a class="ajout-chronologie">
|
||||
<img class="calendar-heure-img" src="{{heure.icon}}" alt="{{nomHeure}}"/>
|
||||
<span class="calendar-heure-texte">{{heure.label}}</span>
|
||||
</a>
|
||||
{{#if isGM}}
|
||||
<p class="calendar-minute-texte">{{minute}} minutes</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="calendar-change-heure">
|
||||
<div class="calendar-change-heure-grid">
|
||||
{{#if isGM}}
|
||||
<i class="calendar-btn calendar-lyre fas fa-forward" data-calendar-set="6" title="Avancer à Lyre">
|
||||
<img src="systems/foundryvtt-reve-de-dragon/icons/heures/hd07.svg" alt="Avancer à Lyre"/>
|
||||
</i>
|
||||
<i class="calendar-btn calendar-vaisseau fas fa-forward" data-calendar-set="0" title="Avancer au Vaisseau">
|
||||
<img src="systems/foundryvtt-reve-de-dragon/icons/heures/hd01.svg" alt="Avancer au Vaisseau"/>
|
||||
</i>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -5,5 +5,6 @@
|
||||
<div>{{alias}} souffre de Blessure(s) Grave(s) : n'oubliez pas de faire un Jet de Vie toutes les SC ({{SConst}}) minutes. Un point d'Endurance a été retiré automatiquement.</div>
|
||||
{{/if}}
|
||||
{{#if isCritique}}
|
||||
<div>{{alias}} souffre d'une <strong>Blessure Critique</strong> : faites un <a id="chat-jet-vie" data-actorId="{{actorId}}">Jet de Vie.<a></div>
|
||||
<div>{{alias}} souffre d'une <strong>Blessure Critique</strong> : faites un
|
||||
<a id="chat-jet-vie" class="chat-card-button" data-actorId="{{actorId}}">Jet de Vie.<a></div>
|
||||
{{/if}}
|
17
templates/chat-demande-declencher-sort.hbs
Normal file
17
templates/chat-demande-declencher-sort.hbs
Normal file
@ -0,0 +1,17 @@
|
||||
<p>
|
||||
Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête de Dragon
|
||||
({{#if tete.reserveSecurite}}Réserve en sécurité{{/if}}
|
||||
{{~#if tete.reserveExtensible}}{{#if tete.reserveSecurite}}, {{/if~}}
|
||||
Réserve extensible
|
||||
{{~/if}}), vous pouvez contrôler le déclenchement. Cliquez sur le sort que vous souhaitez déclencher en {{coord}} - {{caseTmr-label coord}}:
|
||||
</p>
|
||||
<ul>
|
||||
{{#each sorts as |sort|}}
|
||||
<li>
|
||||
<a class="chat-card-button declencher-sort-reserve" data-actor-id="{{actor.id}}" data-tmr-coord="{{sort.system.coord}}" data-sort-id="{{sort.id}}">
|
||||
{{sort.name}} (r{{sort.system.ptreve}})
|
||||
</a>
|
||||
{{#if sort.system.heurecible }} HN {{timestamp-imgSigneHeure sort.system.heurecible}}{{/if}}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
8
templates/chat-empoignade-entrainer-sol.html
Normal file
8
templates/chat-empoignade-entrainer-sol.html
Normal file
@ -0,0 +1,8 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attacker.name}} a entraîné {{defender.name}} au sol
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
L'empoignade peut continuer.
|
||||
</div>
|
16
templates/chat-empoignade-entrainer.html
Normal file
16
templates/chat-empoignade-entrainer.html
Normal file
@ -0,0 +1,16 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attacker.name}} a empoigné {{defender.name}}
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
<span class='chat-card-button-area'>
|
||||
{{attacker.name}} vient d'obtenir 2 points d'Emp, et peut
|
||||
entraîner {{defender.name}} au sol. Les deux protagonistes
|
||||
restent empoignés.
|
||||
<br>
|
||||
<a class='empoignade-entrainer-sol chat-card-button'>
|
||||
Entraîner au sol
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
35
templates/chat-empoignade-immobilise.html
Normal file
35
templates/chat-empoignade-immobilise.html
Normal file
@ -0,0 +1,35 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attacker.name}} a empoigné {{defender.name}}
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
<span class='chat-card-button-area'>
|
||||
<p>
|
||||
{{attacker.name}} a obtenu 2 points d'Emp à la fin du round précédent, et peut:
|
||||
|
||||
<ul><li>
|
||||
faire perdre des points d'Endurance à {{defender.name}}
|
||||
<br>
|
||||
<a class='empoignade-perte-endurance chat-card-button'>
|
||||
<select class='empoignade-perte-endurance'>
|
||||
<option value="none">Faire perdre de l'endurance (selectionnez)</option>
|
||||
<option value="end0">Endurance à 0</option>
|
||||
<option value="end1">Endurance à 1</option>
|
||||
<option value="endmoitie">La moitié de l'endurance</option>
|
||||
<option value="endquart">Le quart de l'endurance</option>
|
||||
</select>
|
||||
</a>
|
||||
{{#if empoignade.system.ausol}}
|
||||
{{else}}
|
||||
</li><li>
|
||||
projeter {{defender.name}} au sol. Les deux protagonistes ne sont plus empoignés.
|
||||
<br>
|
||||
<a class='empoignade-projeter-sol chat-card-button'>
|
||||
Projeter au sol
|
||||
</a>
|
||||
{{/if}}
|
||||
</li></ul>
|
||||
</p>
|
||||
</span>
|
||||
</div>
|
8
templates/chat-empoignade-perte-endurance.html
Normal file
8
templates/chat-empoignade-perte-endurance.html
Normal file
@ -0,0 +1,8 @@
|
||||
<img class="chat-icon" src="{{competence.img}}" />
|
||||
<h4>
|
||||
{{attacker.name}} a fait perdre de l'endurance à {{defender.name}}
|
||||
</h4>
|
||||
<hr>
|
||||
<div>
|
||||
{{defender.name}} reste immobilisé. L'empoignade peut continuer.
|
||||
</div>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user