Files
foundryvtt-reve-de-dragon/module/item-sort.js
Vincent Vandemeulebrouck 7fb0ee1659 await ChatMessage.create
ChatMessage.create est async, il faut donc de préférence
l'appeler avec un await.

Des effets secondaires avaient lieu (ordre de messages, updates
ultérieurs parfois pas pris en compte)
2026-05-02 00:42:45 +02:00

221 lines
8.0 KiB
JavaScript

import { Grammar } from "./grammar.js";
import { RdDItemCompetence } from "./item-competence.js";
import { ITEM_TYPES } from "./constants.js";
import { Misc } from "./misc.js";
import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js";
import { RdDItem } from "./item.js";
export const VOIES_DRACONIC = [
{ code: 'O', label: "Voie d'Oniros", short: 'Oniros', ordre: 'a' },
{ code: 'H', label: "Voie d'Hypnos", short: 'Hypnos', ordre: 'b' },
{ code: 'N', label: "Voie de Narcos", short: 'Narcos', ordre: 'c' },
{ code: 'T', label: "Voie de Thanatos", short: 'Thanatos', ordre: 'd' },
{ code: 'O/H/N/T', label: "Oniros/Hypnos/Narcos/Thanatos", short: 'O/H/N/T', ordre: 'e' },
{ code: 'O/H/N', label: "Oniros/Hypnos/Narcos", short: "O/H/N", ordre: 'f' }
]
/* -------------------------------------------- */
export class RdDItemSort extends RdDItem {
static preloadHandlebars() {
Handlebars.registerHelper('itemSort-codeDraconic', voie => RdDItemSort.getCode(voie))
Handlebars.registerHelper('itemSort-shortDraconic', voie => RdDItemSort.getShortVoie(voie))
Handlebars.registerHelper('itemSort-diffReve', sort => RdDItemSort.diffReve(sort))
Handlebars.registerHelper('itemSort-coutReve', sort => RdDItemSort.coutReve(sort))
}
static lancements(sort) { return sort?.system.lancements.length ?? 0 }
static findEnchantement(actor) { return RdDItemSort.findSort(actor, 'Enchantement', ['Narcos', 'N']) }
static findPermanence(actor) { return RdDItemSort.findSort(actor, 'Permanence', ['Narcos', 'N']) }
static findPurification(actor) { return RdDItemSort.findSort(actor, 'Purification', ['Narcos', 'N']) }
static findSort(actor, name, draconics) {
return actor.itemTypes[ITEM_TYPES.sort].find(it => Grammar.includesLowerCaseNoAccent(it.name, name)
&& (draconics == undefined || draconics.includes(it.system.draconic)))
}
static async changeLancementsSort(sort, changement) {
await sort?.update({ 'system.lancements': changement(sort.system.lancements) });
}
static toVar(value) {
return value ? value.replace('variable', 'var') : ''
}
static computeTotalXP(sorts) {
return sorts.map(sort => RdDItemSort.isDifficulteVariable(sort) ? 70 : -10 * Misc.toInt(sort.system.difficulte))
.reduce(Misc.sum(), 0)
}
static isSortOnCoord(sort, coord) {
let tmr = TMRUtility.getTMR(coord)
const caseTMR = sort.system.caseTMR.toLowerCase();
const caseTMRspeciale = sort.system.caseTMRspeciale.toLowerCase();
return caseTMR.includes('variable')
|| caseTMRspeciale.includes('variable')
|| (caseTMR == tmr.type)
|| (caseTMR.includes('special') && caseTMRspeciale.includes(coord.toLowerCase()))
}
static getCaseTMR(sort) {
const caseTMR = sort.system.caseTMR.toLowerCase();
const caseTMRspeciale = sort.system.caseTMRspeciale.toLowerCase();
if (caseTMR.includes('variable') || caseTMRspeciale.includes('variable') || caseTMR.includes('special')) {
return sort.system.caseTMRspeciale
}
return sort.system.caseTMR
}
static diffReve(sort) { return RdDItemSort.toVar((sort.system.difficulte.match(/\-?(\d)+/) ? 'R' : 'R ') + sort.system.difficulte) }
static coutReve(sort) { return RdDItemSort.toVar((Number.isInteger(sort.system.ptreve) || sort.system.ptreve.match(/(\d)+\+?/) ? 'r' : 'r ') + sort.system.ptreve) }
static getDraconicsSort(competencesDraconic, sort) {
// se baser sur la voie du sort?
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
case "lecture d'aura":
case "detection d'aura":
return competencesDraconic
case "annulation de magie":
return competencesDraconic.filter(it => !RdDItemCompetence.isThanatos(it))
}
const voies = sort.system.draconic.split('/')
return voies.map(voie => RdDItemCompetence.getVoieDraconic(competencesDraconic, voie))
}
static getBestDraconicSort(competencesDraconic, sort) {
return RdDItemSort.getDraconicsSort(competencesDraconic, sort).sort(Misc.descending(it => it.system.niveau)).find(it => true)
}
static getOrdreCode(code) {
return (VOIES_DRACONIC.find(it => it.code == code)?.ordre ?? '?')
}
static getCodeVoie(voie) {
return VOIES_DRACONIC.find(it => [it.code, it.short, it.label].includes(voie))?.code ?? '?'
}
static getShortVoie(voie) {
return VOIES_DRACONIC.find(it => [it.code, it.short, it.label].includes(voie))?.short ?? voie
}
static getCode(sort, codeVoies = ['O', 'H', 'N', 'T']) {
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
case "lecture d'aura":
case "detection d'aura":
return RdDItemSort.$voiesConnues('O/H/N/T', codeVoies)
case "annulation de magie":
return RdDItemSort.$voiesConnues('O/H/N', codeVoies)
}
return RdDItemSort.getCodeVoie(sort.system.draconic)
}
static $voiesConnues(voiesSort, voies) {
const codes = voies.filter(it => voiesSort.includes(it))
.sort(Misc.ascending(it => RdDItemSort.getOrdreCode(it)))
return Misc.join(codes ?? [''], '/');
}
/* -------------------------------------------- */
static isDifficulteVariable(sort) {
return sort && (sort.system.difficulte.toLowerCase() == "variable");
}
/* -------------------------------------------- */
static isCoutVariable(sort) {
return sort && !Number.isInteger(sort.system.ptreve) && (sort.system.ptreve.toLowerCase() == "variable" || sort.system.ptreve.indexOf("+") >= 0);
}
/* -------------------------------------------- */
static setCoutReveReel(sort) {
if (sort) {
sort.system.ptreve_reel = this.isCoutVariable(sort) ? 1 : sort.system.ptreve;
}
}
/* -------------------------------------------- */
static getDifficulte(sort, variable) {
if (sort && !RdDItemSort.isDifficulteVariable(sort)) {
return Misc.toInt(sort.system.difficulte);
}
return variable;
}
/**
* Retourne une liste de bonus/case pour un item-sheet
* @param {} item
*/
static getBonusCaseList(item) {
// Gestion spéciale case bonus
if (item.type == ITEM_TYPES.sort) {
return RdDItemSort.stringToBonuscases(item.system.bonuscase)
}
return [];
}
/* -------------------------------------------- */
static async incrementBonusCase(actor, sort, coord) {
let bonuscase = RdDItemSort.calculBonuscase(sort, coord)
await actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]);
}
static calculBonuscase(sort, coord) {
if (TMRUtility.isFleuve(coord)) {
coord = FLEUVE_COORD
}
let list = RdDItemSort.stringToBonuscases(sort.system.bonuscase)
const existing = list.find(it => it.case == coord)
const bonus = Number(existing?.bonus ?? 0) + 1
if (existing) {
existing.bonus = bonus
}
else {
list.push({ case: coord, bonus: 1 })
}
return RdDItemSort.bonuscasesToString(list)
}
/* -------------------------------------------- */
static getCaseBonus(sort, coord) {
const search = TMRUtility.isFleuve(coord)
? it => it.case == 'Fleuve'
: it => it.case == coord;
const bc = RdDItemSort.stringToBonuscases(sort.system.bonuscase)
.find(search)
return Number(bc?.bonus ?? 0);
}
static bonuscasesToString(list) {
return list.map(it => `${it.case}:${it.bonus}`)
.sort(Misc.ascending())
.join(',');
}
static stringToBonuscases(bonuscase) {
if (bonuscase == undefined || bonuscase == '') {
return []
}
return bonuscase.split(',')
.map(it => it.split(':'))
.map(it => { return { case: it[0], bonus: it[1] } });
}
static prepareSortEnReserve(sort, draconic, ptreve, coord) {
return {
type: ITEM_TYPES.sortreserve,
name: sort.name,
img: sort.img,
system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' }
};
}
static prepareSortAddLancement(sort, reveSort) {
const precedents = sort.system.lancements ?? []
const lancements = [...precedents, {
timestamp: game.system.rdd.calendrier.getTimestamp(),
reve: reveSort
}]
return lancements
}
}