foundryvtt-wh4-lang-fr-fr/modules/import-stat-2.js

362 lines
16 KiB
JavaScript
Raw Normal View History

2020-11-08 00:22:04 +01:00
/************************************************************************************/
2020-11-08 23:12:52 +01:00
// Some internal test strings
let strfr = `LA TERREUR DE LA TEUFEL, TROLL DE RIVIÈRE RUSÉ
M
CC CT
F
E
I
Ag Dex Int FM Soc B
4
40 15
55
45
20
15 15 30 20 5 38
Traits : Amphibie, Arme +9, Armure (2), Dur à Cuire, Insensible
à la douleur, Morsure +8, Régénération, Taille (Grande), Vision
Nocturne, Vomissement`
2020-11-08 00:22:04 +01:00
let str1 = `JABBERSLYTHE
2020-11-07 13:46:15 +01:00
M WS BS S T I Agi Dex
Int WP Fel W
7 45 40 55
50 20 35 - 10 20 - 20
Traits: Armour 3, Bestial, Bite+9, Bounce, Corrosive
Blood, Distracting, Infected, Maddening Aura (see
page 17), Night Vision, Size (Enormous), Tail +8,
Tongue Attack +5 (12), Venom, Weapon +9.
`;
2020-11-08 00:22:04 +01:00
let str = `REINER AND DIETER LEDERMANN
SMUGGLERS (BRASS 3)
M WS BS S
T
I
Agi Dex Int WP Fel W
4
33 33 32 35 38 41 39 33 37 38 12
Traits: Weapon (Dagger +5, Sword +7)
Skills: Bribery 43, Charm 43, Cool 42,
Consume Alcohol 45, Gossip 43, Haggle 43,
Lore (Local 38), Perception 43,
Secret Signs (Smuggler) 37
Talents: Briber, Criminal, Dealmaker,
Etiquette (Criminals, Doktor, Guilder)
Trappings: Dagger, Hand Weapon (Sword)
`
2022-09-01 08:18:00 +02:00
//import ItemWfrp4e from "/systems/wfrp4e/modules/item/item-wfrp4e.js"
//import ItemWfrp4e from "/systems/wfrp4e/wfrp4e.js"
2020-11-07 13:46:15 +01:00
2020-11-08 23:12:52 +01:00
/************************************************************************************/
2020-11-07 13:46:15 +01:00
import "./xregexp-all.js";
const us_carac = 'm\\s+ws\\s+bs\\s+s\\s+t\\s+i\\s+agi?\\s+dex\\s+int\\s+\\wp\\s+fel\\s+w';
const fr_carac = 'm\\s+cc\\s+ct\\s+f\\s+e\\s+i\\s+agi?\\s+dex\\s+int\\s+fm\\s+soc\\s+b';
2022-01-30 09:18:49 +01:00
const carac_val = '(?<m>[0-9\\-]+)\\s+(?<ws>[0-9\\-]+)\\s+(?<bs>[0-9\\-]+)\\s+(?<s>[0-9\\-]+)\\s+(?<t>[0-9\\-]+)\\s+(?<i>[0-9\\-]+)\\s+(?<ag>[0-9\\-]+)\\s+(?<dex>[0-9\\-]+)\\s+(?<int>[0-9\\-]+)\\s+(?<wp>[0-9\\-]+)\\s+(?<fel>[0-9\\-]+)\\s+(?<w>[0-9\\-\*]+)';
2020-11-10 15:01:06 +01:00
const name_val = '(?<name>[a-zA-Z\\s\\-,]*)[\\s\\r\\na-zA-Z]*(?<tiers>.*|[\\(\\)a-z0-9]+)';
let sectionDataFR = [
{ name: "trait", toFind: "Traits\\s*:", secondParse: '(?<name>[a-zàéè\\s]*)[\\s\\+]*(?<value>.*|[\\+0-9]+)', index: -1 },
{ name: "skill", toFind: "Compétences\\s*:", secondParse: '(?<name>[a-zàéè\\s\\(\\)]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
{ name: "talent", toFind: "Talents\\s*:", secondParse: '(?<name>[a-zàéè\\-\\s!/]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
{ name: "mutation", toFind: "Mutations\\s*:", secondParse: '(?<name>[a-zàéè\\s]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
{ name: "trapping", toFind: "Equiement\\s*:", secondParse: '(?<name>[a-zàéè\\s]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 }
];
let sectionDataUS = [
2021-11-02 21:03:04 +01:00
{ name: "trait", toFind: "Traits\\s*:", secondParse: '(?<name>[a-z\\s]*)[\\s\\+]*(?<value>.*|[\\+0-9]+)', index: -1 },
2021-07-29 22:53:35 +02:00
{ name: "skill", toFind: "Skills\\s*:", secondParse: '(?<name>[a-z\\s\\(\\)]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
{ name: "talent", toFind: "Talents\\s*:", secondParse: '(?<name>[a-z\\-\\s!/]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
2021-11-02 21:03:04 +01:00
{ name: "mutation", toFind: "Mutations\\s*:", secondParse: '(?<name>[a-z\\s]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
2021-07-29 22:53:35 +02:00
{ name: "trapping", toFind: "Trappings\\s*:", secondParse: '(?<name>[a-z\\s]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 }
];
2020-11-08 00:22:04 +01:00
let regSep = XRegExp('\\s*,\\s*', 'gi'); // Term separator, with auto trim
2020-11-08 23:39:47 +01:00
let regLine1 = XRegExp('[\\r\\n\\.]', 'gi'); // Term separator, with auto trim
2020-11-08 23:12:52 +01:00
let regName = XRegExp(name_val, 'gi');
2020-11-07 13:46:15 +01:00
2020-11-08 00:22:04 +01:00
/************************************************************************************/
2020-11-08 23:12:52 +01:00
async function __findItem(itemName, itemType, location = null) {
2021-07-29 22:53:35 +02:00
let toSearch = itemName.toLowerCase().trim();
let items = game.items.contents.filter(i => i.type == itemType)
2020-11-08 23:12:52 +01:00
// Search imported items first
for (let i of items) {
if (i.name == itemName && i.type == itemType)
return i;
}
let itemList
// find pack -> search pack -> return entity
if (location) {
let pack = game.packs.find(p => {
location.split(".")[0] == p.metadata.package &&
location.split(".")[1] == p.metadata.name
})
if (pack) {
2021-07-29 22:53:35 +02:00
await pack.getIndex().then(index => itemList = index);
let searchResult = itemList.find(t => (t.translated && t.originalName.toLowerCase() == toSearch) || (t.name.toLowerCase() == toSearch) );
if (searchResult)
return await pack.getDocument(searchResult._id)
2020-11-08 23:12:52 +01:00
}
}
// If all else fails, search each pack
2021-07-29 22:53:35 +02:00
for (let p of game.wfrp4e.tags.getPacksWithTag(itemType)) {
await p.getIndex().then(index => itemList = index);
let searchResult = itemList.find(t => (t.translated && t.originalName.toLowerCase() == toSearch) || (t.name.toLowerCase() == toSearch) );
if (searchResult)
return await p.getDocument(searchResult._id)
2020-11-08 23:12:52 +01:00
}
}
2020-11-07 13:46:15 +01:00
2021-07-29 22:53:35 +02:00
2020-11-08 23:12:52 +01:00
/************************************************************************************/
2021-07-29 22:53:35 +02:00
async function __findSkill(skillName, value = undefined) {
let toSearch = skillName.toLowerCase().trim();
let parseStr = '(?<name>[a-z\\s]*)[\\s\\+]*(?<specialized>[a-z\\s\\(\\)]*)';
let skillSplit = XRegExp.exec(skillName, XRegExp(parseStr, 'gi'));
2020-11-08 23:12:52 +01:00
// First try world items
2021-07-29 22:53:35 +02:00
let worldItem = game.items.contents.filter(i => i.type == "skill" && i.name.toLowerCase() == toSearch)[0];
if (worldItem) return worldItem;
2020-11-08 23:12:52 +01:00
2021-07-29 22:53:35 +02:00
let packs = game.wfrp4e.tags.getPacksWithTag("skill");
2020-11-08 23:12:52 +01:00
for (let pack of packs) {
2021-07-29 22:53:35 +02:00
let skillList = await pack.getIndex();
// Search for specific skill (won't find unlisted specializations)
let searchResult = skillList.find(s => (s.translated && s.originalName.toLowerCase() == toSearch) || (s.name.toLowerCase() == toSearch ) );
if (!searchResult) {
let toSearchClean = toSearch.split("(")[0].trim();
searchResult = skillList.find(s => (s.translated && s.originalName.toLowerCase().split("(")[0].trim() == toSearchClean) ||
(s.name.toLowerCase().split("(")[0].trim() == toSearchClean) );
}
if (searchResult) {
let dbSkill;
await pack.getDocument(searchResult._id).then(packSkill => dbSkill = packSkill);
if (skillSplit.specialized && ( dbSkill.name.includes('()') || dbSkill.name.includes('( )' ) ) ) {
let spec = XRegExp.replace(skillSplit.specialized, "(", "");
spec = XRegExp.replace(spec, ")", "");
let skillSplit2 = XRegExp.exec(dbSkill.name, XRegExp(parseStr, 'gi'));
2022-09-30 20:56:12 +02:00
dbSkill.update( { name: skillSplit2.name + '(' + game.i18n.localize( spec.trim() ) + ')' } );
2020-11-08 23:12:52 +01:00
}
2021-07-29 22:53:35 +02:00
//game.babele.translate('wfrp4e-core.skills', dbSkill);
return dbSkill;
2020-11-08 23:12:52 +01:00
}
}
throw "Could not find skill (or specialization of) " + skillName + " in compendum or world"
}
/************************************************************************************/
async function __findTalent(talentName) {
2021-07-29 22:53:35 +02:00
let parseStr = '(?<name>[a-z\\s]*)[\\s\\+]*(?<specialized>[a-z\\s\\(\\)]*)';
let talentSplit = XRegExp.exec(talentName, XRegExp(parseStr, 'gi'));
let toSearch = talentSplit.name.toLowerCase().trim();
2020-11-08 23:12:52 +01:00
// First try world items
2021-07-29 22:53:35 +02:00
let worldItem = game.items.contents.filter(i => i.type == "talent" && i.name.toLowerCase() == toSearch)[0];
if (worldItem) return worldItem;
2020-11-08 23:12:52 +01:00
2021-07-29 22:53:35 +02:00
let packs = game.wfrp4e.tags.getPacksWithTag("talent");
2020-11-08 23:12:52 +01:00
for (let pack of packs) {
2021-07-29 22:53:35 +02:00
let talentList = await pack.getIndex();
// Search for specific skill (won't find unlisted specializations)
let searchResult = talentList.find(s => (s.translated && s.originalName.toLowerCase() == toSearch) || (s.name.toLowerCase() == toSearch ) );
if (!searchResult) {
let toSearchClean = toSearch.split("(")[0].trim();
searchResult = talentList.find(s => (s.translated && s.originalName.toLowerCase().split("(")[0].trim() == toSearchClean) ||
(s.name.toLowerCase().split("(")[0].trim() == toSearchClean) );
}
if (searchResult) {
let dbTalent;
await pack.getDocument(searchResult._id).then(packTalent => dbTalent = packTalent);
if ( talentSplit.specialized ) {
let spec = XRegExp.replace(talentSplit.specialized, "(", "");
spec = XRegExp.replace(spec, ")", "");
2022-09-30 20:56:12 +02:00
dbTalent.update( { name: talentSplit.name + '(' + game.i18n.localize( spec.trim() ) + ')' } );
2020-11-08 23:12:52 +01:00
}
2021-07-29 22:53:35 +02:00
return dbTalent;
2020-11-08 23:12:52 +01:00
}
}
throw "Could not find talent (or specialization of) " + talentName + " in compendium or world"
}
2021-11-02 21:03:04 +01:00
/************************************************************************************/
function __patchName ( name) {
if (name.toLowerCase == 'magic sense')
name = 'Magical Sense'
return name
2021-11-02 21:03:04 +01:00
}
2020-11-08 23:12:52 +01:00
/************************************************************************************/
2021-07-29 22:53:35 +02:00
export default async function statParserFR(statString, type = "npc") {
2020-11-08 23:12:52 +01:00
let model = duplicate(game.system.model.Actor[type]);
2020-11-08 00:22:04 +01:00
2022-01-30 09:18:49 +01:00
// Patch wront/strange carac value before processing
statString = statString.replace(/ /g, " 0")
let statNameReg = us_carac
let sectionData = sectionDataUS
// Detect French stat block
if (statString.includes('CC') && statString.includes('CT') && statString.includes('FM')) {
ui.notifications.warn("Le parsing de stablock en Français n'est pas encore prêt")
statNameReg = fr_carac
sectionData = sectionDataFR
}
let reg1 = XRegExp(statNameReg, 'gi')
let res = reg1.test(statString)
2020-11-08 00:22:04 +01:00
if (res) { //stat block identified go on
2020-11-08 23:12:52 +01:00
// Extract the name
let res1 = XRegExp.exec(statString, reg1)
console.log("REG", res1)
let pnjStr = statString.substring(0, res1.index)
let nameRes = XRegExp.exec(pnjStr, regName)
console.log(nameRes)
2021-07-29 22:53:35 +02:00
if (nameRes.tiers && nameRes.tiers.length > 0 && hasProperty(model, "details.status.value")) {
2020-11-08 23:12:52 +01:00
let regTiers = XRegExp("(?<name>[A-Za-z]*)\\s+(?<level>[0-9]*)");
let resTiers = XRegExp.exec(nameRes.tiers, regTiers);
console.log(resTiers);
2021-07-29 22:53:35 +02:00
model.details.status.value = game.i18n.localize(resTiers.name.trim()) + " " + resTiers.level;
2020-11-08 23:12:52 +01:00
}
// Compute the PNJ name
let pnjName = nameRes.name.split("—")[0].split(" ").filter(f => !!f);
pnjName = pnjName.map(word => {
2021-07-29 22:53:35 +02:00
if (word == "VON")
return word.toLowerCase();
2020-11-08 23:12:52 +01:00
2021-07-29 22:53:35 +02:00
word = word.toLowerCase();
word = word[0].toUpperCase() + word.substring(1, word.length);
return word;
2020-11-08 23:12:52 +01:00
})
pnjName = pnjName.join(" ")
// Get the carac values
let reg2 = XRegExp(carac_val, 'gi')
let resCarac = XRegExp.exec(statString, reg2) // resr contains all carac found
2021-07-29 22:53:35 +02:00
2020-11-08 23:12:52 +01:00
// Setup carac
2022-01-30 09:18:49 +01:00
//console.log("CARAC", resCarac)
if (resCarac["Agi"]) resCarac["Ag"] = resCarac["Agi"] // Auto patch
model.details.move.value = Number(resCarac["m"])
2020-11-08 23:12:52 +01:00
for (let key in model.characteristics) {
if (resCarac[key] === '-') resCarac[key] = 0
model.characteristics[key].initial = Number(resCarac[key])
2020-11-08 23:12:52 +01:00
}
//console.log("CARAC", model.characteristics);
2020-11-08 00:22:04 +01:00
// Search position of skills/talents/...
2021-07-29 22:53:35 +02:00
for (let def of sectionData) {
2020-11-08 00:22:04 +01:00
def.regDef = XRegExp(def.toFind, 'gi');
2020-11-08 23:12:52 +01:00
let res = XRegExp.exec(statString, def.regDef);
2021-07-29 22:53:35 +02:00
if (res) def.index = res.index; // Get the index in the string
2020-11-08 00:22:04 +01:00
//console.log(" Parsing", def.name, res);
}
2020-11-08 23:12:52 +01:00
// Sort to split position of various substring
2021-07-29 22:53:35 +02:00
sectionData.sort(function (a, b) { return a.index - b.index; });
2020-11-08 23:12:52 +01:00
let globalItemList = [];
// Then loop again and process each item type
2021-07-29 22:53:35 +02:00
for (let i = 0; i < sectionData.length; i++) {
2020-11-08 00:22:04 +01:00
let def = sectionData[i];
2021-07-29 22:53:35 +02:00
if (def.index > -1) {
let maxIndex = statString.length
2021-07-29 22:53:35 +02:00
if (sectionData[i + 1] && sectionData[i + 1].index > -1)
maxIndex = sectionData[i + 1].index
def.substring = statString.substring(def.index, maxIndex)
def.substring = XRegExp.replace(def.substring, def.regDef, "")
def.substring = XRegExp.replace(def.substring, regLine1, " ")
2020-11-08 23:12:52 +01:00
// At this point, def.substring contains the items list as a string
2021-07-29 22:53:35 +02:00
2020-11-08 23:12:52 +01:00
// Then create a table of it in termList, with specific sub-parsing rules
2020-11-08 00:22:04 +01:00
let termList = XRegExp.split(def.substring, regSep);
for (let name of termList) {
2021-07-29 22:53:35 +02:00
let itemFound, subres, value;
if (def.secondParse) {
subres = XRegExp.exec(name, XRegExp(def.secondParse, 'gi'))
name = subres.name.trim().replace("\n", "").replace("\r", "")
value = XRegExp.replace(subres.value, "(", "")
value = XRegExp.replace(value, ")", "")
2021-11-02 21:03:04 +01:00
}
name = __patchName(name)
2021-07-29 22:53:35 +02:00
if (def.name == 'trait') {
try {
itemFound = await __findItem(name, "trait")
2020-11-08 23:12:52 +01:00
}
2021-07-29 22:53:35 +02:00
catch { }
2021-11-02 21:03:04 +01:00
if (itemFound)
itemFound = itemFound.toObject()
if (itemFound && value && value.length > 0) {
if (name.toLowerCase() == 'weapon' || name.toLowerCase() == "bite" || name.toLowerCase() == "tail" ||
name.toLowerCase() == 'arme' || name.toLowerCase() == "morsure" || name.toLowerCase() == "queue") {
2022-09-30 20:56:12 +02:00
itemFound.system.specification.value = Number(value) - Math.floor( Number(model.characteristics.s.initial) / 10)
2021-11-02 21:03:04 +01:00
} else {
2022-09-30 20:56:12 +02:00
itemFound.system.specification.value = game.i18n.localize(value)
2021-11-02 21:03:04 +01:00
}
2020-11-08 23:12:52 +01:00
}
if (!itemFound)
2021-07-29 22:53:35 +02:00
ui.notifications.error("Trait non trouvé, à ajouter manuellement : " + name, { permanent: true })
2021-07-29 22:53:35 +02:00
} else if (def.name == 'skill') {
2020-11-08 23:12:52 +01:00
try {
2021-07-29 22:53:35 +02:00
itemFound = await __findSkill(name, value);
2020-11-08 23:12:52 +01:00
}
2021-07-29 22:53:35 +02:00
catch { }
2021-11-02 21:03:04 +01:00
if (itemFound)
itemFound = itemFound.toObject();
2021-07-29 22:53:35 +02:00
if (itemFound && subres && value) {
2022-09-30 20:56:12 +02:00
itemFound.system.advances.value = Number(value) - Number(model.characteristics[itemFound.system.characteristic.value].initial);
2020-11-08 13:53:15 +01:00
}
2020-11-08 23:12:52 +01:00
if (!itemFound)
ui.notifications.error("Compétence non trouvée, à ajouter manuellement : " + name, { permanent: true })
} else if (def.name == 'talent') {
try {
itemFound = await __findTalent(name);
}
2021-07-29 22:53:35 +02:00
catch { }
2021-11-02 21:03:04 +01:00
if (itemFound)
itemFound = itemFound.toObject();
2021-07-29 22:53:35 +02:00
if (itemFound && subres && value)
2022-09-30 20:56:12 +02:00
itemFound.system.advances.value = Number(value);
2020-11-08 23:12:52 +01:00
if (!itemFound)
ui.notifications.error("Talent non trouvé, à ajouter manuellement : " + name, { permanent: true })
} else if (def.name == 'trapping') {
try {
itemFound = await __findItem(name, "trapping");
}
2021-07-29 22:53:35 +02:00
catch { }
2021-11-02 21:03:04 +01:00
if (!itemFound && name) {
2022-09-01 08:18:00 +02:00
itemFound = new game.entities.ItemWfrp4e({ img: "systems/wfrp4e/icons/blank.png", name: name, type: "trapping", data: game.system.model.Item.trapping })
2022-09-30 20:56:12 +02:00
itemFound.system.trappingType.value = "misc"
2021-11-02 21:03:04 +01:00
}
if (itemFound)
itemFound = itemFound.toObject();
} else if (def.name == 'mutation') {
try {
itemFound = await __findItem(name, "mutation");
2021-07-29 22:53:35 +02:00
}
2021-11-02 21:03:04 +01:00
catch { }
if (itemFound)
itemFound = itemFound.toObject();
2020-11-08 00:22:04 +01:00
}
2021-11-02 21:03:04 +01:00
2020-11-08 23:12:52 +01:00
if (itemFound)
2021-07-29 22:53:35 +02:00
globalItemList.push(itemFound);
2020-11-08 00:22:04 +01:00
}
}
}
2020-11-08 23:12:52 +01:00
let moneyItems = await game.wfrp4e.utility.allMoneyItems() || [];
2022-09-30 20:56:12 +02:00
moneyItems = moneyItems.sort((a, b) => (a.system.coinValue.value > b.system.coinValue.value) ? -1 : 1);
moneyItems.forEach(m => m.system.quantity.value = 0)
2020-11-08 23:12:52 +01:00
globalItemList = globalItemList.concat(moneyItems);
//console.log("My liste :", globalItemList);
let name = pnjName;
2021-07-29 22:53:35 +02:00
2022-09-30 20:56:12 +02:00
let effects = globalItemList.reduce((total, globItem) => total.concat(globItem.effects), [])
2021-07-29 22:53:35 +02:00
effects = effects.filter(e => !!e)
effects = effects.filter(e => e.transfer)
return { name, type, data: model, items: globalItemList, effects }
2020-11-07 13:46:15 +01:00
}
2020-11-08 23:12:52 +01:00
// If the carac string has not been found
2021-07-29 22:53:35 +02:00
ui.notifications.error("Impossible de convertir ces statitiques, les caractéristiques n'ont pas été trouvées", { permanent: true })
2020-11-08 23:12:52 +01:00
}