Compare commits

...

39 Commits

Author SHA1 Message Date
6de4fff403 Merge pull request 'v11.0.15 - L'apprentissage de Khrachtchoum' (#666) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #666
2023-08-03 09:10:32 +02:00
3543f081b2 Version 11.0.15 2023-08-03 00:41:16 +02:00
56f14e12a2 Fix: regression sur les particulières
L'utilisation de la méthode clone() pôur cloner la compétence
supprime l'id de la compétence, du coup l'update pour y
ajouter de l'expérience ne marchait plus et bloquait la suite de la
résolution (pas de messages dans le tchat, ...)
2023-08-03 00:41:16 +02:00
e226af5ac5 Merge pull request 'v11.0.14' (#665) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #665
2023-07-30 09:25:10 +02:00
d8be37a2ec v11.0.14 2023-07-29 23:47:08 +02:00
ba2d9de7b6 Version 11.0.13
Les pincettes de Khrachtchoum le Problémeux
- Correction du calcul de la place restante lors de l'ajout dans un conteneur
2023-07-29 23:44:56 +02:00
6b8fb3267a Fix: calcul de la place dans un conteneur
Correction de l'ajout dans un conteneur, en faisant un calcul arrondi
pour éviter les problèmes de virgule flotante
2023-07-29 23:42:22 +02:00
05d6f64a31 Merge pull request 'v11.0.13 - La multiplication de l'eau de Khrachtchoum le Problémeux' (#664) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #664
2023-07-28 10:11:26 +02:00
c0570e58b4 Version 11.0.13 2023-07-27 19:21:48 +02:00
8389d578bc Fix: achat d'objet illimités
Lors de l'achat à un commerce avec une quantité illimité, on était
tout de même limité à la quantité de l'objet, même si elle n'était
pas diminuée
2023-07-27 19:17:57 +02:00
f05ef79b97 Merge pull request 'v11.0.12 - Les poids de la mesure de Khrachtchoum le Problémeux' (#663) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #663
2023-07-14 00:36:37 +02:00
d2a8bfae4f v11.0.12 - Les poids de la mesure
- Correction des malus de surencombrement
- Le malus armure est correctement affiché dans l'onglet des
  caractéristiques
2023-07-13 01:02:03 +02:00
d54834fa71 Amélioration des messages d'art 2023-07-13 01:02:03 +02:00
c898bf5212 Merge pull request 'Encombrement et malus armure' (#661) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #661
2023-07-11 14:46:14 +02:00
a118dc7334 Correction sur-Encombrement v2
Le malus appliqué est maintenant correct.

Avant, le malus pouvait avoir une virgule, et donc être arrondi
dans le malus vraiment appliqué même si affiché correctement.
2023-07-11 02:53:34 +02:00
46401e5d63 Cleanup: simplification _computeFinalLevel
méthode supprimée dasn RdDRoll (car basée sur les ajustements),
pas utile ici non plus.
2023-07-11 02:36:39 +02:00
7eb1d9f838 Fix affichage Malus Armure
Le malus armure est correctement affiché dans l'onglet caractéristiques.

Il n'est plus stocké dans l'acteur mais calculé.
2023-07-11 02:36:39 +02:00
1d8f4ebb88 Merge pull request 'Fix: sélection de compendiums que pour le MJ' (#660) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #660
2023-07-09 11:09:28 +02:00
145a92f462 Fix: sélection de compendiums que pour le MJ 2023-07-07 00:47:05 +02:00
5148d02314 Correction sur arrondi sur-encombrement 2023-07-01 21:28:18 +02:00
000c89b11a Merge pull request 'V11.0.11 - Les bleus de Khrachtchoum le Problémeux' (#659) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #659
2023-06-25 09:48:17 +02:00
5d4a18aac5 Version 11.0.11 2023-06-24 23:59:25 +02:00
34b5df637f Notifier le joueur qu'il peut passer sa nuit
Lorsque le MJ configure la nuit des personnages, une notification est
envoyée aux joueurs pour leur dire de gérer leur nuit.
2023-06-24 23:50:05 +02:00
22572ca98c Support des armes non mortelles 2023-06-24 23:40:07 +02:00
a6a1c1009e Merge pull request 'v11.0.10 - Les Songes de Khrachtchoum le Problémeux' (#658) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #658
2023-06-24 09:22:24 +02:00
288cf9162c Version v11.0.10 2023-06-24 01:48:34 +02:00
4b1381e535 Decompte des heure en cas de réveil
Si le gardien gère la durée des nuits, en cas de rêve de dragon,
les heures restant à dormir sont mises à jour.
2023-06-24 01:41:12 +02:00
78336a3f45 Fix: affichage sommeil avec RdD première heure
Le message ne s'affichait pas en cas de rêve de dragon dès la
première récupération
2023-06-24 01:19:54 +02:00
3001ae44de Endurance limitée en cas d'insomnie 2023-06-24 01:19:54 +02:00
a43ceb3188 Fix: lire depuis un livre 2023-06-24 01:19:54 +02:00
9e95a44efd Fix: click pour se déplacer dans les TMR 2023-06-24 01:19:54 +02:00
179ea0c85b Fix: selection de TMR des signes draconiques 2023-06-24 01:19:53 +02:00
3821b5bea1 Merge pull request 'v11.0.9 - Les Souvenirs de Khrachtchoum le Problémeux' (#657) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #657
2023-06-21 10:40:17 +02:00
2739c650d9 Version 11.0.9 - Les Souvenirs de Khrachtchoum 2023-06-20 23:43:59 +02:00
b101d58bee Correction typo "optionnelle" 2023-06-20 23:43:58 +02:00
0e3d721fc7 Nouvelle incarnation de l'archétype 2023-06-20 23:35:38 +02:00
e1e45a83be Correction titre des fenêtres Item 2023-06-20 23:35:38 +02:00
3b14e54829 Mode de saisie d'archétype 2023-06-20 23:35:38 +02:00
615a3f1315 Organisation des règles optionelles 2023-06-20 03:05:48 +02:00
46 changed files with 501 additions and 369 deletions

View File

@ -1,5 +1,39 @@
# v11.0
## 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

View File

@ -7,7 +7,7 @@ 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";
@ -33,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,
});
}
@ -56,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;
@ -114,7 +116,7 @@ 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;
@ -353,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;

View File

@ -18,7 +18,7 @@ import { RdDAlchimie } from "./rdd-alchimie.js";
import { STATUSES, StatusEffects } from "./settings/status-effects.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { RdDItemSigneDraconique } from "./item/signedraconique.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { Draconique } from "./tmr/draconique.js";
import { RdDCarac } from "./rdd-carac.js";
@ -95,7 +95,6 @@ export class RdDActor extends RdDBaseActor {
this.computeIsHautRevant();
await this.cleanupConteneurs();
await this.computeEncTotal();
await this.computeMalusArmure();
}
/* -------------------------------------------- */
@ -134,7 +133,7 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
getFatigueActuelle() {
if (ReglesOptionelles.isUsing("appliquer-fatigue") && this.isPersonnage()) {
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && this.isPersonnage()) {
return this.system.sante.fatigue?.value;
}
return 0;
@ -218,7 +217,12 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
getMalusArmure() {
return Misc.toInt(this.system.attributs?.malusarmure?.value)
if (this.isPersonnage()) {
return this.itemTypes[TYPES.armure].filter(it => it.system.equipe)
.map(it => it.system.malus)
.reduce(Misc.sum(), 0);
}
return 0;
}
/* -------------------------------------------- */
@ -261,7 +265,7 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
getDraconicList() {
return this.items.filter(it => it.isCompetencePersonnage() && it.system.categorie == 'draconic')
return this.itemTypes[TYPES.competence].filter(it => it.system.categorie == 'draconic')
}
/* -------------------------------------------- */
getBestDraconic() {
@ -271,13 +275,13 @@ export class RdDActor extends RdDBaseActor {
}
getDraconicOuPossession() {
const possession = this.items.filter(it => it.type == TYPES.competencecreature && it.system.categorie == 'possession')
const possession = this.itemTypes[TYPES.competencecreature].filter(it => it.system.categorie == 'possession')
.sort(Misc.descending(it => it.system.niveau))
.find(it => true);
if (possession) {
return possession.clone();
return possession;
}
const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0).map(it => it.clone()),
const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0),
POSSESSION_SANS_DRACONIC]
.sort(Misc.descending(it => it.system.niveau));
return draconics[0];
@ -387,6 +391,14 @@ export class RdDActor extends RdDBaseActor {
await this.distribuerStress('stress', consigne.stress.valeur, consigne.stress.motif);
}
await this.update({ 'system.sommeil': consigne.sommeil })
const player = this.findPlayer();
if (player) {
ChatUtility.notifyUser(player.id, 'info', `Vous pouvez gérer la nuit de ${this.name}`);
}
}
findPlayer() {
return game.users.players.find(player => player.active && player.character?.id == this.id);
}
async onTimeChanging(oldTimestamp, newTimestamp) {
@ -457,7 +469,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async dormirChateauDormant() {
if (!ReglesOptionelles.isUsing("chateau-dormant-gardien") || !this.system.sommeil || this.system.sommeil.nouveaujour) {
if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !this.system.sommeil || this.system.sommeil.nouveaujour) {
const message = {
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
content: ""
@ -621,21 +633,22 @@ export class RdDActor extends RdDBaseActor {
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
content: this.name + ': '
};
await this.recupereEndurance(message);
if (this.system.sommeil?.insomnie || heures == 0) {
const insomnie = this.system.sommeil?.insomnie || heures == 0;
await this.recupereEndurance({ message: message, demi: insomnie });
if (insomnie) {
message.content += 'Vous ne trouvez pas le sommeil';
}
else {
let jetsReve = [];
let dormi = await this.dormirDesHeures(jetsReve, message, heures, options);
message.content += `Vous dormez ${dormi.heures <= 1 ? 'une heure' : (dormi.heures + ' heures')}. `;
if (jetsReve.length > 0) {
message.content += `Vous récupérez ${jetsReve.filter(it => it >= 0).reduce(Misc.joining("+"))} Points de rêve. `;
message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '(dragon)' : it).reduce(Misc.joining("+"))} Points de rêve. `;
}
if (dormi.etat == 'eveil') {
message.content += 'Vous êtes réveillé par un Rêve de Dragon.'
await this.reveilReveDeDragon(message, dormi.heures);
}
options.chateauDormant = options.chateauDormant && dormi.heures >= heures;
message.content += `Vous avez dormi ${dormi.heures <= 1 ? 'une heure' : (dormi.heures + ' heures')}. `;
}
if (!options.grisReve) {
@ -649,6 +662,14 @@ export class RdDActor extends RdDBaseActor {
}
}
async reveilReveDeDragon(message, heures) {
message.content += 'Vous êtes réveillé par un Rêve de Dragon.';
const restant = Math.max(this.system.sommeil?.heures - heures, 0)
if (restant > 0) {
await this.update({ 'system.sommeil': { heures: restant } });
}
}
async dormirDesHeures(jetsReve, message, heures, options) {
const dormi = { heures: 0, etat: 'dort' };
for (; dormi.heures < heures && dormi.etat == 'dort'; dormi.heures++) {
@ -702,8 +723,13 @@ export class RdDActor extends RdDBaseActor {
}
/* -------------------------------------------- */
async recupereEndurance(message) {
const manquant = this._computeEnduranceMax() - this.system.sante.endurance.value;
async recupereEndurance({ message, demi }) {
let max = this._computeEnduranceMax();
if (demi) {
max = Math.floor(max / 2);
}
const manquant = max - this.system.sante.endurance.value;
if (manquant > 0) {
await this.santeIncDec("endurance", manquant);
message.content += `Vous récuperez ${manquant} points d'endurance. `;
@ -712,7 +738,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async recupererFatigue(message) {
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
let fatigue = this.system.sante.fatigue.value;
const fatigueMin = this._computeFatigueMin();
if (fatigue <= fatigueMin) {
@ -1092,7 +1118,7 @@ export class RdDActor extends RdDBaseActor {
case 'entite': case 'vehicule':
return 0;
}
return Math.min(0, this.getEncombrementMax() - Math.ceil(Number(this.getEncTotal())));
return Math.min(0, Math.floor(this.getEncombrementMax() - this.encTotal));
}
getMessageSurEncombrement() {
@ -1120,20 +1146,6 @@ export class RdDActor extends RdDBaseActor {
}
}
/* -------------------------------------------- */
async computeMalusArmure() {
if (this.isPersonnage()) {
const malusArmure = this.filterItems(it => it.type == 'armure' && it.system.equipe)
.map(it => it.system.malus ?? 0)
.reduce(Misc.sum(), 0);
// Mise à jour éventuelle du malus armure
if (this.system.attributs?.malusarmure?.value != malusArmure) {
await this.updateAttributeValue("malusarmure", malusArmure);
}
}
}
/* -------------------------------------------- */
computeResumeBlessure() {
const blessures = this.filterItems(it => it.system.gravite > 0, 'blessure')
@ -1178,7 +1190,7 @@ export class RdDActor extends RdDBaseActor {
}
// Pour les autres
let state = Math.min(this.system.sante.vie.value - this.system.sante.vie.max, 0);
if (ReglesOptionelles.isUsing("appliquer-fatigue") && this.system.sante.fatigue) {
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && this.system.sante.fatigue) {
state += RdDUtility.currentFatigueMalus(this.system.sante.fatigue.value, this.system.sante.endurance.max);
}
// Ajout de l'éthylisme
@ -1395,9 +1407,9 @@ export class RdDActor extends RdDBaseActor {
await this.deleteEmbeddedDocuments('Item', obsoletes);
}
async $finDeRoundEmpoignade(){
async $finDeRoundEmpoignade() {
const immobilisations = this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id);
immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this,
immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this,
game.actors.get(emp.system.empoigneid),
emp
))
@ -1505,7 +1517,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async santeIncDec(name, inc, isCritique = false) {
if (name == 'fatigue' && !ReglesOptionelles.isUsing("appliquer-fatigue")) {
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
return;
}
const sante = duplicate(this.system.sante)
@ -1547,7 +1559,7 @@ export class RdDActor extends RdDBaseActor {
}
compteur.value = result.newValue;
// If endurance lost, then the same amount of fatigue cannot be recovered
if (ReglesOptionelles.isUsing("appliquer-fatigue") && sante.fatigue && fatigue > 0) {
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && sante.fatigue && fatigue > 0) {
sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this._computeFatigueMin());
}
await this.update({ "system.sante": sante })
@ -1706,6 +1718,7 @@ export class RdDActor extends RdDBaseActor {
await this.rollTache(tache.id);
}
}
async actionHerbe(item, onActionItem = async () => { }) {
if (item.isHerbeAPotion()) {
return DialogFabriquerPotion.create(this, item, onActionItem);
@ -2449,7 +2462,7 @@ export class RdDActor extends RdDBaseActor {
/* -------------------------------------------- */
async _tacheResult(rollData, options) {
// Mise à jour de la tache
rollData.appliquerFatigue = ReglesOptionelles.isUsing("appliquer-fatigue");
rollData.appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue");
rollData.tache = duplicate(rollData.tache);
rollData.tache.system.points_de_tache_courant += rollData.rolled.ptTache;
if (rollData.rolled.isETotal) {
@ -3230,7 +3243,7 @@ export class RdDActor extends RdDBaseActor {
return;
}
const attackerId = attacker?.id;
if (ReglesOptionelles.isUsing('validation-encaissement-gr') && !game.user.isGM) {
if (ReglesOptionnelles.isUsing('validation-encaissement-gr') && !game.user.isGM) {
RdDBaseActor.remoteActorCall({
actorId: this.id,
method: 'appliquerEncaissement',
@ -3243,7 +3256,7 @@ export class RdDActor extends RdDBaseActor {
async appliquerEncaissement(rollData, show, attackerId) {
const armure = await this.computeArmure(rollData);
if (ReglesOptionelles.isUsing('validation-encaissement-gr')) {
if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) {
DialogValidationEncaissement.validerEncaissement(this, rollData, armure, show, attackerId, (encaissement, show, attackerId) => this._appliquerEncaissement(encaissement, show, attackerId));
}
else {
@ -3830,5 +3843,39 @@ export class RdDActor extends RdDBaseActor {
content: `${this.name} a reçu un/une ${item.type}: ${item.name}, qui ${manualMessage ? "n'est pas" : "est"} géré(e) automatiquement. ${manualMessage ? manualMessage : ''}`
});
}
async nouvelleIncarnation() {
let incarnation = this.toObject();
incarnation.items = Array.from(this.items.filter(it => it.type == TYPES.competence),
it => {
it = it.toObject();
it.id = undefined;
it.system.niveau = it.system.base;
it.system.niveau_archetype = Math.max(it.system.niveau + (it.system.xp > 0 ? 1 : 0), it.system.niveau_archetype);
it.system.xp = 0;
it.system.xp_sort = 0;
it.system.default_diffLibre = 0;
return it;
});
incarnation.name = 'Réincarnation de ' + incarnation.name
incarnation.system = {
carac: duplicate(this.system.carac),
heure: RdDTimestamp.defHeure(await RdDDice.rollTotal("1dh", { rollMode: "selfroll", showDice: SHOW_DICE })).key,
age: 18,
biographie: '',
notes: '',
experiencelog: [],
'compteurs.experience.value': 3000,
'reve.seuil.value': this.system.carac.reve.value,
'reve.reve.value': this.system.carac.reve.value,
subacteurs: { suivants: [], montures: [], vehicules: [] },
}
incarnation = await RdDBaseActor.create(incarnation);
await incarnation.deleteEmbeddedDocuments('ActiveEffect', incarnation.getEmbeddedCollection("ActiveEffect").map(it => it.id));
await incarnation.remiseANeuf();
incarnation.sheet.render(true);
}
}

View File

@ -119,7 +119,7 @@ export class RdDBaseActor extends Actor {
}
listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); }
filterItems(filter, type = undefined) { return type ? this.itemTypes[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,7 +144,7 @@ export class RdDBaseActor extends Actor {
.forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp))
}
async creerObjetParMJ(object){
async creerObjetParMJ(object) {
if (!Misc.isUniqueConnectedGM()) {
RdDBaseActor.remoteActorCall({
actorId: this.id,
@ -262,10 +262,10 @@ export class RdDBaseActor extends Actor {
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} !`);
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 && !this.verifierQuantite(itemVendu, quantite)) {
if (vendeur && !vendeur.verifierQuantite(itemVendu, quantite)) {
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
return
}
@ -318,7 +318,7 @@ export class RdDBaseActor extends Actor {
}
verifierQuantite(item, quantiteDemande) {
const disponible = item?.getQuantite();
const disponible = this.getQuantiteDisponible(item);
return disponible == undefined || disponible >= quantiteDemande;
}
@ -447,62 +447,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 */

View File

@ -28,6 +28,7 @@ export class RdDCommerce extends RdDBaseActor {
verifierFortune(cout) {
return this.system.illimite || super.verifierFortune(cout);
}
async depenserSols(cout) {
if (this.system.illimite) {
return

View File

@ -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;
}

View File

@ -8,18 +8,18 @@ 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 },
];
/* -------------------------------------------- */
@ -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);
}
/* -------------------------------------------- */

View File

@ -5,7 +5,7 @@ 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";
@ -157,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());

View File

@ -395,6 +395,16 @@ export class RdDItem extends Item {
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':
@ -404,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()
}
@ -675,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()

View File

@ -1,6 +1,6 @@
import { RdDItem } from "../item.js";
import { Misc } from "../misc.js";
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
export class RdDItemArmure extends RdDItem {
@ -9,7 +9,7 @@ export class RdDItemArmure extends RdDItem {
}
deteriorerArmure(dmg) {
if (!ReglesOptionelles.isUsing('deteriorationArmure') || this.system.protection == '0') {
if (!ReglesOptionnelles.isUsing('deteriorationArmure') || this.system.protection == '0') {
return;
}
let deterioration = (this.system.deterioration ?? 0) + dmg;

View File

@ -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)}`)
: '';
}

View File

@ -9,7 +9,7 @@ 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";
@ -789,8 +789,7 @@ export class RdDCombat {
let rollData = {
passeArme: randomID(16),
mortalite: arme?.system.mortalite,
coupsNonMortels: false,
competence: competence.clone(),
competence: competence,
surprise: this.attacker.getSurprise(true),
surpriseDefenseur: this.defender.getSurprise(true),
targetToken: Targets.extractTokenData(this.target),
@ -1045,10 +1044,10 @@ export class RdDCombat {
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,
attackerRoll: attackerRoll,
competence: this.defender.getCompetence(competenceParade).clone(),
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: {}
@ -1126,7 +1125,7 @@ export class RdDCombat {
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,
attackerRoll: attackerRoll,
competence: competence.clone(),
competence: competence,
surprise: this.defender.getSurprise(true),
surpriseDefenseur: this.defender.getSurprise(true),
carac: this.defender.system.carac,
@ -1166,7 +1165,7 @@ export class RdDCombat {
/* -------------------------------------------- */
async computeDeteriorationArme(defenderRoll) {
if (!ReglesOptionelles.isUsing('resistanceArmeParade')) {
if (!ReglesOptionnelles.isUsing('resistanceArmeParade')) {
return;
}
const attackerRoll = defenderRoll.attackerRoll;
@ -1215,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,
@ -1230,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) {

View File

@ -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();
}
}

View File

@ -4,7 +4,7 @@ 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 { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { TYPES } from "./item.js";
/* -------------------------------------------- */
@ -181,7 +181,7 @@ export class RdDEmpoignade {
let rollData = {
mode, empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetence("Corps à corps").clone(),
competence: attacker.getCompetence("Corps à corps"),
selectedCarac: attacker.system.carac.melee,
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
}
@ -210,7 +210,7 @@ export class RdDEmpoignade {
mode: "immobilise",
empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetence("Corps à corps").clone()
competence: attacker.getCompetence("Corps à corps")
}
const msg = await ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(attacker.name),
@ -272,7 +272,7 @@ export class RdDEmpoignade {
mode, attacker, defender, empoignade, attackerRoll,
diffLibre: attackerRoll.diffLibre,
attaqueParticuliere: attackerRoll.particuliere,
competence: defender.getCompetence(competenceName).clone(),
competence: defender.getCompetence(competenceName),
surprise: defender.getSurprise(true),
carac: defender.system.carac,
selectedCarac: defender.system.carac[carac],

View File

@ -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";
@ -186,7 +186,7 @@ export class SystemReveDeDragon {
RdDCalendrier.init();
SystemCompendiums.init();
DialogChronologie.init();
ReglesOptionelles.init();
ReglesOptionnelles.init();
RdDUtility.init();
RdDDice.init();
RdDCommands.init();

View File

@ -39,7 +39,7 @@ export class RdDPossession {
let rollData = {
mode: "attaque",
isECNIDefender: false,
competence: competence.clone(),
competence: competence,
possession: possession,
attacker: attacker,
defender: defender,

View File

@ -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
@ -126,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;
}

View File

@ -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();

View File

@ -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);
@ -319,7 +317,7 @@ export class RdDRoll extends Dialog {
// 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;

View File

@ -12,7 +12,7 @@ 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";
@ -55,7 +55,7 @@ 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();
@ -207,7 +207,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
@ -227,7 +227,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);
@ -263,7 +263,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>";
}
@ -367,7 +367,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;
@ -451,7 +451,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);
@ -906,7 +906,7 @@ export class RdDTMRDialog extends Dialog {
if (this.viewOnly) {
return;
}
let clickOddq = RdDTMRDialog._computeEventOddq(event.data.originalEvent);
let clickOddq = RdDTMRDialog._computeEventOddq(event.nativeEvent);
await this._onClickTMRPos(clickOddq); // Vérifier l'état des compteurs reve/fatigue/vie
}
@ -1004,7 +1004,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();

View File

@ -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";
@ -121,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',
@ -179,24 +180,25 @@ 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-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',
@ -278,7 +280,7 @@ 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));
@ -478,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: '' };
@ -554,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;
@ -571,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) {
@ -624,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));

View File

@ -7,7 +7,7 @@ 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.
@ -86,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()
},
@ -164,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)
}
/* -------------------------------------------- */

View File

@ -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();
}
}

View 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();
}
}

View File

@ -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
})
}

View File

@ -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),

View File

@ -6,7 +6,7 @@ import { RdDDice } from "../rdd-dice.js";
import { Misc } from "../misc.js";
import { DialogChronologie } from "../dialog-chronologie.js";
import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "../constants.js";
import { ReglesOptionelles } from "../settings/regles-optionelles.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";
@ -305,7 +305,7 @@ 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;

View File

@ -156,7 +156,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);

View File

@ -287,6 +287,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));
@ -1898,34 +1908,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;

View File

@ -1,8 +1,8 @@
{
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "11.0.8",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.8.zip",
"version": "11.0.15",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.15.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": {

View File

@ -393,12 +393,6 @@
"label": "Encombrement",
"derivee": true
},
"malusarmure": {
"type": "number",
"value": 0,
"label": "Malus Armure",
"derivee": true
},
"protection": {
"type": "number",
"value": 0,
@ -594,7 +588,8 @@
"iscombat": false,
"isnaturelle": true,
"ispossession": false,
"dommages": 0
"dommages": 0,
"mortalite": "mortel"
},
"empoignade": {
"templates": ["description"],
@ -671,6 +666,7 @@
"resistance": 0,
"categorie_parade": "",
"dommages": "0",
"mortalite": "mortel",
"penetration": 0,
"force": "0",
"competence": "",

View File

@ -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}}
&nbsp;&nbsp;
{{#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,6 +93,11 @@
{{> "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}}

View 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>

View File

@ -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>

View File

@ -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>

View File

@ -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>&nbsp;</li>
</ul>
</div>

View File

@ -1,14 +1,14 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<h4>
{{alias}} tente de chanter : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} {{#if rolled.isSuccess}}chante{{else}}tente de chanter{{/if}} {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
<div>
{{#if rolled.isSuccess}}
{{alias}} réussi son interprétation avec une qualité de {{qualiteFinale}} .
{{alias}} réussit son interprétation avec une qualité de {{qualiteFinale}} .
{{else}}
{{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}.
{{alias}} manque d'inspiration, son interprétation a une qualité de {{qualiteFinale}}.
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>

View File

@ -1,14 +1,14 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<h4>
{{alias}} tente de danser : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} {{#if rolled.isSuccess}}danse{{else}}tente de danser{{/if}} {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
<div>
{{#if rolled.isSuccess}}
{{alias}} réussi son interprétation avec une qualité de {{qualiteFinale}} .
{{alias}} réussit son interprétation avec une qualité de {{qualiteFinale}} .
{{else}}
{{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}.
{{alias}} manque d'inspiration, son interprétation a une qualité de {{qualiteFinale}}.
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>

View File

@ -1,6 +1,6 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<h4>
{{alias}} tente de jouer le morceau : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} {{#if rolled.isSuccess}}interprete{{else}}tente de jouer{{/if}} le morceau : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>
@ -8,7 +8,7 @@
{{#if rolled.isSuccess}}
{{alias}} réussit son interprétation avec une qualité de {{qualiteFinale}} .
{{else}}
{{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}.
{{alias}} manque d'inspiration, son interprétation a une qualité de {{qualiteFinale}}.
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>

View File

@ -7,9 +7,9 @@
<hr>
<div>
{{#if rolled.isSuccess}}
{{alias}} réussi son interprétation avec une qualité de {{qualiteFinale}} .
{{alias}} réussit son interprétation avec une qualité de {{qualiteFinale}} .
{{else}}
{{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}.
{{alias}} manque d'inspiration, son interprétation a une qualité de {{qualiteFinale}}.
{{/if}}
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html"}}
</div>

View File

@ -1,6 +1,6 @@
<img class="chat-icon" src="{{competence.img}}" alt="{{oeuvre.system.competence}}" />
<h4>
{{alias}} tente de cuisiner la recette : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
{{alias}} {{#if rolled.isSuccess}}réalise{{else}}tente de cuisiner{{/if}} la recette : {{oeuvre.name}} (niveau {{oeuvre.system.niveau}})
</h4>
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}}
<hr>

View File

@ -54,7 +54,7 @@
<label>Empoignade</label>
{{else}}
<span>
<input class="attribute-value" type="checkbox" name="coupsNonMortels" {{#unless (eq mortalite 'mortel')}}checked{{/unless}} />
<input class="attribute-value" type="checkbox" name="motalite" {{#unless (eq mortalite 'mortel')}}checked{{/unless}} />
<label class="dmg-arme-actor"></label>
</span>
{{/if}}

View File

@ -0,0 +1,3 @@
<option value="mortel">Mortel</option>
<option value="non-mortel">Non mortel</option>
<option value="empoignade">Empoignade</option>

View File

@ -37,6 +37,14 @@
<label for="system.dommages">Dommages </label>
<input class="attribute-value" type="text" name="system.dommages" value="{{system.dommages}}" data-dtype="String"/>
</div>
<div class="form-group">
<label for="system.mortalite">Mortalité</label>
<select name="system.mortalite" data-dtype="String">
{{#select system.mortalite}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-mortalite.html"}}
{{/select}}
</select>
</div>
<div class="form-group">
<label for="system.resistance">Résistance </label>
<input class="attribute-value" type="text" name="system.resistance" value="{{system.resistance}}" data-dtype="Number"/>

View File

@ -27,6 +27,14 @@
<label for="niveau">Dommages (+dom)</label>
<input class="attribute-value" type="text" name="system.dommages" value="{{system.dommages}}" data-dtype="Number"/>
</div>
<div class="form-group">
<label for="system.mortalite">Mortalité</label>
<select name="system.mortalite" data-dtype="String">
{{#select system.mortalite}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-mortalite.html"}}
{{/select}}
</select>
</div>
{{/if}}
{{#if isparade}}
<div class="form-group">