Compare commits

...

11 Commits
12.0.24 ... v11

Author SHA1 Message Date
39ce66a26c Setup auto-publish action
Some checks failed
Release Creation / build (release) Failing after 1m18s
2024-12-03 14:30:18 +01:00
5265c013c1 Setup auto-publish action
Some checks failed
Release Creation / build (release) Failing after 15s
2024-12-03 14:15:43 +01:00
a03cee5d60 Setup auto-publish action 2024-12-03 14:12:19 +01:00
296c4babbb Setup auto-publish action
Some checks failed
Release Creation / build (release) Has been cancelled
2024-12-03 14:09:32 +01:00
d9c1804a08 Merge pull request 'Imports créatures et entités de cauchemar' (#727) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #727
2024-12-03 07:31:22 +01:00
fa375f8092 Améliorations parser
- armure équipée
- armes équipées
- ajout des bonus de cases
- dommages des créatures
- ajout des esquives spéciales
- fix édition feuilles de compétences créatures

- déplacement des valeurs de test en fin de fichier
2024-12-03 00:50:39 +01:00
a27e3894a0 Fix Import entités de cauchemar&créatures
- utiliser les carac liées au type d'entités
- fix: +dom&protection 0 ou négatifs
- fix compétences (qui peuvent ne pas avoir d'init)
2024-12-02 22:21:43 +01:00
ce8616c34e Merge compétences créatures/entités
Les deux compendiums n'avaient pas de raison d'être séparés
2024-12-02 22:21:43 +01:00
bbfac286a6 Amelioration parser : heures, cheveux, yeux et sorts 2024-12-01 14:22:40 +01:00
c0563efcfa Merge pull request 'Amélioration du parser' (#725) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #725
2024-12-01 12:38:50 +01:00
c481bad81a Amélioration du parser:
- correction de la taille (ne prennait que avant le 'm'
- ajout du sexe masculin/féminin
- correction heure de naissance (support heure composée, articles)
- support Unicode (nom, HN)
- support groupes de compétences (saut, danse +1)
- ignorer parenthèses dans ccompétences
- armes avec compétences accentuées
2024-11-30 22:32:00 +01:00
27 changed files with 541 additions and 537 deletions

View File

@ -27,7 +27,7 @@ jobs:
env:
version: ${{steps.get_version.outputs.version-without-v}}
url: https://www.uberwald.me/gitea/${{gitea.repository}}
manifest: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download//${{github.event.release.tag_name}}/system.json
manifest: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json
download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/rddsystem.zip
- name: Set up Node.js
@ -61,3 +61,14 @@ jobs:
./rddsystem.zip
system.json
api_key: '${{secrets.ALLOW_PUSH_RELEASE}}'
- name: Publish to Foundry server
uses: djlechuck/foundryvtt-publish-package-action@v1
with:
token: ${{ secrets.FOUNDRYVTT_RELEASE_TOKEN }}
id: 'foundryvtt-reve-de-dragon'
version: ${{github.event.release.tag_name}}
manifest: 'https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json'
notes: 'https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md'
compatibility-minimum: '12'
compatibility-verified: '12'

View File

@ -2,6 +2,373 @@
import "./xregexp-all.js";
import { SystemCompendiums } from "../settings/system-compendiums.js";
import { RdDBaseActorReve } from "../actor/base-actor-reve.js";
import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js";
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
const WHITESPACES = "\\s+"
const NUMERIC = "[\\+\\-]?\\d+"
const NUMERIC_VALUE = "(?<value>" + NUMERIC + ")"
const XREGEXP_NAME = "(?<name>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)"
const XREGEXP_COMP_CREATURE = WHITESPACES + "(?<carac>\\d+)"
+ WHITESPACES + NUMERIC_VALUE
+ "(" + WHITESPACES + "(?<init>\\d+)?\\s+?(?<dommages>[\\+\\-]?\\d+)?" + ")?"
// Skill parser depending on the type of actor
const compParser = {
personnage: "(\\D+)*" + WHITESPACES + NUMERIC_VALUE,
creature: XREGEXP_COMP_CREATURE,
entite: XREGEXP_COMP_CREATURE
}
const XREGEXP_SORT_VOIE = "[OHNT\\/]+"
const XREGEXP_SORT_CASE = "\\((?<case>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)\\)";
const XREGEXP_SORT = "(" + XREGEXP_SORT_VOIE
+ WHITESPACES + XREGEXP_NAME
+ WHITESPACES + XREGEXP_SORT_CASE
+ WHITESPACES + "R(?<diff>([\\-\\d]+|(\\w|\\s)+))"
+ WHITESPACES + "r(?<reve>(\\d+(\\+)?|\\s\\w+))"
+ "(" + WHITESPACES + "\\+(?<bonus>\\d+)\\s?%" + WHITESPACES + "en" + WHITESPACES + "(?<bonuscase>[A-M]\\d{1,2})" + ")?"
+ ")"
// Main class for parsing a stat block
export class RdDStatBlockParser {
static openInputDialog() {
let dialog = new Dialog({
title: "Import de stats de PNJ/Créatures",
content: `
<div>
<p>Coller le texte de la stat ici</p>
<textarea id="statBlock" style="width: 100%; height: 200px;"></textarea>
</div>
`,
buttons: {
ok: {
label: "OK",
callback: async (html) => {
let statBlock = html.find("#statBlock")[0].value;
await RdDStatBlockParser.parseStatBlock(statBlock);
dialog.close();
}
},
cancel: {
label: "Cancel"
}
}
});
dialog.render(true);
}
static fixWeirdPDF(statString) {
// Split the statString into lines
let lines = statString.split("\n");
let newLines = [];
let index = 0;
let nextType = "string";
// Loop through each line
for (let i = 0; i < lines.length; i++) {
// remove trailing spaces
lines[i] = lines[i].trim();
// Is it text ?
if (lines[i].match(/^[a-zA-Zéêè\s]+/)) {
if (nextType == "string") {
newLines[index] = lines[i];
nextType = "number";
} else {
console.log("Wrong sequence string detected...", lines[i], nextType);
}
}
// Is it a number ?
if (lines[i].match(/^[\d\s]+/)) {
if (nextType == "number") {
newLines[index] = newLines[index] + lines[i];
nextType = "string";
index++;
} else {
console.log("Wrong sequence number detected...", lines[i], nextType);
}
}
}
}
static getHeureKey(heure) {
for (let h of game.system.rdd.config.heuresRdD) {
if (h.label.toLowerCase() == heure.toLowerCase()) {
return h.value;
}
}
return "vaisseau";
}
static async parseStatBlock(statString, type = "npc") {
//statString = statBlock03;
if (!statString) {
return;
}
// Special function to fix strange/weird copy/paste from PDF readers
// Unused up to now : this.fixWeirdPDF(statString);
// Replace all endline by space in the statString
statString = statString.replace(/\n/g, " ");
// Remove all multiple spaces
statString = statString.replace(/\s{2,}/g, " ");
// Remove all leading and trailing spaces
statString = statString.trim();
// TODO: check for entite
let actorType = RdDStatBlockParser.parseActorType(statString);
// Now start carac
let actorData = foundry.utils.deepClone(game.model.Actor[actorType]);
for (let key in actorData.carac) {
let caracDef = actorData.carac[key];
// Parse the stat string for each caracteristic
let carac = XRegExp.exec(statString, XRegExp(caracDef.label + "\\s+(?<value>\\d+)", 'giu'));
if (carac?.value) {
actorData.carac[key].value = Number(carac.value);
}
}
// If creature we need to setup additionnal fields
switch (actorType) {
case "creature":
RdDStatBlockParser.parseCreature(statString, actorData)
break
case "entite":
RdDStatBlockParser.parseEntite(statString, actorData)
break
}
let items = [];
// Get skills from compendium
const competences = await SystemCompendiums.getCompetences(actorType);
//console.log("Competences : ", competences);
for (let comp of competences) {
let compMatch = XRegExp.exec(statString, XRegExp(comp.name + compParser[actorType], 'giu'));
if (compMatch) {
comp = comp.toObject()
comp.system.niveau = Number(compMatch.value);
if (actorType == "creature" || actorType == "entite") {
comp.system.carac_value = Number(compMatch.carac);
if (compMatch.dommages != undefined) {
comp.system.dommages = Number(compMatch.dommages);
comp.system.iscombat = true;
}
}
items.push(comp)
}
else if (actorType == "personnage") {
comp = comp.toObject()
items.push(comp)
}
}
// Now process weapons
const weapons = await SystemCompendiums.getWorldOrCompendiumItems("arme", "equipement")
//console.log("Equipement : ", equipment);
// TODO: les noms d'armes peuvent avoir un suffixe (à une main, lancée) qui détermine la compétence correspondante
// TODO: une arme peut être spécifique ("fourche"), ajouter une compétence dans ces cas là?
for (let weapon of weapons) {
let weapMatch = XRegExp.exec(statString, XRegExp(weapon.name + "\\s+(?<value>\\+\\d+)", 'giu'));
if (weapMatch) {
weapon = weapon.toObject()
weapon.system.equipe = 'true'
items.push(weapon)
// now process the skill
if (weapon.system?.competence != "") {
let wComp = items.find(i => Grammar.equalsInsensitive(i.name, weapon.system.competence))
if (wComp) {
wComp.system.niveau = Number(weapMatch.value);
}
}
if (weapon.system?.tir != "") {
let wComp = items.find(i => Grammar.equalsInsensitive(i.name, weapon.system.tir))
if (wComp) {
wComp.system.niveau = Number(weapMatch.value);
}
}
if (weapon.system?.lancer != "") {
let wComp = items.find(i => Grammar.equalsInsensitive(i.name, weapon.system.lancer))
if (wComp) {
wComp.system.niveau = Number(weapMatch.value);
}
}
}
}
// Now process armors
const armors = await SystemCompendiums.getWorldOrCompendiumItems("armure", "equipement")
for (let armor of armors) {
let matchArmor = XRegExp.exec(statString, XRegExp(armor.name, 'giu'));
if (matchArmor) {
armor = armor.toObject()
armor.system.equipe = true
items.push(armor);
}
}
// Attemp to detect spell
let hautRevant = false
let sorts = await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-oniros")
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-hypnos"))
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-narcos"))
sorts = sorts.concat(await SystemCompendiums.getWorldOrCompendiumItems("sort", "sorts-thanatos"))
XRegExp.forEach(statString, XRegExp(XREGEXP_SORT, 'giu'),
function (matchSort, i) {
let sort = sorts.find(s => Grammar.equalsInsensitive(s.name, matchSort.name))
if (sort) {
hautRevant = true
sort = sort.toObject();
if (matchSort.bonus && matchSort.bonuscase) {
sort.system.bonuscase = `${matchSort.bonuscase}:${matchSort.bonus}`
}
items.push(sort);
}
});
if (hautRevant) {
let tetes = await SystemCompendiums.getWorldOrCompendiumItems("tete", "tetes-de-dragon-pour-tous-personnages")
let donHR = tetes.find(t => Grammar.equalsInsensitive(t.name, "Don de Haut-Rêve"))
if (donHR) {
items.push(donHR.toObject());
}
}
if (actorType == "personnage") {
let feminin = XRegExp.exec(statString, XRegExp("né(?<value>e?) à", 'giu'));
actorData.sexe = (feminin?.value == 'e') ? 'féminin' : 'masculin'
// Get hour name : heure du XXXXX
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 age
let age = XRegExp.exec(statString, XRegExp("(?<value>\\d+) ans", 'giu'));
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 beauty
let beaute = XRegExp.exec(statString, XRegExp("beauté\\s+(?<value>\\d+)", 'giu'));
if (beaute?.value) {
actorData.beaute = Number(beaute.value);
}
}
// Name is all string before ', né'
let name = RdDStatBlockParser.extractName(actorType, statString);
let newActor = RdDBaseActorReve.create({ name: name || "Importé", type: actorType, system: actorData, items: items });
// DUmp....
console.log(actorData);
}
static parseCreature(statString, actorData) {
let plusDom = XRegExp.exec(statString, XRegExp("\\+dom\\s+(?<value>[\\+\\-]?\\d+)", 'giu'));
if (plusDom?.values) {
actorData.attributs.plusdom.value = Number(plusDom.value);
}
let protection = XRegExp.exec(statString, XRegExp("protection\\s+(?<value>[\\-]?\\d+)", 'giu'));
if (protection?.value) {
actorData.attributs.protection.value = Number(protection.value);
}
let endurance = XRegExp.exec(statString, XRegExp("endurance\\s+(?<value>\\d+)", 'giu'));
if (endurance?.value) {
actorData.sante.endurance.value = Number(endurance.value);
actorData.sante.endurance.max = Number(endurance.value);
}
let vie = XRegExp.exec(statString, XRegExp("vie\\s+(?<value>\\d+)", 'giu'));
if (vie.value) {
actorData.sante.vie.value = Number(vie.value);
actorData.sante.vie.max = Number(vie.value);
}
let vitesse = XRegExp.exec(statString, XRegExp("vitesse\\s+(?<value>[\\d\\/]+)", 'giu'));
if (vitesse?.value) {
actorData.attributs.vitesse.value = vitesse.value;
}
}
static parseEntite(statString, actorData) {
let plusDom = XRegExp.exec(statString, XRegExp("\\+dom\\s+(?<value>[\\+\\-]?\\d+)", 'giu'));
if (plusDom?.values) {
actorData.attributs.plusdom.value = Number(plusDom.value);
}
actorData.definition.categorieentite = 'cauchemar'
actorData.definition.typeentite = ENTITE_NONINCARNE
let endurance = XRegExp.exec(statString, XRegExp("endurance\\s+(?<value>\\d+)", 'giu'));
if (endurance?.value) {
actorData.sante.endurance.value = Number(endurance.value);
actorData.sante.endurance.max = Number(endurance.value);
actorData.definition.typeentite = ENTITE_INCARNE
}
let vitesse = XRegExp.exec(statString, XRegExp("vitesse\\s+(?<value>[\\d\\/]+)", 'giu'));
if (vitesse?.value) {
actorData.attributs.vitesse.value = vitesse.value;
}
}
static parseActorType(statString) {
let niveau = XRegExp.exec(statString, XRegExp("Niveau\\s+(?<value>[\\+\\-]?\\d+)", 'giu'))
let perception = XRegExp.exec(statString, XRegExp("perception\\s+(?<value>\\d+)", 'giu'))
if (perception?.value) {
return "creature"
}
if (niveau?.value) {
return "entite"
}
return "personnage"
}
static extractName(actorType, statString) {
switch (actorType) {
case "personnage": return RdDStatBlockParser.extractNamePersonnage(statString);
case "creature": return RdDStatBlockParser.extractNameCreature(statString);
}
return RdDStatBlockParser.extractNameCreature(statString);
}
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'));
}
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é");
}
}
/************************************************************************************/
// Some internal test strings
@ -76,7 +443,7 @@ Corps à corps
(0)
Esquive
+8
Escalade +4 / Saut +5 / Commerce +3 / Équitation
Escalade, Saut +4 / Commerce +3 / Équitation
+6 / Chirurgie 0 / Survie en extérieur +4 / Survie fo-
rêt +6 / Acrobatie -2 / Métallurgie +2 / Natation +3 /
Légendes -1 / Écriture -4
@ -194,240 +561,4 @@ Discrétion
Vigilance
13
+3
`
// Skill parser depending on the type of actor
const compParser = { personnage: "\\s+(?<value>[\\+\\-]?\\d+)", creature: "\\s+(?<carac>\\d+)\\s+(?<value>[\\+\\-]?\\d+)\\s?(?<init>\\d+)?\\s+?(?<dommages>\\+\\d+)?" };
// Main class for parsing a stat block
export class RdDStatBlockParser {
static openInputDialog() {
let dialog = new Dialog({
title: "Import de stats de PNJ/Créatures",
content: `
<div>
<p>Coller le texte de la stat ici</p>
<textarea id="statBlock" style="width: 100%; height: 200px;"></textarea>
</div>
`,
buttons: {
ok: {
label: "OK",
callback: async (html) => {
let statBlock = html.find("#statBlock")[0].value;
await RdDStatBlockParser.parseStatBlock(statBlock);
dialog.close();
}
},
cancel: {
label: "Cancel"
}
}
});
dialog.render(true);
}
static fixWeirdPDF(statString) {
// Split the statString into lines
let lines = statString.split("\n");
let newLines = [];
let index = 0;
let nextType = "string";
// Loop through each line
for (let i = 0; i < lines.length; i++) {
// remove trailing spaces
lines[i] = lines[i].trim();
// Is it text ?
if (lines[i].match(/^[a-zA-Zéêè\s]+/)) {
if ( nextType == "string" ) {
newLines[index] = lines[i];
nextType = "number";
} else {
console.log("Wrong sequence string detected...", lines[i], nextType);
}
}
// Is it a number ?
if (lines[i].match(/^[\d\s]+/)) {
if ( nextType == "number" ) {
newLines[index] = newLines[index] + lines[i];
nextType = "string";
index++;
} else {
console.log("Wrong sequence number detected...", lines[i], nextType);
}
}
}
}
static async parseStatBlock(statString, type = "npc") {
//statString = statBlock03;
if (!statString) {
return;
}
// Special function to fix strange/weird copy/paste from PDF readers
// Unused up to now : this.fixWeirdPDF(statString);
// Replace all endline by space in the statString
statString = statString.replace(/\n/g, " ");
// Remove all multiple spaces
statString = statString.replace(/\s{2,}/g, " ");
// Remove all leading and trailing spaces
statString = statString.trim();
let actorType = "personnage";
let perception = XRegExp.exec(statString.toLowerCase(), XRegExp("perception\\s+(?<value>\\d+)", 'gi'));
if (perception?.value ) {
actorType = "creature";
}
// Now start carac
let actorData = foundry.utils.deepClone(game.model.Actor[actorType]);
for (let key in game.model.Actor.personnage.carac) {
let caracDef = game.model.Actor.personnage.carac[key];
// Parse the stat string for each caracteristic
let carac = XRegExp.exec(statString.toLowerCase(), XRegExp(caracDef.label.toLowerCase()+"\\s+(?<value>\\d+)", 'gi'));
if (carac?.value) {
actorData.carac[key].value = Number(carac.value);
}
}
// If creature we need to setup additionnal fields
if (actorType == "creature") {
let plusDom = XRegExp.exec(statString.toLowerCase(), XRegExp("\\+dom\\s+(?<value>\\+\\d+)", 'gi'));
if (plusDom?.values) {
actorData.attributs.plusdom.value = Number(plusDom.value);
}
let protection = XRegExp.exec(statString.toLowerCase(), XRegExp("protection\\s+(?<value>\\d+)", 'gi'));
if (protection?.value) {
actorData.attributs.protection.value = Number(protection.value);
}
let endurance = XRegExp.exec(statString.toLowerCase(), XRegExp("endurance\\s+(?<value>\\d+)", 'gi'));
if (endurance?.value) {
actorData.sante.endurance.value = Number(endurance.value);
actorData.sante.endurance.max = Number(endurance.value);
}
let vie = XRegExp.exec(statString.toLowerCase(), XRegExp("vie\\s+(?<value>\\d+)", 'gi'));
if (vie.value) {
actorData.sante.vie.value = Number(vie.value);
actorData.sante.vie.max = Number(vie.value);
}
let vitesse = XRegExp.exec(statString.toLowerCase(), XRegExp("vitesse\\s+(?<value>[\\d\\/]+)", 'gi'));
if (vitesse?.value) {
actorData.attributs.vitesse.value = vitesse.value;
}
}
let items = [];
// Get skills from compendium
const competences = await SystemCompendiums.getCompetences(actorType);
//console.log("Competences : ", competences);
let allComp = competences.map(i => i.toObject())
for (let comp of allComp) {
let skill = XRegExp.exec(statString.toLowerCase(), XRegExp(comp.name.toLowerCase()+compParser[actorType], 'gi'));
if (skill) {
comp.system.niveau = Number(skill.value);
if (actorType == "creature") {
comp.system.carac_value = Number(skill.carac);
if (skill.init) {
comp.system.dommages = Number(skill.dommages);
comp.system.iscombat = true;
}
items.push(comp); // Only selective push
}
}
if (actorType == "personnage") {
items.push(comp); // Always push
}
}
// Now process weapons
const weapons = await SystemCompendiums.getWorldOrCompendiumItems("arme", "equipement")
//console.log("Equipement : ", equipment);
for (let w of weapons) {
let weapon = XRegExp.exec(statString.toLowerCase(), XRegExp(w.name.toLowerCase()+"\\s+(?<value>\\+\\d+)", 'gi'));
if (weapon) {
w.system.equipe = true
items.push(w.toObject());
// now process the skill
if ( w.system?.competence != "") {
let wComp = items.find(i => i.name.toLowerCase() == w.system.competence.toLowerCase());
if (wComp) {
wComp.system.niveau = Number(weapon.value);
}
}
if ( w.system?.tir != "") {
let wComp = items.find(i => i.name.toLowerCase() == w.system.tir.toLowerCase());
if (wComp) {
wComp.system.niveau = Number(weapon.value);
}
}
if ( w.system?.lancer != "") {
let wComp = items.find(i => i.name.toLowerCase() == w.system.lancer.toLowerCase());
if (wComp) {
wComp.system.niveau = Number(weapon.value);
}
}
}
}
// Now process armors
const armors = await SystemCompendiums.getWorldOrCompendiumItems("armure", "equipement")
for (let a of armors) {
let armor = XRegExp.exec(statString.toLowerCase(), XRegExp(a.name.toLowerCase(), 'gi'));
if (armor) {
a.system.equipe = true
items.push(a.toObject());
}
}
// Get hour name : heure du XXXXX
let heure = XRegExp.exec(statString.toLowerCase(), XRegExp("heure du\\s+(?<value>\\w+)", 'gi'));
if (heure?.value) {
actorData.heure = heure.value;
}
// Get age
let age = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>\\d+) ans", 'gi'));
if (age?.value) {
actorData.age = Number(age.value);
}
// Get height
let taille = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>\\d+)m\\d+", 'gi'));
if (taille?.value) {
actorData.taille = taille.value;
}
// Get weight
let poids = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>\\d+) kg", 'gi'));
if (poids?.value) {
actorData.poids = poids.value;
}
// Get beauty
let beaute = XRegExp.exec(statString.toLowerCase(), XRegExp("beauté\\s+(?<value>\\d+)", 'gi'));
if (beaute?.value) {
actorData.beaute = Number(beaute.value);
}
// Name is all string before ', né'
let name
if (actorType == "personnage") {
name = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>[\\w\\s\\d]+),", 'gi'));
if (!name?.value) {
name = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>.+)\\s+taille", 'gi'));
}
name = name?.value || "Importé";
}
if (actorType == "creature") {
name = XRegExp.exec(statString.toLowerCase(), XRegExp("(?<value>.+)\\s+taille", 'gi'));
name = name?.value || "Importé";
}
let newActor = RdDBaseActorReve.create({name: name || "Importé", type:actorType, system: actorData, items: items});
// DUmp....
console.log(actorData);
}
}
`

View File

@ -81,7 +81,7 @@ export class RdDItemCompetenceCreature extends Item {
static isParade(item) {
if (item.type == ITEM_TYPES.competencecreature) {
return armeData.system.categorie_parade || armeData.system.isparade
return item.system.categorie_parade || item.system.isparade
}
return false
}

View File

@ -32,7 +32,7 @@ export class SystemCompendiums extends FormApplication {
compendium: compendium,
default: SystemCompendiums._getDefaultCompendium(compendium),
setting: SystemCompendiums._getSettingCompendium(compendium)
});
})
game.settings.register(SYSTEM_RDD, definition.setting, {
name: definition.label,
@ -40,8 +40,8 @@ export class SystemCompendiums extends FormApplication {
scope: "world",
config: false,
type: String
});
});
})
})
game.settings.registerMenu(SYSTEM_RDD, "compendium-settings", {
name: "Choisir les compendiums système",
@ -71,16 +71,18 @@ export class SystemCompendiums extends FormApplication {
static async getCompetences(actorType) {
switch (actorType ?? 'personnage') {
case 'personnage': return await SystemCompendiums.getWorldOrCompendiumItems('competence', 'competences');
case 'creature': return await SystemCompendiums.getWorldOrCompendiumItems('competencecreature', 'competences-creatures');
case 'entite': return await SystemCompendiums.getWorldOrCompendiumItems('competencecreature', 'competences-entites');
case 'personnage':
return await SystemCompendiums.getWorldOrCompendiumItems('competence', 'competences')
case 'entite':
case 'creature':
return await SystemCompendiums.getWorldOrCompendiumItems('competencecreature', 'competences-creatures')
case 'vehicule': return [];
}
}
/* -------------------------------------------- */
static async getWorldOrCompendiumItems(itemType, compendium) {
let items = game.items.filter(it => it.type == itemType);
let items = game.items.filter(it => it.type == itemType)
if (compendium) {
const ids = items.map(it => it.id);
const names = items.map(it => it.name.toLowerCase());
@ -284,7 +286,7 @@ export class CompendiumTableHelpers {
}
/* -------------------------------------------- */
static async tableRowToChatMessage(row, type, options = {showSource: true}) {
static async tableRowToChatMessage(row, type, options = { showSource: true }) {
if (!row) {
return;
}

View File

@ -6,17 +6,16 @@ effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: generale
carac_value: 10
niveau: 1
default_diffLibre: -2
categorie: melee
categorie_parade: ''
iscombat: true
isnaturelle: true
ispossession: false
dommages: 0
mortalite: mortel
carac-value: null
isparade: false
ownership:
default: 0

View File

@ -6,17 +6,16 @@ effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
carac_value: 10
niveau: 1
default_diffLibre: -2
categorie: melee
categorie_parade: boucliers
iscombat: true
isnaturelle: true
ispossession: false
dommages: 0
mortalite: mortel
carac-value: null
isparade: true
ownership:
default: 0

View File

@ -1,22 +1,21 @@
_id: WsYnwR8GcOxfuCI0
name: Bras-Galet
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/competence_course.webp
img: systems/foundryvtt-reve-de-dragon/icons/compcreature-pierretenue.webp
effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
carac_value: 10
niveau: 1
default_diffLibre: -2
categorie: melee
categorie_parade: ''
iscombat: true
isnaturelle: true
ispossession: false
dommages: 1
mortalite: mortel
carac-value: null
isparade: false
ownership:
default: 0

View File

@ -6,10 +6,10 @@ effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
carac_value: 10
niveau: 1
default_diffLibre: -2
categorie: melee
categorie_parade: sans-armes
iscombat: true
isnaturelle: true

View File

@ -6,17 +6,16 @@ effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
carac_value: 10
niveau: 1
default_diffLibre: -2
categorie: melee
categorie_parade: ''
iscombat: true
isnaturelle: true
ispossession: false
dommages: 1
mortalite: mortel
carac-value: null
isparade: false
ownership:
default: 0

View File

@ -6,9 +6,9 @@ effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
carac_value: 10
niveau: 1
default_diffLibre: -2
categorie: melee
categorie_parade: dagues
iscombat: true

View File

@ -6,17 +6,16 @@ effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
carac_value: 10
niveau: 1
default_diffLibre: -2
categorie: melee
categorie_parade: epees-lourdes
iscombat: true
isnaturelle: true
isnaturelle: false
ispossession: false
dommages: 4
mortalite: mortel
carac-value: null
isparade: true
ownership:
default: 0

View File

@ -6,8 +6,8 @@ effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
carac_value: 10
niveau: 1
default_diffLibre: 0
categorie: generale
categorie_parade: ''

View File

@ -0,0 +1,35 @@
name: Esquive eau
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp
effects: []
system:
description: ''
descriptionmj: ''
carac_value: 10
niveau: 1
default_diffLibre: 0
categorie: generale
categorie_parade: ''
iscombat: false
isnaturelle: true
ispossession: false
dommages: 0
mortalite: mortel
isparade: false
ownership:
default: 0
folder: null
_stats:
compendiumSource: null
duplicateSource: null
coreVersion: '12.331'
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.24
createdTime: 1733182927319
modifiedTime: 1733182927336
lastModifiedBy: Hp9ImM4o9YRTSdfu
flags: {}
_id: Qrg3ADB9LOhGthaO
sort: 1300000
_key: '!items!Qrg3ADB9LOhGthaO'

View File

@ -1,15 +1,14 @@
_id: 0Ms9iKxqigNNpZEx
name: Esquive
name: Esquive sol
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp
effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
carac_value: 10
niveau: 1
default_diffLibre: 0
categorie: ''
categorie: generale
categorie_parade: ''
iscombat: false
isnaturelle: true
@ -20,10 +19,17 @@ system:
ownership:
default: 0
folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
compendiumSource: null
duplicateSource: null
coreVersion: '12.331'
_key: '!items!0Ms9iKxqigNNpZEx'
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.24
createdTime: 1733182930109
modifiedTime: 1733182930109
lastModifiedBy: Hp9ImM4o9YRTSdfu
flags: {}
_id: siPvW3hAMCJbrYvq
sort: 0
_key: '!items!siPvW3hAMCJbrYvq'

View File

@ -0,0 +1,35 @@
name: Esquive vol
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp
effects: []
system:
description: ''
descriptionmj: ''
carac_value: 10
niveau: 1
default_diffLibre: 0
categorie: generale
categorie_parade: ''
iscombat: false
isnaturelle: true
ispossession: false
dommages: 0
mortalite: mortel
isparade: false
ownership:
default: 0
folder: null
_stats:
compendiumSource: null
duplicateSource: null
coreVersion: '12.331'
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.24
createdTime: 1733182932133
modifiedTime: 1733182932133
lastModifiedBy: Hp9ImM4o9YRTSdfu
flags: {}
_id: 3ScoGTkQ0VBOpaX6
sort: 0
_key: '!items!3ScoGTkQ0VBOpaX6'

View File

@ -6,17 +6,16 @@ effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
categorie_parade: ''
iscombat: false
carac_value: 10
niveau: 1
default_diffLibre: -2
categorie: melee
categorie_parade: boucliers
iscombat: true
isnaturelle: true
ispossession: false
dommages: 0
mortalite: mortel
carac-value: null
isparade: false
ownership:
default: 0

View File

@ -7,7 +7,7 @@ system:
descriptionmj: ''
carac_value: 14
niveau: 2
default_diffLibre: 0
default_diffLibre: -4
categorie: draconic
categorie_parade: ''
iscombat: true

View File

@ -1,29 +0,0 @@
name: Possession
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp
effects: []
system:
description: <p>L'entit&eacute; tente de prendre possession du corps de sa victime.</p>
descriptionmj: ''
carac_value: 14
niveau: 2
default_diffLibre: 0
categorie: draconic
categorie_parade: ''
iscombat: true
isnaturelle: true
ispossession: true
dommages: 0
mortalite: mortel
isparade: false
_id: duVgxI3Cdko0KzAj
folder: null
sort: 0
ownership:
default: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
_key: '!items!duVgxI3Cdko0KzAj'

View File

@ -6,10 +6,10 @@ effects: []
system:
description: <p>Attaque ou parade avec un tentacule.</p>
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
carac_value: 10
niveau: 1
default_diffLibre: -2
categorie: melee
categorie_parade: boucliers
iscombat: true
isnaturelle: true

View File

@ -6,9 +6,9 @@ effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
carac_value: 10
niveau: 1
default_diffLibre: -2
categorie: melee
categorie_parade: ''
iscombat: true

View File

@ -1,29 +0,0 @@
_id: d5SZ09sFaG3cL2Rg
name: Bec
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp
effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
categorie_parade: ''
iscombat: true
isnaturelle: true
ispossession: false
dommages: 0
mortalite: mortel
isparade: false
ownership:
default: 0
folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
_key: '!items!d5SZ09sFaG3cL2Rg'

View File

@ -1,29 +0,0 @@
_id: lDZ3qUPKN35ob5TH
name: Grande morsure
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp
effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
categorie_parade: ''
iscombat: true
isnaturelle: true
ispossession: false
dommages: 2
mortalite: mortel
isparade: false
ownership:
default: 0
folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
_key: '!items!lDZ3qUPKN35ob5TH'

View File

@ -1,29 +0,0 @@
_id: 6eWCVDYLXXO1Z48D
name: Grandes griffes
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp
effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
categorie_parade: sans-armes
iscombat: true
isnaturelle: true
ispossession: false
dommages: 2
mortalite: mortel
isparade: false
ownership:
default: 0
folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
_key: '!items!6eWCVDYLXXO1Z48D'

View File

@ -1,30 +0,0 @@
_id: 9Y83OsQgeyR5oCdH
name: Griffes
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp
effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
categorie_parade: sans-armes
iscombat: true
isnaturelle: true
ispossession: false
dommages: 1
mortalite: mortel
carac-value: null
isparade: false
ownership:
default: 0
folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
_key: '!items!9Y83OsQgeyR5oCdH'

View File

@ -1,29 +0,0 @@
_id: j1xHCzfIeYKgXxoH
name: Morsure
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp
effects: []
system:
description: ''
descriptionmj: ''
carac_value: 0
niveau: 0
default_diffLibre: 0
categorie: ''
categorie_parade: ''
iscombat: true
isnaturelle: true
ispossession: false
dommages: 1
mortalite: mortel
isparade: false
ownership:
default: 0
folder: null
sort: 0
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
_key: '!items!j1xHCzfIeYKgXxoH'

View File

@ -1,29 +0,0 @@
name: Possession
type: competencecreature
img: systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp
effects: []
system:
description: <p>L'entit&eacute; tente de prendre possession du corps de sa victime.</p>
descriptionmj: ''
carac_value: 14
niveau: 2
default_diffLibre: -4
categorie: melee
categorie_parade: ''
iscombat: true
isnaturelle: true
ispossession: true
dommages: 0
mortalite: mortel
isparade: false
ownership:
default: 0
folder: null
sort: 0
_id: wDHR5UHWq568lfGa
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
_key: '!items!wDHR5UHWq568lfGa'

View File

@ -2,8 +2,8 @@
"id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon",
"version": "12.0.24",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/latest/rddsystem.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/latest/system.json",
"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.24/system.json",
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": {
"minimum": "11",
@ -53,7 +53,7 @@
]
}
},
"url": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/",
"url": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon",
"license": "LICENSE.txt",
"esmodules": [
"module/rdd-main.js"
@ -115,19 +115,6 @@
},
"flags": {}
},
{
"name": "competences-entites",
"label": "Compétences des Entités",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/competences-entites",
"banner": "systems/foundryvtt-reve-de-dragon/styles/img/ui/compendium_banner.webp",
"type": "Item",
"ownership": {
"PLAYER": "NONE",
"ASSISTANT": "OWNER"
},
"flags": {}
},
{
"name": "sorts-oniros",
"label": "Sorts d'Oniros",
@ -458,7 +445,7 @@
"label": "Méditations et Ecrits",
"system": "foundryvtt-reve-de-dragon",
"path": "packs/meditations-et-ecrits",
"banner": "systems/foundryvtt-reve-de-dragon/styles/img/ui/compendium_banner.webp",
"banner": "systems/foundryvtt-reve-de-dragon/styles/img/ui/compendium_banner.webp",
"type": "Item",
"ownership": {
"PLAYER": "NONE",
@ -513,7 +500,9 @@
"arts-et-divertissements",
"meditations-et-ecrits",
"recettes-alchimiques"
]
],
"color": null,
"folders": []
},
{
"name": "Le Haut-rêve",
@ -530,7 +519,9 @@
"ombres-de-thanatos",
"souffles-de-dragon",
"tetes-de-dragon-pour-haut-revants"
]
],
"color": null,
"folders": []
},
{
"name": "Découverte du monde",
@ -541,9 +532,10 @@
"entites",
"faune-flore-mineraux",
"competences-creatures",
"competences-entites",
"maladies-et-poisons"
]
],
"color": null,
"folders": []
},
{
"name": "Outils du Gardien",
@ -554,14 +546,16 @@
"macros",
"tarot-draconique",
"extrait-poetique"
]
],
"color": null,
"folders": []
}
]
],
"color": null
}
],
"socket": true,
"grid": {
"distance": 1,
"units": "m"
},
"primaryTokenAttribute": "sante.vie",
@ -590,4 +584,4 @@
"flags": {}
}
]
}
}