Compare commits

...

33 Commits

Author SHA1 Message Date
599fdc752d Fix naming + charset 2024-09-27 13:44:56 +02:00
fa890491e5 Fix wrong object import 2024-09-27 13:41:30 +02:00
80435b6bca Fix wrong object import 2024-09-27 13:21:42 +02:00
1a476bd5bc Fix wrong object import 2024-09-27 13:20:29 +02:00
8d6c4565a9 Merge pull request 'v12.0.9 - Le scriptorium d'Astrobazzarh' (#711) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #711
2024-09-27 10:16:54 +02:00
6819f1c2f5 Correction du mapping
- gestion des armes une/deux mains/lancées
- dommages des armes une/deux mains
- correction de la voie de draconic
- correction des bonus de cases
- correction des retours à la ligne
2024-09-27 02:36:54 +02:00
43607afc12 Correction du parser des bonus de case 2024-09-27 02:33:01 +02:00
538cf5bdbf Extraction des calculs de dommages
Préparation pour le Mapping des armes
2024-09-27 02:32:13 +02:00
75507f3eca Fix deprecation 2024-09-27 02:30:48 +02:00
a622814295 Amélioration message tchat de tirage 2024-09-26 00:55:37 +02:00
2aa8fcb980 Amélioration export voies draconiques 2024-09-26 00:55:08 +02:00
a65326d658 Version 12.0.9
Export format csv
2024-09-25 23:43:04 +02:00
b6a203b82a Export vers un fichier csv 2024-09-25 23:43:04 +02:00
7e8f642d87 Export csv pour Scriptarium
Activable dans les options avancées du système
Un menu contextuel permet d'écrire dans les logs
2024-09-25 23:43:04 +02:00
91be2761f5 Passage html -> hbs 2024-09-25 23:43:03 +02:00
2ac39e3428 Ajout de la taille (manquante) 2024-09-25 23:43:03 +02:00
a162001ba4 Cleanup 2024-09-25 23:43:03 +02:00
52e1f9dfbf Rename TYPES en ITEM_TYPES
Pour ajouter les ACTOR_TYPES
2024-09-25 23:43:03 +02:00
c586a90690 Merge pull request 'Version 12.0.8 - La quincaillerie d'Astrobazzarh' (#710) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #710
2024-09-06 15:14:23 +02:00
16e40b0ed8 12.0.8 - La quincaillerie d'Astrobazzarh
- le propriétaire est indiqué dans les feuilles d'équipements/
   compétences/...
- Ecaille d'efficacité
  - l'écaille d'efficacité est prise en compte même si on n'utilise
     pas le ciblage en combat
  - l'écaille d'efficacité est prise en compte pour l'initiative
- Corrections
  - l'état général est pris en compte pour les initiatives
  - le tooltip de l'initiative affiche correctement l'initiative
2024-09-06 00:49:39 +02:00
427a950954 L'initiative utilise l'écaille d'efficacité 2024-09-06 00:47:32 +02:00
a7b20bdd35 Ecaille d'efficacité sans cible
L'écaille d'efficacité est prise en compte si on n'utilise pas
l'automatisation de combat avec une cible
2024-09-06 00:45:49 +02:00
3b18e0b919 Ajout du propriétaire sur les Items 2024-09-05 23:54:02 +02:00
ff8a5d7ba3 Fix tooltip initiative 2024-09-05 23:54:02 +02:00
3aa8c0f0af Fix weapon in the HUD 2024-09-01 20:39:25 +02:00
8d9f09c18c Fix warnings 2024-09-01 20:22:52 +02:00
9d654246c2 Merge pull request '12.0.7 - La propriété d'Astrobazzarh' (#709) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #709
2024-09-01 20:21:04 +02:00
111fac2b2d Amélioration dialogue voyage
- le changement de terrain change l'affichage de compétences
- le total de fatigue est affiché (ajustement + base)
2024-09-01 20:13:09 +02:00
3e99265125 Version 12.0.7 - La propriété d'Astrobazzarh
- correction des opérations faites à la création d'un Item:
  - la durée des queues/rencontres/souffles
  - les effets draconiques d'un souffle/queue
  - mise à jour des points de tâche des blessures lors des soins
- pas d'expérience sur les particulières quand aucun MJ n'est connecté
- Le drag&drop d'un acteur depuis la liste des acteurs sur la fiche
  d'une entité incarnée permet d'accorder le personnage
- Les messages pour résister aux possessions/conjuration sont envoyées
  au défenseur
- Les messages pour résister aux empoignades sont envoyées au défenseur
2024-08-31 00:59:26 +02:00
28878b74fc Fix: demandes au défenseur
Les demandes de résistance pour les possessions sont envoyées au
défenseur

Les demlandes de défense contre une empoignade dont envoyées au
 défenseur
2024-08-31 00:58:58 +02:00
ba8276ef37 Possibilité d'accorder un personnage
Le drag&drop d'un acteur depuis la liste des acteurs sur la fiche
d'une entité incarnée permet d'accorder le personnage
2024-08-31 00:21:24 +02:00
b9e8c24461 Pas d'expérience si le MJ n'est pas connecté
Pour éviter les jets de dés abusifs quand le MJ n'est pas là,
les réussites particulières ne rapportent plus d'expérience
lorsque le MJ n'est pas connecté
2024-08-30 23:56:20 +02:00
8754ea9f5f Fix hook sur creation
Correction des Hooks qui font des calculs à la création d'un item.

- document instanceof Document est false pour un Actor
- le tri des users ne marche pas sur foundry 12
- mise à jour des blessures lors des soins

Correction de la détermination du MJ connecté permettant de nouveau:
- jets de dés quand aucun MJ n'est connecté
- affichage de l'horloge
2024-08-30 23:54:06 +02:00
49 changed files with 1147 additions and 472 deletions

View File

@ -1,4 +1,29 @@
# 12.0 # 12.0
## 12.0.9 - Le scriptorium d'Astrobazzarh
- ajout d'une fonction avancée pour exporter les personnages dans un format csv
## 12.0.8 - La quincaillerie d'Astrobazzarh
- le propriétaire est indiqué dans les feuilles d'équipements/compétences/...
- Ecaille d'efficacité
- l'écaille d'efficacité est prise en compte même si on n'utilise pas le ciblage en combat
- l'écaille d'efficacité est prise en compte pour l'initiative
- Corrections
- l'état général est pris en compte pour les initiatives
- le tooltip de l'initiative affiche correctement l'initiative
## 12.0.7 - La propriété d'Astrobazzarh
- correction des opérations faites à la création d'un Item:
- la durée des queues/rencontres/souffles
- les effets draconiques d'un souffle/queue
- mise à jour des points de tâche des blessures lors des soins
- pas d'expérience sur les particulières quand aucun MJ n'est connecté
- Le drag&drop d'un acteur depuis la liste des acteurs sur la fiche
d'une entité incarnée permet d'accorder le personnage
- Les messages pour résister aux possessions/conjuration sont envoyées
au défenseur
- Les messages pour résister aux empoignades sont envoyées au défenseur
- la commande /voyage affiche maintenant le total de fatigue pour chaque voyageur
- la commande /voyage affiche maintenant les compétences liées au terrain
## 12.0.6 - Le bazar d'Astrobazzarh ## 12.0.6 - Le bazar d'Astrobazzarh
- Corrections de l'inventaire en bazar: - Corrections de l'inventaire en bazar:

View File

@ -32,7 +32,7 @@ import { RdDItemBlessure } from "./item/blessure.js";
import { AppAstrologie } from "./sommeil/app-astrologie.js"; import { AppAstrologie } from "./sommeil/app-astrologie.js";
import { RdDEmpoignade } from "./rdd-empoignade.js"; import { RdDEmpoignade } from "./rdd-empoignade.js";
import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js"; import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js";
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
import { RdDBaseActorSang } from "./actor/base-actor-sang.js"; import { RdDBaseActorSang } from "./actor/base-actor-sang.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js"; import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js";
@ -92,7 +92,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
canReceive(item) { canReceive(item) {
return ![TYPES.competencecreature, TYPES.tarot, TYPES.service].includes(item.type) return ![ITEM_TYPES.competencecreature, ITEM_TYPES.tarot, ITEM_TYPES.service].includes(item.type)
} }
isPersonnageJoueur() { isPersonnageJoueur() {
@ -125,7 +125,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
getMalusArmure() { getMalusArmure() {
return this.itemTypes[TYPES.armure].filter(it => it.system.equipe) return this.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe)
.map(it => it.system.malus) .map(it => it.system.malus)
.reduce(Misc.sum(), 0); .reduce(Misc.sum(), 0);
} }
@ -142,7 +142,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
getDemiReve() { return this.system.reve.tmrpos.coord } getDemiReve() { return this.system.reve.tmrpos.coord }
getDraconicList() { return this.itemTypes[TYPES.competence].filter(it => it.system.categorie == 'draconic') } getDraconicList() { return this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == 'draconic') }
getBestDraconic() { return foundry.utils.duplicate(this.getDraconicList().sort(Misc.descending(it => it.system.niveau)).find(it => true)) } getBestDraconic() { return foundry.utils.duplicate(this.getDraconicList().sort(Misc.descending(it => it.system.niveau)).find(it => true)) }
getDraconicOuPossession() { getDraconicOuPossession() {
return [...this.getDraconicList().filter(it => it.system.niveau >= 0), return [...this.getDraconicList().filter(it => it.system.niveau >= 0),
@ -153,7 +153,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async $perteRevePotionsEnchantees() { async $perteRevePotionsEnchantees() {
let potions = this.itemTypes[TYPES.potion] let potions = this.itemTypes[ITEM_TYPES.potion]
.filter(it => Grammar.includesLowerCaseNoAccent(it.system.categorie, 'enchanté') && !it.system.prpermanent) .filter(it => Grammar.includesLowerCaseNoAccent(it.system.categorie, 'enchanté') && !it.system.prpermanent)
const potionUpdates = await Promise.all(potions.map(async it => { const potionUpdates = await Promise.all(potions.map(async it => {
@ -345,7 +345,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _recupererBlessures(message, isMaladeEmpoisonne) { async _recupererBlessures(message, isMaladeEmpoisonne) {
const timestamp = game.system.rdd.calendrier.getTimestamp() const timestamp = game.system.rdd.calendrier.getTimestamp()
const blessures = this.filterItems(it => it.system.gravite > 0, TYPES.blessure).sort(Misc.ascending(it => it.system.gravite)) const blessures = this.filterItems(it => it.system.gravite > 0, ITEM_TYPES.blessure).sort(Misc.ascending(it => it.system.gravite))
await Promise.all(blessures.map(async b => b.recuperationBlessure({ await Promise.all(blessures.map(async b => b.recuperationBlessure({
actor: this, actor: this,
@ -361,7 +361,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _recupererVie(message, isMaladeEmpoisonne) { async _recupererVie(message, isMaladeEmpoisonne) {
const tData = this.system const tData = this.system
let blessures = this.filterItems(it => it.system.gravite > 0, TYPES.blessure); let blessures = this.filterItems(it => it.system.gravite > 0, ITEM_TYPES.blessure);
if (blessures.length > 0) { if (blessures.length > 0) {
return return
} }
@ -636,7 +636,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async sortMisEnReserve(sort, draconic, coord, ptreve) { async sortMisEnReserve(sort, draconic, coord, ptreve) {
await this.createEmbeddedDocuments("Item", [{ await this.createEmbeddedDocuments("Item", [{
type: TYPES.sortreserve, type: ITEM_TYPES.sortreserve,
name: sort.name, name: sort.name,
img: sort.img, img: sort.img,
system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' } system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' }
@ -991,24 +991,24 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
buildTMRInnaccessible() { buildTMRInnaccessible() {
return this.items.filter(it => it.type == TYPES.casetmr).filter(it => EffetsDraconiques.isInnaccessible(it)).map(it => it.system.coord) return this.items.filter(it => it.type == ITEM_TYPES.casetmr).filter(it => EffetsDraconiques.isInnaccessible(it)).map(it => it.system.coord)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getRencontresTMR() { getRencontresTMR() {
return this.itemTypes[TYPES.rencontre]; return this.itemTypes[ITEM_TYPES.rencontre];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async deleteRencontreTMRAtPosition() { async deleteRencontreTMRAtPosition() {
const rencontreIds = this.itemTypes[TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id) const rencontreIds = this.itemTypes[ITEM_TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id)
if (rencontreIds.length > 0) { if (rencontreIds.length > 0) {
await this.deleteEmbeddedDocuments('Item', rencontreIds) await this.deleteEmbeddedDocuments('Item', rencontreIds)
} }
} }
getRencontreTMREnAttente() { getRencontreTMREnAttente() {
return this.itemTypes[TYPES.rencontre].find(this.filterRencontreTMRDemiReve()) return this.itemTypes[ITEM_TYPES.rencontre].find(this.filterRencontreTMRDemiReve())
} }
filterRencontreTMRDemiReve() { filterRencontreTMRDemiReve() {
@ -1160,11 +1160,11 @@ export class RdDActor extends RdDBaseActorSang {
if (result) { return result } if (result) { return result }
switch (item.type) { switch (item.type) {
case TYPES.potion: return await this.consommerPotion(item, onActionItem); case ITEM_TYPES.potion: return await this.consommerPotion(item, onActionItem);
case TYPES.livre: return await this.actionLire(item); case ITEM_TYPES.livre: return await this.actionLire(item);
case TYPES.conteneur: return await item.sheet.render(true); case ITEM_TYPES.conteneur: return await item.sheet.render(true);
case TYPES.herbe: return await this.actionHerbe(item, onActionItem); case ITEM_TYPES.herbe: return await this.actionHerbe(item, onActionItem);
case TYPES.queue: case TYPES.ombre: return await this.actionRefoulement(item); case ITEM_TYPES.queue: case ITEM_TYPES.ombre: return await this.actionRefoulement(item);
} }
return undefined return undefined
} }
@ -1548,6 +1548,9 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { async appliquerAjoutExperience(rollData, hideChatMessage = 'show') {
if (!Misc.firstConnectedGM()){
return
}
hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM)
let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence, rollData.jetResistance); let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence, rollData.jetResistance);
if (xpData.length) { if (xpData.length) {
@ -1556,7 +1559,7 @@ export class RdDActor extends RdDBaseActorSang {
xpData xpData
}) })
if (hideChatMessage) { if (hideChatMessage) {
ChatUtility.blindMessageToGM({ content: content }); ChatUtility.blindMessageToGM({ content: content })
} }
else { else {
ChatMessage.create({ ChatMessage.create({
@ -1599,7 +1602,7 @@ export class RdDActor extends RdDBaseActorSang {
computeDraconicAndSortIndex(sortList) { computeDraconicAndSortIndex(sortList) {
let draconicList = this.getDraconicList(); let draconicList = this.getDraconicList();
for (let sort of sortList) { for (let sort of sortList) {
let draconicsSort = this.getDraconicsSort(draconicList, sort).map(it => it.name); let draconicsSort = RdDItemSort.getDraconicsSort(draconicList, sort).map(it => it.name);
for (let index = 0; index < draconicList.length && sort.system.listIndex == undefined; index++) { for (let index = 0; index < draconicList.length && sort.system.listIndex == undefined; index++) {
if (draconicsSort.includes(draconicList[index].name)) { if (draconicsSort.includes(draconicList[index].name)) {
sort.system.listIndex = index; sort.system.listIndex = index;
@ -1609,19 +1612,6 @@ export class RdDActor extends RdDBaseActorSang {
return draconicList; return draconicList;
} }
/* -------------------------------------------- */
getDraconicsSort(draconicList, sort) {
//console.log(draconicList, bestDraconic, draconic, voie);
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
case "lecture d'aura":
case "detection d'aura":
return draconicList;
case "annulation de magie":
return draconicList.filter(it => !RdDItemCompetence.isThanatos(it));
}
return [RdDItemCompetence.getVoieDraconic(draconicList, sort.system.draconic)];
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollUnSort(coord) { async rollUnSort(coord) {
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
@ -1823,7 +1813,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
blessuresASoigner() { blessuresASoigner() {
return (this.itemTypes[TYPES.blessure]) return (this.itemTypes[ITEM_TYPES.blessure])
.filter(it => it.system.gravite > 0 && it.system.gravite <= 6) .filter(it => it.system.gravite > 0 && it.system.gravite <= 6)
.filter(it => !(it.system.premierssoins.done && it.system.soinscomplets.done)) .filter(it => !(it.system.premierssoins.done && it.system.soinscomplets.done))
.sort(Misc.descending(b => (b.system.premierssoins.done ? "A" : "B") + b.system.gravite)) .sort(Misc.descending(b => (b.system.premierssoins.done ? "A" : "B") + b.system.gravite))
@ -3062,7 +3052,7 @@ export class RdDActor extends RdDBaseActorSang {
async nouvelleIncarnation() { async nouvelleIncarnation() {
let incarnation = this.toObject(); let incarnation = this.toObject();
incarnation.items = Array.from(this.items.filter(it => it.type == TYPES.competence), incarnation.items = Array.from(this.items.filter(it => it.type == ITEM_TYPES.competence),
it => { it => {
it = it.toObject(); it = it.toObject();
it.id = undefined; it.id = undefined;

View File

@ -12,7 +12,7 @@ import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
import { RdDBaseActor } from "./base-actor.js"; import { RdDBaseActor } from "./base-actor.js";
import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
import { StatusEffects } from "../settings/status-effects.js"; import { StatusEffects } from "../settings/status-effects.js";
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { Targets } from "../targets.js"; import { Targets } from "../targets.js";
import { RdDPossession } from "../rdd-possession.js"; import { RdDPossession } from "../rdd-possession.js";
import { RdDCombat } from "../rdd-combat.js"; import { RdDCombat } from "../rdd-combat.js";
@ -108,14 +108,14 @@ export class RdDBaseActorReve extends RdDBaseActor {
async $finDeRoundSupprimerObsoletes() { async $finDeRoundSupprimerObsoletes() {
const obsoletes = [] const obsoletes = []
.concat(this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp <= 0)) .concat(this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp <= 0))
.concat(this.itemTypes[TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2)) .concat(this.itemTypes[ITEM_TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2))
.map(it => it.id); .map(it => it.id);
await this.deleteEmbeddedDocuments('Item', obsoletes); 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); const immobilisations = this.itemTypes[ITEM_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), game.actors.get(emp.system.empoigneid),
emp emp
@ -151,13 +151,13 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
getPossession(possessionId) { getPossession(possessionId) {
return this.itemTypes[TYPES.possession].find(it => it.system.possessionid == possessionId); return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId);
} }
getPossessions() { getPossessions() {
return this.itemTypes[TYPES.possession]; return this.itemTypes[ITEM_TYPES.possession];
} }
getEmpoignades() { getEmpoignades() {
return this.itemTypes[TYPES.empoignade]; return this.itemTypes[ITEM_TYPES.empoignade];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -318,11 +318,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollCompetence(idOrName, options = { tryTarget: true }) { async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) {
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
const competence = this.getCompetence(idOrName); const competence = this.getCompetence(idOrName);
let rollData = { carac: this.system.carac, competence: competence } let rollData = { carac: this.system.carac, competence: competence, arme: options.arme }
if (competence.type == TYPES.competencecreature) { if (competence.type == ITEM_TYPES.competencecreature) {
const arme = RdDItemCompetenceCreature.armeCreature(competence) const arme = RdDItemCompetenceCreature.armeCreature(competence)
if (arme && options.tryTarget && Targets.hasTargets()) { if (arme && options.tryTarget && Targets.hasTargets()) {
Targets.selectOneToken(target => { Targets.selectOneToken(target => {
@ -361,7 +361,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
* @returns * @returns
*/ */
rollArme(arme, categorieArme = "competence") { rollArme(arme, categorieArme = "competence") {
let compToUse = this.$getCompetenceArme(arme, categorieArme) const compToUse = this.$getCompetenceArme(arme, categorieArme)
if (!RdDItemArme.isArmeUtilisable(arme)) { if (!RdDItemArme.isArmeUtilisable(arme)) {
ui.notifications.warn(`Arme inutilisable: ${arme.name} a une résistance de 0 ou moins`) ui.notifications.warn(`Arme inutilisable: ${arme.name} a une résistance de 0 ou moins`)
return return
@ -375,7 +375,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
title: 'Ne pas utiliser les automatisation de combat', title: 'Ne pas utiliser les automatisation de combat',
buttonLabel: "Pas d'automatisation", buttonLabel: "Pas d'automatisation",
onAction: async () => { onAction: async () => {
this.rollCompetence(compToUse, { tryTarget: false }) this.rollCompetence(compToUse, { tryTarget: false, arme: arme })
} }
}); });
return return
@ -396,19 +396,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
$getCompetenceArme(arme, competenceName) { $getCompetenceArme(arme, competenceName) {
switch (arme.type) { return RdDItemArme.getCompetenceArme(arme, competenceName)
case TYPES.competencecreature:
return arme.name
case TYPES.arme:
switch (competenceName) {
case 'competence': return arme.system.competence;
case 'unemain': return RdDItemArme.competence1Mains(arme);
case 'deuxmains': return RdDItemArme.competence2Mains(arme);
case 'tir': return arme.system.tir;
case 'lancer': return arme.system.lancer;
}
}
return undefined
} }
verifierForceMin(item) { verifierForceMin(item) {
@ -508,8 +496,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
isEntiteAccordee(attacker) { return true } isEntiteAccordee(attacker) { return true }
async setEntiteReveAccordee(attacker) { async setEntiteReveAccordee(actor) {
ui.notifications.error("Impossible de s'accorder à " + this.name + ": ce n'est pas une entite de cauchemer/rêve"); ui.notifications.error("Impossible de s'accorder à " + this.name + ": ce n'est pas une entité incarnée");
} }
} }

View File

@ -1,7 +1,7 @@
import { MAX_ENDURANCE_FATIGUE, RdDUtility } from "../rdd-utility.js"; import { MAX_ENDURANCE_FATIGUE, RdDUtility } from "../rdd-utility.js";
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
import { STATUSES } from "../settings/status-effects.js"; import { STATUSES } from "../settings/status-effects.js";
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { RdDBaseActorReve } from "./base-actor-reve.js"; import { RdDBaseActorReve } from "./base-actor-reve.js";
import { RdDDice } from "../rdd-dice.js"; import { RdDDice } from "../rdd-dice.js";
import { RdDItemBlessure } from "../item/blessure.js"; import { RdDItemBlessure } from "../item/blessure.js";
@ -50,9 +50,9 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
isDead() { return this.system.sante.vie.value < -this.getSConst() } isDead() { return this.system.sante.vie.value < -this.getSConst() }
nbBlessuresLegeres() { return this.itemTypes[TYPES.blessure].filter(it => it.isLegere()).length } nbBlessuresLegeres() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isLegere()).length }
nbBlessuresGraves() { return this.itemTypes[TYPES.blessure].filter(it => it.isGrave()).length } nbBlessuresGraves() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isGrave()).length }
nbBlessuresCritiques() { return this.itemTypes[TYPES.blessure].filter(it => it.isCritique()).length } nbBlessuresCritiques() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isCritique()).length }
/* -------------------------------------------- */ /* -------------------------------------------- */
computeResumeBlessure() { computeResumeBlessure() {
@ -197,7 +197,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
} }
async supprimerBlessures(filterToDelete) { async supprimerBlessures(filterToDelete) {
const toDelete = this.filterItems(filterToDelete, TYPES.blessure) const toDelete = this.filterItems(filterToDelete, ITEM_TYPES.blessure)
.map(it => it.id); .map(it => it.id);
await this.deleteEmbeddedDocuments('Item', toDelete); await this.deleteEmbeddedDocuments('Item', toDelete);
} }

View File

@ -3,7 +3,7 @@ import { Misc } from "../misc.js";
import { DialogSplitItem } from "../dialog-split-item.js"; import { DialogSplitItem } from "../dialog-split-item.js";
import { RdDSheetUtility } from "../rdd-sheet-utility.js"; import { RdDSheetUtility } from "../rdd-sheet-utility.js";
import { Monnaie } from "../item-monnaie.js"; import { Monnaie } from "../item-monnaie.js";
import { RdDItem, TYPES } from "../item.js"; import { RdDItem, ITEM_TYPES } from "../item.js";
import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -51,7 +51,7 @@ export class RdDBaseActorSheet extends ActorSheet {
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires); this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires); this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs); formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
formData.competences.filter(it => it.type == TYPES.competencecreature) formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature)
.forEach(it => it.isdommages = RdDItemCompetenceCreature.isDommages(it)) .forEach(it => it.isdommages = RdDItemCompetenceCreature.isDommages(it))
return formData; return formData;
} }

View File

@ -3,7 +3,7 @@ import { ChatUtility } from "../chat-utility.js";
import { SYSTEM_SOCKET_ID } from "../constants.js"; import { SYSTEM_SOCKET_ID } from "../constants.js";
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { Monnaie } from "../item-monnaie.js"; import { Monnaie } from "../item-monnaie.js";
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDAudio } from "../rdd-audio.js"; import { RdDAudio } from "../rdd-audio.js";
import { RdDConfirm } from "../rdd-confirm.js"; import { RdDConfirm } from "../rdd-confirm.js";
@ -542,7 +542,7 @@ export class RdDBaseActor extends Actor {
// Calculer le total actuel des contenus // Calculer le total actuel des contenus
const encContenu = dest.getEncContenu(); const encContenu = dest.getEncContenu();
const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet
const placeDisponible = Math.roundDecimals(dest.system.capacite - encContenu - newEnc, 4) const placeDisponible = Misc.keepDecimals(dest.system.capacite - encContenu - newEnc, 4)
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet // Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
if (placeDisponible < 0) { if (placeDisponible < 0) {
@ -704,7 +704,7 @@ export class RdDBaseActor extends Actor {
async actionPrincipale(item, onActionItem = async () => { }) { async actionPrincipale(item, onActionItem = async () => { }) {
switch (item.type) { switch (item.type) {
case TYPES.conteneur: return await item.sheet.render(true); case ITEM_TYPES.conteneur: return await item.sheet.render(true);
} }
return undefined return undefined
} }

View File

@ -1,5 +1,5 @@
import { ENTITE_INCARNE } from "../constants.js"; import { ENTITE_INCARNE } from "../constants.js";
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { STATUSES } from "../settings/status-effects.js"; import { STATUSES } from "../settings/status-effects.js";
import { RdDBaseActorSang } from "./base-actor-sang.js"; import { RdDBaseActorSang } from "./base-actor-sang.js";
@ -12,7 +12,7 @@ export class RdDCreature extends RdDBaseActorSang {
isCreature() { return true } isCreature() { return true }
canReceive(item) { canReceive(item) {
return item.type == TYPES.competencecreature || item.isInventaire(); return item.type == ITEM_TYPES.competencecreature || item.isInventaire();
} }
async remiseANeuf() { async remiseANeuf() {
@ -33,27 +33,4 @@ export class RdDCreature extends RdDBaseActorSang {
} }
} }
isEntiteAccordee(attacker) {
if (this.isEntite([ENTITE_INCARNE])) {
let resonnance = this.system.sante.resonnance
return (resonnance.actors.find(it => it == attacker.id))
}
return true
}
/* -------------------------------------------- */
async setEntiteReveAccordee(attacker) {
if (this.isEntite([ENTITE_INCARNE])) {
let resonnance = foundry.utils.duplicate(this.system.sante.resonnance);
if (resonnance.actors.find(it => it == attacker.id)) {
// déjà accordé
return;
}
await this.update({ "system.sante.resonnance": [...resonnance, attacker.id] });
}
else {
super.setEntiteReveAccordee(attacker)
}
}
} }

View File

@ -54,6 +54,12 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
}); });
} }
async _onDropActor(event, dragData) {
const dropActor = fromUuidSync(dragData.uuid)
await this.actor.setEntiteReveAccordee(dropActor)
super._onDropActor(event, dragData)
}
async deleteSubActeur(actorId) { async deleteSubActeur(actorId) {
let newResonances = this.actor.system.sante.resonnance.actors.filter(id => id != actorId); let newResonances = this.actor.system.sante.resonnance.actors.filter(id => id != actorId);
await this.actor.update({ 'system.sante.resonnance.actors': newResonances }, { renderSheet: false }); await this.actor.update({ 'system.sante.resonnance.actors': newResonances }, { renderSheet: false });

View File

@ -1,5 +1,5 @@
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js"; import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDEncaisser } from "../rdd-roll-encaisser.js"; import { RdDEncaisser } from "../rdd-roll-encaisser.js";
import { STATUSES } from "../settings/status-effects.js"; import { STATUSES } from "../settings/status-effects.js";
@ -12,7 +12,7 @@ export class RdDEntite extends RdDBaseActorReve {
} }
canReceive(item) { canReceive(item) {
return item.type == TYPES.competencecreature return item.type == ITEM_TYPES.competencecreature
} }
isEntite(typeentite = []) { isEntite(typeentite = []) {
@ -29,7 +29,7 @@ export class RdDEntite extends RdDBaseActorReve {
getChance() { return this.getReve() } getChance() { return this.getReve() }
getDraconicOuPossession() { getDraconicOuPossession() {
return this.itemTypes[TYPES.competencecreature] return this.itemTypes[ITEM_TYPES.competencecreature]
.filter(it => it.system.categorie == 'possession') .filter(it => it.system.categorie == 'possession')
.sort(Misc.descending(it => it.system.niveau)) .sort(Misc.descending(it => it.system.niveau))
.find(it => true); .find(it => true);
@ -67,7 +67,7 @@ export class RdDEntite extends RdDBaseActorReve {
if (this.isNonIncarnee()) { if (this.isNonIncarnee()) {
return return
} }
await RdDEncaisser.encaisser(this) await RdDEncaisser.encaisser(this)
} }
isEffectAllowed(effectId) { isEffectAllowed(effectId) {
@ -91,20 +91,16 @@ export class RdDEntite extends RdDBaseActorReve {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async setEntiteReveAccordee(attacker) { async setEntiteReveAccordee(actor) {
if (this.isEntite([ENTITE_INCARNE])) { if (this.isEntite([ENTITE_INCARNE])) {
let resonnance = foundry.utils.duplicate(this.system.sante.resonnance); if (this.system.sante.resonnance.actors.find(it => it == actor.id)) {
if (resonnance.actors.find(it => it == attacker.id)) {
// déjà accordé // déjà accordé
return; return
} }
resonnance.actors.push(attacker.id); await this.update({ "system.sante.resonnance.actors": [...this.system.sante.resonnance.actors, actor.id] })
await this.update({ "system.sante.resonnance": resonnance });
} }
else { else {
super.setEntiteReveAccordee(attacker) super.setEntiteReveAccordee(actor)
} }
} }
} }

View File

@ -0,0 +1,80 @@
import { ACTOR_TYPES } from "../../item.js"
import { Misc } from "../../misc.js"
import { EXPORT_CSV_SCRIPTARIUM, OptionsAvancees } from "../../settings/options-avancees.js"
import { Mapping } from "./mapping.js"
const IMG_SCRIPTARIUM = '<img class="context-menu-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/scriptarium.svg">'
export class ExportScriptarium {
static init() {
ExportScriptarium.INSTANCE = new ExportScriptarium()
}
constructor() {
this.mapping = Mapping.getMapping()
Hooks.on("getActorDirectoryFolderContext", (actorDirectory, menus) => { ExportScriptarium.INSTANCE.onActorDirectoryMenu(actorDirectory, menus) })
Hooks.on("getActorDirectoryEntryContext", (actorDirectory, menus) => { ExportScriptarium.INSTANCE.onActorDirectoryMenu(actorDirectory, menus) })
}
onActorDirectoryMenu(actorDirectory, menus) {
menus.push({
name: 'Export Personnages',
icon: IMG_SCRIPTARIUM,
condition: (target) => game.user.isGM &&
OptionsAvancees.isUsing(EXPORT_CSV_SCRIPTARIUM) &&
this.$getActors(actorDirectory, target).length > 0,
callback: target => this.exportActors(this.$getActors(actorDirectory, target), this.$getTargetName(actorDirectory, target))
})
}
$getTargetName(actorDirectory, target) {
const li = target.closest(".directory-item")
const folderId = li.data("folderId")
const actorId = li.data("documentId")
return actorId
? game.actors.get(actorId).name
: actorDirectory.folders.find(it => it.id == folderId).name
}
$getActors(actorDirectory, target) {
const li = target.closest(".directory-item")
const folderId = li.data("folderId")
const actorId = li.data("documentId")
const actors = actorId
? [game.actors.get(actorId)]
: folderId
? actorDirectory.folders.find(it => it.id == folderId).contents
: []
return actors.filter(it => it.type == ACTOR_TYPES.personnage)
}
exportActors(actors, targetName) {
const eol = '\n'
const header = Misc.join(this.getHeaderLine(), ';')
const actorLines = actors.map(actor => Misc.join(this.getActorLine(actor), ';'))
const data = Misc.join([header, ...actorLines], eol)
const filename = `scriptarium-${targetName?.slugify()}.csv`;
saveDataToFile(data, "text/csv;charset=utf-8", `${filename}`);
}
getHeaderLine() {
return this.mapping.map(it => it.column)
}
getActorLine(actor) {
const context = Mapping.prepareContext(actor)
return this.mapping.map(it => it.getter(actor, context))
//.map(it => JSON.stringify(it))
.map(it => this.$escapeQuotes(it))
.map(it => it.replaceAll("\n", " ").replaceAll("\r", ""))
}
$escapeQuotes(it) {
it = '' + it
if (it.includes('"') || it.includes(';')) {
return `"${it.replaceAll('"', '\\"')}"`
}
return it
}
}

View File

@ -0,0 +1,308 @@
import { Grammar } from "../../grammar.js"
import { RdDItemArme } from "../../item-arme.js"
import { RdDItemCompetence } from "../../item-competence.js"
import { RdDItemSort } from "../../item-sort.js"
import { ITEM_TYPES } from "../../item.js"
import { Misc } from "../../misc.js"
import { RdDTimestamp } from "../../time/rdd-timestamp.js"
import { RdDBonus } from "../../rdd-bonus.js"
const CATEGORIES_COMPETENCES = [
"generale",
"particuliere",
"specialisee",
"connaissance",
]
const CATEGORIES_DRACONIC = [
"draconic",
]
const CATEGORIES_COMBAT = [
"melee",
"tir",
"lancer"
]
const NIVEAU_BASE = {
"generale": -4,
"particuliere": -8,
"specialisee": -11,
"connaissance": -11,
"draconic": -11,
"melee": -6,
"tir": -8,
"lancer": -8,
}
class ColumnMappingFactory {
static createMappingArme(part, i) {
return { column: `arme-${part}-${i}`, getter: (actor, context) => Mapping.getArme(actor, context, part, i) }
}
static createMappingSort(part, i) {
return { column: `sort-${part}-${i}`, getter: (actor, context) => Mapping.getSort(actor, context, part, i) }
}
}
const NB_ARMES = 10
const NB_SORTS = 20
const TABLEAU_ARMES = [...Array(NB_ARMES).keys()]
const TABLEAU_SORTS = [...Array(NB_SORTS).keys()]
const MAPPING_BASE = [
{ column: "ID", getter: (actor, context) => actor.id },
{ column: "name", getter: (actor, context) => actor.name },
// { column: "biographie", getter: (actor, context) => actor.system.biographie },
{ column: "taille", getter: (actor, context) => actor.system.carac.taille.value },
{ column: "apparence", getter: (actor, context) => actor.system.carac.apparence.value },
{ column: "constitution", getter: (actor, context) => actor.system.carac.constitution.value },
{ column: "force", getter: (actor, context) => actor.system.carac.force.value },
{ column: "agilite", getter: (actor, context) => actor.system.carac.agilite.value },
{ column: "dexterite", getter: (actor, context) => actor.system.carac.dexterite.value },
{ column: "vue", getter: (actor, context) => actor.system.carac.vue.value },
{ column: "ouie", getter: (actor, context) => actor.system.carac.ouie.value },
{ column: "odoratgout", getter: (actor, context) => actor.system.carac.odoratgout.value },
{ column: "volonte", getter: (actor, context) => actor.system.carac.volonte.value },
{ column: "intellect", getter: (actor, context) => actor.system.carac.intellect.value },
{ column: "empathie", getter: (actor, context) => actor.system.carac.empathie.value },
{ column: "reve", getter: (actor, context) => actor.system.carac.reve.value },
{ column: "chance", getter: (actor, context) => actor.system.carac.chance.value },
{ column: "melee", getter: (actor, context) => actor.system.carac.melee.value },
{ column: "tir", getter: (actor, context) => actor.system.carac.tir.value },
{ column: "lancer", getter: (actor, context) => actor.system.carac.lancer.value },
{ column: "derobee", getter: (actor, context) => actor.system.carac.derobee.value },
{ column: "vie", getter: (actor, context) => actor.system.sante.vie.max },
{ column: "plusdom", getter: (actor, context) => actor.system.attributs.plusdom.value },
{ column: "protectionnaturelle", getter: (actor, context) => actor.system.attributs.protection.value },
{ column: "endurance", getter: (actor, context) => actor.system.sante.endurance.max },
{ column: "description", getter: (actor, context) => Mapping.getDescription(actor) },
{ column: "armure", getter: (actor, context) => Mapping.getArmure(actor, context) },
{ column: "protection", getter: (actor, context) => Mapping.getProtectionArmure(actor, context) },
{ column: "malus-armure", getter: (actor, context) => Mapping.getMalusArmure(actor, context) },
{ column: "esquive", getter: (actor, context) => Mapping.getEsquiveNiveau(context) },
{ column: "competences", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_COMPETENCES) },
{ column: "draconic", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_DRACONIC) },
]
const MAPPING_ARMES = TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('name', i))
.concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('niveau', i)))
.concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('init', i)))
.concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('dommages', i)))
const MAPPING_SORTS = TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('voie', i))
.concat(TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('description', i)))
.concat(TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('bonus', i)))
const MAPPING = MAPPING_BASE
.concat(MAPPING_ARMES)
.concat(MAPPING_SORTS)
export class Mapping {
static getMapping() {
return MAPPING
}
static prepareContext(actor) {
return {
armes: Mapping.prepareArmes(actor),
armure: Mapping.prepareArmure(actor),
esquive: Mapping.prepareEsquive(actor),
sorts: Mapping.prepareSorts(actor)
}
}
static prepareArmes(actor) {
const armes = actor.items.filter(it => it.type == ITEM_TYPES.arme)
return armes.map(arme =>
[
arme.system.tir != "" ? Mapping.prepareArme(actor, arme, 'tir') : undefined,
arme.system.lancer = "" ? Mapping.prepareArme(actor, arme, 'lancer') : undefined,
arme.system.unemain ? Mapping.prepareArme(actor, arme, 'unemain') : undefined,
arme.system.deuxmains ? Mapping.prepareArme(actor, arme, 'deuxmains') : undefined,
!(arme.system.unemain || arme.system.deuxmains) ? Mapping.prepareArme(actor, arme, 'competence') : undefined
]
.filter(it => it != undefined)
).reduce((a, b) => a.concat(b), [])
}
static prepareArme(actor, arme, maniement) {
const nameCompArme = RdDItemArme.getCompetenceArme(arme, maniement)
const competence = actor.getCompetence(nameCompArme)
if (RdDItemCompetence.isNiveauBase(competence)) {
return undefined
}
const dmgArme = RdDItemArme.dommagesReels(arme, maniement)
const dommages = dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme)
return {
name: arme.name,
niveau: Misc.toSignedString(competence.system.niveau),
init: Mapping.calculBaseInit(actor, competence.system.categorie) + competence.system.niveau,
dommages: Misc.toSignedString(dommages)
}
}
static calculBaseInit(actor, categorie) {
const mapping = MAPPING_BASE.find(it => it.column == categorie)
if (mapping) {
switch (categorie) {
case 'melee':
case 'tir':
case 'lancer':
const caracteristique = Number(actor.system.carac[categorie].value)
return Math.floor(caracteristique / 2)
}
}
return 0
}
static prepareArmure(actor) {
const armures = actor.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe)
if (armures.length > 1) {
console.warn(`${actor.name} a équipé ${armures.length} armures, seule la première sera considérée`)
}
if (armures.length > 0) {
const armure = armures[0]
return {
name: armure.name,
protection: armure.system.protection,
malus: armure.system.malus ?? 0
}
}
return {
name: '',
protection: actor.system.attributs.protection.value,
malus: 0
}
}
static prepareEsquive(actor) {
const esquives = actor.getCompetences("Esquive")
if (esquives.length > 0) {
const esquive = esquives[0]
return {
name: esquive.name,
niveau: Misc.toSignedString(esquive.system.niveau)
}
}
return undefined
}
static prepareSorts(actor) {
return actor.itemTypes[ITEM_TYPES.sort].map(it => Mapping.prepareSort(it))
}
static prepareSort(sort) {
return {
voie: RdDItemSort.getCodeDraconic(sort),
description: Mapping.descriptionSort(sort),
bonus: Mapping.bonusCase(sort)
}
}
static descriptionSort(sort) {
const ptSeuil = Array(sort.system.coutseuil).map(it => '*')
const caseTMR = sort.system.caseTMRspeciale.length > 0 ? sort.system.caseTMRspeciale : sort.system.caseTMR
return `${sort.name}${ptSeuil} (${caseTMR}) R${sort.system.difficulte} r${sort.system.ptreve}`
}
static bonusCase(sort) {
const list = RdDItemSort.bonuscaseStringToList(sort.system.bonuscase).sort(Misc.descending(it => it.bonus))
if (list.length > 0) {
const bonus = list[0]
return `+${bonus.bonus}% en ${bonus.case}`
}
return ''
}
static getDescription(actor) {
const sexe = actor.system.sexe
const sexeFeminin = sexe.length > 0 && sexe.charAt(0).toLowerCase() == 'f' ? 'Née' : 'Né'
const race = ['', 'humain'].includes(Grammar.toLowerCaseNoAccent(actor.system.race)) ? '' : (actor.system.race + ' ')
const heure = actor.system.heure
const hn = `${sexeFeminin} à l'heure ${RdDTimestamp.definition(heure).avecArticle}`
const age = actor.system.age ? `${actor.system.age} ans` : undefined
const taille = actor.system.taille
const poids = actor.system.poids
const cheveux = actor.system.cheveux ? `cheveux ${actor.system.cheveux}` : undefined
const yeux = actor.system.yeux ? `yeux ${actor.system.yeux}` : undefined
const beaute = actor.system.beaute ? `Beauté ${actor.system.beaute}` : undefined
const list = [race, hn, age, taille, poids, cheveux, yeux, beaute]
return Misc.join(list.filter(it => it), ', ')
}
static getArmure(actor, context) {
return context.armure?.name ?? ''
}
static getProtectionArmure(actor, context) {
return Number(context?.armure?.protection ?? 0) + Number(actor.system.attributs.protection.value)
}
static getMalusArmure(actor, context) {
return context?.armure?.malus ?? 0
}
static getEsquiveNiveau(context) {
if (context.esquive) {
const niveau = context.esquive.niveau + context.armure.malus
return niveau > 0 ? ('+' + niveau) : ('' + niveau)
}
return ''
}
static getCompetences(actor, categories) {
const competences = Mapping.getCompetencesCategorie(actor, categories)
if (competences.length == 0) {
return ''
}
const byCartegories = Mapping.competencesByCategoriesByNiveau(competences, categories)
const txtByCategories = Object.values(byCartegories)
.map(it => it.competencesParNiveau)
.map(byNiveau => {
const niveaux = Object.keys(byNiveau).map(it => Number(it)).sort(Misc.ascending())
if (niveaux.length == 0) {
return ''
}
const txtCategorieByNiveau = niveaux.map(niveau => {
const names = Misc.join(byNiveau[niveau].map(it => it.name).sort(Misc.ascending()), ', ')
return names + ' ' + Misc.toSignedString(niveau)
})
const txtCategorie = Misc.join(txtCategorieByNiveau, ' / ')
return txtCategorie
}).filter(it => it != '')
return Misc.join(txtByCategories, ' / ')
}
static competencesByCategoriesByNiveau(competences, categories) {
return categories.map(c => {
return {
categorie: c,
competencesParNiveau: Misc.classify(
competences.filter(comp => comp.system.categorie == c),
comp => comp.system.niveau)
}
})
}
static getArme(actor, context, part, numero) {
if (numero < context.armes.length) {
return context.armes[numero][part] ?? ''
}
return ''
}
static getCompetencesCategorie(actor, categories) {
return actor.itemTypes[ITEM_TYPES.competence]
.filter(it => categories.includes(it.system.categorie))
.filter(it => !RdDItemCompetence.isNiveauBase(it))
}
static getSort(actor, context, part, numero) {
if (numero < context.sorts.length) {
return context.sorts[numero][part]
}
return ''
}
}

View File

@ -1,5 +1,5 @@
import { RdDItemCompetenceCreature } from "./item-competencecreature.js" import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
import { RdDCombatManager } from "./rdd-combat.js"; import { RdDCombatManager } from "./rdd-combat.js";
const nomCategorieParade = { const nomCategorieParade = {
@ -20,19 +20,35 @@ const nomCategorieParade = {
export class RdDItemArme extends Item { export class RdDItemArme extends Item {
static isArme(item) { static isArme(item) {
return item.type == TYPES.arme || RdDItemCompetenceCreature.getCategorieAttaque(item); return item.type == ITEM_TYPES.arme || RdDItemCompetenceCreature.getCategorieAttaque(item);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getArme(arme) { static getArme(arme) {
switch (arme ? arme.type : '') { switch (arme ? arme.type : '') {
case TYPES.arme: return arme; case ITEM_TYPES.arme: return arme;
case TYPES.competencecreature: case ITEM_TYPES.competencecreature:
return RdDItemCompetenceCreature.armeCreature(arme); return RdDItemCompetenceCreature.armeCreature(arme);
} }
return RdDItemArme.mainsNues(); return RdDItemArme.mainsNues();
} }
static getCompetenceArme(arme, maniement) {
switch (arme.type) {
case ITEM_TYPES.competencecreature:
return arme.name
case ITEM_TYPES.arme:
switch (maniement) {
case 'competence': return arme.system.competence;
case 'unemain': return RdDItemArme.competence1Mains(arme);
case 'deuxmains': return RdDItemArme.competence2Mains(arme);
case 'tir': return arme.system.tir;
case 'lancer': return arme.system.lancer;
}
}
return undefined
}
static computeNiveauArmes(armes, competences) { static computeNiveauArmes(armes, competences) {
for (const arme of armes) { for (const arme of armes) {
arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences); arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
@ -68,14 +84,14 @@ export class RdDItemArme extends Item {
return armeData.system.categorie_parade; return armeData.system.categorie_parade;
} }
// pour compatibilité avec des personnages existants // pour compatibilité avec des personnages existants
if (armeData.type == TYPES.competencecreature || armeData.system.categorie == 'creature') { if (armeData.type == ITEM_TYPES.competencecreature || armeData.system.categorie == 'creature') {
return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : ''); return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '');
} }
if (!armeData.type.match(/arme|competencecreature/)) { if (!armeData.type.match(/arme|competencecreature/)) {
return ''; return '';
} }
if (armeData.system.competence == undefined) { if (armeData.system.competence == undefined) {
return TYPES.competencecreature; return ITEM_TYPES.competencecreature;
} }
let compname = armeData.system.competence.toLowerCase(); let compname = armeData.system.competence.toLowerCase();
if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return ''; if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return '';
@ -132,43 +148,46 @@ export class RdDItemArme extends Item {
return true; return true;
} }
/* -------------------------------------------- */ static dommagesReels(arme, maniement) {
static armeUneOuDeuxMains(armeData, aUneMain) { switch (maniement) {
if (armeData && !armeData.system.cac) { case 'tir':
armeData.system.unemain = armeData.system.unemain || !armeData.system.deuxmains; case 'lancer':
const uneOuDeuxMains = armeData.system.unemain && armeData.system.deuxmains; case 'competence':
const containsSlash = !Number.isInteger(armeData.system.dommages) && armeData.system.dommages.includes("/"); return Number(arme.system.dommages)
if (containsSlash) { // Sanity check
armeData = foundry.utils.duplicate(armeData);
const tableauDegats = armeData.system.dommages.split("/");
if (aUneMain)
armeData.system.dommagesReels = Number(tableauDegats[0]);
else // 2 mains
armeData.system.dommagesReels = Number(tableauDegats[1]);
}
else {
armeData.system.dommagesReels = Number(armeData.system.dommages);
}
if (uneOuDeuxMains != containsSlash) {
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + armeData.name + " ne sont pas corrects (ie sous la forme X/Y)");
}
} }
return armeData; if (arme.system.unemain && arme.system.deuxmains) {
const containsSlash = !Number.isInteger(arme.system.dommages) && arme.system.dommages.includes("/")
if (!containsSlash) {
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
return Number(arme.system.dommages)
}
const tableauDegats = arme.system.dommages.split("/");
return Number(tableauDegats[maniement == 'unemain' ? 0 : 1])
}
return Number(arme.system.dommages);
} }
static competence2Mains(arme) {
return arme.system.competence.replace(" 1 main", " 2 mains"); /* -------------------------------------------- */
static armeUneOuDeuxMains(arme, aUneMain) {
if (arme && !arme.system.cac) {
arme = foundry.utils.duplicate(arme);
arme.system.dommagesReels = RdDItemArme.dommagesReels(arme, aUneMain ? 'unemain' : 'deuxmains')
}
return arme;
} }
static competence1Mains(arme) { static competence1Mains(arme) {
return arme.system.competence.replace(" 2 mains", " 1 main"); return arme.system.competence.replace(" 2 mains", " 1 main");
} }
static competence2Mains(arme) {
return arme.system.competence.replace(" 1 main", " 2 mains");
}
static isArmeUtilisable(arme) { static isArmeUtilisable(arme) {
switch (arme.type) { switch (arme.type) {
case TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0) case ITEM_TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0)
case TYPES.competencecreature: return true case ITEM_TYPES.competencecreature: return true
} }
return false return false
} }
@ -180,11 +199,11 @@ export class RdDItemArme extends Item {
static corpsACorps(actor) { static corpsACorps(actor) {
let competence = actor?.getCompetenceCorpsACorps() ?? { system: { niveau: -6 } }; let competence = actor?.getCompetenceCorpsACorps() ?? { system: { niveau: -6 } };
let melee = actor? actor.system.carac['melee'].value : 0 let melee = actor ? actor.system.carac['melee'].value : 0
return { return {
_id: competence?.id, _id: competence?.id,
name: 'Corps à corps', name: 'Corps à corps',
type: TYPES.arme, type: ITEM_TYPES.arme,
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp', img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
system: { system: {
initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee), initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee),

View File

@ -1,5 +1,5 @@
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
import { RdDCombatManager } from "./rdd-combat.js"; import { RdDCombatManager } from "./rdd-combat.js";
const categories = { const categories = {
@ -54,7 +54,7 @@ export class RdDItemCompetenceCreature extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isCompetenceAttaque(item) { static isCompetenceAttaque(item) {
if (item.type == TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
case "melee": case "melee":
case "tir": case "tir":
@ -68,7 +68,7 @@ export class RdDItemCompetenceCreature extends Item {
} }
static getCategorieAttaque(item) { static getCategorieAttaque(item) {
if (item.type == TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
case "melee": case "melee":
case "tir": case "tir":
@ -82,7 +82,7 @@ export class RdDItemCompetenceCreature extends Item {
return undefined return undefined
} }
static isDommages(item) { static isDommages(item) {
if (item.type == TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
case "melee": case "melee":
case "tir": case "tir":
@ -94,7 +94,7 @@ export class RdDItemCompetenceCreature extends Item {
return false return false
} }
static isParade(item) { static isParade(item) {
if (item.type == TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
case "melee": case "melee":
case "naturelle": case "naturelle":

View File

@ -12,7 +12,7 @@ import { SystemCompendiums } from "./settings/system-compendiums.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
/** /**
* Extend the basic ItemSheet for RdD specific items * Extend the basic ItemSheet for RdD specific items
@ -53,7 +53,8 @@ export class RdDItemSheet extends ItemSheet {
} }
get title() { get title() {
return `${Misc.typeName('Item', this.item.type)}: ${this.item.name}`; const owner = (this.item.parent instanceof Actor) ? `(${this.item.parent.name})` : '';
return `${Misc.typeName('Item', this.item.type)}: ${this.item.name} ${owner}`;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -100,7 +101,7 @@ export class RdDItemSheet extends ItemSheet {
isComestible: this.item.getUtilisationCuisine(), isComestible: this.item.getUtilisationCuisine(),
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable), options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable),
} }
if (this.item.type == TYPES.competencecreature) { if (this.item.type == ITEM_TYPES.competencecreature) {
formData.isparade = RdDItemCompetenceCreature.isParade(this.item) formData.isparade = RdDItemCompetenceCreature.isParade(this.item)
formData.isdommages = RdDItemCompetenceCreature.isDommages(this.item) formData.isdommages = RdDItemCompetenceCreature.isDommages(this.item)
} }

View File

@ -1,9 +1,43 @@
import { Grammar } from "./grammar.js";
import { RdDItemCompetence } from "./item-competence.js";
import { ITEM_TYPES } from "./item.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
const VOIES_DRACONIC = [
{ code: 'O', label: "Voie d'Oniros", short: 'Oniros' },
{ code: 'H', label: "Voie d'Hypnos", short: 'Hypnos' },
{ code: 'N', label: "Voie de Narcos", short: 'Narcos' },
{ code: 'T', label: "Voie de Thanatos", short: 'Thanatos' },
{ code: 'O/H/N/T', label: "Oniros/Hypnos/Narcos/Thanatos", short: 'Oniros/Hypnos/Narcos/Thanatos' },
{ code: 'O/H/N', label: "Oniros/Hypnos/Narcos" }
]
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDItemSort extends Item { export class RdDItemSort extends Item {
static getDraconicsSort(draconicList, sort) {
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
case "lecture d'aura":
case "detection d'aura":
return draconicList;
case "annulation de magie":
return draconicList.filter(it => !RdDItemCompetence.isThanatos(it));
}
return [RdDItemCompetence.getVoieDraconic(draconicList, sort.system.draconic)];
}
static getCodeDraconic(sort) {
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
case "lecture d'aura":
case "detection d'aura":
return 'O/H/N/T'
case "annulation de magie":
return 'O/H/N'
}
const voie = VOIES_DRACONIC.find(it => it.label.includes(sort.system.draconic))
return voie?.code ?? sort.system.draconic
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static isDifficulteVariable(sort) { static isDifficulteVariable(sort) {
return sort && (sort.system.difficulte.toLowerCase() == "variable"); return sort && (sort.system.difficulte.toLowerCase() == "variable");
@ -31,9 +65,9 @@ export class RdDItemSort extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static buildBonusCaseList(bonuscase, newCase) { static buildBonusCaseList(bonuscase, newCase) {
const list = RdDItemSort._bonuscaseStringToList(bonuscase) const list = RdDItemSort.bonuscaseStringToList(bonuscase)
if (newCase) { if (newCase) {
return list.concat({ case: "Nouvelle", bonus: 0 }); list.push({ case: "Nouvelle", bonus: 0 })
} }
return list; return list;
} }
@ -44,7 +78,7 @@ export class RdDItemSort extends Item {
*/ */
static getBonusCaseList(item, newCase = false) { static getBonusCaseList(item, newCase = false) {
// Gestion spéciale case bonus // Gestion spéciale case bonus
if (item.type == 'sort') { if (item.type == ITEM_TYPES.sort) {
return RdDItemSort.buildBonusCaseList(item.system.bonuscase, newCase); return RdDItemSort.buildBonusCaseList(item.system.bonuscase, newCase);
} }
return undefined; return undefined;
@ -104,8 +138,11 @@ export class RdDItemSort extends Item {
.sort(Misc.ascending()) .sort(Misc.ascending())
.join(','); .join(',');
} }
static _bonuscaseStringToList(bonuscase) { static bonuscaseStringToList(bonuscase) {
return (bonuscase ?? '').split(',').map(it => { if (bonuscase == undefined || bonuscase == '') {
return []
}
return bonuscase.split(',').map(it => {
const b = it.split(':'); const b = it.split(':');
return { case: b[0], bonus: b[1] }; return { case: b[0], bonus: b[1] };
}); });

View File

@ -9,7 +9,15 @@ import { RdDRaretes } from "./item/raretes.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
export const TYPES = { export const ACTOR_TYPES = {
personnage: 'personnage',
creature: 'creature',
entite: 'entite',
commerce: 'commerce',
vehicule: 'vehicule'
}
export const ITEM_TYPES = {
competence: 'competence', competence: 'competence',
competencecreature: 'competencecreature', competencecreature: 'competencecreature',
empoignade: 'empoignade', empoignade: 'empoignade',
@ -56,33 +64,33 @@ export const TYPES = {
} }
const typesInventaireMateriel = [ const typesInventaireMateriel = [
TYPES.arme, ITEM_TYPES.arme,
TYPES.armure, ITEM_TYPES.armure,
TYPES.conteneur, ITEM_TYPES.conteneur,
TYPES.faune, ITEM_TYPES.faune,
TYPES.gemme, ITEM_TYPES.gemme,
TYPES.herbe, ITEM_TYPES.herbe,
TYPES.plante, ITEM_TYPES.plante,
TYPES.ingredient, ITEM_TYPES.ingredient,
TYPES.livre, ITEM_TYPES.livre,
TYPES.monnaie, ITEM_TYPES.monnaie,
TYPES.munition, ITEM_TYPES.munition,
TYPES.nourritureboisson, ITEM_TYPES.nourritureboisson,
TYPES.objet, ITEM_TYPES.objet,
TYPES.potion, ITEM_TYPES.potion,
] ]
const typesInventaire = { const typesInventaire = {
materiel: typesInventaireMateriel, materiel: typesInventaireMateriel,
all: ['service'].concat(typesInventaireMateriel), all: ['service'].concat(typesInventaireMateriel),
} }
const typesObjetsOeuvres = [TYPES.oeuvre, TYPES.recettecuisine, TYPES.musique, TYPES.chant, TYPES.danse, TYPES.jeu] const typesObjetsOeuvres = [ITEM_TYPES.oeuvre, ITEM_TYPES.recettecuisine, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.jeu]
const typesObjetsDraconiques = [TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.tete, TYPES.signedraconique, TYPES.sortreserve, TYPES.rencontre] const typesObjetsDraconiques = [ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.tete, ITEM_TYPES.signedraconique, ITEM_TYPES.sortreserve, ITEM_TYPES.rencontre]
const typesObjetsConnaissance = [TYPES.meditation, TYPES.recettealchimique, TYPES.sort] const typesObjetsConnaissance = [ITEM_TYPES.meditation, ITEM_TYPES.recettealchimique, ITEM_TYPES.sort]
const typesObjetsEffet = [TYPES.possession, TYPES.poison, TYPES.maladie, TYPES.blessure] const typesObjetsEffet = [ITEM_TYPES.possession, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.blessure]
const typesObjetsCompetence = [TYPES.competence, TYPES.competencecreature] const typesObjetsCompetence = [ITEM_TYPES.competence, ITEM_TYPES.competencecreature]
const typesObjetsTemporels = [TYPES.blessure, TYPES.poison, TYPES.maladie, TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.signedraconique, TYPES.rencontre] const typesObjetsTemporels = [ITEM_TYPES.blessure, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.signedraconique, ITEM_TYPES.rencontre]
const typesObjetsEquipable = [TYPES.arme, TYPES.armure, TYPES.objet]; const typesObjetsEquipable = [ITEM_TYPES.arme, ITEM_TYPES.armure, ITEM_TYPES.objet];
const typesEnvironnement = typesInventaireMateriel; const typesEnvironnement = typesInventaireMateriel;
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc 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 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
@ -141,12 +149,12 @@ export class RdDItem extends Item {
static isFieldInventaireModifiable(type, field) { static isFieldInventaireModifiable(type, field) {
switch (field) { switch (field) {
case 'quantite': case 'quantite':
if ([TYPES.conteneur].includes(type)) { if ([ITEM_TYPES.conteneur].includes(type)) {
return false; return false;
} }
break; break;
case 'cout': case 'cout':
if ([TYPES.monnaie].includes(type)) { if ([ITEM_TYPES.monnaie].includes(type)) {
return game.user.isGM; return game.user.isGM;
} }
break; break;
@ -195,15 +203,15 @@ export class RdDItem extends Item {
getUniteQuantite() { getUniteQuantite() {
switch (this.type) { switch (this.type) {
case TYPES.monnaie: return "(Pièces)" case ITEM_TYPES.monnaie: return "(Pièces)"
case TYPES.herbe: case ITEM_TYPES.herbe:
switch (this.system.categorie) { switch (this.system.categorie) {
case 'Alchimie': case 'Repos': case 'Soin': case 'Alchimie': case 'Repos': case 'Soin':
return "(Brins)" return "(Brins)"
case 'Cuisine': return ''; case 'Cuisine': return '';
} }
return ''; return '';
case TYPES.ingredient: return "(Pépins ou Brins)" case ITEM_TYPES.ingredient: return "(Pépins ou Brins)"
} }
return ''; return '';
} }
@ -212,13 +220,13 @@ export class RdDItem extends Item {
return typesObjetsEquipable.includes(this.type) return typesObjetsEquipable.includes(this.type)
} }
isCompetencePersonnage() { return this.type == TYPES.competence } isCompetencePersonnage() { return this.type == ITEM_TYPES.competence }
isCompetenceCreature() { return this.type == TYPES.competencecreature } isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature }
isConteneur() { return this.type == TYPES.conteneur; } isConteneur() { return this.type == ITEM_TYPES.conteneur; }
isMonnaie() { return this.type == TYPES.monnaie; } isMonnaie() { return this.type == ITEM_TYPES.monnaie; }
isPotion() { return this.type == TYPES.potion; } isPotion() { return this.type == ITEM_TYPES.potion; }
isNourritureBoisson() { return this.type == TYPES.nourritureboisson; } isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; }
isService() { return this.type == TYPES.service; } isService() { return this.type == ITEM_TYPES.service; }
isCompetence() { return typesObjetsCompetence.includes(this.type) } isCompetence() { return typesObjetsCompetence.includes(this.type) }
isEsquive() { isEsquive() {
@ -237,27 +245,27 @@ export class RdDItem extends Item {
return this.isCompetence() && ['melee', 'tir', 'lancer'].includes(this.system.categorie) return this.isCompetence() && ['melee', 'tir', 'lancer'].includes(this.system.categorie)
} }
isCompetencePossession() { return TYPES.competencecreature == this.type && this.system.categorie == "possession" } isCompetencePossession() { return ITEM_TYPES.competencecreature == this.type && this.system.categorie == "possession" }
isTemporel() { return typesObjetsTemporels.includes(this.type) } isTemporel() { return typesObjetsTemporels.includes(this.type) }
isOeuvre() { return typesObjetsOeuvres.includes(this.type) } isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) } isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
isQueueDragon() { return [TYPES.queue, TYPES.ombre].includes(this.type) } isQueueDragon() { return [ITEM_TYPES.queue, ITEM_TYPES.ombre].includes(this.type) }
isEffet() { return typesObjetsEffet.includes(this.type) } isEffet() { return typesObjetsEffet.includes(this.type) }
isConnaissance() { return typesObjetsConnaissance.includes(this.type) } isConnaissance() { return typesObjetsConnaissance.includes(this.type) }
isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); } isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); }
isBoisson() { return this.isNourritureBoisson() && this.system.boisson; } isBoisson() { return this.isNourritureBoisson() && this.system.boisson; }
isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; } isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
isHerbeAPotion() { return this.type == TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); } isHerbeAPotion() { return this.type == ITEM_TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
isBlessure() { return this.type == TYPES.blessure } isBlessure() { return this.type == ITEM_TYPES.blessure }
isPresentDansMilieux(milieux) { isPresentDansMilieux(milieux) {
return this.getEnvironnements(milieux).length > 0 return this.getEnvironnements(milieux).length > 0
} }
getCategories() { getCategories() {
switch (this.type) { switch (this.type) {
case TYPES.competence: return RdDItemCompetence.getCategories() case ITEM_TYPES.competence: return RdDItemCompetence.getCategories()
case TYPES.competencecreature: return RdDItemCompetenceCreature.getCategories() case ITEM_TYPES.competencecreature: return RdDItemCompetenceCreature.getCategories()
} }
return {} return {}
} }
@ -341,15 +349,15 @@ export class RdDItem extends Item {
getUtilisation() { getUtilisation() {
switch (this.type) { switch (this.type) {
case TYPES.potion: case ITEM_TYPES.potion:
switch (this.system.categorie) { switch (this.system.categorie) {
case 'Alchimie': case 'AlchimieEnchante': case 'AlchimieAutre': return 'alchimie' case 'Alchimie': case 'AlchimieEnchante': case 'AlchimieAutre': return 'alchimie'
case 'Cuisine': return 'cuisine' case 'Cuisine': return 'cuisine'
case 'Remede': case 'Repos': case 'ReposEnchante': case 'Soin': case 'SoinEnchante': return 'soins' case 'Remede': case 'Repos': case 'ReposEnchante': case 'Soin': case 'SoinEnchante': return 'soins'
} }
return ''; return '';
case TYPES.nourritureboisson: return 'cuisine'; case ITEM_TYPES.nourritureboisson: return 'cuisine';
case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante: case ITEM_TYPES.herbe: case ITEM_TYPES.faune: case ITEM_TYPES.ingredient: case ITEM_TYPES.plante:
switch (this.system.categorie) { switch (this.system.categorie) {
case 'Cuisine': return 'cuisine'; case 'Cuisine': return 'cuisine';
case 'Toxique': case 'Poison': return 'poison'; case 'Toxique': case 'Poison': return 'poison';
@ -364,9 +372,9 @@ export class RdDItem extends Item {
getUtilisationCuisine() { getUtilisationCuisine() {
if (this.getUtilisation() == 'cuisine') { if (this.getUtilisation() == 'cuisine') {
switch (this.type) { switch (this.type) {
case TYPES.nourritureboisson: case ITEM_TYPES.nourritureboisson:
return 'pret'; return 'pret';
case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante: case ITEM_TYPES.herbe: case ITEM_TYPES.faune: case ITEM_TYPES.ingredient: case ITEM_TYPES.plante:
return 'brut'; return 'brut';
} }
} }
@ -374,7 +382,7 @@ export class RdDItem extends Item {
} }
isCristalAlchimique() { isCristalAlchimique() {
return this.type == TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0; return this.type == ITEM_TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0;
} }
isMagique() { isMagique() {
@ -402,11 +410,11 @@ export class RdDItem extends Item {
getEnc() { getEnc() {
switch (this.type) { switch (this.type) {
case TYPES.service: case ITEM_TYPES.service:
return 0; return 0;
case TYPES.herbe: case ITEM_TYPES.herbe:
return this.getEncHerbe(); return this.getEncHerbe();
case TYPES.gemme: case ITEM_TYPES.gemme:
return encPepin * this.system.taille; return encPepin * this.system.taille;
} }
return Math.max(this.system.encombrement ?? 0, 0); return Math.max(this.system.encombrement ?? 0, 0);
@ -484,7 +492,7 @@ export class RdDItem extends Item {
getActionPrincipale(options = { warnIfNot: true }) { getActionPrincipale(options = { warnIfNot: true }) {
switch (this.type) { switch (this.type) {
case TYPES.conteneur: return 'Ouvrir'; case ITEM_TYPES.conteneur: return 'Ouvrir';
} }
if (this.actor?.isPersonnage()) { if (this.actor?.isPersonnage()) {
const warn = options.warnIfNot; const warn = options.warnIfNot;
@ -492,11 +500,11 @@ export class RdDItem extends Item {
return 'Cuisiner'; return 'Cuisiner';
} }
switch (this.type) { switch (this.type) {
case TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn); case ITEM_TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
case TYPES.potion: return this._actionOrWarnQuantiteZero('Consommer', warn); case ITEM_TYPES.potion: return this._actionOrWarnQuantiteZero('Consommer', warn);
case TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn); case ITEM_TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn);
case TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined; case ITEM_TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
case TYPES.queue: case TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined; case ITEM_TYPES.queue: case ITEM_TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined;
} }
} }
return undefined; return undefined;

View File

@ -2,7 +2,7 @@ import { RdDBaseActor } from "./actor/base-actor.js";
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js"; import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Monnaie } from "./item-monnaie.js"; import { Monnaie } from "./item-monnaie.js";
import { RdDItem, TYPES } from "./item.js"; import { RdDItem, ITEM_TYPES } from "./item.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDRaretes } from "./item/raretes.js"; import { RdDRaretes } from "./item/raretes.js";
import { RdDCalendrier } from "./time/rdd-calendrier.js"; import { RdDCalendrier } from "./time/rdd-calendrier.js";
@ -465,7 +465,7 @@ class _10_7_19_CategorieCompetenceCreature extends Migration {
async migrate() { async migrate() {
await this.applyItemsUpdates(items => items await this.applyItemsUpdates(items => items
.filter(it => TYPES.competencecreature == it.type) .filter(it => ITEM_TYPES.competencecreature == it.type)
.map(it => this.migrateCompetenceCreature(it)) .map(it => this.migrateCompetenceCreature(it))
); );
} }
@ -502,7 +502,7 @@ class _10_7_19_PossessionsEntiteVictime extends Migration {
async migrate() { async migrate() {
await this.applyItemsUpdates(items => items await this.applyItemsUpdates(items => items
.filter(it => TYPES.possession == it.type) .filter(it => ITEM_TYPES.possession == it.type)
.map(it => this.migratePossession(it)) .map(it => this.migratePossession(it))
); );
} }

View File

@ -166,11 +166,12 @@ export class Misc {
} }
static firstConnectedGM() { static firstConnectedGM() {
if (game.users?.activeGM) { if (foundry.utils.isNewerVersion(game.release.version, '12.0')) {
return game.users.activeGM return game.users.activeGM
} }
return game.users.sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active); return game.users.find(u => u.isGM && u.active);
} }
static connectedGMs() { static connectedGMs() {
return game.users.filter(u => u.isGM && u.active); return game.users.filter(u => u.isGM && u.active);
} }
@ -188,16 +189,20 @@ export class Misc {
* and there is no connected GM * and there is no connected GM
*/ */
static documentIfResponsible(document) { static documentIfResponsible(document) {
if (document instanceof Document) { if (foundry.utils.isNewerVersion(game.release.version, '12.0')) {
if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) { if (game.users.activeGM || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document)))
{
return document return document
} }
} }
else if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) {
return document
}
return undefined return undefined
} }
static isOwnerPlayer(actor) { static isOwnerPlayer(document) {
return actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) return document.testUserPermission && document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
} }
static isOwnerPlayerOrUniqueConnectedGM(actor) { static isOwnerPlayerOrUniqueConnectedGM(actor) {

View File

@ -31,8 +31,8 @@ export class RdDBonus {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static dmg(rollData, dmgActor, isEntiteIncarnee = false) { static dmg(rollData, actor, isEntiteIncarnee = false) {
const dmgArme = RdDBonus._dmgArme(rollData) const dmgArme = RdDBonus.dmgArme(rollData.arme)
let dmg = { let dmg = {
total: 0, total: 0,
dmgArme: dmgArme, dmgArme: dmgArme,
@ -41,7 +41,7 @@ export class RdDBonus {
dmgParticuliere: RdDBonus._dmgParticuliere(rollData), dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used), dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used),
mortalite: RdDBonus._calculMortalite(rollData, isEntiteIncarnee), mortalite: RdDBonus._calculMortalite(rollData, isEntiteIncarnee),
dmgActor: RdDBonus._dmgPerso(dmgActor, rollData.selectedCarac?.label, dmgArme) dmgActor: RdDBonus.bonusDmg(actor, rollData.selectedCarac?.label.toLowerCase(), dmgArme)
} }
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere; dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere;
return dmg; return dmg;
@ -71,11 +71,11 @@ export class RdDBonus {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _dmgArme(rollData) { static dmgArme(arme) {
if (rollData.arme) { if (arme) {
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0); let dmgBase = arme.system.dommagesReels ?? Number(arme.system.dommages ?? 0);
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278) //Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0); return dmgBase + Math.min(dmgBase, arme.system.magique ? arme.system.ecaille_efficacite : 0);
} }
return 0; return 0;
} }
@ -86,13 +86,14 @@ export class RdDBonus {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _dmgPerso(dmgActor, categorie, dmgArme) { static bonusDmg(actor, categorie, dmgArme) {
const dmgActor = actor.getBonusDegat()
if (categorie == undefined) { if (categorie == undefined) {
return 0 return 0
} }
switch (categorie) { switch (categorie) {
case "Tir": return 0; case "tir": return 0;
case "Lancer": return Math.max(0, Math.min(dmgArme, dmgActor)); case "lancer": return Math.max(0, Math.min(dmgArme, dmgActor));
} }
return dmgActor; return dmgActor;
} }

View File

@ -75,6 +75,12 @@ export class RdDCombatManager extends Combat {
} }
} }
} }
static calculAjustementInit(actor, arme) {
const efficacite = (arme?.system.magique) ? arme.system.ecaille_efficacite : 0
const etatGeneral = actor.getEtatGeneral() ?? 0
return efficacite + etatGeneral
}
/************************************************************************************/ /************************************************************************************/
async rollInitiative(ids, formula = undefined, messageOptions = {}) { async rollInitiative(ids, formula = undefined, messageOptions = {}) {
@ -84,12 +90,14 @@ export class RdDCombatManager extends Combat {
// calculate initiative // calculate initiative
for (let cId = 0; cId < ids.length; cId++) { for (let cId = 0; cId < ids.length; cId++) {
const combatant = this.combatants.get(ids[cId]); const combatant = this.combatants.get(ids[cId]);
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0); const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, undefined);
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, ajustement);
if (!formula) { if (!formula) {
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') { if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
const competence = combatant.actor.items.find(it => RdDItemCompetenceCreature.isCompetenceAttaque(it)) const competence = combatant.actor.items.find(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
if (competence) { if (competence) {
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, 0); rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, etatGeneral);
} }
} else { } else {
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe) const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
@ -109,8 +117,9 @@ export class RdDCombatManager extends Combat {
if (competence && competence.system.defaut_carac) { if (competence && competence.system.defaut_carac) {
const carac = combatant.actor.system.carac[competence.system.defaut_carac].value; const carac = combatant.actor.system.carac[competence.system.defaut_carac].value;
const niveau = competence.system.niveau; const niveau = competence.system.niveau;
const bonusEcaille = (armeCombat?.system.magique) ? armeCombat.system.ecaille_efficacite : 0;
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, bonusEcaille); const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, armeCombat)
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, ajustement);
} else { } else {
ui.notifications.warn(`Votre arme ${armeCombat.name} n'a pas de compétence renseignée`); ui.notifications.warn(`Votre arme ${armeCombat.name} n'a pas de compétence renseignée`);
} }
@ -214,13 +223,16 @@ export class RdDCombatManager extends Combat {
static $prepareAttaqueArme(infoAttaque) { static $prepareAttaqueArme(infoAttaque) {
const comp = infoAttaque.competences.find(c => c.name == infoAttaque.competence); const comp = infoAttaque.competences.find(c => c.name == infoAttaque.competence);
const attaque = foundry.utils.duplicate(infoAttaque.arme); const arme = infoAttaque.arme;
const attaque = foundry.utils.duplicate(arme);
attaque.action = 'attaque'; attaque.action = 'attaque';
attaque.system.competence = infoAttaque.competence; attaque.system.competence = infoAttaque.competence;
attaque.system.dommagesReels = infoAttaque.dommagesReel; attaque.system.dommagesReels = infoAttaque.dommagesReel;
attaque.system.infoMain = infoAttaque.infoMain; attaque.system.infoMain = infoAttaque.infoMain;
attaque.system.niveau = comp.system.niveau; attaque.system.niveau = comp.system.niveau;
attaque.system.initiative = RdDCombatManager.calculInitiative(comp.system.niveau, infoAttaque.carac[comp.system.defaut_carac].value);
const ajustement = (arme?.parent?.getEtatGeneral() ?? 0) + (arme?.system.magique) ? arme.system.ecaille_efficacite : 0;
attaque.system.initiative = RdDCombatManager.calculInitiative(comp.system.niveau, infoAttaque.carac[comp.system.defaut_carac].value, ajustement);
return attaque; return attaque;
} }
@ -335,7 +347,6 @@ export class RdDCombatManager extends Combat {
ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`) ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
return []; return [];
} }
let initInfo = ""; let initInfo = "";
let initOffset = 0; let initOffset = 0;
let caracForInit = 0; let caracForInit = 0;
@ -370,9 +381,9 @@ export class RdDCombatManager extends Combat {
initOffset = RdDCombatManager._baseInitOffset(compData.system.categorie, action); initOffset = RdDCombatManager._baseInitOffset(compData.system.categorie, action);
} }
let malus = combatant.actor.getEtatGeneral(); // Prise en compte état général
// Cas des créatures et entités vs personnages // Cas des créatures et entités vs personnages
let rollFormula = RdDCombatManager.formuleInitiative(initOffset, caracForInit, compNiveau, malus); const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, action)
let rollFormula = RdDCombatManager.formuleInitiative(initOffset, caracForInit, compNiveau, ajustement);
// Garder la trace de l'arme/compétence utilisée pour l'iniative // Garder la trace de l'arme/compétence utilisée pour l'iniative
combatant.initiativeData = { arme: action } // pour reclasser l'init au round 0 combatant.initiativeData = { arme: action } // pour reclasser l'init au round 0
game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo }); game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo });
@ -787,7 +798,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
_prepareAttaque(competence, arme) { _prepareAttaque(competence, arme) {
let rollData = { let rollData = {
passeArme: randomID(16), passeArme: foundry.utils.randomID(16),
mortalite: arme?.system.mortalite, mortalite: arme?.system.mortalite,
competence: competence, competence: competence,
surprise: this.attacker.getSurprise(true), surprise: this.attacker.getSurprise(true),
@ -853,7 +864,7 @@ export class RdDCombat {
async _onAttaqueNormale(attackerRoll) { async _onAttaqueNormale(attackerRoll) {
console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll); console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll);
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntite()); attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite());
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} } let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
attackerRoll.show = { attackerRoll.show = {
cible: this.target ? this.defender.name : 'la cible', cible: this.target ? this.defender.name : 'la cible',

View File

@ -5,7 +5,7 @@ import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js";
import { STATUSES } from "./settings/status-effects.js"; import { STATUSES } from "./settings/status-effects.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -92,18 +92,18 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isEmpoignadeEnCours(actor) { static isEmpoignadeEnCours(actor) {
return actor.itemTypes[TYPES.empoignade].find(it => it.system.pointsemp > 0) return actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.pointsemp > 0)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getEmpoignadeById(actor, id) { static getEmpoignadeById(actor, id) {
let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id) let emp = actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id)
return emp && foundry.utils.duplicate(emp) || undefined; return emp && foundry.utils.duplicate(emp) || undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getEmpoignade(attacker, defender) { static getEmpoignade(attacker, defender) {
let emp = attacker.itemTypes[TYPES.empoignade].find(it => let emp = attacker.itemTypes[ITEM_TYPES.empoignade].find(it =>
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) || (it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id) (it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
) )
@ -248,7 +248,7 @@ export class RdDEmpoignade {
if (rollData.rolled.isPart) { if (rollData.rolled.isPart) {
rollData.particuliere = "finesse"; rollData.particuliere = "finesse";
} }
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html'); let msg = await RdDResolutionTable.displayRollData(rollData, defender, 'chat-empoignade-resultat.html');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
@ -427,7 +427,7 @@ export class RdDEmpoignade {
name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name, name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name,
type: 'empoignade', type: 'empoignade',
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp", 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 } system: { description: "", empoignadeid: foundry.utils.randomID(16), compteempoigne: 0, empoigneurid: attacker.id, empoigneid: defender.id, ptsemp: 0, empoigneurname: attacker.name, empoignename: defender.name }
}, },
{ {
temporary: true temporary: true

View File

@ -6,7 +6,7 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
export class RdDHerbes extends Item { export class RdDHerbes extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async initializeHerbes() { static async onReady() {
this.herbesSoins = await RdDHerbes.listCategorieHerbes('Soin'); this.herbesSoins = await RdDHerbes.listCategorieHerbes('Soin');
this.herbesRepos = await RdDHerbes.listCategorieHerbes('Repos'); this.herbesRepos = await RdDHerbes.listCategorieHerbes('Repos');
} }

View File

@ -1,6 +1,6 @@
import { RdDItemArme } from "./item-arme.js"; import { RdDItemArme } from "./item-arme.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
export class RdDHotbar { export class RdDHotbar {
@ -35,7 +35,7 @@ export class RdDHotbar {
static async addToHotbar(item, slot) { static async addToHotbar(item, slot) {
switch (item?.type ?? '') { switch (item?.type ?? '') {
case TYPES.arme: case ITEM_TYPES.arme:
{ {
// Les armes peuvent avoir plusieurs usages // Les armes peuvent avoir plusieurs usages
if (item.system.competence != '') { if (item.system.competence != '') {
@ -54,12 +54,12 @@ export class RdDHotbar {
} }
} }
return return
case TYPES.competencecreature: case ITEM_TYPES.competencecreature:
const categorie = RdDItemCompetenceCreature.getCategorieAttaque(item) ?? 'competence'; const categorie = RdDItemCompetenceCreature.getCategorieAttaque(item) ?? 'competence';
await this.createItemMacro(item, slot, categorie) await this.createItemMacro(item, slot, categorie)
return return
default: default:
case TYPES.competence: case ITEM_TYPES.competence:
await this.createItemMacro(item, slot++, 'competence') await this.createItemMacro(item, slot++, 'competence')
if (item.isCorpsACorps()) { if (item.isCorpsACorps()) {
await this.createItemMacro(item, slot++, 'pugilat') await this.createItemMacro(item, slot++, 'pugilat')
@ -79,7 +79,7 @@ export class RdDHotbar {
* Actor - open actor sheet * Actor - open actor sheet
* Journal - open journal sheet * Journal - open journal sheet
*/ */
static initDropbar() { static init() {
Hooks.on('hotbarDrop', (bar, documentData, slot) => { Hooks.on('hotbarDrop', (bar, documentData, slot) => {
@ -88,9 +88,9 @@ export class RdDHotbar {
const item = fromUuidSync(documentData.uuid) ?? this.actor.items.get(documentData.uuid) const item = fromUuidSync(documentData.uuid) ?? this.actor.items.get(documentData.uuid)
console.log('DROP', documentData, item) console.log('DROP', documentData, item)
switch (item?.type) { switch (item?.type) {
case TYPES.arme: case ITEM_TYPES.arme:
case TYPES.competence: case ITEM_TYPES.competence:
case TYPES.competencecreature: case ITEM_TYPES.competencecreature:
this.addToHotbar(item, slot) this.addToHotbar(item, slot)
return false return false
} }
@ -116,9 +116,9 @@ export class RdDHotbar {
// Trigger the item roll // Trigger the item roll
switch (item.type) { switch (item.type) {
case TYPES.arme: case ITEM_TYPES.arme:
return actor.rollArme(item, categorieArme); return actor.rollArme(item, categorieArme);
case TYPES.competence: case ITEM_TYPES.competence:
if (item.isCorpsACorps()) { if (item.isCorpsACorps()) {
switch (categorieArme) { switch (categorieArme) {
case 'pugilat': case 'pugilat':
@ -128,7 +128,7 @@ export class RdDHotbar {
} }
} }
return actor.rollCompetence(item); return actor.rollCompetence(item);
case TYPES.competencecreature: case ITEM_TYPES.competencecreature:
return item.system.iscombat && !item.system.isparade return item.system.iscombat && !item.system.isparade
? actor.rollArme(item, categorieArme) ? actor.rollArme(item, categorieArme)
: actor.rollCompetence(item); : actor.rollCompetence(item);

View File

@ -1,69 +1,72 @@
import { SYSTEM_RDD, SYSTEM_SOCKET_ID, RDD_CONFIG } from "./constants.js"; import { SYSTEM_RDD, SYSTEM_SOCKET_ID, RDD_CONFIG } from "./constants.js"
import { Migrations } from './migrations.js'; import { Migrations } from './migrations.js'
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js"
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js"
import { TMRRencontres } from "./tmr-rencontres.js"; import { TMRRencontres } from "./tmr-rencontres.js"
import { RdDCalendrier } from "./time/rdd-calendrier.js"; import { RdDCalendrier } from "./time/rdd-calendrier.js"
import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js"
import { DialogChronologie } from "./dialog-chronologie.js"; import { DialogChronologie } from "./dialog-chronologie.js"
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js"
import { RdDTokenHud } from "./rdd-token-hud.js"; import { RdDTokenHud } from "./rdd-token-hud.js"
import { RdDCommands } from "./rdd-commands.js"; import { RdDCommands } from "./rdd-commands.js"
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js"; import { RdDCombatManager, RdDCombat } from "./rdd-combat.js"
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js"
import { StatusEffects } from "./settings/status-effects.js"; import { StatusEffects } from "./settings/status-effects.js"
import { RdDCompendiumOrganiser } from "./rdd-compendium-organiser.js"; import { RdDCompendiumOrganiser } from "./rdd-compendium-organiser.js"
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"
import { RdDHotbar } from "./rdd-hotbar-drop.js" import { RdDHotbar } from "./rdd-hotbar-drop.js"
import { EffetsDraconiques } from "./tmr/effets-draconiques.js"; import { EffetsDraconiques } from "./tmr/effets-draconiques.js"
import { RdDHerbes } from "./rdd-herbes.js"; import { RdDHerbes } from "./rdd-herbes.js"
import { RdDDice } from "./rdd-dice.js"; import { RdDDice } from "./rdd-dice.js"
import { RdDPossession } from "./rdd-possession.js"; import { RdDPossession } from "./rdd-possession.js"
import { Misc } from "./misc.js"; import { Misc } from "./misc.js"
import { SystemCompendiums } from "./settings/system-compendiums.js"; import { SystemCompendiums } from "./settings/system-compendiums.js"
import { Environnement } from "./environnement.js"; import { Environnement } from "./environnement.js"
import { RdDActor } from "./actor.js"; import { RdDActor } from "./actor.js"
import { RdDBaseActor } from "./actor/base-actor.js"; import { RdDBaseActor } from "./actor/base-actor.js"
import { RdDCommerce } from "./actor/commerce.js"; import { RdDCommerce } from "./actor/commerce.js"
import { RdDEntite } from "./actor/entite.js"; import { RdDEntite } from "./actor/entite.js"
import { RdDVehicule } from "./actor/vehicule.js"; import { RdDVehicule } from "./actor/vehicule.js"
import { RdDActorSheet } from "./actor-sheet.js"; import { RdDActorSheet } from "./actor-sheet.js"
import { RdDCommerceSheet } from "./actor/commerce-sheet.js"; import { RdDCommerceSheet } from "./actor/commerce-sheet.js"
import { RdDCreatureSheet } from "./actor/creature-sheet.js"; import { RdDCreatureSheet } from "./actor/creature-sheet.js"
import { RdDActorEntiteSheet } from "./actor/entite-sheet.js"; import { RdDActorEntiteSheet } from "./actor/entite-sheet.js"
import { RdDActorVehiculeSheet } from "./actor/vehicule-sheet.js"; import { RdDActorVehiculeSheet } from "./actor/vehicule-sheet.js"
import { RdDItem } from "./item.js"; import { RdDItem } from "./item.js"
import { RdDItemBlessure } from "./item/blessure.js"; import { RdDItemBlessure } from "./item/blessure.js"
import { RdDItemService } from "./item/service.js"; import { RdDItemService } from "./item/service.js"
import { RdDItemMaladie } from "./item/maladie.js"; import { RdDItemMaladie } from "./item/maladie.js"
import { RdDItemPoison } from "./item/poison.js"; import { RdDItemPoison } from "./item/poison.js"
import { RdDItemSigneDraconique } from "./item/signedraconique.js"; import { RdDItemSigneDraconique } from "./item/signedraconique.js"
import { RdDItemQueue } from "./item/queue.js"; import { RdDItemQueue } from "./item/queue.js"
import { RdDItemOmbre } from "./item/ombre.js"; import { RdDItemOmbre } from "./item/ombre.js"
import { RdDItemSouffle } from "./item/souffle.js"; import { RdDItemSouffle } from "./item/souffle.js"
import { RdDRencontre } from "./item/rencontre.js"; import { RdDRencontre } from "./item/rencontre.js"
import { RdDItemSheet } from "./item-sheet.js"; import { RdDItemSheet } from "./item-sheet.js"
import { RdDBlessureItemSheet } from "./item/sheet-blessure.js"; import { RdDBlessureItemSheet } from "./item/sheet-blessure.js"
import { RdDServiceItemSheet } from "./item/sheet-service.js"; import { RdDServiceItemSheet } from "./item/sheet-service.js"
import { RdDRencontreItemSheet } from "./item/sheet-rencontre.js"; import { RdDRencontreItemSheet } from "./item/sheet-rencontre.js"
import { RdDHerbeItemSheet } from "./item/sheet-herbe.js"; import { RdDHerbeItemSheet } from "./item/sheet-herbe.js"
import { RdDPlanteItemSheet } from "./item/sheet-plante.js"; import { RdDPlanteItemSheet } from "./item/sheet-plante.js"
import { RdDIngredientItemSheet } from "./item/sheet-ingredient.js"; import { RdDIngredientItemSheet } from "./item/sheet-ingredient.js"
import { RdDFauneItemSheet } from "./item/sheet-faune.js"; import { RdDFauneItemSheet } from "./item/sheet-faune.js"
import { RdDConteneurItemSheet } from "./item/sheet-conteneur.js"; import { RdDConteneurItemSheet } from "./item/sheet-conteneur.js"
import { RdDSigneDraconiqueItemSheet } from "./item/sheet-signedraconique.js"; import { RdDSigneDraconiqueItemSheet } from "./item/sheet-signedraconique.js"
import { RdDItemInventaireSheet } from "./item/sheet-base-inventaire.js"; import { RdDItemInventaireSheet } from "./item/sheet-base-inventaire.js"
import { AppAstrologie } from "./sommeil/app-astrologie.js"; import { AppAstrologie } from "./sommeil/app-astrologie.js"
import { RdDItemArmure } from "./item/armure.js"; import { RdDItemArmure } from "./item/armure.js"
import { AutoAdjustDarkness as AutoAdjustDarkness } from "./time/auto-adjust-darkness.js"; import { AutoAdjustDarkness as AutoAdjustDarkness } from "./time/auto-adjust-darkness.js"
import { RdDCreature } from "./actor/creature.js"; import { RdDCreature } from "./actor/creature.js"
import { RdDTMRDialog } from "./rdd-tmr-dialog.js"; import { RdDTMRDialog } from "./rdd-tmr-dialog.js"
//import { RdDActorExportSheet } from "./actor/actor-export-sheet.js"
import { OptionsAvancees } from "./settings/options-avancees.js"
import { ExportScriptarium } from "./actor/export-scriptarium/export-scriptarium.js"
/** /**
* RdD system * RdD system
@ -71,18 +74,18 @@ import { RdDTMRDialog } from "./rdd-tmr-dialog.js";
* Software License: GNU GPLv3 * Software License: GNU GPLv3
*/ */
export class SystemReveDeDragon { export class SystemReveDeDragon {
static start() { static start() {
const system = new SystemReveDeDragon() const system = new SystemReveDeDragon()
Hooks.once('init', async () => await system.onInit()) Hooks.once('init', async () => await system.onInit())
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d)) Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d))
Hooks.once('ready', () => system.onReady()) Hooks.once('ready', () => system.onReady())
} }
constructor() { constructor() {
this.config = RDD_CONFIG; this.config = RDD_CONFIG
this.RdDUtility = RdDUtility; this.RdDUtility = RdDUtility
this.RdDHotbar = RdDHotbar; this.RdDHotbar = RdDHotbar
this.itemClasses = { this.itemClasses = {
armure: RdDItemArmure, armure: RdDItemArmure,
blessure: RdDItemBlessure, blessure: RdDItemBlessure,
@ -108,42 +111,42 @@ export class SystemReveDeDragon {
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
/* -------------------------------------------- */ /* -------------------------------------------- */
async onInit() { async onInit() {
game.system.rdd = this; game.system.rdd = this
this.AppAstrologie = AppAstrologie; this.AppAstrologie = AppAstrologie
console.log(`Initializing Reve de Dragon System`); console.log(`Initializing Reve de Dragon System`)
// preload handlebars templates // preload handlebars templates
RdDUtility.preloadHandlebarsTemplates(); RdDUtility.preloadHandlebarsTemplates()
/* -------------------------------------------- */ /* -------------------------------------------- */
this.initSystemSettings(); this.initSystemSettings()
/* -------------------------------------------- */ /* -------------------------------------------- */
// Set an initiative formula for the system // Set an initiative formula for the system
CONFIG.Combat.initiative = { CONFIG.Combat.initiative = {
formula: "1+(1d6/10)", formula: "1+(1d6/10)",
decimals: 2 decimals: 2
}; }
/* -------------------------------------------- */ /* -------------------------------------------- */
game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => { game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => {
console.log(">>>>> MSG RECV", sockmsg); console.log(">>>>> MSG RECV", sockmsg)
try { try {
RdDUtility.onSocketMessage(sockmsg); RdDUtility.onSocketMessage(sockmsg)
RdDCombat.onSocketMessage(sockmsg); RdDCombat.onSocketMessage(sockmsg)
ChatUtility.onSocketMessage(sockmsg); ChatUtility.onSocketMessage(sockmsg)
RdDBaseActor.onSocketMessage(sockmsg); RdDBaseActor.onSocketMessage(sockmsg)
} catch (e) { } catch (e) {
console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg, ' => ', e) console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg, ' => ', e)
} }
}); })
/* -------------------------------------------- */ /* -------------------------------------------- */
// Define custom Entity classes // Define custom Entity classes
CONFIG.Actor.documentClass = RdDBaseActor; CONFIG.Actor.documentClass = RdDBaseActor
CONFIG.Item.documentClass = RdDItem; CONFIG.Item.documentClass = RdDItem
CONFIG.RDD = { CONFIG.RDD = {
resolutionTable: RdDResolutionTable.resolutionTable, resolutionTable: RdDResolutionTable.resolutionTable,
carac_array: RdDUtility.getCaracArray(), carac_array: RdDUtility.getCaracArray(),
@ -153,30 +156,31 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */ /* -------------------------------------------- */
// Register sheet application classes // Register sheet application classes
Actors.unregisterSheet("core", ActorSheet); Actors.unregisterSheet("core", ActorSheet)
Actors.registerSheet(SYSTEM_RDD, RdDCommerceSheet, { types: ["commerce"], makeDefault: true }); Actors.registerSheet(SYSTEM_RDD, RdDCommerceSheet, { types: ["commerce"], makeDefault: true })
Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true }); //Actors.registerSheet(SYSTEM_RDD, RdDActorExportSheet, { types: ["personnage"], makeDefault: false })
Actors.registerSheet(SYSTEM_RDD, RdDCreatureSheet, { types: ["creature"], makeDefault: true }); Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true })
Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true }); Actors.registerSheet(SYSTEM_RDD, RdDCreatureSheet, { types: ["creature"], makeDefault: true })
Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true }); Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true })
Items.unregisterSheet("core", ItemSheet); Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true })
Items.unregisterSheet("core", ItemSheet)
RdDItemSheet.register(RdDSigneDraconiqueItemSheet); RdDItemSheet.register(RdDSigneDraconiqueItemSheet)
RdDItemSheet.register(RdDRencontreItemSheet); RdDItemSheet.register(RdDRencontreItemSheet)
RdDItemSheet.register(RdDConteneurItemSheet); RdDItemSheet.register(RdDConteneurItemSheet)
RdDItemSheet.register(RdDHerbeItemSheet); RdDItemSheet.register(RdDHerbeItemSheet)
RdDItemSheet.register(RdDFauneItemSheet); RdDItemSheet.register(RdDFauneItemSheet)
RdDItemSheet.register(RdDPlanteItemSheet); RdDItemSheet.register(RdDPlanteItemSheet)
RdDItemSheet.register(RdDIngredientItemSheet); RdDItemSheet.register(RdDIngredientItemSheet)
RdDItemSheet.register(RdDServiceItemSheet); RdDItemSheet.register(RdDServiceItemSheet)
RdDItemSheet.register(RdDBlessureItemSheet); RdDItemSheet.register(RdDBlessureItemSheet)
Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, { Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, {
types: [ types: [
"objet", "arme", "armure", "livre", "potion", "munition", "objet", "arme", "armure", "livre", "potion", "munition",
"monnaie", "nourritureboisson", "gemme", "monnaie", "nourritureboisson", "gemme",
], makeDefault: true ], makeDefault: true
}); })
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, { Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
types: [ types: [
"competence", "competencecreature", "competence", "competencecreature",
@ -185,31 +189,32 @@ export class SystemReveDeDragon {
"nombreastral", "tache", "maladie", "poison", "possession", "nombreastral", "tache", "maladie", "poison", "possession",
"tarot", "extraitpoetique", "empoignade" "tarot", "extraitpoetique", "empoignade"
], makeDefault: true ], makeDefault: true
}); })
CONFIG.Combat.documentClass = RdDCombatManager; CONFIG.Combat.documentClass = RdDCombatManager
// préparation des différents modules // préparation des différents modules
AutoAdjustDarkness.init(); AutoAdjustDarkness.init()
RdDTimestamp.init(); RdDTimestamp.init()
RdDCalendrier.init(); RdDCalendrier.init()
SystemCompendiums.init(); SystemCompendiums.init()
DialogChronologie.init(); DialogChronologie.init()
ReglesOptionnelles.init(); ReglesOptionnelles.init()
RdDUtility.init(); OptionsAvancees.init()
RdDDice.init(); RdDUtility.init()
RdDCommands.init(); RdDDice.init()
RdDCombatManager.init(); RdDCommands.init()
RdDTokenHud.init(); RdDCombatManager.init()
RdDBaseActor.init(); RdDTokenHud.init()
RdDCompendiumOrganiser.init(); RdDBaseActor.init()
RdDCompendiumOrganiser.init()
EffetsDraconiques.init() EffetsDraconiques.init()
TMRUtility.init(); TMRUtility.init()
await RdDTMRDialog.init() await RdDTMRDialog.init()
RdDHotbar.initDropbar(); RdDHotbar.init()
RdDPossession.init(); RdDPossession.init()
TMRRencontres.init(); TMRRencontres.init()
Environnement.init(); Environnement.init()
ExportScriptarium.init()
} }
initSystemSettings() { initSystemSettings() {
@ -225,7 +230,7 @@ export class SystemReveDeDragon {
"avant-encaissement": "Avant l'encaissement", "avant-encaissement": "Avant l'encaissement",
}, },
default: "avant-encaissement" default: "avant-encaissement"
}); })
/* -------------------------------------------- */ /* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", { game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", {
@ -235,7 +240,7 @@ export class SystemReveDeDragon {
config: true, config: true,
default: true, default: true,
type: Boolean type: Boolean
}); })
/* -------------------------------------------- */ /* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "activer-sons-audio", { game.settings.register(SYSTEM_RDD, "activer-sons-audio", {
@ -245,7 +250,8 @@ export class SystemReveDeDragon {
config: true, config: true,
default: true, default: true,
type: Boolean type: Boolean
}); })
/* -------------------------------------------- */ /* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "appliquer-famine-soif", { game.settings.register(SYSTEM_RDD, "appliquer-famine-soif", {
name: "Notifier de la famine et la soif pour", name: "Notifier de la famine et la soif pour",
@ -259,7 +265,7 @@ export class SystemReveDeDragon {
"famine-soif": "la famine et la soif", "famine-soif": "la famine et la soif",
}, },
default: "aucun" default: "aucun"
}); })
} }
async onReady() { async onReady() {
@ -267,47 +273,47 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
/* -------------------------------------------- */ /* -------------------------------------------- */
game.system.rdd.calendrier = new RdDCalendrier(); game.system.rdd.calendrier = new RdDCalendrier()
if (Misc.isUniqueConnectedGM()) { if (Misc.isUniqueConnectedGM()) {
new Migrations().migrate(); new Migrations().migrate()
this.messageDeBienvenue(); this.messageDeBienvenue()
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter=>{ import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => {
console.log("ClassCounter loaded", moduleCounter) console.log("ClassCounter loaded", moduleCounter)
moduleCounter.ClassCounter.registerUsageCount() moduleCounter.ClassCounter.registerUsageCount()
}).catch(err=> }).catch(err =>
console.log("No stats available, giving up.") console.log("No stats available, giving up.")
) )
} }
StatusEffects.onReady(); StatusEffects.onReady()
RdDHerbes.initializeHerbes(); RdDHerbes.onReady()
RdDDice.onReady(); RdDDice.onReady()
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Affiche/Init le calendrier */ /* Affiche/Init le calendrier */
game.system.rdd.calendrier.display(); game.system.rdd.calendrier.display()
// Avertissement si joueur sans personnage // Avertissement si joueur sans personnage
if (!game.user.isGM && game.user.character == undefined) { if (!game.user.isGM && game.user.character == undefined) {
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !"); ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !")
ChatMessage.create({ ChatMessage.create({
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !", content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !",
user: game.user.id user: game.user.id
}); })
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
messageDeBienvenue() { messageDeBienvenue() {
if (game.user.isGM) { if (game.user.isGM) {
ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">'); ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">')
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
content: `<div id="message-bienvenue-rdd"><span class="rdd-roll-part">Bienvenue dans le Rêve des Dragons !</span> content: `<div id="message-bienvenue-rdd"><span class="rdd-roll-part">Bienvenue dans le Rêve des Dragons !</span>
<br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs} <br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs}
<br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div> <br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
` }); ` })
} }
} }
} }
SystemReveDeDragon.start(); SystemReveDeDragon.start()

View File

@ -3,7 +3,7 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDRoll } from "./rdd-roll.js"; import { RdDRoll } from "./rdd-roll.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { Targets } from "./targets.js"; import { Targets } from "./targets.js";
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
/* On part du principe qu'une entité démarre tjs /* On part du principe qu'une entité démarre tjs
@ -20,9 +20,9 @@ export class RdDPossession {
/* -------------------------------------------- */ /* -------------------------------------------- */
static searchPossessionFromEntite(attacker, defender) { static searchPossessionFromEntite(attacker, defender) {
let poss = attacker.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id); let poss = attacker.items.find(poss => poss.type == ITEM_TYPES.possession && poss.system.victime.actorid == defender.id);
if (!poss) { if (!poss) {
poss = defender.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id); poss = defender.items.find(poss => poss.type == ITEM_TYPES.possession && poss.system.victime.actorid == defender.id);
} }
return poss && foundry.utils.duplicate(poss) || undefined; return poss && foundry.utils.duplicate(poss) || undefined;
} }
@ -131,7 +131,7 @@ export class RdDPossession {
} }
const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid) const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid)
RdDPossession.storePossessionAttaque(possession, rollData) RdDPossession.storePossessionAttaque(possession, rollData)
await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html'); await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html');
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -171,7 +171,7 @@ export class RdDPossession {
rollData.possession = possession rollData.possession = possession
RdDPossession.$updateEtatPossession(rollData.possession) RdDPossession.$updateEtatPossession(rollData.possession)
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html') await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html')
if (rollData.possession.isPosseder || rollData.possession.isConjurer) { if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
// conjuration // conjuration
victime.deleteEmbeddedDocuments("Item", [rollData.possession._id]) victime.deleteEmbeddedDocuments("Item", [rollData.possession._id])
@ -230,7 +230,7 @@ export class RdDPossession {
system: { system: {
description: "", typepossession: attacker.name, description: "", typepossession: attacker.name,
possede: false, possede: false,
possessionid: randomID(16), possessionid: foundry.utils.randomID(16),
entite: { actorid: attacker.id }, entite: { actorid: attacker.id },
victime: { actorid: defender.id }, victime: { actorid: defender.id },
compteur: 0 compteur: 0

View File

@ -97,7 +97,7 @@ export class RdDResolutionTable {
} }
static actorChatName(actor) { static actorChatName(actor) {
return actor?.userName ?? game.user.name; return actor?.name ?? game.user.name;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -307,7 +307,7 @@ export class RdDRoll extends Dialog {
async updateRollResult(html) { async updateRollResult(html) {
const rollData = this.rollData; const rollData = this.rollData;
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat()) rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor)
rollData.caracValue = parseInt(rollData.selectedCarac.value) rollData.caracValue = parseInt(rollData.selectedCarac.value)
rollData.dmg.mortalite = rollData.dmg.mortalite ?? 'mortel'; rollData.dmg.mortalite = rollData.dmg.mortalite ?? 'mortel';
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac); rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);

View File

@ -16,7 +16,7 @@ import { RdDDice } from "./rdd-dice.js";
import { STATUSES } from "./settings/status-effects.js"; import { STATUSES } from "./settings/status-effects.js";
import { RdDRencontre } from "./item/rencontre.js"; import { RdDRencontre } from "./item/rencontre.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
const TMR_DISPLAY_SIZE = { const TMR_DISPLAY_SIZE = {
@ -208,11 +208,11 @@ export class RdDTMRDialog extends Dialog {
} }
get sortsReserve() { get sortsReserve() {
return this.actor.itemTypes[TYPES.sortreserve]; return this.actor.itemTypes[ITEM_TYPES.sortreserve];
} }
getSortsReserve(coord) { getSortsReserve(coord) {
return this.actor.itemTypes[TYPES.sortreserve].filter(// Reserve sur une case fleuve ou normale return this.actor.itemTypes[ITEM_TYPES.sortreserve].filter(// Reserve sur une case fleuve ou normale
TMRUtility.getTMR(coord).type == 'fleuve' TMRUtility.getTMR(coord).type == 'fleuve'
? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve' ? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve'
: it => it.system.coord == coord : it => it.system.coord == coord
@ -270,7 +270,7 @@ export class RdDTMRDialog extends Dialog {
} }
_getTokensSortsReserve() { _getTokensSortsReserve() {
const sortsReserve = this.actor.itemTypes[TYPES.sortreserve]; const sortsReserve = this.actor.itemTypes[ITEM_TYPES.sortreserve];
return Misc.concat(sortsReserve.map(sortReserve => return Misc.concat(sortsReserve.map(sortReserve =>
EffetsDraconiques.sortReserve.tokens(this.pixiTMR, sortReserve, () => sortReserve.system.coord))) EffetsDraconiques.sortReserve.tokens(this.pixiTMR, sortReserve, () => sortReserve.system.coord)))
} }

View File

@ -769,7 +769,7 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static createMonnaie(name, cout, img = "", enc = 0.01) { static createMonnaie(name, cout, img = "", enc = 0.01) {
let piece = { let piece = {
name: name, type: 'monnaie', img: img, _id: randomID(16), name: name, type: 'monnaie', img: img, _id: foundry.utils.randomID(16),
dasystemta: { dasystemta: {
quantite: 0, quantite: 0,
cout: cout, cout: cout,

View File

@ -111,7 +111,7 @@ export const referenceAjustements = {
isVisible: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0, isVisible: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
isUsed: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0, isUsed: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
getLabel: (rollData, actor) => "Ecaille d'Efficacité: ", getLabel: (rollData, actor) => "Ecaille d'Efficacité: ",
getValue: (rollData, actor) => Math.max(Number(rollData.arme?.system.ecaille_efficacite), 0), getValue: (rollData, actor) => rollData.arme?.system.magique ? Math.max(Number(rollData.arme?.system.ecaille_efficacite), 0) : 0,
}, },
finesse: { finesse: {
isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData), isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData),

View File

@ -0,0 +1,91 @@
import { SYSTEM_RDD } from "../constants.js"
import { Misc } from "../misc.js"
export const EXPORT_CSV_SCRIPTARIUM = 'export-csv-scriptarium'
const OPTIONS_AVANCEES = [
{ group: 'Menus', name: EXPORT_CSV_SCRIPTARIUM, descr: "Proposer le menu d'export csv Scriptarium (raffraichissement requis)" },
]
export class OptionsAvancees extends FormApplication {
static init() {
for (const regle of OPTIONS_AVANCEES) {
const name = regle.name
const id = OptionsAvancees._getId(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-avancees", {
name: "Configurer les options avancées",
label: "Options avancées",
hint: "Ouvre la fenêtre de configuration des options avancées",
icon: "fas fa-bars",
type: OptionsAvancees
})
}
constructor(...args) {
super(...args)
}
static _getId(name) {
return `rdd-advanced-${name}`
}
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
id: "options-avancees",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/options-avancees.hbs",
height: 650,
width: 550,
minimizable: false,
closeOnSubmit: true,
title: "Options avancées"
}, { inplace: false })
}
getData() {
let formData = super.getData()
const regles = OPTIONS_AVANCEES.filter(it => game.user.isGM || it.scope == "client")
.map(it => {
it = foundry.utils.duplicate(it)
it.id = OptionsAvancees._getId(it.name)
it.active = OptionsAvancees.isSet(it.name)
return it
})
formData.regles = regles
formData.groups = Misc.classify(regles, it => it.group)
return formData
}
static getSettingKey(name){
return `${SYSTEM_RDD}.${this._getId(name)}`
}
static isUsing(name) {
return OptionsAvancees.isSet(name)
}
static isSet(name) {
return game.settings.get(SYSTEM_RDD, OptionsAvancees._getId(name))
}
static set(name, value) {
return game.settings.set(SYSTEM_RDD, OptionsAvancees._getId(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

@ -73,7 +73,7 @@ export class ReglesOptionnelles extends FormApplication {
static get defaultOptions() { static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
id: "regles-optionnelles", id: "regles-optionnelles",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.html", template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.hbs",
height: 650, height: 650,
width: 550, width: 550,
minimizable: false, minimizable: false,

View File

@ -1,7 +1,6 @@
import { MAX_NOMBRE_ASTRAL, RdDTimestamp, WORLD_TIMESTAMP_SETTING } from "./rdd-timestamp.js"; import { MAX_NOMBRE_ASTRAL, RdDTimestamp, WORLD_TIMESTAMP_SETTING } from "./rdd-timestamp.js";
import { RdDCalendrierEditor } from "./rdd-calendrier-editor.js"; import { RdDCalendrierEditor } from "./rdd-calendrier-editor.js";
import { RdDResolutionTable } from "../rdd-resolution-table.js"; import { RdDResolutionTable } from "../rdd-resolution-table.js";
import { RdDUtility } from "../rdd-utility.js";
import { RdDDice } from "../rdd-dice.js"; import { RdDDice } from "../rdd-dice.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { DialogChronologie } from "../dialog-chronologie.js"; import { DialogChronologie } from "../dialog-chronologie.js";

View File

@ -15,18 +15,18 @@ export const RDD_MINUTES_PAR_JOUR = 1440; //RDD_HEURES_PAR_JOUR * RDD_MINUTES_PA
const ROUNDS_PAR_MINUTE = 10; const ROUNDS_PAR_MINUTE = 10;
const DEFINITION_HEURES = [ const DEFINITION_HEURES = [
{ key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "Printemps", darkness: 0.9 }, { key: "vaisseau", article: "du ", label: "Vaisseau", lettreFont: 'v', saison: "Printemps", darkness: 0.9 },
{ key: "sirene", label: "Sirène", lettreFont: 'i', saison: "Printemps", darkness: 0.1 }, { key: "sirene", article: "de la ", label: "Sirène", lettreFont: 'i', saison: "Printemps", darkness: 0.1 },
{ key: "faucon", label: "Faucon", lettreFont: 'f', saison: "Printemps", darkness: 0 }, { key: "faucon", article: "du ", label: "Faucon", lettreFont: 'f', saison: "Printemps", darkness: 0 },
{ key: "couronne", label: "Couronne", lettreFont: '', saison: "Eté", darkness: 0 }, { key: "couronne", article: "de la ", label: "Couronne", lettreFont: '', saison: "Eté", darkness: 0 },
{ key: "dragon", label: "Dragon", lettreFont: 'd', saison: "Eté", darkness: 0 }, { key: "dragon", article: "du ", label: "Dragon", lettreFont: 'd', saison: "Eté", darkness: 0 },
{ key: "epees", label: "Epées", lettreFont: 'e', saison: "Eté", darkness: 0 }, { key: "epees", article: "des ", label: "Epées", lettreFont: 'e', saison: "Eté", darkness: 0 },
{ key: "lyre", label: "Lyre", lettreFont: 'l', saison: "Automne", darkness: 0.1 }, { key: "lyre", article: "de la ", label: "Lyre", lettreFont: 'l', saison: "Automne", darkness: 0.1 },
{ key: "serpent", label: "Serpent", lettreFont: 's', saison: "Automne", darkness: 0.9 }, { key: "serpent", article: "du ", label: "Serpent", lettreFont: 's', saison: "Automne", darkness: 0.9 },
{ key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne", darkness: 1 }, { key: "poissonacrobate", article: "du ", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne", darkness: 1 },
{ key: "araignee", label: "Araignée", lettreFont: 'a', saison: "Hiver", darkness: 1 }, { key: "araignee", article: "de l'", label: "Araignée", lettreFont: 'a', saison: "Hiver", darkness: 1 },
{ key: "roseau", label: "Roseau", lettreFont: 'r', saison: "Hiver", darkness: 1 }, { key: "roseau", article: "du ", label: "Roseau", lettreFont: 'r', saison: "Hiver", darkness: 1 },
{ key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "Hiver", darkness: 1 }, { key: "chateaudormant", article: "du ", label: "Château Dormant", lettreFont: 'c', saison: "Hiver", darkness: 1 },
] ]
const FORMULES_DUREE = [ const FORMULES_DUREE = [
@ -64,6 +64,7 @@ export class RdDTimestamp {
DEFINITION_HEURES[i].hh = RdDTimestamp.hh(i); DEFINITION_HEURES[i].hh = RdDTimestamp.hh(i);
DEFINITION_HEURES[i].icon = RdDTimestamp.iconeHeure(i); DEFINITION_HEURES[i].icon = RdDTimestamp.iconeHeure(i);
DEFINITION_HEURES[i].webp = DEFINITION_HEURES[i].icon.replace(".svg", ".webp"); DEFINITION_HEURES[i].webp = DEFINITION_HEURES[i].icon.replace(".svg", ".webp");
DEFINITION_HEURES[i].avecArticle = DEFINITION_HEURES[i].article + DEFINITION_HEURES[i].label
} }
} }
@ -241,7 +242,7 @@ export class RdDTimestamp {
get darkness() { get darkness() {
const darknessDebut = 100 * RdDTimestamp.definition(this.heure).darkness const darknessDebut = 100 * RdDTimestamp.definition(this.heure).darkness
const darknessFin = 100 * RdDTimestamp.definition(this.heure + 1).darkness const darknessFin = 100 * RdDTimestamp.definition(this.heure + 1).darkness
const darknessMinute = Math.round((darknessFin - darknessDebut) * this.minute / RDD_MINUTES_PAR_HEURES); const darknessMinute = Math.round((darknessFin - darknessDebut) * this.minute / RDD_MINUTES_PAR_HEURES);
return (darknessDebut + darknessMinute) / 100 return (darknessDebut + darknessMinute) / 100
} }

View File

@ -1,4 +1,4 @@
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { TMRUtility } from "../tmr-utility.js"; import { TMRUtility } from "../tmr-utility.js";
import { PixiTMR } from "./pixi-tmr.js"; import { PixiTMR } from "./pixi-tmr.js";
@ -12,10 +12,10 @@ export class Draconique {
static init() { static init() {
} }
static isCaseTMR(item) { return item.type == TYPES.casetmr; } static isCaseTMR(item) { return item.type == ITEM_TYPES.casetmr; }
static isQueueDragon(item) { return item.isQueueDragon(); } static isQueueDragon(item) { return item.isQueueDragon(); }
static isSouffleDragon(item) { return item.type == TYPES.souffle; } static isSouffleDragon(item) { return item.type == ITEM_TYPES.souffle; }
static isTeteDragon(item) { return item.type == TYPES.tete; } static isTeteDragon(item) { return item.type == ITEM_TYPES.tete; }
static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); } static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); }
static register(draconique, code = undefined) { static register(draconique, code = undefined) {

View File

@ -18,7 +18,7 @@ import { Periple } from "./periple.js";
import { UrgenceDraconique } from "./urgence-draconique.js"; import { UrgenceDraconique } from "./urgence-draconique.js";
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { AugmentationSeuil } from "./augmentation-seuil.js"; import { AugmentationSeuil } from "./augmentation-seuil.js";
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
export class EffetsDraconiques { export class EffetsDraconiques {
static carteTmr = new CarteTmr(); static carteTmr = new CarteTmr();
@ -122,11 +122,11 @@ export class EffetsDraconiques {
} }
static tetesDragon(actor, name) { static tetesDragon(actor, name) {
return actor.itemTypes[TYPES.tete].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name)); return actor.itemTypes[ITEM_TYPES.tete].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
} }
static soufflesDragon(actor, name) { static soufflesDragon(actor, name) {
return actor.itemTypes[TYPES.souffle].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name)); return actor.itemTypes[ITEM_TYPES.souffle].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
} }
static queuesDragon(actor, name) { static queuesDragon(actor, name) {
@ -134,7 +134,7 @@ export class EffetsDraconiques {
} }
static queuesSoufflesDragon(actor, name) { static queuesSoufflesDragon(actor, name) {
return actor.filterItems(it => [TYPES.queue, TYPES.ombre, TYPES.souffle].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, name)); return actor.filterItems(it => [ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, name));
} }
static countAugmentationSeuil(actor) { static countAugmentationSeuil(actor) {

View File

@ -5,7 +5,7 @@ import { RdDRollTables } from "../rdd-rolltables.js";
import { TMRUtility } from "../tmr-utility.js"; import { TMRUtility } from "../tmr-utility.js";
import { tmrTokenZIndex } from "../tmr-constants.js"; import { tmrTokenZIndex } from "../tmr-constants.js";
import { Draconique } from "./draconique.js"; import { Draconique } from "./draconique.js";
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { TMRAnimations } from "./animation.js"; import { TMRAnimations } from "./animation.js";
export class UrgenceDraconique extends Draconique { export class UrgenceDraconique extends Draconique {
@ -14,7 +14,7 @@ export class UrgenceDraconique extends Draconique {
match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); } match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
manualMessage() { return false } manualMessage() { return false }
async onActorCreateOwned(actor, queue) { async onActorCreateOwned(actor, queue) {
const coordSortsReserve = actor.itemTypes[TYPES.sortreserve].map(it => it.system.coord) ?? []; const coordSortsReserve = actor.itemTypes[ITEM_TYPES.sortreserve].map(it => it.system.coord) ?? [];
if (coordSortsReserve.length == 0) { if (coordSortsReserve.length == 0) {
// La queue se transforme en idée fixe // La queue se transforme en idée fixe
const ideeFixe = await RdDRollTables.getIdeeFixe(); const ideeFixe = await RdDRollTables.getIdeeFixe();

View File

@ -1,6 +1,7 @@
import { TYPES } from "../item.js" import { ITEM_TYPES } from "../item.js"
import { RdDItemCompetence } from "../item-competence.js" import { RdDItemCompetence } from "../item-competence.js"
import { ChatUtility } from "../chat-utility.js" import { ChatUtility } from "../chat-utility.js"
import { Misc } from "../misc.js"
const CODES_COMPETENCES_VOYAGE = ['Extérieur', 'Forêt', 'Montagne', 'Marais', 'Glace', 'Equitation'] const CODES_COMPETENCES_VOYAGE = ['Extérieur', 'Forêt', 'Montagne', 'Marais', 'Glace', 'Equitation']
const TABLEAU_FATIGUE_MARCHE = [ const TABLEAU_FATIGUE_MARCHE = [
@ -36,7 +37,7 @@ export class DialogFatigueVoyage extends Dialog {
const parameters = { const parameters = {
tableauFatigueMarche: TABLEAU_FATIGUE_MARCHE, tableauFatigueMarche: TABLEAU_FATIGUE_MARCHE,
playerActors: game.actors.filter(actor => actor.isPersonnageJoueur()) playerActors: game.actors.filter(actor => actor.isPersonnageJoueur())
.map(actor => DialogFatigueVoyage.prepareActor(actor)), .map(actor => DialogFatigueVoyage.prepareActorParameters(actor)),
nombreHeures: 1, nombreHeures: 1,
} }
DialogFatigueVoyage.setModeDeplacement(parameters, undefined, undefined) DialogFatigueVoyage.setModeDeplacement(parameters, undefined, undefined)
@ -53,21 +54,37 @@ export class DialogFatigueVoyage extends Dialog {
parameters.typeTerrain = ligneFatigueMarche parameters.typeTerrain = ligneFatigueMarche
parameters.vitesseDeplacement = rythme.vitesse parameters.vitesseDeplacement = rythme.vitesse
parameters.fatigueHoraire = rythme.fatigue parameters.fatigueHoraire = rythme.fatigue
parameters.playerActors.forEach(voyageur =>
DialogFatigueVoyage.selectSurvie(voyageur, parameters.typeTerrain.code)
)
} }
static prepareActor(actor) { static prepareActorParameters(actor) {
const competencesVoyage = {} const actorParameters = {
CODES_COMPETENCES_VOYAGE.forEach(codeSurvie => id: actor.id,
competencesVoyage[codeSurvie] = RdDItemCompetence.findCompetence(actor.itemTypes[TYPES.competence], codeSurvie, { onMessage: () => { } })
)
return {
actor: actor, actor: actor,
selected: true, selected: true,
ajustementFatigue: 0, ajustementFatigue: 0,
competencesVoyage: competencesVoyage survies: {}
} }
const competencesVoyage = {}
CODES_COMPETENCES_VOYAGE.forEach(codeSurvie => {
competencesVoyage[codeSurvie] = RdDItemCompetence.findCompetence(actor.itemTypes[ITEM_TYPES.competence], codeSurvie, { onMessage: () => { } })
})
TABLEAU_FATIGUE_MARCHE.forEach(terrain => {
actorParameters.survies[terrain.code] = Misc.join(
terrain.survies.map(survie => {
const niveau = competencesVoyage[survie]?.system.niveau
return `${survie}: ${niveau}`
}),
', ')
})
return actorParameters
} }
static selectSurvie(actorParameters, code) {
actorParameters.survieCourante = actorParameters.survies[code]
}
constructor(html, parameters) { constructor(html, parameters) {
const options = { const options = {
@ -97,6 +114,7 @@ export class DialogFatigueVoyage extends Dialog {
this.html.find('select[name="code-terrain"]').change(event => this.changeParameters()) this.html.find('select[name="code-terrain"]').change(event => this.changeParameters())
this.html.find('select[name="vitesse-deplacement"]').change(event => this.changeParameters()) this.html.find('select[name="vitesse-deplacement"]').change(event => this.changeParameters())
this.html.find('input[name="nombre-heures"]').change(event => this.changeParameters()) this.html.find('input[name="nombre-heures"]').change(event => this.changeParameters())
this.html.find('.list-item input[name="ajustement-fatigue"]').change(event => this.changeParameters())
this.html.find('button[name="appliquer-fatigue"]').click(event => this.appliquerFatigue()) this.html.find('button[name="appliquer-fatigue"]').click(event => this.appliquerFatigue())
} }
@ -118,6 +136,10 @@ export class DialogFatigueVoyage extends Dialog {
selectVitesseDeplacement.append(await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs', rythme)) selectVitesseDeplacement.append(await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs', rythme))
}) })
selectVitesseDeplacement.val(this.parameters.vitesseDeplacement).change() selectVitesseDeplacement.val(this.parameters.vitesseDeplacement).change()
Promise.all(this.getActorRows()
.map(async row => row.find('label.voyage-liste-survies').text(this.$extractActorParameters(row).survieCourante)
))
} }
} }
@ -132,16 +154,24 @@ export class DialogFatigueVoyage extends Dialog {
} }
async setFatigue() { async setFatigue() {
this.html.find('input[name="base-fatigue"]').val(this.parameters.nombreHeures * this.parameters.fatigueHoraire) const baseFatigue = this.parameters.nombreHeures * this.parameters.fatigueHoraire
this.html.find('input[name="base-fatigue"]').val(baseFatigue)
this.updateActorTotalFatigue(baseFatigue)
}
async updateActorTotalFatigue(baseFatigue) {
Promise.all(this.getActorRows()
.map(async row => {
const actor = this.$extractActorParameters(row)
row.find('input[name="total-fatigue"]').val(actor.ajustement + baseFatigue)
}))
} }
async appliquerFatigue() { async appliquerFatigue() {
const fatigueBase = parseInt(this.html.find('input[name="base-fatigue"]').val() ?? 0) const fatigueBase = parseInt(this.html.find('input[name="base-fatigue"]').val() ?? 0)
const actors = jQuery.map( this.getActorRows()
this.html.find('div.fatigue-actors-list li.list-item'), .map(row => this.$extractActorParameters(row))
it => this.$extractActor(this.html.find(it)) .filter(it => it.selected)
)
actors.filter(it => it.selected)
.forEach(async it => { .forEach(async it => {
const perteFatigue = fatigueBase + it.ajustement const perteFatigue = fatigueBase + it.ajustement
ChatMessage.create({ ChatMessage.create({
@ -161,16 +191,24 @@ export class DialogFatigueVoyage extends Dialog {
}) })
} }
$extractActor(actorRow) { getActorRows() {
const actor = game.actors.get(actorRow.data('actor-id')) return jQuery.map(
this.html.find('div.fatigue-actors-list li.list-item'),
it => this.html.find(it))
}
$extractActorParameters(actorRow) {
const actorId = actorRow.data('actor-id')
const actorParameters = this.parameters.playerActors.find(it => it.id == actorId)
const actor = game.actors.get(actorId)
if (!actor) { if (!actor) {
ui.notifications.warn(`Acteur ${it.actorId} introuvable`) ui.notifications.warn(`Acteur ${it.actorId} introuvable`)
return {}
} }
return { actorParameters.ajustement = parseInt(actorRow.find('input[name="ajustement-fatigue"]').val() ?? 0)
actor: actor, actorParameters.selected = actor && actorRow.find('input[name="selectionner-acteur"]').is(':checked')
ajustement: parseInt(actorRow.find('input[name="ajustement-fatigue"]').val() ?? 0), return actorParameters
selected: actor && actorRow.find('input[name="selectionner-acteur"]').is(':checked')
}
} }
async close() { async close() {

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 56 KiB

View File

@ -572,6 +572,15 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) {
border: none; border: none;
padding: 0.1rem; padding: 0.1rem;
} }
.context-menu-img {
max-width: 2rem;
max-height: 1rem;
flex-grow: 0;
margin: 0.2rem 0.3rem 0 0;
vertical-align: middle;
border: none;
padding: 0rem;
}
.button-img { .button-img {
vertical-align: baseline; vertical-align: baseline;
@ -1374,7 +1383,7 @@ table.table-nombres-astraux tr:hover {
flex-direction: column; flex-direction: column;
position: absolute; position: absolute;
top: 4.6rem; top: 4.6rem;
right: 3.5rem; left: -19rem;
} }
.token-hud-ext.soins { .token-hud-ext.soins {
flex-direction: column; flex-direction: column;

View File

@ -1,8 +1,8 @@
{ {
"id": "foundryvtt-reve-de-dragon", "id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon", "title": "Rêve de Dragon",
"version": "12.0.6", "version": "12.0.10",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.6.zip", "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.10.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", "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", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": { "compatibility": {

View File

@ -21,6 +21,7 @@
"race": "Humain", "race": "Humain",
"yeux": "", "yeux": "",
"cheveux": "", "cheveux": "",
"taille": "",
"poids": "", "poids": "",
"heure": "", "heure": "",
"sexe": "", "sexe": "",

View File

@ -25,7 +25,7 @@
<span class="competence-value">{{plusMoins arme.system.niveau}}</span> <span class="competence-value">{{plusMoins arme.system.niveau}}</span>
<span class="competence-value">{{plusMoins arme.system.dommagesReels}}</span> <span class="competence-value">{{plusMoins arme.system.dommagesReels}}</span>
<span class="competence-value"></span> <span class="competence-value"></span>
<span class="initiative-value arme-initiative"><a data-tooltip="{{arme.name}}: initiative {{plusMoins arme.system.initiative}}">{{arme.system.initiative}}</a></span> <span class="initiative-value arme-initiative"><a data-tooltip="{{arme.name}}: initiative {{arme.system.initiative}}">{{arme.system.initiative}}</a></span>
</li> </li>
{{/each}} {{/each}}
{{#each esquives as |esq key|}} {{#each esquives as |esq key|}}

View File

@ -1,5 +1,5 @@
<h4>Tirage aléatoire: {{typeName}}</h4> <h4>Tirage aléatoire: {{document.name}}</h4>
<div>{{document.pack}}</div> <div>Tirage de {{typeName}} aléatoire depuis {{document.pack}}</div>
<div>Jet {{roll.formula}} : {{roll.total}}{{percentages}}</div> <div>Jet {{roll.formula}} : {{roll.total}}{{percentages}}</div>
<hr> <hr>
<div> <div>
@ -15,4 +15,4 @@
{{{document.system.description}}} {{{document.system.description}}}
</div> </div>
{{/if}} {{/if}}
</div> </div>

View File

@ -3,3 +3,5 @@
<option value="{{competence.name}}">{{competence.name}}</option> <option value="{{competence.name}}">{{competence.name}}</option>
{{/if}} {{/if}}
{{/each}} {{/each}}
<option value="O/H/N/T">Oniros/Hypnos/Narcos/Thanatos</option>
<option value="O/H/N">Oniros/Hypnos/Narcos</option>

View File

@ -0,0 +1,13 @@
<form autocomplete="off" onsubmit="event.preventDefault();">
{{#each groups as |group key|}}
<h3>{{key}}</h3>
<ul>
{{#each group as |regle r|}}
<li>
<input class="select-option" type="checkbox" name="{{regle.id}}" {{#if regle.active}}checked{{/if}}/>
<label>{{regle.descr}}</label>
</li>
{{/each}}
</ul>
{{/each}}
</form>

View File

@ -42,7 +42,8 @@
<li class="competence-header flexrow"> <li class="competence-header flexrow">
<span class="flex-grow-2">Personnage</span> <span class="flex-grow-2">Personnage</span>
<span class="flex-grow-2">Survies</span> <span class="flex-grow-2">Survies</span>
<span class="flex-grow-1" data-tooltip="Ajustements à appliquer pour les personnages se reposant (par exemple, à cheval)">Ajustements</span> <span class="flex-grow-1" data-tooltip="Ajustements à appliquer (par exemple, repos à cheval)">Ajustements</span>
<span class="flex-grow-1" data-tooltip="Total de fatigue pour le voyageur">Total</span>
</li> </li>
{{#each playerActors as |selected|}} {{#each playerActors as |selected|}}
{{>'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs' voyageur=selected survies=@root.typeTerrain.survies}} {{>'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs' voyageur=selected survies=@root.typeTerrain.survies}}

View File

@ -8,16 +8,13 @@
</span> </span>
<span class="flex-grow-2"> <span class="flex-grow-2">
<div class="flexcol "> <div class="flexcol ">
<label class="voyage-liste-survies"> <label class="voyage-liste-survies">{{voyageur.survieCourante}}</label>
{{#each voyageur.competencesVoyage as |comp key|}}
{{#if (array-includes ../survies key)}}
{{key}} {{comp.system.niveau}},
{{/if}}
{{/each}}
</label>
</div> </div>
</span> </span>
<span class="flex-grow-1"> <span class="flex-grow-1">
<input type="number" name="ajustement-fatigue" class="number-x2 ajustement-fatigue" data-dtype="Number" value="{{voyageur.ajustementFatigue}}" min="-6" max="6"/> <input type="number" name="ajustement-fatigue" class="number-x2 ajustement-fatigue" data-dtype="Number" value="{{voyageur.ajustementFatigue}}" min="-6" max="6"/>
</span> </span>
<span class="flex-grow-1">
<input type="number" name="total-fatigue" class="number-x2 total-fatigue" data-dtype="Number" value="1" min="0" max="24" disabled/>
</span>
</li> </li>