Compare commits

..

8 Commits

561 changed files with 8658 additions and 237 deletions

View File

@@ -0,0 +1,92 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
// Patterns pour détecter les variables JavaScript nommées "Blessures"
const patterns = [
// Déclarations de variables
/\b(let|const|var)\s+Blessures\b/g,
// Paramètres de fonction
/function\s+\w*\s*\([^)]*\bBlessures\b[^)]*\)/g,
// Arrow functions avec paramètres
/\(\s*[^)]*\bBlessures\b[^)]*\)\s*=>/g,
// Arrow function avec un seul paramètre sans parenthèses
/\bBlessures\s*=>/g,
// Destructuration d'objets
/\{\s*[^}]*\bBlessures\b[^}]*\}\s*=/g,
// Destructuration de tableaux
/\[\s*[^\]]*\bBlessures\b[^\]]*\]\s*=/g,
// Catch clause
/catch\s*\(\s*Blessures\s*\)/g,
// For...of/in loops
/for\s*\(\s*(let|const|var)?\s*Blessures\s+(of|in)\b/g,
];
function findBlessuresInFile(filePath) {
const content = fs.readFileSync(filePath, 'utf-8');
const lines = content.split('\n');
const results = [];
lines.forEach((line, index) => {
patterns.forEach(pattern => {
pattern.lastIndex = 0; // Reset regex
if (pattern.test(line)) {
results.push({
line: index + 1,
content: line.trim()
});
}
});
});
return results;
}
function walkDirectory(dir) {
const files = fs.readdirSync(dir);
const allResults = {};
files.forEach(file => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
Object.assign(allResults, walkDirectory(filePath));
} else if (file.endsWith('.js')) {
const results = findBlessuresInFile(filePath);
if (results.length > 0) {
allResults[filePath] = results;
}
}
});
return allResults;
}
// Main
const scriptsDir = path.join(__dirname, 'scripts');
console.log('🔍 Recherche des variables JavaScript nommées "Blessures" dans le répertoire scripts/...\n');
if (!fs.existsSync(scriptsDir)) {
console.error('❌ Le répertoire scripts/ n\'existe pas');
process.exit(1);
}
const results = walkDirectory(scriptsDir);
if (Object.keys(results).length === 0) {
console.log('✅ Aucune variable JavaScript nommée "Blessures" trouvée.');
} else {
console.log(`⚠️ ${Object.keys(results).length} fichier(s) contenant des variables "Blessures" :\n`);
Object.entries(results).forEach(([filePath, occurrences]) => {
const relativePath = path.relative(__dirname, filePath);
console.log(`📄 ${relativePath}`);
occurrences.forEach(({ line, content }) => {
console.log(` Ligne ${line}: ${content}`);
});
console.log('');
});
}

92
find-tests-variables.cjs Normal file
View File

@@ -0,0 +1,92 @@
#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
// Patterns pour détecter les variables JavaScript nommées "Tests"
const patterns = [
// Déclarations de variables
/\b(let|const|var)\s+Tests\b/g,
// Paramètres de fonction
/function\s+\w*\s*\([^)]*\bTests\b[^)]*\)/g,
// Arrow functions avec paramètres
/\(\s*[^)]*\bTests\b[^)]*\)\s*=>/g,
// Arrow function avec un seul paramètre sans parenthèses
/\bTests\s*=>/g,
// Destructuration d'objets
/\{\s*[^}]*\bTests\b[^}]*\}\s*=/g,
// Destructuration de tableaux
/\[\s*[^\]]*\bTests\b[^\]]*\]\s*=/g,
// Catch clause
/catch\s*\(\s*Tests\s*\)/g,
// For...of/in loops
/for\s*\(\s*(let|const|var)?\s*Tests\s+(of|in)\b/g,
];
function findTestsInFile(filePath) {
const content = fs.readFileSync(filePath, 'utf-8');
const lines = content.split('\n');
const results = [];
lines.forEach((line, index) => {
patterns.forEach(pattern => {
pattern.lastIndex = 0; // Reset regex
if (pattern.test(line)) {
results.push({
line: index + 1,
content: line.trim()
});
}
});
});
return results;
}
function walkDirectory(dir) {
const files = fs.readdirSync(dir);
const allResults = {};
files.forEach(file => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
Object.assign(allResults, walkDirectory(filePath));
} else if (file.endsWith('.js')) {
const results = findTestsInFile(filePath);
if (results.length > 0) {
allResults[filePath] = results;
}
}
});
return allResults;
}
// Main
const scriptsDir = path.join(__dirname, 'scripts');
console.log('🔍 Recherche des variables JavaScript nommées "Tests" dans le répertoire scripts/...\n');
if (!fs.existsSync(scriptsDir)) {
console.error('❌ Le répertoire scripts/ n\'existe pas');
process.exit(1);
}
const results = walkDirectory(scriptsDir);
if (Object.keys(results).length === 0) {
console.log('✅ Aucune variable JavaScript nommée "Tests" trouvée.');
} else {
console.log(`⚠️ ${Object.keys(results).length} fichier(s) contenant des variables "Tests" :\n`);
Object.entries(results).forEach(([filePath, occurrences]) => {
const relativePath = path.relative(__dirname, filePath);
console.log(`📄 ${relativePath}`);
occurrences.forEach(({ line, content }) => {
console.log(` Ligne ${line}: ${content}`);
});
console.log('');
});
}

View File

@@ -5,9 +5,6 @@
}, },
{ {
"path": "../WFRP4e-FoundryVTT" "path": "../WFRP4e-FoundryVTT"
},
{
"path": "../WarhammerLibrary-FVTT"
} }
], ],
"settings": {} "settings": {}

View File

@@ -1192,6 +1192,10 @@
"CHAT.ExpReceivedNoReason":"Vous avez reçu <b>{amount}</b> points d'expérience", "CHAT.ExpReceivedNoReason":"Vous avez reçu <b>{amount}</b> points d'expérience",
"CHAT.CriticalDeflection":"Déviation de Critique", "CHAT.CriticalDeflection":"Déviation de Critique",
"CHAT.DamageToArmour":"1 Dommages appliqués à {item} ({type})", "CHAT.DamageToArmour":"1 Dommages appliqués à {item} ({type})",
"CHAT.CastSpell":"Incanter {spell}",
"CHAT.Dispel":"Dissiper {spell}",
"CHAT.DissolutionTable":"Lancer sur la Table de Dissolution du Corps et de l'Esprit pour votre Espèce:<br>@Table[corruption]",
"CHAT.InvokePrayer":"Invoquer {prayer}",
"Error.SpeciesSkills" : "Impossible d'ajouter des compétences pour les races", "Error.SpeciesSkills" : "Impossible d'ajouter des compétences pour les races",
"Error.SpeciesTalents" : "Impossible d'ajouter des talents pour les races", "Error.SpeciesTalents" : "Impossible d'ajouter des talents pour les races",
@@ -2348,6 +2352,8 @@
"EFFECT.AffectTheSourceOfFearName":"Tests qui affectent {name}", "EFFECT.AffectTheSourceOfFearName":"Tests qui affectent {name}",
"EFFECT.DeletingEffectItems":"Suppression des items d'effets: {items}", "EFFECT.DeletingEffectItems":"Suppression des items d'effets: {items}",
"EFFECT.BlackpowderShock":"Contre-coup de Poudre Noire", "EFFECT.BlackpowderShock":"Contre-coup de Poudre Noire",
"EFFECT.BonusModifier":"Modificateur de Bonus",
"EFFECT.CharacteristicsBonus":"Caractéristiques (Modificateur de Bonus)",
"GRIEVANCE.Warning1":"Attention", "GRIEVANCE.Warning1":"Attention",
"GRIEVANCE.Warning2":": Cette information est envoyé sur l'espace Github, qui est un espace publique, donc le Tag Discord est préférable. Sinon, contactez moi (MooMan) directement. Si vous avez l'impression que le bug concerne le module FR, contactez LeRatierBretonnier (Discord Foundry FR)", "GRIEVANCE.Warning2":": Cette information est envoyé sur l'espace Github, qui est un espace publique, donc le Tag Discord est préférable. Sinon, contactez moi (MooMan) directement. Si vous avez l'impression que le bug concerne le module FR, contactez LeRatierBretonnier (Discord Foundry FR)",

View File

@@ -8,7 +8,7 @@
} }
], ],
"url": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr", "url": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr",
"version": "9.3.5", "version": "9.4.3",
"esmodules": [ "esmodules": [
"wh4_fr.js", "wh4_fr.js",
"modules/babele-register.js", "modules/babele-register.js",
@@ -120,7 +120,7 @@
} }
], ],
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/raw/v10/module.json", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/raw/v10/module.json",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/archive/foundryvtt-wh4-lang-fr-9-3-5.zip", "download": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/archive/foundryvtt-wh4-lang-fr-9-4-3.zip",
"id": "wh4-fr-translation", "id": "wh4-fr-translation",
"compatibility": { "compatibility": {
"minimum": "13", "minimum": "13",

View File

@@ -248,16 +248,16 @@ Hooks.once('init', () => {
let translw = translItem?.name || undefined let translw = translItem?.name || undefined
if (translw && translw != s1) { if (translw && translw != s1) {
let res2 = re.exec(translw); let res2 = re.exec(translw);
transl = res2[1] + "(" + subword + ")"; transl = res2[1].trim() + " (" + subword + ")";
} else { } else {
s1 = res[1].trim() + " ( )"; s1 = res[1].trim() + " ( )";
translItem = game.babele.translate(compData.metadata.id, { name: s1, type: "skill" }, true) translItem = game.babele.translate(compData.metadata.id, { name: s1, type: "skill" }, true)
translw = translItem?.name || undefined translw = translItem?.name || undefined
if(translw) { if(translw) {
let res2 = re.exec(translw); let res2 = re.exec(translw);
transl = res2[1] + "(" + subword + ")"; transl = res2[1].trim() + " (" + subword + ")";
} else { } else {
transl = res[1] + " (" + subword + ")"; transl = res[1].trim() + " (" + subword + ")";
} }
} }
} }
@@ -366,7 +366,7 @@ Hooks.once('init', () => {
translItem = game.babele.translate(compData.metadata.id, { name: s1 }, true) translItem = game.babele.translate(compData.metadata.id, { name: s1 }, true)
let translw = translItem?.name || undefined let translw = translItem?.name || undefined
if (translw && translw != s1) { if (translw && translw != s1) {
transl = translw + " (" + subword + ")"; transl = translw.trim() + " (" + subword + ")";
} }
} }
} }
@@ -424,8 +424,10 @@ Hooks.once('init', () => {
if (trait_fr?.name && trait_fr?.name != name_en) { if (trait_fr?.name && trait_fr?.name != name_en) {
trait_fr.name = trait_fr.name || trait_en.name trait_fr.name = trait_fr.name || trait_en.name
trait_en.name = nbt + trait_fr.name + special; trait_en.name = nbt + trait_fr.name + special;
trait_en.system.description.value = trait_fr.system.description.value; if ( trait_en.system?.description?.value && trait_fr.system?.description?.value) {
if (trait_en.system?.specification && isNaN(trait_en.system.specification.value)) { // This is a string, so translate it trait_en.system.description.value = trait_fr.system.description.value;
}
if (trait_en?.system?.specification && isNaN(trait_en.system.specification?.value)) { // This is a string, so translate it
//console.log("Translating : ", trait_en.system.specification.value); //console.log("Translating : ", trait_en.system.specification.value);
trait_en.system.specification.value = game.i18n.localize(trait_en.system.specification.value.trim()); trait_en.system.specification.value = game.i18n.localize(trait_en.system.specification.value.trim());
} }

File diff suppressed because one or more lines are too long

View File

@@ -1 +1 @@
MANIFEST-001259 MANIFEST-001307

View File

@@ -1,7 +1,7 @@
2026/01/07-15:26:43.527176 7f93eaffd6c0 Recovering log #1257 2026/03/05-20:38:02.743870 7f7930fff6c0 Recovering log #1305
2026/01/07-15:26:43.536993 7f93eaffd6c0 Delete type=3 #1255 2026/03/05-20:38:02.754744 7f7930fff6c0 Delete type=3 #1303
2026/01/07-15:26:43.537037 7f93eaffd6c0 Delete type=0 #1257 2026/03/05-20:38:02.754879 7f7930fff6c0 Delete type=0 #1305
2026/01/07-15:53:28.412551 7f93e9ffb6c0 Level-0 table #1262: started 2026/03/05-20:42:36.083534 7f78e15b46c0 Level-0 table #1310: started
2026/01/07-15:53:28.412580 7f93e9ffb6c0 Level-0 table #1262: 0 bytes OK 2026/03/05-20:42:36.083606 7f78e15b46c0 Level-0 table #1310: 0 bytes OK
2026/01/07-15:53:28.419118 7f93e9ffb6c0 Delete type=0 #1260 2026/03/05-20:42:36.090385 7f78e15b46c0 Delete type=0 #1308
2026/01/07-15:53:28.432727 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!3IgmiprzLB6Lwenc' @ 72057594037927935 : 1 .. '!journal.pages!suuYN87Al1ZZWtQQ.jhgNnhWhrkOpKs1B' @ 0 : 0; will stop at (end) 2026/03/05-20:42:36.111635 7f78e15b46c0 Manual compaction at level-0 from '!journal!3IgmiprzLB6Lwenc' @ 72057594037927935 : 1 .. '!journal.pages!suuYN87Al1ZZWtQQ.jhgNnhWhrkOpKs1B' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2026/01/07-15:09:19.276373 7f93eaffd6c0 Recovering log #1253 2026/03/05-20:35:58.958021 7f78e2ffd6c0 Recovering log #1301
2026/01/07-15:09:19.291800 7f93eaffd6c0 Delete type=3 #1251 2026/03/05-20:35:59.014393 7f78e2ffd6c0 Delete type=3 #1299
2026/01/07-15:09:19.291847 7f93eaffd6c0 Delete type=0 #1253 2026/03/05-20:35:59.014563 7f78e2ffd6c0 Delete type=0 #1301
2026/01/07-15:13:49.642315 7f93e9ffb6c0 Level-0 table #1258: started 2026/03/05-20:36:36.801154 7f78e15b46c0 Level-0 table #1306: started
2026/01/07-15:13:49.642358 7f93e9ffb6c0 Level-0 table #1258: 0 bytes OK 2026/03/05-20:36:36.801207 7f78e15b46c0 Level-0 table #1306: 0 bytes OK
2026/01/07-15:13:49.649460 7f93e9ffb6c0 Delete type=0 #1256 2026/03/05-20:36:36.851951 7f78e15b46c0 Delete type=0 #1304
2026/01/07-15:13:49.662442 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!3IgmiprzLB6Lwenc' @ 72057594037927935 : 1 .. '!journal.pages!suuYN87Al1ZZWtQQ.jhgNnhWhrkOpKs1B' @ 0 : 0; will stop at (end) 2026/03/05-20:36:36.886757 7f78e15b46c0 Manual compaction at level-0 from '!journal!3IgmiprzLB6Lwenc' @ 72057594037927935 : 1 .. '!journal.pages!suuYN87Al1ZZWtQQ.jhgNnhWhrkOpKs1B' @ 0 : 0; will stop at (end)

View File

@@ -1 +1 @@
MANIFEST-001261 MANIFEST-001309

View File

@@ -1,7 +1,7 @@
2026/01/07-15:26:43.539401 7f93ebfff6c0 Recovering log #1259 2026/03/05-20:38:02.758975 7f78e37fe6c0 Recovering log #1307
2026/01/07-15:26:43.549699 7f93ebfff6c0 Delete type=3 #1257 2026/03/05-20:38:02.770688 7f78e37fe6c0 Delete type=3 #1305
2026/01/07-15:26:43.549758 7f93ebfff6c0 Delete type=0 #1259 2026/03/05-20:38:02.770801 7f78e37fe6c0 Delete type=0 #1307
2026/01/07-15:53:28.419273 7f93e9ffb6c0 Level-0 table #1264: started 2026/03/05-20:42:36.097432 7f78e15b46c0 Level-0 table #1312: started
2026/01/07-15:53:28.419304 7f93e9ffb6c0 Level-0 table #1264: 0 bytes OK 2026/03/05-20:42:36.097481 7f78e15b46c0 Level-0 table #1312: 0 bytes OK
2026/01/07-15:53:28.426268 7f93e9ffb6c0 Delete type=0 #1262 2026/03/05-20:42:36.104419 7f78e15b46c0 Delete type=0 #1310
2026/01/07-15:53:28.440100 7f93e9ffb6c0 Manual compaction at level-0 from '!folders!3uquYH73ttCdoH0I' @ 72057594037927935 : 1 .. '!items!ylFhk7mGZOnAJTUT' @ 0 : 0; will stop at (end) 2026/03/05-20:42:36.111679 7f78e15b46c0 Manual compaction at level-0 from '!folders!3uquYH73ttCdoH0I' @ 72057594037927935 : 1 .. '!items!ylFhk7mGZOnAJTUT' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2026/01/07-15:09:19.293766 7f93ea7fc6c0 Recovering log #1255 2026/03/05-20:35:59.019628 7f7930fff6c0 Recovering log #1303
2026/01/07-15:09:19.310998 7f93ea7fc6c0 Delete type=3 #1253 2026/03/05-20:35:59.074111 7f7930fff6c0 Delete type=3 #1301
2026/01/07-15:09:19.311072 7f93ea7fc6c0 Delete type=0 #1255 2026/03/05-20:35:59.074362 7f7930fff6c0 Delete type=0 #1303
2026/01/07-15:13:49.675722 7f93e9ffb6c0 Level-0 table #1260: started 2026/03/05-20:36:37.079874 7f78e15b46c0 Level-0 table #1308: started
2026/01/07-15:13:49.675750 7f93e9ffb6c0 Level-0 table #1260: 0 bytes OK 2026/03/05-20:36:37.079944 7f78e15b46c0 Level-0 table #1308: 0 bytes OK
2026/01/07-15:13:49.682225 7f93e9ffb6c0 Delete type=0 #1258 2026/03/05-20:36:37.117249 7f78e15b46c0 Delete type=0 #1306
2026/01/07-15:13:49.688884 7f93e9ffb6c0 Manual compaction at level-0 from '!folders!3uquYH73ttCdoH0I' @ 72057594037927935 : 1 .. '!items!ylFhk7mGZOnAJTUT' @ 0 : 0; will stop at (end) 2026/03/05-20:36:37.117631 7f78e15b46c0 Manual compaction at level-0 from '!folders!3uquYH73ttCdoH0I' @ 72057594037927935 : 1 .. '!items!ylFhk7mGZOnAJTUT' @ 0 : 0; will stop at (end)

View File

@@ -1 +1 @@
MANIFEST-001259 MANIFEST-001307

View File

@@ -1,7 +1,7 @@
2026/01/07-15:26:43.564495 7f93eb7fe6c0 Recovering log #1257 2026/03/05-20:38:02.790472 7f78e3fff6c0 Recovering log #1305
2026/01/07-15:26:43.574446 7f93eb7fe6c0 Delete type=3 #1255 2026/03/05-20:38:02.801425 7f78e3fff6c0 Delete type=3 #1303
2026/01/07-15:26:43.574512 7f93eb7fe6c0 Delete type=0 #1257 2026/03/05-20:38:02.801553 7f78e3fff6c0 Delete type=0 #1305
2026/01/07-15:53:28.432738 7f93e9ffb6c0 Level-0 table #1262: started 2026/03/05-20:42:36.090593 7f78e15b46c0 Level-0 table #1310: started
2026/01/07-15:53:28.432770 7f93e9ffb6c0 Level-0 table #1262: 0 bytes OK 2026/03/05-20:42:36.090646 7f78e15b46c0 Level-0 table #1310: 0 bytes OK
2026/01/07-15:53:28.439930 7f93e9ffb6c0 Delete type=0 #1260 2026/03/05-20:42:36.097257 7f78e15b46c0 Delete type=0 #1308
2026/01/07-15:53:28.446625 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!cZtNgayIw2QFhC9u' @ 72057594037927935 : 1 .. '!journal.pages!cZtNgayIw2QFhC9u.ts265H1XkisLgdow' @ 0 : 0; will stop at (end) 2026/03/05-20:42:36.111659 7f78e15b46c0 Manual compaction at level-0 from '!journal!cZtNgayIw2QFhC9u' @ 72057594037927935 : 1 .. '!journal.pages!cZtNgayIw2QFhC9u.ts265H1XkisLgdow' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2026/01/07-15:09:19.333002 7f93ea7fc6c0 Recovering log #1253 2026/03/05-20:35:59.141622 7f7930fff6c0 Recovering log #1301
2026/01/07-15:09:19.348597 7f93ea7fc6c0 Delete type=3 #1251 2026/03/05-20:35:59.197458 7f7930fff6c0 Delete type=3 #1299
2026/01/07-15:09:19.348662 7f93ea7fc6c0 Delete type=0 #1253 2026/03/05-20:35:59.197605 7f7930fff6c0 Delete type=0 #1301
2026/01/07-15:13:49.682345 7f93e9ffb6c0 Level-0 table #1258: started 2026/03/05-20:36:36.998926 7f78e15b46c0 Level-0 table #1306: started
2026/01/07-15:13:49.682371 7f93e9ffb6c0 Level-0 table #1258: 0 bytes OK 2026/03/05-20:36:36.999012 7f78e15b46c0 Level-0 table #1306: 0 bytes OK
2026/01/07-15:13:49.688691 7f93e9ffb6c0 Delete type=0 #1256 2026/03/05-20:36:37.079601 7f78e15b46c0 Delete type=0 #1304
2026/01/07-15:13:49.688891 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!cZtNgayIw2QFhC9u' @ 72057594037927935 : 1 .. '!journal.pages!cZtNgayIw2QFhC9u.ts265H1XkisLgdow' @ 0 : 0; will stop at (end) 2026/03/05-20:36:37.117606 7f78e15b46c0 Manual compaction at level-0 from '!journal!cZtNgayIw2QFhC9u' @ 72057594037927935 : 1 .. '!journal.pages!cZtNgayIw2QFhC9u.ts265H1XkisLgdow' @ 0 : 0; will stop at (end)

View File

@@ -1 +1 @@
MANIFEST-001259 MANIFEST-001307

View File

@@ -1,7 +1,7 @@
2026/01/07-15:26:43.514726 7f93ea7fc6c0 Recovering log #1257 2026/03/05-20:38:02.727495 7f78e2ffd6c0 Recovering log #1305
2026/01/07-15:26:43.524436 7f93ea7fc6c0 Delete type=3 #1255 2026/03/05-20:38:02.739900 7f78e2ffd6c0 Delete type=3 #1303
2026/01/07-15:26:43.524498 7f93ea7fc6c0 Delete type=0 #1257 2026/03/05-20:38:02.740017 7f78e2ffd6c0 Delete type=0 #1305
2026/01/07-15:53:28.406072 7f93e9ffb6c0 Level-0 table #1262: started 2026/03/05-20:42:36.060514 7f78e15b46c0 Level-0 table #1310: started
2026/01/07-15:53:28.406116 7f93e9ffb6c0 Level-0 table #1262: 0 bytes OK 2026/03/05-20:42:36.060577 7f78e15b46c0 Level-0 table #1310: 0 bytes OK
2026/01/07-15:53:28.412401 7f93e9ffb6c0 Delete type=0 #1260 2026/03/05-20:42:36.067949 7f78e15b46c0 Delete type=0 #1308
2026/01/07-15:53:28.419261 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!50u8VAjdmovyr0hx' @ 72057594037927935 : 1 .. '!journal.pages!yzw9I0r3hCK7PJnz.sPNCYj2nR3Cp3jHd' @ 0 : 0; will stop at (end) 2026/03/05-20:42:36.083144 7f78e15b46c0 Manual compaction at level-0 from '!journal!50u8VAjdmovyr0hx' @ 72057594037927935 : 1 .. '!journal.pages!yzw9I0r3hCK7PJnz.sPNCYj2nR3Cp3jHd' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2026/01/07-15:09:19.258501 7f93eb7fe6c0 Recovering log #1253 2026/03/05-20:35:58.885055 7f78e37fe6c0 Recovering log #1301
2026/01/07-15:09:19.274117 7f93eb7fe6c0 Delete type=3 #1251 2026/03/05-20:35:58.952601 7f78e37fe6c0 Delete type=3 #1299
2026/01/07-15:09:19.274190 7f93eb7fe6c0 Delete type=0 #1253 2026/03/05-20:35:58.952732 7f78e37fe6c0 Delete type=0 #1301
2026/01/07-15:13:49.656004 7f93e9ffb6c0 Level-0 table #1258: started 2026/03/05-20:36:36.852227 7f78e15b46c0 Level-0 table #1306: started
2026/01/07-15:13:49.656029 7f93e9ffb6c0 Level-0 table #1258: 0 bytes OK 2026/03/05-20:36:36.852283 7f78e15b46c0 Level-0 table #1306: 0 bytes OK
2026/01/07-15:13:49.662317 7f93e9ffb6c0 Delete type=0 #1256 2026/03/05-20:36:36.886395 7f78e15b46c0 Delete type=0 #1304
2026/01/07-15:13:49.662464 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!50u8VAjdmovyr0hx' @ 72057594037927935 : 1 .. '!journal.pages!yzw9I0r3hCK7PJnz.sPNCYj2nR3Cp3jHd' @ 0 : 0; will stop at (end) 2026/03/05-20:36:36.886780 7f78e15b46c0 Manual compaction at level-0 from '!journal!50u8VAjdmovyr0hx' @ 72057594037927935 : 1 .. '!journal.pages!yzw9I0r3hCK7PJnz.sPNCYj2nR3Cp3jHd' @ 0 : 0; will stop at (end)

View File

@@ -1 +1 @@
MANIFEST-001259 MANIFEST-001307

View File

@@ -1,7 +1,7 @@
2026/01/07-15:26:43.501310 7f93eb7fe6c0 Recovering log #1257 2026/03/05-20:38:02.710364 7f7930fff6c0 Recovering log #1305
2026/01/07-15:26:43.512173 7f93eb7fe6c0 Delete type=3 #1255 2026/03/05-20:38:02.722794 7f7930fff6c0 Delete type=3 #1303
2026/01/07-15:26:43.512224 7f93eb7fe6c0 Delete type=0 #1257 2026/03/05-20:38:02.722917 7f7930fff6c0 Delete type=0 #1305
2026/01/07-15:53:28.398067 7f93e9ffb6c0 Level-0 table #1262: started 2026/03/05-20:42:36.068193 7f78e15b46c0 Level-0 table #1310: started
2026/01/07-15:53:28.398117 7f93e9ffb6c0 Level-0 table #1262: 0 bytes OK 2026/03/05-20:42:36.068246 7f78e15b46c0 Level-0 table #1310: 0 bytes OK
2026/01/07-15:53:28.405830 7f93e9ffb6c0 Delete type=0 #1260 2026/03/05-20:42:36.074966 7f78e15b46c0 Delete type=0 #1308
2026/01/07-15:53:28.412533 7f93e9ffb6c0 Manual compaction at level-0 from '!tables!4l60Lxv8cpsyy2Cg' @ 72057594037927935 : 1 .. '!tables.results!tfaYKDZqu7kgZvRG.yvbwKursaixh2dby' @ 0 : 0; will stop at (end) 2026/03/05-20:42:36.083182 7f78e15b46c0 Manual compaction at level-0 from '!tables!4l60Lxv8cpsyy2Cg' @ 72057594037927935 : 1 .. '!tables.results!tfaYKDZqu7kgZvRG.yvbwKursaixh2dby' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2026/01/07-15:09:19.238733 7f93ebfff6c0 Recovering log #1253 2026/03/05-20:35:58.822672 7f78e2ffd6c0 Recovering log #1301
2026/01/07-15:09:19.256250 7f93ebfff6c0 Delete type=3 #1251 2026/03/05-20:35:58.879917 7f78e2ffd6c0 Delete type=3 #1299
2026/01/07-15:09:19.256331 7f93ebfff6c0 Delete type=0 #1253 2026/03/05-20:35:58.880051 7f78e2ffd6c0 Delete type=0 #1301
2026/01/07-15:13:49.649560 7f93e9ffb6c0 Level-0 table #1258: started 2026/03/05-20:36:36.762561 7f78e15b46c0 Level-0 table #1306: started
2026/01/07-15:13:49.649585 7f93e9ffb6c0 Level-0 table #1258: 0 bytes OK 2026/03/05-20:36:36.762639 7f78e15b46c0 Level-0 table #1306: 0 bytes OK
2026/01/07-15:13:49.655885 7f93e9ffb6c0 Delete type=0 #1256 2026/03/05-20:36:36.800890 7f78e15b46c0 Delete type=0 #1304
2026/01/07-15:13:49.662454 7f93e9ffb6c0 Manual compaction at level-0 from '!tables!4l60Lxv8cpsyy2Cg' @ 72057594037927935 : 1 .. '!tables.results!tfaYKDZqu7kgZvRG.yvbwKursaixh2dby' @ 0 : 0; will stop at (end) 2026/03/05-20:36:36.886730 7f78e15b46c0 Manual compaction at level-0 from '!tables!4l60Lxv8cpsyy2Cg' @ 72057594037927935 : 1 .. '!tables.results!tfaYKDZqu7kgZvRG.yvbwKursaixh2dby' @ 0 : 0; will stop at (end)

View File

@@ -1 +1 @@
MANIFEST-000902 MANIFEST-000950

View File

@@ -1,7 +1,7 @@
2026/01/07-15:26:43.552530 7f93eaffd6c0 Recovering log #900 2026/03/05-20:38:02.775184 7f7930fff6c0 Recovering log #948
2026/01/07-15:26:43.562158 7f93eaffd6c0 Delete type=3 #898 2026/03/05-20:38:02.786747 7f7930fff6c0 Delete type=3 #946
2026/01/07-15:26:43.562231 7f93eaffd6c0 Delete type=0 #900 2026/03/05-20:38:02.786856 7f7930fff6c0 Delete type=0 #948
2026/01/07-15:53:28.426399 7f93e9ffb6c0 Level-0 table #905: started 2026/03/05-20:42:36.104620 7f78e15b46c0 Level-0 table #953: started
2026/01/07-15:53:28.426431 7f93e9ffb6c0 Level-0 table #905: 0 bytes OK 2026/03/05-20:42:36.104679 7f78e15b46c0 Level-0 table #953: 0 bytes OK
2026/01/07-15:53:28.432585 7f93e9ffb6c0 Delete type=0 #903 2026/03/05-20:42:36.111433 7f78e15b46c0 Delete type=0 #951
2026/01/07-15:53:28.440113 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!056ILNNrLiPq3Gi3' @ 72057594037927935 : 1 .. '!journal.pages!yfZxl4I7XAuUF6r3.apXmOlZRmGT4GreB' @ 0 : 0; will stop at (end) 2026/03/05-20:42:36.111701 7f78e15b46c0 Manual compaction at level-0 from '!journal!056ILNNrLiPq3Gi3' @ 72057594037927935 : 1 .. '!journal.pages!yfZxl4I7XAuUF6r3.apXmOlZRmGT4GreB' @ 0 : 0; will stop at (end)

View File

@@ -1,7 +1,7 @@
2026/01/07-15:09:19.313936 7f93eaffd6c0 Recovering log #896 2026/03/05-20:35:59.080273 7f78e2ffd6c0 Recovering log #944
2026/01/07-15:09:19.330494 7f93eaffd6c0 Delete type=3 #894 2026/03/05-20:35:59.136381 7f78e2ffd6c0 Delete type=3 #942
2026/01/07-15:09:19.330571 7f93eaffd6c0 Delete type=0 #896 2026/03/05-20:35:59.136563 7f78e2ffd6c0 Delete type=0 #944
2026/01/07-15:13:49.669421 7f93e9ffb6c0 Level-0 table #901: started 2026/03/05-20:36:36.924587 7f78e15b46c0 Level-0 table #949: started
2026/01/07-15:13:49.669459 7f93e9ffb6c0 Level-0 table #901: 0 bytes OK 2026/03/05-20:36:36.924663 7f78e15b46c0 Level-0 table #949: 0 bytes OK
2026/01/07-15:13:49.675608 7f93e9ffb6c0 Delete type=0 #899 2026/03/05-20:36:36.998629 7f78e15b46c0 Delete type=0 #947
2026/01/07-15:13:49.688874 7f93e9ffb6c0 Manual compaction at level-0 from '!journal!056ILNNrLiPq3Gi3' @ 72057594037927935 : 1 .. '!journal.pages!yfZxl4I7XAuUF6r3.apXmOlZRmGT4GreB' @ 0 : 0; will stop at (end) 2026/03/05-20:36:37.117578 7f78e15b46c0 Manual compaction at level-0 from '!journal!056ILNNrLiPq3Gi3' @ 72057594037927935 : 1 .. '!journal.pages!yfZxl4I7XAuUF6r3.apXmOlZRmGT4GreB' @ 0 : 0; will stop at (end)

View File

@@ -0,0 +1 @@
return !args.skill?.name.includes(game.i18n.localize("NAME.Row")) && !args.skill?.name.includes(game.i18n.localize("NAME.Sail"));

View File

@@ -0,0 +1,4 @@
if (!this.item.system.properties.qualities.fast)
this.item.system.qualities.value.push({name : 'fast'});
if (!this.item.system.properties.qualities.magical)
this.item.system.qualities.value.push({name : 'magical'});

View File

@@ -16,6 +16,6 @@ if (location)
let roll = await new Roll("max(1, 1d10 - @system.characteristics.t.bonus)", this.actor).roll() let roll = await new Roll("max(1, 1d10 - @system.characteristics.t.bonus)", this.actor).roll()
roll.toMessage(this.script.getChatData({flavor : `${this.effet.name} (Durée)`})); roll.toMessage(this.script.getChatData({flavor : `${this.effect.name} (Durée)`}));
this.effet.updateSource({"duration.rounds" : roll.total}) this.effect.updateSource({"duration.rounds" : roll.total})

View File

@@ -0,0 +1,9 @@
if (args.skill?.name != game.i18n.localize("NAME.Gossip"))
{
return true;
}
else
{
args.data.reversal = {allowed : true, if: "success"}; // Kind of a kludge here, the talent Tests has a specific condition, but the description simply says "any gossip test can be reversed" so check it here instead of submission
}

View File

@@ -0,0 +1,7 @@
this.actor.setupSkill(game.i18n.localize("NAME.Cool"), {skipTargets: true, appendTitle : ` - ${this.effect.name}`}).then(async test => {
await test.roll()
if (test.failed)
{
this.actor.addCondition("stunned")
}
})

View File

@@ -0,0 +1,18 @@
const balanced = game.i18n.localize("WFRP4E.YenluiBalanced");
const light = game.i18n.localize("WFRP4E.YenluiLight");
const dark = game.i18n.localize("WFRP4E.YenluiDark");
let newName, newDescription;
if (this.effect.name === game.i18n.localize("WFRP4E.YenluiDark")) {
newName = game.i18n.localize("WFRP4E.YenluiBalanced");
newDescription = game.i18n.localize("WFRP4E.YenluiBalancedDesc");
} else if (this.effect.name === game.i18n.localize("WFRP4E.YenluiBalanced")) {
newName = game.i18n.localize("WFRP4E.YenluiLight");
newDescription = game.i18n.localize("WFRP4E.YenluiLightDesc");
}
if (newName) {
await this.effect.update({name: newName});
await this.item.update({name: newName, "system.description.value": newDescription});
}

View File

@@ -1,31 +1,28 @@
if (!this.item.name.includes("(") || this.item.system.Tests.value.includes("Terrain") || this.item.system.Tests.value.toLowerCase().includes("(any)")) if (!this.item.name.includes("(") || this.item.system.tests.value.includes("Terrain") || this.item.system.tests.value.toLowerCase().includes("(any)")) {
{ let tests = this.item.system.tests.value
let Tests = this.item.system.Tests.value let name = this.item.name
let name = this.item.name
// If name already specifies, make sure Tests value reflects that // If name already specifies, make sure Tests value reflects that
if (name.includes("(") && !name.toLowerCase().includes("(any)")) if (name.includes("(") && !name.toLowerCase().includes("(any)")) {
{ let terrain = name.split("(")[1].split(")")[0]
let terrain = name.split("(")[1].split(")")[0] tests = tests.replace("the Terrain", terrain)
tests = tests.replace("the Terrain", terrain) }
} else // If no sense specified, provide dialog choice
else // If no sense specified, provide dialog choice {
{ let choice = await ItemDialog.create(ItemDialog.objectToArray({
let choice = await ItemDialog.create(ItemDialog.objectToArray({ coastal: "Littoral",
coastal : "Littoral", deserts: "Déserts",
deserts : "Déserts", marshes: "Marécages",
marshes : "Marécages", rocky: "Rocailleux",
rocky : "Rocailleux", tundra: "Toundra",
tundra : "Toundra", woodlands: "Régions boisées"
woodlands : "Régions boisées" }, this.item.img), 1, "Choisissez un Terrain");
}, this.item.img), 1, "Choisissez un Terrain"); if (choice[0]) {
if (choice[0]) name = `${name.split("(")[0].trim()} (${choice[0].name})`
{ tests = tests.replace("Terrain", choice[0].name + " Terrain")
name = `${name.split("(")[0].trim()} (${choice[0].name})`
tests = tests.replace("Terrain", choice[0].name + " Terrain")
}
} }
}
this.effet.updateSource({name}) this.effect.updateSource({ name })
this.item.updateSource({name, "system.tests.value" : tests}) this.item.updateSource({ name, "system.tests.value": tests })
} }

View File

@@ -0,0 +1 @@
return !args.skill?.name.includes(game.i18n.localize("NAME.Language"));

View File

@@ -83,7 +83,7 @@ for (let trapping of trappings)
} }
} }
updateObj.name = updateObj.name += " " + this.effet.name updateObj.name = updateObj.name += " " + this.effect.name
await this.actor.update(updateObj) await this.actor.update(updateObj)
this.actor.createEmbeddedDocuments("Item", items); this.actor.createEmbeddedDocuments("Item", items);

View File

@@ -0,0 +1 @@
return args.skill?.name.includes(game.i18n.localize("NAME.Channelling")) || args.skill?.name == `${game.i18n.localize("NAME.Language")} (${game.i18n.localize("SPEC.Magick")})`

View File

@@ -0,0 +1,3 @@
const qualities = foundry.utils.deepClone(args.item.system.qualities.value);
qualities.push({name:"fine", value: 1});
args.item?.update({"system.qualities.value": qualities});

View File

@@ -1,4 +1,4 @@
let test = await args.actor.setupCharacteristic("wp", {skipTargets: true, appendTitle : " - " + this.effet.name, context : {failure: "Gain de 1 état Sonné"}}) let test = await args.actor.setupCharacteristic("wp", {skipTargets: true, appendTitle : " - " + this.effect.name, context : {failure: "Gain de 1 état Sonné"}})
await Test.roll(); await Test.roll();
if (Test.Échoué) if (Test.Échoué)
{ {

View File

@@ -0,0 +1,19 @@
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {skipTargets: true, appendTitle : " - " + this.effect.name})
await test.roll();
if (!test.succeeded)
{
let item = await fromUuid("Compendium.wfrp4e-core.items.ZhMADOqoo0y8Q9bx")
let data = item.toObject();
if (this.item.system.location.key == "rLeg")
{
data.system.location.value = "Orteil Droit"
data.system.location.key = "rToe";
}
else if (this.item.system.location.key == "lLeg")
{
data.system.location.value = "Orteil Gauche"
data.system.location.key = "lToe";
}
this.actor.createEmbeddedDocuments("Item", [data])
}
this.effect.delete();

View File

@@ -0,0 +1,7 @@
this.actor.setupSkill(game.i18n.localize("NAME.Cool"), {skipTargets: true, appendTitle : ` - ${this.effect.name}`}).then(async test => {
await test.roll();
if (test.failed)
{
this.actor.addCondition("stunned", 3)
}
})

View File

@@ -0,0 +1 @@
return !args.skill?.name?.includes(game.i18n.localize("NAME.Sail"))

View File

@@ -0,0 +1 @@
return args.type != "channelling" && !args.skill?.name.includes(game.i18n.localize("NAME.Channelling"))

View File

@@ -0,0 +1,5 @@
if (args.item.range && args.item.range.bands)
{
args.item.range.bands[game.i18n.localize("Long Range")].modifier = 0
args.item.range.bands[game.i18n.localize("Extreme")].modifier /= 2
}

View File

@@ -0,0 +1,6 @@
if (args.test.result.castOutcome == "success" && args.test.spell.system.lore.value.includes("high"))
{
this.effect.update({name: this.effect.setSpecifier(parseInt(this.effect.specifier - 1))})
this.script.message("La valeur de Protection est maintenant de " + (this.effect.specifier - 1), {flavor: this.effect.sourceItem.name})
}

View File

@@ -0,0 +1 @@
return args.skill?.name == game.i18n.localize("NAME.Bribery") || args.skill?.name.includes(game.i18n.localize("NAME.Stealth"));

View File

@@ -0,0 +1 @@
return args.item?.name != game.i18n.localize("NAME.Navigation")

View File

@@ -0,0 +1,9 @@
if (args.totalWoundLoss > 0)
{
let test = await args.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {skipTargets: true, appendTitle : ` - ${this.effect.name}`})
await test.roll();
if (test.failed && parseInt(args.sourceTest?.result.SL) > 0)
{
args.actor.addCondition("stunned", parseInt(args.sourceTest?.attackerTest.result.SL))
}
}

View File

@@ -0,0 +1,19 @@
let skill = `${game.i18n.localize("NAME.Trade")} (${this.item.parenthesesText})`
let currentCareer = this.actor.system.currentCareer;
let existingSkill = this.actor.itemTypes.skill.find(i => i.name == skill);
if (!currentCareer) return
let inCurrentCareer = currentCareer.system.skills.concat(currentCareer.system.addedSkills).includes(skill);
let craftsmanAdded = this.actor.getFlag("wfrp4e", "craftsmanAdded") || {};
if (existingSkill && inCurrentCareer && !craftsmanAdded[existingSkill.name])
{
existingSkill.system.advances.costModifier = -5;
}
else
{
craftsmanAdded[skill] = true;
currentCareer.system.addedSkills.push(skill);
foundry.utils.setProperty(this.actor, "flags.wfrp4e.craftsmanAdded", craftsmanAdded)
}

View File

@@ -0,0 +1,4 @@
let item = await fromUuid("Compendium.wfrp4e-core.items.9h82z72XGo9tfgQS")
let data = item.toObject();
data.name = data.name += ` (${game.i18n.localize("SPEC.Hearing")})`
this.actor.createEmbeddedDocuments("Item", [data], {fromEffect : this.effect.id})

View File

@@ -0,0 +1 @@
return args.skill?.name.includes(game.i18n.localize("NAME.Lore"));

View File

@@ -0,0 +1,20 @@
if (!["Goblin", "Orc"].includes(this.actor.system.details.species.value)) {
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), { appendTitle: ` - ${this.effect.name}` })
await test.roll();
if (test.failed) {
let infection = await fromUuid("Compendium.wfrp4e-core.items.Item.1hQuVFZt9QnnbWzg")
this.actor.createEmbeddedDocuments("Item", [infection])
}
}
// Since wounds change when the effect is deleted, need to wait until after
// the max wounds have been recalculated to apply damage
warhammer.utility.sleep(1000).then(async () => {
let roll = await new Roll("1d10").roll({allowInteractive : false});
roll.toMessage(this.script.getChatData());
this.script.message(await this.actor.applyBasicDamage(roll.total, { damageType: game.wfrp4e.config.DAMAGE_TYPE.IGNORE_ALL, suppressMsg: true }))
})

View File

@@ -0,0 +1,18 @@
let currentCareer = this.actor.system.currentCareer;
if (!currentCareer)
{
return;
}
let talents = [game.i18n.localize("NAME.AA"),
`${game.i18n.localize("NAME.ArcaneMagic")} (${game.i18n.localize("SPEC.Any")})`,
game.i18n.localize("NAME.ChaosMagic") + " " + "(Tzeentch)",
game.i18n.localize("NAME.FastHands"),
game.i18n.localize("NAME.ID"),
game.i18n.localize("NAME.MagicalSense"),
game.i18n.localize("NAME.PettyMagic"),
game.i18n.localize("NAME.SecondSight"),
game.i18n.localize("NAME.WarWizard"),
game.i18n.localize("NAME.Witch")].filter(t => !currentCareer.system.talents.includes(t))
currentCareer.system.talents = currentCareer.system.talents.concat(talents)

View File

@@ -0,0 +1,3 @@
const qualities = foundry.utils.deepClone(args.item.system.qualities.value);
qualities.push({name:"lightweight"});
args.item?.update({"system.qualities.value": qualities});

View File

@@ -0,0 +1,3 @@
return !args.actor?.has(game.i18n.localize("NAME.Swarm")) ||
![game.wfrp4e.config.actorSizeNums.tiny, game.wfrp4e.config.actorSizeNums.ltl]
.includes(args.actor?.sizeNum)

View File

@@ -0,0 +1,14 @@
if (Number(this.actor.system.details.age.value) > 870) {
if (["t", "wp", "fel"].includes(args.characteristic))
args.fields.slBonus -= 3;
if (["ag", "dex", "int"].includes(args.characteristic))
args.fields.slBonus -= 2;
} else if (Number(this.actor.system.details.age.value) > 350) {
if (["t", "wp"].includes(args.characteristic))
args.fields.slBonus -= 2;
if (["fel"].includes(args.characteristic))
args.fields.slBonus -= 1;
} else {
if (["t", "wp"].includes(args.characteristic))
args.fields.slBonus -= 1;
}

View File

@@ -0,0 +1 @@
this.effect.updateSource({name: this.effect.setSpecifier("9")});

View File

@@ -0,0 +1,44 @@
let choice = await ItemDialog.create(ItemDialog.objectToArray(game.wfrp4e.config.locations, this.effect.img), 1, "Choose Location");
if (choice[0])
{
this.effect.updateSource({name : `${this.effect.name} (${choice[0].name})`})
this.effect.updateSource({"flags.wfrp4e.location" : choice[0].id})
}
let location = choice[0].id;
if (["lArm", "rArm"].includes(location))
{
let dropped = this.actor.itemTypes.weapon.filter(i => i.isEquipped & i.system.usesHands.includes(location));
if (dropped.length)
{
this.script.notification(`Dropped ${dropped.map(i => i.name).join(", ")}!`)
for(let weapon of dropped)
{
await weapon.system.toggleEquip();
}
}
}
if (location == "body")
{
await this.actor.addCondition("fatigued");
test = await this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {fields : {difficulty : "hard"}, skipTargets: true, appendTitle : ` - ${this.effect.name}`})
await test.roll();
if (test.failed)
{
this.actor.addCondition("prone");
}
}
if (location == "head")
{
await this.actor.addCondition("stunned");
test = await this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {fields : {difficulty : "average"}, skipTargets: true, appendTitle : ` - ${this.effect.name}`})
await test.roll();
if (test.failed)
{
this.actor.addCondition("unconscious");
}
}

View File

@@ -0,0 +1,2 @@
args.abort = true;
this.script.notification("Impossible d'attaquer cette cible !");

View File

@@ -0,0 +1 @@
return args.skill?.name != game.i18n.localize("NAME.CharmAnimal") && !args.skill?.name.includes(game.i18n.localize("NAME.AnimalTraining"));

View File

@@ -0,0 +1 @@
return !["NAME.Evaluate", "NAME.Gamble"].map(i => game.i18n.localize(i)).includes(args.skill?.name)

View File

@@ -0,0 +1,4 @@
if (this.actor.hasCondition("surprised"))
{
this.actor.setupSkill(game.i18n.localize("NAME.Cool"), {fields : {difficulty : "average"}, skipTargets: true, appendTitle : " - " + this.effect.name}).then(test => test.roll())
}

View File

@@ -0,0 +1 @@
return this.effect.name !== game.i18n.localize("WFRP4E.YenluiLight")

View File

@@ -0,0 +1 @@
return args.skill?.name == game.i18n.localize("NAME.ConsumeAlcohol");

View File

@@ -0,0 +1 @@
return args.item?.system.isRanged;

View File

@@ -0,0 +1 @@
return args.skill?.name != game.i18n.localize("NAME.Research") && !args.skill?.name?.includes(game.i18n.localize("NAME.Language"));

View File

@@ -69,7 +69,7 @@ for (let trapping of trappings)
} }
} }
updateObj.name = updateObj.name += " " + this.effet.name updateObj.name = updateObj.name += " " + this.effect.name
await this.actor.update(updateObj) await this.actor.update(updateObj)
this.actor.createEmbeddedDocuments("Item", items); this.actor.createEmbeddedDocuments("Item", items);

View File

@@ -0,0 +1 @@
this.actor.addEffectItems("Compendium.wfrp4e-core.items.Item.EO05HX7jql0g605A", this.effect, {"system.specification.value": this.actor.system.characteristics.ag.value});

View File

@@ -0,0 +1 @@
return args.skill?.name !== game.i18n.localize("NAME.Endurance");

View File

@@ -0,0 +1,10 @@
this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {skipTargets: true, appendTitle : ` - ${this.effect.name}`, fields: {difficulty : "average"}}).then(async test =>
{
await test.roll()
if (test.failed)
{
let char = Math.ceil(CONFIG.Dice.randomUniform() * 2) == 2 ? "s" : "t";
this.script.message(`<strong>${this.actor.name}</strong> perd 1 point de ${game.wfrp4e.config.characteristics[char]}`)
this.actor.update({[`system.characteristics.${char}.initial`] : this.actor.system.characteristics[char].initial - 1})
}
})

View File

@@ -44,7 +44,7 @@ for (let trait of traits)
updateObj.name = updateObj.name += " " + this.effet.name updateObj.name = updateObj.name += " " + this.effect.name
await this.actor.update(updateObj) await this.actor.update(updateObj)
this.actor.createEmbeddedDocuments("Item", items); this.actor.createEmbeddedDocuments("Item", items);

View File

@@ -0,0 +1 @@
return args.skill?.name?.includes(game.i18n.localize("NAME.Language")) || args.type == "cast"

View File

@@ -0,0 +1,7 @@
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {skipTargets: true, appendTitle : ` - ${this.effect.name}`, fields : {difficulty : "average"}, context : {failure: "1 Corruption Point Gained"}})
await test.roll();
if (test.failed && this.actor.type == "character")
{
this.actor.update({"system.status.corruption.value" : parseInt(this.actor.status.corruption.value) + 1})
this.script.message("Gain de 1 point de Corruption", {whisper : ChatMessage.getWhisperRecipients("GM")})
}

View File

@@ -1,4 +1,4 @@
let test = await this.actor.setupCharacteristic("ag", {skipTargets: true, appendTitle : ` - ${this.effet.name}`}); let test = await this.actor.setupCharacteristic("ag", {skipTargets: true, appendTitle : ` - ${this.effect.name}`});
await Test.roll(); await Test.roll();
if (Test.Échoué) if (Test.Échoué)
{ {

View File

@@ -0,0 +1,10 @@
if (args.totalWoundLoss > 0)
{
let test = await args.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {skipTargets: true, appendTitle : " - " + this.effect.name})
await test.roll();
if (test.failed)
{
args.totalWoundLoss += 5;
args.modifiers.other.push({label : this.effect.name, value : 5})
}
}

View File

@@ -106,7 +106,7 @@ if (ride)
items = items.concat({name : "Chaos Steed", type: "trapping", "system.trappingType.value" : "misc"}, skill) items = items.concat({name : "Chaos Steed", type: "trapping", "system.trappingType.value" : "misc"}, skill)
} }
updateObj.name = updateObj.name += " " + this.effet.name updateObj.name = updateObj.name += " " + this.effect.name
await this.actor.update(updateObj) await this.actor.update(updateObj)
this.actor.createEmbeddedDocuments("Item", items); this.actor.createEmbeddedDocuments("Item", items);

View File

@@ -0,0 +1 @@
return args.skill?.name != game.i18n.localize("NAME.Research");

View File

@@ -0,0 +1 @@
return args.skill?.name.includes(game.i18n.localize("NAME.Channelling")) || args.type == "channelling" || args.skill?.name == game.i18n.localize("NAME.Charm") || args.skill?.name.includes(`${game.i18n.localize("NAME.Language")} (${game.i18n.localize("SPEC.Magick")})`) || args.type == "cast"

View File

@@ -69,7 +69,7 @@ for (let trapping of trappings)
} }
} }
updateObj.name = updateObj.name += " " + this.effet.name updateObj.name = updateObj.name += " " + this.effect.name
await this.actor.update(updateObj) await this.actor.update(updateObj)
this.actor.createEmbeddedDocuments("Item", items); this.actor.createEmbeddedDocuments("Item", items);

View File

@@ -0,0 +1 @@
await this.effect.update({duration:{rounds: this.actor.system.characteristics.ws.bonus}});

View File

@@ -0,0 +1,9 @@
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {fields: {difficulty : "average"}, appendTitle : " - Wounded"})
await test.roll();
if (test.failed)
{
fromUuid("Compendium.wfrp4e-core.items.kKccDTGzWzSXCBOb").then(disease => {
this.actor.createEmbeddedDocuments("Item", [disease.toObject()])
this.script.scriptNotification("Gain de " + disease.name)
})
}

View File

@@ -10,17 +10,17 @@ scriptData[0].script = `
let chatData = {whisper: ChatMessage.getWhisperRecipients("GM")}; let chatData = {whisper: ChatMessage.getWhisperRecipients("GM")};
let message = ""; let message = "";
let Blessures = foundry.utils.duplicate(this.actor.status.Blessures); let wounds = foundry.utils.duplicate(this.actor.status.wounds);
let regenRoll = await new Roll("1d10").roll({allowInteractive : false}); let regenRoll = await new Roll("1d10").roll({allowInteractive : false});
let regen = regenRoll.total; let regen = regenRoll.total;
if (Blessures.value >= Blessures.max) if (wounds.value >= wounds.max)
return; return;
if (Blessures.value > 0) { if (wounds.value > 0) {
Blessures.value += Math.floor(regen / 2); wounds.value += Math.floor(regen / 2);
if (Blessures.value > Blessures.max) { if (wounds.value > wounds.max) {
Blessures.value = Blessures.max; wounds.value = wounds.max;
} }
message += \`<b>\${this.actor.name}</b> regagne \${regen} Blessures.\`; message += \`<b>\${this.actor.name}</b> regagne \${regen} Blessures.\`;
@@ -29,7 +29,7 @@ scriptData[0].script = `
} }
} else if (regen >= 8) { } else if (regen >= 8) {
message += \`<b>\${this.actor.name}</b> a obtenu un \${regen} et regagne 1 Blessure.\`; message += \`<b>\${this.actor.name}</b> a obtenu un \${regen} et regagne 1 Blessure.\`;
Blessures.value += 1; wounds.value += 1;
if (regen === 10) { if (regen === 10) {
message += "<br>De plus, il régénère une Blessure Critique."; message += "<br>De plus, il régénère une Blessure Critique.";
} }
@@ -37,7 +37,7 @@ scriptData[0].script = `
message += \`<b>\${this.actor.name}</b> Résultat de régénération de \${regen} - Aucun effet.\`; message += \`<b>\${this.actor.name}</b> Résultat de régénération de \${regen} - Aucun effet.\`;
} }
await this.actor.update({"system.status.wounds": Blessures}); await this.actor.update({"system.status.wounds": wounds});
this.script.message(message, {whisper: ChatMessage.getWhisperRecipients("GM")}); this.script.message(message, {whisper: ChatMessage.getWhisperRecipients("GM")});
` `
@@ -46,4 +46,4 @@ await effet.update({
"system.scriptData": scriptData "system.scriptData": scriptData
}); });
await trait.update({name}); await trait.update({ name });

View File

@@ -69,7 +69,7 @@ for (let trapping of trappings)
} }
} }
updateObj.name = updateObj.name += " " + this.effet.name updateObj.name = updateObj.name += " " + this.effect.name
await this.actor.update(updateObj) await this.actor.update(updateObj)
this.actor.createEmbeddedDocuments("Item", items); this.actor.createEmbeddedDocuments("Item", items);

View File

@@ -0,0 +1 @@
return !args.item?.name.includes(game.i18n.localize("NAME.Stealth"))

View File

@@ -0,0 +1,2 @@
const traits = this.actor.itemTypes.trait.filter(t => ["bestial", "skittish"].includes(s.name.toLowerCase()));
trait.system.disabled = true;

View File

@@ -0,0 +1 @@
return !([game.i18n.localize("NAME.AnimalCare"), game.i18n.localize("NAME.CharmAnimal")].includes(args.item?.name) || args.item?.name.includes(game.i18n.localize("NAME.Ride")) || args.item?.name.includes(game.i18n.localize("NAME.AnimalTraining")));

View File

@@ -0,0 +1,8 @@
let bite = await fromUuid("Compendium.wfrp4e-core.items.pLW9SVX0TVTYPiPv")
let sense = await fromUuid("Compendium.wfrp4e-core.items.9h82z72XGo9tfgQS")
let biteData = bite.toObject();
let senseData = sense.toObject();
biteData.system.specification.value = 6 - this.actor.characteristics.s.bonus;
senseData.name = senseData.name += game.i18n.localize("SPEC.Smell")
this.actor.createEmbeddedDocuments("Item", [biteData, senseData], {fromEffect : this.effect.id})

View File

@@ -0,0 +1,6 @@
let test = await this.actor.setupSkill(game.i18n.localize("NAME.Endurance"), {skipTargets: true, appendTitle : ` - ${this.effect.name}`})
await test.roll();
if (test.failed)
{
this.actor.addCondition("prone");
}

View File

@@ -0,0 +1,11 @@
let roll = Math.ceil(CONFIG.Dice.randomUniform() * 10)
if (args.test.isFumble && roll == 1 && !args.test.result.misfire)
{
args.test.result.misfire = game.i18n.localize("Misfire") + " (Rolled 1)"
args.test.result.misfireDamage = eval(parseInt(args.test.result.roll.toString().split('').pop()) + args.test.item.Damage)
}
else if (args.test.isFumble && roll != 1)
{
args.test.result.other.push("Misfire Roll: " + roll)
}

View File

@@ -0,0 +1,6 @@
const deduct = this.effect.setFlag("wfrp4e", "failed");
if (!deduct) return;
this.actor.system.characteristics.ws.modifier -= 20;
this.actor.system.characteristics.bs.modifier -= 20;

Some files were not shown because too many files have changed in this diff Show More