Compare commits

..

1 Commits

Author SHA1 Message Date
dd296822bc Bouton "don de haut-rêve"
Pour permettre au MJ de rendre un personnage haut rêvant
sans avoir à chercher dans les compendiums
2024-12-03 23:32:43 +01:00
8 changed files with 91 additions and 119 deletions

View File

@ -169,10 +169,10 @@ export class Mapping {
arme: arme arme: arme
} }
} }
static dommagesArme(actor, arme, maniement) { static dommagesArme(actor, arme, maniement){
const dmgArme = RdDItemArme.dommagesReels(arme, maniement) const dmgArme = RdDItemArme.dommagesReels(arme, maniement)
const dommages = Misc.toSignedString(dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme)) const dommages = Misc.toSignedString(dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme))
switch (arme.system.mortalite) { switch(arme.system.mortalite) {
case 'non-mortel': return `(${dommages})` case 'non-mortel': return `(${dommages})`
case 'empoignade': return '-' case 'empoignade': return '-'
} }
@ -259,9 +259,6 @@ export class Mapping {
const diff = 'R' + RdDItemSort.addSpaceToNonNumeric(sort.system.difficulte) const diff = 'R' + RdDItemSort.addSpaceToNonNumeric(sort.system.difficulte)
return `${sort.name}${ptSeuil} (${caseTMR}) ${diff} ${coutReve}` return `${sort.name}${ptSeuil} (${caseTMR}) ${diff} ${coutReve}`
} }
static toVar(caseSpeciale) {
return Grammar.toLowerCaseNoAccent(caseSpeciale).startsWith('var') ? 'var' : caseSpeciale
}
static bonusCase(sort) { static bonusCase(sort) {
const list = RdDItemSort.stringToBonuscases(sort.system.bonuscase).sort(Misc.descending(it => it.bonus)) const list = RdDItemSort.stringToBonuscases(sort.system.bonuscase).sort(Misc.descending(it => it.bonus))

View File

@ -5,12 +5,12 @@ import { RdDBaseActorReve } from "../actor/base-actor-reve.js";
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js"; import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
import { RdDItemTete } from "../item/tete.js";
const WHITESPACES = "\\s+" const WHITESPACES = "\\s+"
const NUMERIC = "[\\+\\-]?\\d+" const NUMERIC = "[\\+\\-]?\\d+"
const NUMERIC_VALUE = "(?<value>" + NUMERIC + ")" const NUMERIC_VALUE = "(?<value>" + NUMERIC + ")"
const XREGEXP_NAME = "(?<name>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)"
const XREGEXP_COMP_CREATURE = WHITESPACES + "(?<carac>\\d+)" const XREGEXP_COMP_CREATURE = WHITESPACES + "(?<carac>\\d+)"
+ WHITESPACES + NUMERIC_VALUE + WHITESPACES + NUMERIC_VALUE
+ "(" + WHITESPACES + "(?<init>\\d+)?\\s+?(?<dommages>[\\+\\-]?\\d+)?" + ")?" + "(" + WHITESPACES + "(?<init>\\d+)?\\s+?(?<dommages>[\\+\\-]?\\d+)?" + ")?"
@ -22,12 +22,11 @@ const compParser = {
entite: XREGEXP_COMP_CREATURE entite: XREGEXP_COMP_CREATURE
} }
const XREGEXP_SORT_VOIE = "(?<voies>[OHNT](\\/[OHNT])*)" const XREGEXP_SORT_VOIE = "[OHNT\\/]+"
const XREGEXP_SORT_NAME = "(?<name>[^\\(]+)"
const XREGEXP_SORT_CASE = "\\((?<case>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)\\)"; const XREGEXP_SORT_CASE = "\\((?<case>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)\\)";
const XREGEXP_SORT = "(" + XREGEXP_SORT_VOIE const XREGEXP_SORT = "(" + XREGEXP_SORT_VOIE
+ WHITESPACES + XREGEXP_SORT_NAME + WHITESPACES + XREGEXP_NAME
+ WHITESPACES + XREGEXP_SORT_CASE + WHITESPACES + XREGEXP_SORT_CASE
+ WHITESPACES + "R(?<diff>([\\-\\d]+|(\\w|\\s)+))" + WHITESPACES + "R(?<diff>([\\-\\d]+|(\\w|\\s)+))"
+ WHITESPACES + "r(?<reve>(\\d+(\\+)?|\\s\\w+))" + WHITESPACES + "r(?<reve>(\\d+(\\+)?|\\s\\w+))"
@ -105,7 +104,7 @@ export class RdDStatBlockParser {
return "vaisseau"; return "vaisseau";
} }
static async parseStatBlock(statString) { static async parseStatBlock(statString, type = "npc") {
//statString = statBlock03; //statString = statBlock03;
if (!statString) { if (!statString) {
@ -123,10 +122,10 @@ export class RdDStatBlockParser {
statString = statString.trim(); statString = statString.trim();
// TODO: check for entite // TODO: check for entite
let type = RdDStatBlockParser.parseActorType(statString); let actorType = RdDStatBlockParser.parseActorType(statString);
// Now start carac // Now start carac
let actorData = foundry.utils.deepClone(game.model.Actor[type]); let actorData = foundry.utils.deepClone(game.model.Actor[actorType]);
for (let key in actorData.carac) { for (let key in actorData.carac) {
let caracDef = actorData.carac[key]; let caracDef = actorData.carac[key];
// Parse the stat string for each caracteristic // Parse the stat string for each caracteristic
@ -137,7 +136,7 @@ export class RdDStatBlockParser {
} }
// If creature we need to setup additionnal fields // If creature we need to setup additionnal fields
switch (type) { switch (actorType) {
case "creature": case "creature":
RdDStatBlockParser.parseCreature(statString, actorData) RdDStatBlockParser.parseCreature(statString, actorData)
break break
@ -148,14 +147,14 @@ export class RdDStatBlockParser {
let items = []; let items = [];
// Get skills from compendium // Get skills from compendium
const competences = await SystemCompendiums.getCompetences(type); const competences = await SystemCompendiums.getCompetences(actorType);
//console.log("Competences : ", competences); //console.log("Competences : ", competences);
for (let comp of competences) { for (let comp of competences) {
let compMatch = XRegExp.exec(statString, XRegExp(comp.name + compParser[type], 'giu')); let compMatch = XRegExp.exec(statString, XRegExp(comp.name + compParser[actorType], 'giu'));
if (compMatch) { if (compMatch) {
comp = comp.toObject() comp = comp.toObject()
comp.system.niveau = Number(compMatch.value); comp.system.niveau = Number(compMatch.value);
if (type == "creature" || type == "entite") { if (actorType == "creature" || actorType == "entite") {
comp.system.carac_value = Number(compMatch.carac); comp.system.carac_value = Number(compMatch.carac);
if (compMatch.dommages != undefined) { if (compMatch.dommages != undefined) {
comp.system.dommages = Number(compMatch.dommages); comp.system.dommages = Number(compMatch.dommages);
@ -164,7 +163,7 @@ export class RdDStatBlockParser {
} }
items.push(comp) items.push(comp)
} }
else if (type == "personnage") { else if (actorType == "personnage") {
comp = comp.toObject() comp = comp.toObject()
items.push(comp) items.push(comp)
} }
@ -214,101 +213,81 @@ export class RdDStatBlockParser {
} }
} }
if (type == "personnage") {
await RdDStatBlockParser.parseHautReve(statString, actorData, items);
RdDStatBlockParser.parsePersonnage(statString, actorData);
}
let name = RdDStatBlockParser.extractName(type, statString);
let newActor = await RdDBaseActorReve.create({ name, type: type, system: actorData, items });
await newActor.remiseANeuf()
// DUmp....
console.log(actorData);
}
static async parseHautReve(statString, actorData, items) {
let hautRevant = false;
// Attemp to detect spell // Attemp to detect spell
let sorts = await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-oniros"); let hautRevant = false
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-hypnos")); let sorts = await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-oniros")
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-narcos")); sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-hypnos"))
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-thanatos")); sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-narcos"))
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-thanatos"))
XRegExp.forEach(statString, XRegExp(XREGEXP_SORT, 'gu' /* keep case sensitive to match the spell draconic skill */), XRegExp.forEach(statString, XRegExp(XREGEXP_SORT, 'giu'),
function (matchSort, i) { function (matchSort, i) {
const sortName = Grammar.toLowerCaseNoAccent(matchSort.name).trim().replace("", "'"); let sort = sorts.find(s => Grammar.equalsInsensitive(s.name, matchSort.name))
let sort = sorts.find(s => Grammar.toLowerCaseNoAccent(s.name) == sortName)
if (sort) { if (sort) {
hautRevant = true; hautRevant = true
sort = sort.toObject(); sort = sort.toObject();
if (matchSort.bonus && matchSort.bonuscase) { if (matchSort.bonus && matchSort.bonuscase) {
sort.system.bonuscase = `${matchSort.bonuscase}:${matchSort.bonus}`; sort.system.bonuscase = `${matchSort.bonuscase}:${matchSort.bonus}`
} }
items.push(sort); items.push(sort);
} }
else{
ui.notifications.warn(`Impossible de trouver le sort ${matchSort.name} / ${sortName}`)
console.warn(`Impossible de trouver le sort ${matchSort.name} / ${sortName}`)
}
}); });
if (hautRevant) { if (hautRevant) {
const donHR = await RdDItemTete.teteDonDeHautReve(); const donHR = await RdDItemTete.teteDonDeHautReve()
if (donHR) { if (donHR) {
items.push(donHR.toObject()); items.push(donHR.toObject());
} }
const demiReve = XRegExp.exec(statString, XRegExp("Demi-rêve\\s+(?<value>[A-M]\\d{1,2})", 'giu'))
actorData.reve.tmrpos.coord = demiReve?.value ?? 'A1'
} }
} if (actorType == "personnage") {
static parsePersonnage(statString, actorData) {
actorData.reve.seuil.value = actorData.carac.reve.value
const reveActuel = XRegExp.exec(statString, XRegExp("Rêve actuel\\s+(?<value>\\d+)", 'giu')) let feminin = XRegExp.exec(statString, XRegExp("né(?<value>e?) à", 'giu'));
actorData.reve.reve.value = reveActuel?.value ? Number(reveActuel.value) : actorData.reve.seuil.value actorData.sexe = (feminin?.value == 'e') ? 'féminin' : 'masculin'
const feminin = XRegExp.exec(statString, XRegExp("né(?<value>e?) à", 'giu')); // Get hour name : heure du XXXXX
actorData.sexe = (feminin?.value == 'e') ? 'féminin' : 'masculin'; let heure = XRegExp.exec(statString, XRegExp("heure (du|de la|des|de l\')\\s*(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s]+),", 'giu'));
actorData.heure = this.getHeureKey(heure?.value || "Vaisseau");
// Get hour name : heure du XXXXX // Get age
const heure = XRegExp.exec(statString, XRegExp("heure (du|de la|des|de l\')\\s*(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s]+),", 'giu')); let age = XRegExp.exec(statString, XRegExp("(?<value>\\d+) ans", 'giu'));
actorData.heure = this.getHeureKey(heure?.value || "Vaisseau"); if (age?.value) {
actorData.age = Number(age.value);
}
// Get height
let taille = XRegExp.exec(statString, XRegExp("(?<value>\\d+m\\d+)", 'giu'));
if (taille?.value) {
actorData.taille = taille.value;
}
// Get weight
let poids = XRegExp.exec(statString, XRegExp("(?<value>\\d+) kg", 'giu'));
if (poids?.value) {
actorData.poids = poids.value;
}
// Get cheveux
let cheveux = XRegExp.exec(statString, XRegExp("kg,\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+),\\s+yeux", 'giu'));
if (cheveux?.value) {
actorData.cheveux = cheveux.value;
}
// Get yeux
let yeux = XRegExp.exec(statString, XRegExp("yeux\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+), Beau", 'giu'));
if (yeux?.value) {
actorData.yeux = yeux.value;
}
// Get age // Get beauty
const age = XRegExp.exec(statString, XRegExp("(?<value>\\d+) ans", 'giu')); let beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?<value>\\d+)", 'giu'));
if (age?.value) { if (beaute?.value) {
actorData.age = Number(age.value); actorData.beaute = Number(beaute.value);
} }
// Get height
const taille = XRegExp.exec(statString, XRegExp("(?<value>\\d+m\\d+)", 'giu'));
if (taille?.value) {
actorData.taille = taille.value;
}
// Get weight
const poids = XRegExp.exec(statString, XRegExp("(?<value>\\d+) kg", 'giu'));
if (poids?.value) {
actorData.poids = poids.value;
}
// Get cheveux
const cheveux = XRegExp.exec(statString, XRegExp("kg,\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+),\\s+yeux", 'giu'));
if (cheveux?.value) {
actorData.cheveux = cheveux.value;
}
// Get yeux
const yeux = XRegExp.exec(statString, XRegExp("yeux\\s+(?<value>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+), Beau", 'giu'));
if (yeux?.value) {
actorData.yeux = yeux.value;
} }
// Get beauty // Name is all string before ', né'
const beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?<value>\\d+)", 'giu')); let name = RdDStatBlockParser.extractName(actorType, statString);
if (beaute?.value) {
actorData.beaute = Number(beaute.value); let newActor = RdDBaseActorReve.create({ name: name || "Importé", type: actorType, system: actorData, items: items });
}
// DUmp....
console.log(actorData);
} }
static parseCreature(statString, actorData) { static parseCreature(statString, actorData) {
@ -370,17 +349,24 @@ export class RdDStatBlockParser {
static extractName(actorType, statString) { static extractName(actorType, statString) {
switch (actorType) { switch (actorType) {
case "personnage": case "personnage": return RdDStatBlockParser.extractNamePersonnage(statString);
// Name is all string before first comma ',' case "creature": return RdDStatBlockParser.extractNameCreature(statString);
const namePersonnage = XRegExp.exec(statString, XRegExp("(?<value>[\\p{Letter}\\s\\d]+),", 'giu')); }
if (namePersonnage?.value) { return RdDStatBlockParser.extractNameCreature(statString);
return Misc.upperFirst(namePersonnage?.value); }
}
static extractNamePersonnage(statString) {
let name = XRegExp.exec(statString, XRegExp("(?<value>[\\p{Letter}\\s\\d]+),", 'giu'));
if (!name?.value) {
name = XRegExp.exec(statString, XRegExp("(?<value>.+)\\s+taille", 'giu'));
} }
const name = XRegExp.exec(statString, XRegExp("(?<value>.+)\\s+taille", 'giu'));
return Misc.upperFirst(name?.value || "Importé"); return Misc.upperFirst(name?.value || "Importé");
} }
static extractNameCreature(statString) {
const name = XRegExp.exec(statString, XRegExp("(?<value>.+)\\s+taille", 'giu'));
return Misc.upperFirst(name?.value || "Importé");
}
} }
/************************************************************************************/ /************************************************************************************/

View File

@ -137,7 +137,7 @@ class _10_0_21_VehiculeStructureResistanceMax extends Migration {
} }
class _10_0_33_MigrationNomsDraconic extends Migration { class _10_0_33_MigrationNomsDraconic extends Migration {
get code() { return "competences-nom-draconic"; } get code() { return "competences-creature-parade"; }
get version() { return "10.0.33"; } get version() { return "10.0.33"; }
migrationNomDraconic(ancien) { migrationNomDraconic(ancien) {
@ -530,25 +530,15 @@ class _11_2_20_MigrationAstrologie extends Migration {
} }
} }
class _12_0_26_MigrationVoieSorts extends Migration { class _12_0_24_MigrationVoieSorts extends Migration {
get code() { return "migration-voies-sorts" } get code() { return "migration-voies-sorts" }
get version() { return "12.0.26" } get version() { return "12.0.24" }
async migrate() { async migrate() {
await this.applyItemsUpdates(items => items await this.applyItemsUpdates(items => items
.filter(it => [ITEM_TYPES.sort, ITEM_TYPES.sortreserve].includes(it.type)) .filter(it => ITEM_TYPES.sort == it.type)
.map(it => this.migrateSort(it)) .map(it => this.migrateSort(it))
) )
await this.applyItemsUpdates(items => items
.filter(it => ITEM_TYPES.competence == it.type && it.system.categorie == 'draconic')
.map(it => this.migrateDraconic(it))
)
}
migrateDraconic(it) {
return {
_id: it.id,
name: this.convertDraconic(it.name),
}
} }
migrateSort(it) { migrateSort(it) {
return { return {
@ -585,7 +575,6 @@ export class Migrations {
new _10_7_19_CategorieCompetenceCreature(), new _10_7_19_CategorieCompetenceCreature(),
new _10_7_19_PossessionsEntiteVictime(), new _10_7_19_PossessionsEntiteVictime(),
new _11_2_20_MigrationAstrologie(), new _11_2_20_MigrationAstrologie(),
new _12_0_26_MigrationVoieSorts()
]; ];
} }

View File

@ -1,4 +1,4 @@
name: Hypnos name: Voie d'Hypnos
type: competence type: competence
img: systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp img: systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp
_id: bt2cR4aE6lIOeg4F _id: bt2cR4aE6lIOeg4F

View File

@ -1,4 +1,4 @@
name: Oniros name: Voie d'Oniros
type: competence type: competence
img: systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp img: systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp
_id: nnR2UHelUaF8dxYn _id: nnR2UHelUaF8dxYn

View File

@ -1,4 +1,4 @@
name: Narcos name: Voie de Narcos
type: competence type: competence
img: systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp img: systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp
_id: u1Peok1EYkBcVsmN _id: u1Peok1EYkBcVsmN

View File

@ -1,4 +1,4 @@
name: Thanatos name: Voie de Thanatos
type: competence type: competence
img: systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp img: systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp
_id: dPlTQzvU3CEg5qKc _id: dPlTQzvU3CEg5qKc

View File

@ -1,9 +1,9 @@
{ {
"id": "foundryvtt-reve-de-dragon", "id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon", "title": "Rêve de Dragon",
"version": "12.0.26", "version": "12.0.24",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.26/rddsystem.zip", "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.24/rddsystem.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.26/system.json", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download//12.0.24/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": {
"minimum": "11", "minimum": "11",