This commit is contained in:
alzer
2025-04-28 18:41:57 +02:00
commit 974b8cc491
290 changed files with 72502 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+366
View File
@@ -0,0 +1,366 @@
/*
game.wfrp4e.config.speciesSkills["human"] = [
"Soins aux animaux",
"Charme",
"Calme",
"Evaluation",
"Ragot",
"Marchandage",
"Langue (Bretonnien)",
"Langue (Wastelander)",
"Commandement",
"Savoir (Reikland)",
"Corps à corps (Base)",
"Projectiles (Arc)"
];
game.wfrp4e.config.speciesSkills["dwarf"] = [
"Resistenz à l'alcool",
"Calme",
"Resistenz",
"Divertissement (Raconter)",
"Evaluation",
"Intimidation",
"Langue (Khazalid)",
"Savoir (Nains)",
"Savoir (Geologie)",
"Savoir (Metallurgie)",
"Corps à corps (Base)",
"Métier (Au choix)"
];
game.wfrp4e.config.speciesSkills["halfling"] = [
"Charme",
"Resistenz à l'alcool",
"Esquive",
"Pari",
"Marchandage",
"Intuition",
"Langue (Mootland)",
"Savoir (Reikland)",
"Perception",
"Escamotage",
"Discrétion (Au choix)",
"Métier (Cuisinier)"
];
game.wfrp4e.config.speciesSkills["helf"] = [
"Calme",
"Divertissement (Chant)",
"Evaluation",
"Langue (Eltharin)",
"Commandement",
"Corps à corps (Base)",
"Orientation",
"Perception",
"Musicien (Au choix)",
"Projectiles (Arc)",
"Voile",
"Natation"
];
game.wfrp4e.config.speciesSkills["welf"] = [
"Athlétisme",
"Escalade",
"Resistenz",
"Divertissement (Chant)",
"Intimidation",
"Langue (Eltharin)",
"Corps à corps (Base)",
"Survie en extérieur",
"Perception",
"Projectiles (Arc)",
"Discrétion (Rural)",
"Pistage"
];*/
game.wfrp4e.config.speciesTalents["human"] = [
"Unkenruf",
"Einnehmendes Wesen, Gerissenheit",
3
]
game.wfrp4e.config.speciesTalents["dwarf"] = [
"Magieresistenz",
"Nachtsicht",
"Lesen & Schreiben, Unerbittlich",
"Entschlossen, Willensstärke",
"Stämmig",
0
]
game.wfrp4e.config.speciesTalents["halfling"] = [
"Scharfer Sinn (Gout)",
"Nachtsicht",
"Résistant (Chaos)",
"Zierlich",
2
];
game.wfrp4e.config.speciesTalents["helf"] = [
"Scharfer Sinn (Vue)",
"Kühler Kopf, Gerissenheit",
"Nachtsicht",
"Zweites Gesicht, Sechster Sinn",
"Lesen & Schreiben",
0
]
game.wfrp4e.config.speciesTalents["welf"] = [
"Scharfer Sinn (Vue)",
"Robustheit, Zweites Gesicht",
"Nachtsicht",
"Streuner",
"Lesen & Schreiben, Très Résistant",
0
]
/************************************************************************************/
static perform_rnhd_patch() {
game.wfrp4e.config.species['gnome'] = 'Gnome';
game.wfrp4e.config.speciesSkills["gnome"] = [
"Focalisation (Ulgu)",
"Charme",
"Resistenz à l'alcool",
"Esquive",
"Divertissement (Au choix)",
"Ragot",
"Marchandage",
"Langue (Ghassally)",
"Langue (Magick)",
"Langue (Wastelander)",
"Survie en extérieur",
"Discrétion (Au choix)"
];
game.wfrp4e.config.speciesTalents["gnome"] = [
"Insignifiant, Imprégné avec Uglu",
"Glückspilz, Imitator",
"Nachtsicht",
"Fischer, Lesen & Schreiben",
"Zweites Gesicht, Sechster Sinn",
"Zierlich",
0
];
}
}
game.wfrp4e.config.subspecies["human"]["reiklander"] = {
name: "Reiklander",
skills: [
"Soins aux animaux",
"Charme",
"Calme",
"Evaluation",
"Ragot",
"Marchandage",
"Langue (Bretonnien)",
"Langue (Wastelander)",
"Commandement",
"Savoir (Reikland)",
"Corps à corps (Base)",
"Projectiles (Arc)"
],
talents: [
"Unkenruf",
"Einnehmendes Wesen, Gerissenheit",
3
]
}
if (game.wfrp4e.config.subspecies["welf"]["harioth"]) { // Archives Empire
game.wfrp4e.config.subspecies["welf"]["harioth"] = {
name: "Harioth",
talents: [
"Scharfer Sinn (Vue)",
"Robustheit, Zweites Gesicht",
"Nachtsicht",
"Lesen & Schreiben, Très Résistant",
"Streuner",
"Youngblood",
0
]
}
game.wfrp4e.config.subspecies["halfling"]["ashfield"] = {
name: "Ashfield",
skills: [
"Charme",
"Resistenz à l'alcool",
"Marchandage",
"Savoir (Reikland)",
"Escamotage",
"Discrétion (Au choix)",
"Métier (Cuisinier)",
"Calme",
"Intuition",
"Langue (Mootish)",
"Projectiles (Au choix)"
],
talents: [
"Scharfer Sinn (Goût)",
"Nachtsicht",
"Résistant (Chaos)",
"Zierlich",
"Scharfer Sinn (Vue), Etiquette (Soldats)",
1
]
}
game.wfrp4e.config.subspecies.halfling["brambledown"] = {
name: "Brambledown",
skills: [
"Charme",
"Resistenz à l'alcool",
"Marchandage",
"Savoir (Reikland)",
"Escamotage",
"Discrétion (Au choix)",
"Métier (Cuisinier)",
"Langue (Mootish) ",
"Orientation",
"Survie en extérieur ",
"Natation"
],
talents: [
"Scharfer Sinn (Goût)",
"Nachtsicht",
"Résistant (Chaos)",
"Zierlich",
"Gesellig, Erfahrener Reisender",
1
]
}
game.wfrp4e.config.subspecies.halfling["brandysnap"] = {
name: "Brandysnap",
skills: [
"Charme",
"Resistenz à l'alcool",
"Marchandage",
"Savoir (Reikland)",
"Escamotage",
"Discrétion (Au choix)",
"Métier (Cuisinier)",
"Soins aux animaux",
"Pari",
"Langue (Mootish)",
"Métier (Herboriste)"
],
talents: [
"Scharfer Sinn (Goût)",
"Nachtsicht",
"Résistant (Chaos)",
"Zierlich",
"Handwerksgeschick (Fermier), Stämmig",
1
]
}
game.wfrp4e.config.subspecies.halfling["hayfoot"] = {
name: "Hayfoot",
skills: [
"Charme",
"Resistenz à l'alcool",
"Marchandage",
"Savoir (Reikland)",
"Escamotage",
"Discrétion (Au choix)",
"Métier (Cuisinier)",
"Gamble",
"Pari",
"Evaluation",
"Langue (Mootish)"
],
talents: [
"Scharfer Sinn (Goût)",
"Nachtsicht",
"Résistant (Chaos)",
"Zierlich",
"Verhandlungsgenie, Etiquette (Guildes)",
1
]
}
game.wfrp4e.config.subspecies.halfling["hollyfoot"] = {
name: "Hollyfoot",
skills: [
"Charme",
"Resistenz à l'alcool",
"Marchandage",
"Savoir (Reikland)",
"Escamotage",
"Discrétion (Au choix)",
"Métier (Cuisinier)",
"Subornation",
"Marchandage",
"Ragot",
"Langue (Mootish)"
],
talents: [
"Scharfer Sinn (Goût)",
"Nachtsicht",
"Résistant (Chaos)",
"Zierlich",
"Handwerksgeschick (Au choix), Geschickte Finger",
1
]
}
game.wfrp4e.config.subspecies.halfling["hayfoot—hollyfoot"] = {
name: "Hayfoot—Hollyfoot",
skills: [
"Charme",
"Resistenz à l'alcool",
"Marchandage",
"Savoir (Reikland)",
"Escamotage",
"Discrétion (Au choix)",
"Métier (Cuisinier)",
"Subornation",
"Marchandage",
"Ragot",
"Langue (Mootish)"
],
talents: [
"Scharfer Sinn (Goût)",
"Nachtsicht",
"Résistant (Chaos)",
"Zierlich",
"Wortgewandt, Numismatiker",
1
]
}
game.wfrp4e.config.subspecies.halfling["lostpockets"] = {
name: "Lostpockets",
skills: [
"Charme",
"Resistenz à l'alcool",
"Marchandage",
"Savoir (Reikland)",
"Escamotage",
"Discrétion (Au choix)",
"Métier (Cuisinier)",
"Resistenz",
"Pari",
"Ragot",
"Intuition"
],
talents: [
"Scharfer Sinn (Goût)",
"Nachtsicht",
"Résistant (Chaos)",
"Zierlich",
"Robustheit, Genügsam",
1
]
}
game.wfrp4e.config.subspecies.halfling["lowhaven"] = {
name: "Lowhaven",
skills: [
"Charme",
"Resistenz à l'alcool",
"Marchandage",
"Savoir (Reikland)",
"Escamotage",
"Discrétion (Au choix)",
"Métier (Cuisinier)",
"Subornation",
"Marchandage",
"Intimidation",
"Langue (Mootish)"
],
talents: [
"Scharfer Sinn (Goût)",
"Nachtsicht",
"Résistant (Chaos)",
"Zierlich",
"Kniminell, Etiquette (Kniminells ou Guildes)",
1
]
}
File diff suppressed because it is too large Load Diff
+515
View File
@@ -0,0 +1,515 @@
/************************************************************************************/
// 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`
let str1 = `JABBERSLYTHE
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.
`;
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)
`
//import ItemWfrp4e from "/systems/wfrp4e/modules/item/item-wfrp4e.js"
//import ItemWfrp4e from "/systems/wfrp4e/wfrp4e.js"
/************************************************************************************/
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';
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\\-\*]+)';
const name_val = '(?<name>[a-zA-Z\\s\\-,\']*)[\\s\\r\\na-zA-Z]*(?<tiers>.*|[\\(\\)a-z0-9]+)';
let sectionDataFR = [
{ name: "trait", toFind: "Eigenschaften\\s*:", secondParse: '(?<name>[a-zöàéè\\s]*)[\\s\\+]*(?<value>.*|[\\+0-9]+)', index: -1 },
{ name: "skill", toFind: "Fähigkeiten\\s*:", secondParse: '(?<name>[a-zàéè\\s\\(\\)]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
{ name: "talent", toFind: "Talente\\s*:", secondParse: '(?<name>[a-zöàéè\\-\\!\\(\\)\\s\\/\']*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
{ name: "mutation", toFind: "Mutationen\\s*:", secondParse: '(?<name>[a-zöàéè\\s]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
{ name: "trapping", toFind: "Ausrüstung\\s*:", secondParse: '(?<name>[a-zöàéè0-9\\s(\\)\\-]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
{ name: "spell", toFind: "Spruch\\s*\\([a-z\\s]*\\)*:", secondParse: '(?<name>[a-zöàéè\\s]*)', index: -1 },
{ name: "spellpetty", toFind: "Sprüche\\s*\\(Gering\\)*:", secondParse: '(?<name>[a-zö\\-\\s]*)', index: -1 },
{ name: "spellarcane", toFind: "Sprüche\\s*\\(Arkan[a-z\\s]*\\)*:", secondParse: '(?<name>[a-zö\\-\\s]*)', index: -1 },
{ name: "spellarcane", toFind: "Sprüche\\s*\\(Lehre\\s*(?<lore>[a-z\\s]*)\\)*:", secondParse: '(?<name>[a-zö\\-\\s]*)', index: -1 }
];
let sectionDataUS = [
{ name: "trait", toFind: "Traits\\s*:", secondParse: '(?<name>[a-z\\s]*)[\\s\\+]*(?<value>.*|[\\+0-9]+)', index: -1 },
{ 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 },
{ name: "mutation", toFind: "Mutations\\s*:", secondParse: '(?<name>[a-zö\\s]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
{ name: "trapping", toFind: "Trappings\\s*:", secondParse: '(?<name>[a-zö0-9\\s\\(\\)\\-]*)[\\s\\+]*(?<value>.*|[0-9]+)', index: -1 },
{ name: "spellpetty", toFind: "Spells\\s*\\(Petty\\s*[a-z\\s]*\\)*:", secondParse: '(?<name>[a-zö\\-\\s]*)', index: -1 },
{ name: "spellarcane", toFind: "Spells\\s*\\(Arcane\\s*[a-z\\s]*\\)*:", secondParse: '(?<name>[a-zö\\-\\s]*)', index: -1 },
{ name: "spelllore", toFind: "Spells\\s*\\(Lore\\s*of\\s*(?<lore>[a-z\\s]*)\\)*:", secondParse: '(?<name>[a-zö\\-\\s]*)', index: -1 }
]
let moneyUS = [ {name:" gold crown", key: "gc"}, {name: " gc", key: "gc"},
{name:" silver shilling", key:"ss"}, {name:" ss", key: "ss"}, {name:"/-", key: "ss"}, {name:" brass penn", key: "bp"}, {name:" bp", key: "bp"} ]
let moneyFR = [ {name:" Goldkrone", key: "gc"}, {name: " gk", key: "gc"},
{name:" Silberschilling ", key:"ss"}, {name:" s", key: "ss"}, {name:"/-", key: "ss"}, {name:" Kupferpfennig", key: "bp"}, {name:" g", key: "bp"} ]
let regSep = XRegExp('\\s*,\\s*', 'gi'); // Term separator, with auto trim
let regLine1 = XRegExp('[\\r\\n\\.]', 'gi'); // Term separator, with auto trim
let regName = XRegExp(name_val, 'gi');
// Used to detect/manage the skill groupings in the statblock
const __SkillGroupsUS = ["Melee", "Lore", "Trade"]
const __SkillGroupsFR = ["Nahkampf", "Lehre", "Beruf"]
// Used to auto update the system.tests.value field
const __hasTestValue = {
"etiquette": true,
"resistance": true,
"acute sense": true,
"strider": true,
"savant": true,
"craftsman": true
}
/************************************************************************************/
async function __findItem(itemName, itemType, location = null) {
let toSearch = itemName.toLowerCase().trim();
let items = game.items.contents.filter(i => i.type == itemType)
console.log("Searching for", toSearch, itemType)
// Search imported items first
for (let i of items) {
if (i.name.toLowerCase() == toSearch.toLowerCase() && i.type == itemType)
return i.toObject();
}
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) {
await pack.getIndex().then(index => itemList = index);
let searchResult = itemList.find(t => (t.translated && t.type == itemType && (t.originalName.toLowerCase() == toSearch || s.originalName.toLowerCase().split("(")[0].trim() == toSearch)) || (t.type == itemType && (t.name.toLowerCase() == toSearch || t.name.toLowerCase().split("(")[0].trim() == toSearch)));
if (searchResult) {
let item = await pack.getDocument(searchResult._id)
return item.toObject()
}
}
}
// If all else fails, search each pack
for (let p of game.wfrp4e.tags.getPacksWithTag(itemType)) {
await p.getIndex().then(index => itemList = index);
console.log("Seatch", itemType, toSearch);
let searchResult = itemList.find(t => (t.translated && t.type == itemType && (t.originalName.toLowerCase() == toSearch || s.originalName.toLowerCase().split("(")[0].trim() == toSearch)) || (t.type == itemType && (t.name.toLowerCase() == toSearch || t.name.toLowerCase().split("(")[0].trim() == toSearch)));
if (searchResult) {
let item = await p.getDocument(searchResult._id)
return item.toObject()
}
}
}
/************************************************************************************/
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'));
// First try world items
let item
let worldItem = game.items.contents.filter(i => i.type == "skill" && i.name.toLowerCase() == toSearch)[0];
if (worldItem) {
item = worldItem.toObject()
} else {
let packs = game.wfrp4e.tags.getPacksWithTag("skill");
for (let pack of packs) {
let skillList = await pack.getIndex();
// Search for specific skill (won't find unlisted specializations)
let searchResult = skillList.find(s => (s.type == "skill" && s.translated && s.originalName.toLowerCase() == toSearch) || (s.type == "skill" && s.name.toLowerCase() == toSearch));
if (!searchResult) {
let toSearchClean = toSearch.split("(")[0].trim();
searchResult = skillList.find(s => (s.type == "skill" && s.translated && s.originalName.toLowerCase().split("(")[0].trim() == toSearchClean) ||
(s.type == "skill" && s.name.toLowerCase().split("(")[0].trim() == toSearchClean));
}
if (searchResult) {
let dbSkill;
await pack.getDocument(searchResult._id).then(packSkill => dbSkill = packSkill);
item = dbSkill.toObject();
}
}
}
if (item) {
//console.log("Skill name1", skillSplit)
if (skillSplit.specialized && (item.name.includes('()') || item.name.includes('( )'))) {
let spec = XRegExp.replace(skillSplit.specialized, "(", "");
spec = XRegExp.replace(spec, ")", "");
let skillSplit2 = XRegExp.exec(item.name, XRegExp(parseStr, 'gi'));
item.name = skillSplit2.name + '(' + game.i18n.localize(spec.trim()) + ')'
//dbSkill.update( { name: } );
}
//game.babele.translate('wfrp4e-core.skills', dbSkill);
return item
}
}
/************************************************************************************/
async function __findTalent(talentName) {
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();
//console.log("Talent name", toSearch, talentName, talentSplit)
// First try world items
let item
let worldItem = game.items.contents.filter(i => i.type == "talent" && i.name.toLowerCase() == toSearch)[0];
if (worldItem) {
item = worldItem.toObject()
} else {
let packs = game.wfrp4e.tags.getPacksWithTag("talent");
for (let pack of packs) {
let talentList = await pack.getIndex();
// Search for specific talent (won't find unlisted specializations)
let searchResult = talentList.find(s => (s.type == "talent" && s.translated && s.originalName.toLowerCase() == toSearch) || (s.type == "talent" && s.name.toLowerCase() == toSearch));
if (!searchResult) {
let toSearchClean = toSearch.split("(")[0].trim();
searchResult = talentList.find(s => (s.type == "talent" && s.translated && s.originalName.toLowerCase().split("(")[0].trim() == toSearchClean) ||
(s.type == "talent" && s.name.toLowerCase().split("(")[0].trim() == toSearchClean));
}
if (searchResult) {
let dbTalent;
//console.log("Talent name1", talentSplit)
await pack.getDocument(searchResult._id).then(packTalent => dbTalent = packTalent);
item = dbTalent.toObject();
}
}
}
if (item) {
if (talentSplit.specialized) {
let spec = XRegExp.replace(talentSplit.specialized, "(", "");
spec = XRegExp.replace(spec, ")", "");
spec = spec.trim()
let addToName = true
//console.log("Talent name2", dbTalent.name, spec, game.i18n.localize( spec.trim()) )
if (toSearch == 'doomed') {
item.system.description.value += `<br><br><em>${spec}</em>`;
addToName = false // Very specific case
}
if (__hasTestValue[toSearch]) {
item.system.tests.value = game.i18n.localize(spec);
}
item.name = talentSplit.name
if (addToName) {
item.name += '(' + game.i18n.localize(spec) + ')'
}
item.system.advances.value = 1 // Set 1 advance
}
// Specific Talent post-processing
return item;
}
}
/************************************************************************************/
function __patchName(name) {
if (name.toLowerCase == 'magic sense')
name = 'Magical Sense'
return name
}
/************************************************************************************/
export default async function statParserFR(statString, type = "npc") {
let model = duplicate(game.system.model.Actor[type]);
// Patch wront/strange carac value before processing
statString = statString.replace(/ /g, " 0")
let moneys = { gc: 0, ss: 0, bp: 0 }
let statNameReg = us_carac
let sectionData = duplicate(sectionDataUS)
let skillGrouping = __SkillGroupsUS
let moneyLang = moneyUS
// Detect French stat block
if (statString.includes('KG') && statString.includes('BF') && statString.includes('WK')) {
//ui.notifications.warn("Le parsing de stablock en Français n'est pas encore prêt")
statNameReg = fr_carac
sectionData = duplicate(sectionDataFR)
skillGrouping = __SkillGroupsFR
moneyLang = moneyFR
}
let reg1 = XRegExp(statNameReg, 'gi')
let res = reg1.test(statString)
if (res) { //stat block identified go on
let globalItemList = []
// 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)
if (nameRes.tiers && nameRes.tiers.length > 0 && hasProperty(model, "details.status.value")) {
let regTiers = XRegExp("(?<name>[A-Za-z]*)\\s+(?<level>[0-9]*)");
let resTiers = XRegExp.exec(nameRes.tiers, regTiers);
console.log(resTiers);
model.details.status.value = game.i18n.localize(resTiers.name.trim()) + " " + resTiers.level;
}
let baseName = nameRes.name.split("\n")
// Compute the PNJ name
let pnjName = baseName[0].split("—")[0].split(" ").filter(f => !!f)
pnjName = pnjName.map(word => {
if (word == "VON")
return word.toLowerCase();
word = word.toLowerCase();
word = word[0].toUpperCase() + word.substring(1, word.length);
return word;
})
pnjName = pnjName.join(" ")
if (baseName[1]) {
let careerName = baseName[1].split(",")[0]
//console.log("CAREER", careerName)
let career = await __findItem(careerName, "career")
if (career) {
globalItemList.push(career)
}
}
// Get the carac values
let reg2 = XRegExp(carac_val, 'gi')
let resCarac = XRegExp.exec(statString, reg2) // resr contains all carac found
// Setup carac
//console.log("CARAC", resCarac)
if (resCarac["Agi"]) resCarac["Ag"] = resCarac["Agi"] // Auto patch
model.details.move.value = Number(resCarac["m"])
for (let key in model.characteristics) {
if (resCarac[key] === '-') resCarac[key] = 0
model.characteristics[key].initial = Number(resCarac[key])
}
//console.log("CARAC", model.characteristics);
// Search position of skills/talents/...
for (let def of sectionData) {
def.regDef = XRegExp(def.toFind, 'gi');
let res = XRegExp.exec(statString, def.regDef);
if (res) {
def.index = res.index // Position of the string in the whole statblock
def.lore = res.lore // Extraction of the lore, when present
} // Get the index in the string
//console.log(" Parsing", def.name, res);
}
// Sort to split position of various substring
sectionData.sort(function (a, b) { return a.index - b.index; });
// Then loop again and process each item type
for (let i = 0; i < sectionData.length; i++) {
let def = sectionData[i];
if (def.index > -1) {
let maxIndex = statString.length
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, " ")
// At this point, def.substring contains the items list as a string
// Then create a table of it in termList, with specific sub-parsing rules
let termList = XRegExp.split(def.substring, regSep);
//console.log("Term list identified", termList)
let lastSkillName
for (let name of termList) {
let itemFound, subres, value;
if (def.secondParse) {
subres = XRegExp.exec(name, XRegExp(def.secondParse, 'gi'))
//console.log("Second pars", def, name, subres)
name = subres.name.trim().replace("\n", "").replace("\r", "")
if (subres.value) {
value = XRegExp.replace(subres.value, "(", "")
value = XRegExp.replace(value, ")", "")
} else {
value = 0
}
}
name = __patchName(name)
if (def.name == 'trait') {
try {
itemFound = await __findItem(name, "trait")
}
catch { }
if (itemFound && value && value.length > 0) {
let number = value.match(/\d+/g);
if (number && (name.toLowerCase() == 'ranged' || name.toLowerCase() == 'weapon' || name.toLowerCase() == "bite" || name.toLowerCase() == "tail" ||
name.toLowerCase() == 'waffe' || name.toLowerCase() == "biss" || name.toLowerCase() == "schwanz")) {
//console.log(itemFound)
number = number[0] // Take first number ....
itemFound.system.specification.value = Number(number) - ((name.toLowerCase() == 'ranged') ? 0 : Math.floor(Number(model.characteristics.s.initial) / 10))
} else {
itemFound.system.specification.value = game.i18n.localize(value)
}
//itemFound.name += "(" + value + ")"
}
if (!itemFound)
ui.notifications.error("Gegenstand nicht gefunden, muss manuell hinzgefügt werden: " + name, { permanent: true })
} else if (def.name == 'skill') {
try {
itemFound = await __findSkill(name, value);
}
catch { }
let newName = name
if (!itemFound && lastSkillName) {
newName = lastSkillName + " (" + name + ")"
itemFound = await __findSkill(newName, value)
}
if (itemFound && subres && value) {
itemFound.system.advances.value = Number(value) - Number(model.characteristics[itemFound.system.characteristic.value].initial);
}
lastSkillName = undefined
for (let keySkillGroup of skillGrouping) {
if (newName.includes(keySkillGroup)) { // useful to handle skills grouping
lastSkillName = keySkillGroup
}
}
if (!itemFound) {
ui.notifications.error("Fähigkeit nicht gefunden, muss manuell hinzgefügt werden: " + name, { permanent: true })
}
} else if (def.name == 'talent') {
try {
itemFound = await __findTalent(name);
}
catch { }
if (itemFound && subres && value)
itemFound.system.advances.value = Number(value);
if (!itemFound) {
ui.notifications.error("Talent nicht gefunden, muss manuell hinzgefügt werden: " + name, { permanent: true })
}
} else if (def.name == 'trapping') {
itemFound = await __findItem(name, "trapping");
if (!itemFound) {
itemFound = await __findItem(name, "weapon");
}
if (!itemFound) {
itemFound = await __findItem(name, "armor");
}
if (!itemFound && name) {
if (name.toLowerCase().includes("armor") || name.toLowerCase().includes("rüstung") || name.toLowerCase().includes("armour")) {
itemFound = new ItemWfrp4e({ img: "systems/wfrp4e/icons/blank.png", name: name, type: "armour", system: game.system.model.Item.armor })
} else if (name.toLowerCase().includes("weapon") || name.toLowerCase().includes("waffe")) {
itemFound = new ItemWfrp4e({ img: "systems/wfrp4e/icons/blank.png", name: name, type: "weapon", system: game.system.model.Item.weapon })
} else {
itemFound = new ItemWfrp4e({ img: "systems/wfrp4e/icons/blank.png", name: name, type: "trapping", system: game.system.model.Item.trapping })
itemFound.system.trappingType.value = "misc"
if (name.toLowerCase().includes("cloth")) {
itemFound.system.trappingType.value = "clothingAccessories"
}
}
itemFound = itemFound.toObject()
}
// Searching money stuff
for (let mondeyDef of moneyLang) {
if (name.toLowerCase().includes(mondeyDef.name)) {
let regMoney = XRegExp("(\\d+)\\s*" + mondeyDef.name.trim(), 'gi')
let moneyParsed = XRegExp.exec(name.toLowerCase(), regMoney)
console.log("Parsing money", name, moneyParsed)
moneys[mondeyDef.key] += (moneyParsed && moneyParsed[1]) ? Number(moneyParsed[1]) : 0
}
}
} else if (def.name.includes('spell')) {
console.log("Found spells section!!!!", name, def, def.lore || "NO LORE")
// Lore management, firs pass
if (def.lore) {
let newName = name + " (" + def.lore + ")"
itemFound = await __findItem(newName, "spell");
//console.log("Trying to find ", newName, itemFound)
}
if (!itemFound) { // If not found with Lore, try without the lore
itemFound = await __findItem(name, "spell");
}
if (!itemFound && name) { // Auto-create the spell name
itemFound = new ItemWfrp4e({ img: "systems/wfrp4e/icons/blank.png", name: name + "(To be checked/completed)", type: "spell", system: game.system.model.Item.spell })
itemFound = itemFound.toObject();
}
} else if (def.name == 'mutation') {
try {
itemFound = await __findItem(name, "mutation");
}
catch { }
}
if (itemFound)
globalItemList.push(itemFound);
}
}
}
let moneyItems = await game.wfrp4e.utility.allMoneyItems() || [];
moneyItems = moneyItems.sort((a, b) => (a.system.coinValue.value > b.system.coinValue.value) ? -1 : 1);
for (let m of moneyItems) {
m.system.quantity.value = 0
if (m.system.coinValue.value == 1) {
m.system.quantity.value += moneys.bp
}
if (m.system.coinValue.value == 240) {
m.system.quantity.value += moneys.gc
}
if (m.system.coinValue.value == 12) {
m.system.quantity.value += moneys.ss
}
}
globalItemList = globalItemList.concat(moneyItems);
//DEBUG : console.log("My liste :", moneyItems, moneys);
let name = pnjName;
let effects = globalItemList.reduce((total, globItem) => total.concat(globItem.effects), [])
effects = effects.filter(e => !!e)
effects = effects.filter(e => e.transfer)
for (let e of effects) {
for (let c of e.changes) {
// Charac management stuff
if (c.key?.includes("characteristics")) {
let cKey = c.key.split(".")[2]
model.characteristics[cKey].initial -= Number(c.value)
}
// Move management
if (c.key?.includes("move")) {
model.details.move.value -= Number(c.value)
}
}
}
//DEBUG : console.log("EFFECTS", effects)
return { name, type, data: model, items: globalItemList, effects }
}
// If the carac string has not been found
ui.notifications.error("Nicht möglich, diese Werte zu konvertieren, die Spielwerte wurden nicht gefunden", { permanent: true })
}
File diff suppressed because it is too large Load Diff