Amélioration robustess et vérification sur import des modules
This commit is contained in:
@@ -16,30 +16,27 @@ const _patch_eis = () => {
|
||||
game.wfrp4e.config.symptomTreatment["swelling"] = "La plupart des traitements consistent à plonger la partie affectée, ou parfois tout le corps, dans un bain d'eau glacée pour réduire la chaleur qui accompagne les gonflements. Un <b> Test de Guérison Difficile (-20) étendu </b> nécessitant +3 DR réduit le renflement de <b> <a class ='chat-roll'> 2d10 </a> </b> heures. Chaque test dure une heure. Le patient se retrouve avec l'Etat Exténué +1 pour chaque test effectué au cours du processus. <br> <br> A la place, certains médecins saignent le patient avec une lame ou des sangsues. Un <b>Test de Guérison étendu </b> réussi nécessitant +4 SL et des Outils (médecin) réduit le renflement de (<a class ='chat-roll'> 1d10 </a> + Bonus d'Endurance du patient) heures. Chaque test a une difficulté de base <b> impossible (-50) </b> et dure une demi-heure.";
|
||||
|
||||
game.wfrp4e.config.loreEffects["tzeentch"] = {
|
||||
label: "Domaine de Tzeentch",
|
||||
icon: "modules/wfrp4e-core/icons/spells/tzeentch.png",
|
||||
transfer: true,
|
||||
flags: {
|
||||
wfrp4e: {
|
||||
"effectApplication": "apply",
|
||||
"effectTrigger": "oneTime",
|
||||
"lore": true,
|
||||
"script": `
|
||||
if (this.actor.isOwner)
|
||||
args.actor.setupSkill("Résistance", {context : {failure: "1 Point de Corruption reçu", success : "1 Point de Chance gagné"}}).then(setupData => {
|
||||
args.actor.basicTest(setupData).then(test =>
|
||||
{
|
||||
if (test.result.result == "success" && args.actor.type == "character")
|
||||
{
|
||||
args.actor.update({"system.status.fortune.value" : args.actor.system.status.fortune.value + 1})
|
||||
}
|
||||
else if (test.result.result == "failure" && args.actor.type == "character")
|
||||
{
|
||||
args.actor.update({"system.status.corruption.value" : args.actor.system.status.corruption.value + 1})
|
||||
}
|
||||
})
|
||||
})`
|
||||
}
|
||||
name: "Domaine de Tzeentch",
|
||||
img: "modules/wfrp4e-core/icons/spells/tzeentch.png",
|
||||
system: {
|
||||
transferData: {
|
||||
type: "target"
|
||||
},
|
||||
scriptData: [{
|
||||
trigger: "immediate",
|
||||
label: "Test d'Endurance",
|
||||
script: `
|
||||
this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {appendTitle : " - " + this.effect.name, context : {failure: "1 Point de Corruption reçu", success : "1 Point de Chance gagné"}}).then(setupData => {
|
||||
this.actor.basicTest(setupData).then(test => {
|
||||
if (test.succeeded && this.actor.type == "character") {
|
||||
this.actor.update({"system.status.fortune.value" : this.actor.system.status.fortune.value + 1})
|
||||
} else if (test.failed && this.actor.type == "character") {
|
||||
this.actor.update({"system.status.corruption.value" : this.actor.system.status.corruption.value + 1})
|
||||
}
|
||||
})
|
||||
})
|
||||
return false;`
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -404,6 +401,40 @@ Hooks.on('ready', () => {
|
||||
// Patch function for effects
|
||||
game.wfrp4e.utility.findKey = warhammer.utility.findKey
|
||||
|
||||
// Patch SpellModel.computeSpellDamage to handle English characteristic bonus names.
|
||||
// Babele instantiates actors TWICE: first with untranslated data (English formulas like
|
||||
// "Willpower Bonus+4"), then with translated data. The first pass fails because
|
||||
// characteristicsBonus values are already French ("Bonus de Force Mentale").
|
||||
// This patch pre-replaces English bonus names with numeric values before the original
|
||||
// formula evaluation runs, preventing SyntaxErrors and notification spam.
|
||||
const __EN_BONUS_TO_CHAR = {
|
||||
"weapon skill bonus": "ws", "ballistic skill bonus": "bs",
|
||||
"strength bonus": "s", "toughness bonus": "t",
|
||||
"initiative bonus": "i", "agility bonus": "ag",
|
||||
"dexterity bonus": "dex", "intelligence bonus": "int",
|
||||
"willpower bonus": "wp", "fellowship bonus": "fel"
|
||||
};
|
||||
const SpellModel = CONFIG.Item.dataModels?.["spell"];
|
||||
if (SpellModel?.prototype?.computeSpellDamage) {
|
||||
const _origComputeSpellDamage = SpellModel.prototype.computeSpellDamage;
|
||||
SpellModel.prototype.computeSpellDamage = function(formula, options) {
|
||||
if (typeof formula === "string") {
|
||||
const actor = options?.actor || this.parent?.actor;
|
||||
if (actor?.system?.characteristics) {
|
||||
let f = formula.toLowerCase();
|
||||
for (const [enName, ch] of Object.entries(__EN_BONUS_TO_CHAR)) {
|
||||
if (f.includes(enName)) {
|
||||
const bonus = actor.system.characteristics[ch]?.bonus ?? 0;
|
||||
f = f.replace(enName, bonus);
|
||||
}
|
||||
}
|
||||
formula = f;
|
||||
}
|
||||
}
|
||||
return _origComputeSpellDamage.call(this, formula, options);
|
||||
};
|
||||
}
|
||||
|
||||
// Patch postSymptom to handle English symptom names in @Symptom[...] links.
|
||||
// After i18nInit, config.symptoms values are French strings (e.g. "Fièvre"), so
|
||||
// findKey("Fever", config.symptoms) fails. We normalize via game.i18n.localize first.
|
||||
|
||||
@@ -30,6 +30,20 @@ const __SELECT_BONUS_PREFIX_D = {
|
||||
"agilité": 1
|
||||
}
|
||||
|
||||
// Map English characteristic names (as they appear in spell formulas) to WFRP4e abbreviations
|
||||
const __CHAR_EN_TO_ABBR = {
|
||||
"weapon skill": "ws",
|
||||
"ballistic skill": "bs",
|
||||
"strength": "s",
|
||||
"toughness": "t",
|
||||
"initiative": "i",
|
||||
"agility": "ag",
|
||||
"dexterity": "dex",
|
||||
"intelligence": "int",
|
||||
"willpower": "wp",
|
||||
"fellowship": "fel"
|
||||
}
|
||||
|
||||
/************************************************************************************/
|
||||
export class WFRP4FrTranslation {
|
||||
|
||||
@@ -57,16 +71,23 @@ export class WFRP4FrTranslation {
|
||||
if (value == "You") return "Vous"; // Hop !
|
||||
if (value == "Instant") return "Instantané"; // Hop !
|
||||
let translw = value;
|
||||
let re = /(.*)\s+[Bb]onus\s*(\w*)/i;
|
||||
let re = /(.*)\s+[Bb]onus\s*(.*)/i; // (.*) at end captures modifiers like "+4"
|
||||
let res = re.exec(value);
|
||||
let unit = "";
|
||||
if (res) { // Test "<charac> Bonus <unit>" pattern
|
||||
if (res) { // Test "<charac> Bonus <modifier>" pattern
|
||||
if (res[1]) { // We have char name, then convert it
|
||||
translw = game.i18n.localize(res[1].trim());
|
||||
let bonusPrefix = (translw.toLowerCase() in __SELECT_BONUS_PREFIX_D) ? "Bonus d'" : "Bonus de ";
|
||||
translw = bonusPrefix + translw
|
||||
const charEN = res[1].trim().toLowerCase();
|
||||
const abbr = __CHAR_EN_TO_ABBR[charEN];
|
||||
if (abbr && game.wfrp4e?.config?.characteristicsBonus?.[abbr]) {
|
||||
// Use the localized French bonus name from config (already resolved by localizeConfig at i18nInit)
|
||||
translw = game.wfrp4e.config.characteristicsBonus[abbr];
|
||||
} else {
|
||||
translw = game.i18n.localize(res[1].trim());
|
||||
let bonusPrefix = (translw.toLowerCase() in __SELECT_BONUS_PREFIX_D) ? "Bonus d'" : "Bonus de ";
|
||||
translw = bonusPrefix + translw;
|
||||
}
|
||||
}
|
||||
unit = res[2];
|
||||
unit = res[2]; // may be "+4", "-2", "2", "yards", etc.
|
||||
} else {
|
||||
re = /(\d+) (\w+)/i;
|
||||
res = re.exec(value);
|
||||
@@ -90,6 +111,8 @@ export class WFRP4FrTranslation {
|
||||
if (unit == "Bonus") { // Another weird management
|
||||
console.log("Translating bonus", unit);
|
||||
translw = "Bonus de " + translw;
|
||||
} else if (unit && /^[+\-*\/]/.test(unit)) {
|
||||
translw += unit; // No space before operators like "+4"
|
||||
} else {
|
||||
translw += " " + unit;
|
||||
}
|
||||
@@ -278,6 +301,8 @@ Hooks.once('init', () => {
|
||||
"process_effects": (effectsData, translations, data, tc, tc_translations) => {
|
||||
//console.log("Effects :", effectsData, translations, data, tc, tc_translations)
|
||||
for (let e of effectsData) {
|
||||
// Foundry v13 requires name; migrate legacy data where only label was stored
|
||||
if (e.name == null) e.name = e.label || "";
|
||||
let origName = e.name
|
||||
// Symptom effects have their own name (Fever, Malaise, etc.) — don't overwrite with the parent item name
|
||||
if (e.flags?.wfrp4e?.symptom) {
|
||||
@@ -293,7 +318,7 @@ Hooks.once('init', () => {
|
||||
}
|
||||
e.name = game.i18n.localize(symName) + gravity;
|
||||
} else {
|
||||
e.name = tc_translations.name || game.i18n.localize(e.name)
|
||||
e.name = tc_translations.name || game.i18n.localize(e.name) || e.label || ""
|
||||
}
|
||||
if ( e.flags?.wfrp4e?.scriptData) {
|
||||
for (let script of e.flags.wfrp4e.scriptData) {
|
||||
@@ -411,10 +436,18 @@ Hooks.once('init', () => {
|
||||
return beast_traits
|
||||
}
|
||||
//console.log("TRANS:", beast_traits)
|
||||
// Normalize: Foundry v13 requires ActiveEffect.name; migrate legacy v12 data
|
||||
for (let trait_en of beast_traits) {
|
||||
if (trait_en.effects) {
|
||||
for (let eff of trait_en.effects) {
|
||||
if (eff.name == null) eff.name = eff.label || "";
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let trait_en of beast_traits) {
|
||||
let special = "";
|
||||
let nbt = "";
|
||||
let name_en = trait_en.name.trim(); // strip \r in some traits name
|
||||
let name_en = trait_en.name.replace(/\r/g, '').trim(); // strip \r (including internal) in some traits name
|
||||
if (!trait_en.name || trait_en.name.length == 0) {
|
||||
console.log("Wrong item name found!!!!")
|
||||
continue
|
||||
@@ -430,8 +463,11 @@ Hooks.once('init', () => {
|
||||
} else if (name_en.includes("(") && name_en.includes(")")) { // Then process specific traits name with (xxxx) inside
|
||||
let re = /(.*) \((.*)\)/i;
|
||||
let res = re.exec(name_en);
|
||||
name_en = res[1]; // Get the root traits name
|
||||
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
|
||||
if (!res) { console.warn("WFRP4E-FR | bestiary_traits: regex failed for trait:", name_en); }
|
||||
else {
|
||||
name_en = res[1]; // Get the root traits name
|
||||
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
|
||||
}
|
||||
}
|
||||
let validCompendiums = game.wfrp4e.tags.getPacksWithTag("trait")
|
||||
for (let compData of validCompendiums) {
|
||||
@@ -453,8 +489,11 @@ Hooks.once('init', () => {
|
||||
if (name_en.includes("(") && name_en.includes(")")) { // Then process specific skills name with (xxxx) inside
|
||||
let re = /(.*) +\((.*)\)/i;
|
||||
let res = re.exec(name_en);
|
||||
name_en = res[1].trim(); // Get the root skill name
|
||||
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
|
||||
if (!res) { console.warn("WFRP4E-FR | bestiary_traits: regex failed for skill:", name_en); }
|
||||
else {
|
||||
name_en = res[1].trim(); // Get the root skill name
|
||||
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
|
||||
}
|
||||
}
|
||||
let validCompendiums = game.wfrp4e.tags.getPacksWithTag("skill")
|
||||
for (let compData of validCompendiums) {
|
||||
@@ -499,8 +538,11 @@ Hooks.once('init', () => {
|
||||
if (name_en.includes("(") && name_en.includes(")")) { // Then process specific skills name with (xxxx) inside
|
||||
let re = /(.*) +\((.*)\)/i;
|
||||
let res = re.exec(name_en);
|
||||
name_en = res[1].trim(); // Get the root talent name, no parenthesis this time...
|
||||
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
|
||||
if (!res) { console.warn("WFRP4E-FR | bestiary_traits: regex failed for talent:", name_en); }
|
||||
else {
|
||||
name_en = res[1].trim(); // Get the root talent name, no parenthesis this time...
|
||||
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
|
||||
}
|
||||
}
|
||||
let validCompendiums = game.wfrp4e.tags.getPacksWithTag("talent")
|
||||
for (let compData of validCompendiums) {
|
||||
|
||||
@@ -225,16 +225,15 @@ export class WH4FRPatchConfig {
|
||||
}
|
||||
|
||||
if (game.wfrp4e.config.loreEffects) {
|
||||
game.wfrp4e.config.loreEffects["beasts"].label = "Domaine des Bêtes"
|
||||
game.wfrp4e.config.loreEffects["death"].label = "Domaine de la Mort"
|
||||
game.wfrp4e.config.loreEffects["fire"].label = "Domaine du Feu"
|
||||
game.wfrp4e.config.loreEffects["metal"].label = "Domaine du Métal"
|
||||
game.wfrp4e.config.loreEffects["heavens"].label = "Domaine des Cieux"
|
||||
game.wfrp4e.config.loreEffects["life"].label = "Domaine de la Vie"
|
||||
game.wfrp4e.config.loreEffects["light"].label = "Domaine de la Lumière"
|
||||
game.wfrp4e.config.loreEffects["shadow"].label = "Domaine des Ombres"
|
||||
game.wfrp4e.config.loreEffects["hedgecraft"].label = "Domaine de la Magie de Village"
|
||||
game.wfrp4e.config.loreEffects["hedgecraft"].label = "Domaine de la Sorcellerie"
|
||||
game.wfrp4e.config.loreEffects["beasts"].name = "Domaine des Bêtes"
|
||||
game.wfrp4e.config.loreEffects["death"].name = "Domaine de la Mort"
|
||||
game.wfrp4e.config.loreEffects["fire"].name = "Domaine du Feu"
|
||||
game.wfrp4e.config.loreEffects["metal"].name = "Domaine du Métal"
|
||||
game.wfrp4e.config.loreEffects["heavens"].name = "Domaine des Cieux"
|
||||
game.wfrp4e.config.loreEffects["life"].name = "Domaine de la Vie"
|
||||
game.wfrp4e.config.loreEffects["light"].name = "Domaine de la Lumière"
|
||||
game.wfrp4e.config.loreEffects["shadow"].name = "Domaine des Ombres"
|
||||
game.wfrp4e.config.loreEffects["hedgecraft"].name = "Domaine de la Sorcellerie"
|
||||
}
|
||||
|
||||
if (game.wfrp4e.config.species) {
|
||||
|
||||
@@ -155,7 +155,7 @@ export default class InnRoller {
|
||||
}
|
||||
|
||||
// Extraire les informations du résultat
|
||||
const resultText = rollResult.results[0]?.text || "Résultat inconnu";
|
||||
const resultText = rollResult.results[0]?.name || rollResult.results[0]?.description || "Résultat inconnu";
|
||||
const rollFormula = rollResult.roll?.formula || "1d100";
|
||||
const rollTotal = rollResult.roll?.total || 0;
|
||||
|
||||
@@ -349,7 +349,7 @@ export default class InnRoller {
|
||||
if (rollTable) {
|
||||
try {
|
||||
const roll = await rollTable.draw({ displayChat: false });
|
||||
const resultText = roll.results[0]?.text || "Résultat inconnu";
|
||||
const resultText = roll.results[0]?.name || roll.results[0]?.description || "Résultat inconnu";
|
||||
results.push({
|
||||
category: this.getCategoryName(tableName),
|
||||
name: resultText,
|
||||
|
||||
Reference in New Issue
Block a user