Nouvelles traductions

This commit is contained in:
LeRatierBretonnien 2023-01-15 10:10:26 +01:00
parent 2d6091d477
commit ecbb3dcdf4
5 changed files with 660 additions and 388 deletions

View File

@ -215,7 +215,7 @@ const __check_fix_wrong_modules = (chatFlag, patchFinished) => {
});
if (game.user.isGM && patchFinished) {
ChatMessage.create({
content: "<div>Les modules WFRP4E ont été <strong>patchés avec succés</strong>. Vous pouvez y aller et que <strong>Shallya vous garde !</strong></div>",
content: "<div>Les modules WFRP4E ont été <strong>patchés avec succés</strong>. Vous pouvez y aller et que <strong>Shallya vous garde !</strong></div>Nouveautés 6.2.23: <ul><li>Traduction des items du Starter Set (Ashbury77)</li><li>Traduction des items du d'Archives of the Empire (Bimkiz)</li></ul>",
user: game.user.id,
whisper: ChatMessage.getWhisperRecipients("GM")
});

View File

@ -3,42 +3,45 @@ import statParserFR from "./modules/import-stat-2.js";
/************************************************************************************/
var compmod = "wfrp4e-core";
const vo_conditions = {
"ablaze": "Ablaze",
"bleeding": "Bleeding",
"blinded": "Blinded",
"broken": "Broken",
"deafened": "Deafened",
"entangled": "Entangled",
"fatigued": "Fatigued",
"poisoned": "Poisoned",
"prone": "Prone",
"stunned": "Stunned",
"surprised": "Surprised",
"unconscious": "Unconscious",
"grappling": "Grappling",
"fear": "Fear",
"defeated": "Defeated"
const vo_conditions = {
"ablaze": "Ablaze",
"bleeding": "Bleeding",
"blinded": "Blinded",
"broken": "Broken",
"deafened": "Deafened",
"entangled": "Entangled",
"fatigued": "Fatigued",
"poisoned": "Poisoned",
"prone": "Prone",
"stunned": "Stunned",
"surprised": "Surprised",
"unconscious": "Unconscious",
"grappling": "Grappling",
"fear": "Fear",
"defeated": "Defeated"
}
/************************************************************************************/
Hooks.once('init', () => {
// Check various settings in the installation
game.modules.forEach((module, id) => {
if ( id == "wfrp4e-core" && module.active) {
if (id == "wfrp4e-core" && module.active) {
compmod = "wfrp4e-core";
}
} );
game.wfrp4efr = { compmod: compmod,
vo_conditions: vo_conditions }
game.wfrp4e.apps.StatBlockParser.parseStatBlock = async function( statString, type = "npc") {
return statParserFR( statString, type);
}
});
game.wfrp4efr = {
compmod: compmod,
vo_conditions: vo_conditions
}
game.wfrp4e.apps.StatBlockParser.parseStatBlock = async function (statString, type = "npc") {
return statParserFR(statString, type);
}
/*---------------------------------------------------------------------*/
game.wfrp4e.entities.ItemWfrp4e.prototype.computeSpellDamage = function(formula, isMagicMissile) {
game.wfrp4e.entities.ItemWfrp4e.prototype.computeSpellDamage = function (formula, isMagicMissile) {
try {
formula = formula.toLowerCase();
@ -49,34 +52,31 @@ Hooks.once('init', () => {
}
// Specific case, to avoid wrong matching with "Force"
if (formula.includes("toughness bonus")) {
formula = formula.replace( "toughness bonus", this.actor.characteristics["t"].bonus);
if (formula.includes("toughness bonus")) {
formula = formula.replace("toughness bonus", this.actor.characteristics["t"].bonus);
}
// Specific case, to avoid wrong matching with "Force"
if (formula.includes("force mentale"))
{
if (formula.includes("force mentale")) {
// Determine if it's looking for the bonus or the value
if (formula.includes('bonus')) {
formula = formula.replace( "bonus de force mentale", this.actor.characteristics["wp"].bonus);
formula = formula.replace( "force mentale bonus", this.actor.characteristics["wp"].bonus);
formula = formula.replace("bonus de force mentale", this.actor.characteristics["wp"].bonus);
formula = formula.replace("force mentale bonus", this.actor.characteristics["wp"].bonus);
} else
formula = formula.replace("force mentale", this.actor.characteristics["wp"].value);
formula = formula.replace("force mentale", this.actor.characteristics["wp"].value);
}
// Iterate through characteristics
for(let ch in this.actor.characteristics)
{
for (let ch in this.actor.characteristics) {
// If formula includes characteristic name
while (formula.includes(this.actor.characteristics[ch].label.toLowerCase()))
{
while (formula.includes(this.actor.characteristics[ch].label.toLowerCase())) {
// Determine if it's looking for the bonus or the value
if (formula.includes('bonus')) {
formula = formula.replace("bonus de " + game.wfrp4e.config.characteristics[ch].toLowerCase(), this.actor.characteristics[ch].bonus);
formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase() + " bonus", this.actor.characteristics[ch].bonus);
formula = formula.replace("bonus de " + game.wfrp4e.config.characteristics[ch].toLowerCase(), this.actor.characteristics[ch].bonus);
formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase() + " bonus", this.actor.characteristics[ch].bonus);
}
else
formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase(), this.actor.characteristics[ch].value);
formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase(), this.actor.characteristics[ch].value);
}
}
@ -88,7 +88,7 @@ Hooks.once('init', () => {
}
/*---------------------------------------------------------------------*/
game.wfrp4e.entities.ItemWfrp4e.prototype.computeSpellPrayerFormula = function(type, aoe=false, formulaOverride) {
game.wfrp4e.entities.ItemWfrp4e.prototype.computeSpellPrayerFormula = function (type, aoe = false, formulaOverride) {
let formula = formulaOverride || this[type]?.value
if (Number.isNumeric(formula))
return formula
@ -97,37 +97,33 @@ Hooks.once('init', () => {
formula = formula.toLowerCase();
// Do not process these special values
if (formula != game.i18n.localize("You").toLowerCase() && formula != game.i18n.localize("Special").toLowerCase() && formula != game.i18n.localize("Instant").toLowerCase())
{
if (formula != game.i18n.localize("You").toLowerCase() && formula != game.i18n.localize("Special").toLowerCase() && formula != game.i18n.localize("Instant").toLowerCase()) {
// Specific case, to avoid wrong matching with "Force"
if (formula.includes("force mentale"))
{
if (formula.includes("force mentale")) {
// Determine if it's looking for the bonus or the value
if (formula.includes('bonus')) {
formula = formula.replace( "bonus de force mentale", this.actor.characteristics["wp"].bonus);
formula = formula.replace( "force mentale bonus", this.actor.characteristics["wp"].bonus);
formula = formula.replace("bonus de force mentale", this.actor.characteristics["wp"].bonus);
formula = formula.replace("force mentale bonus", this.actor.characteristics["wp"].bonus);
}
else
formula = formula.replace("force mentale", this.actor.characteristics["wp"].value);
formula = formula.replace("force mentale", this.actor.characteristics["wp"].value);
}
if (formula.includes("yard") )
formula = formula.replace('yard', "mètre" );
if (formula.includes("yds") )
formula = formula.replace('yds', "m." );
if (formula.includes("yard"))
formula = formula.replace('yard', "mètre");
if (formula.includes("yds"))
formula = formula.replace('yds', "m.");
// Iterate through remaining characteristics
for(let ch in this.actor.characteristics)
{
for (let ch in this.actor.characteristics) {
// If formula includes characteristic name
//console.log("Testing :", ch, WFRP4E.characteristics[ch].toLowerCase());
if (formula.includes(game.wfrp4e.config.characteristics[ch].toLowerCase()))
{
if (formula.includes(game.wfrp4e.config.characteristics[ch].toLowerCase())) {
// Determine if it's looking for the bonus or the value
if (formula.includes('bonus')) {
formula = formula.replace("bonus de " + game.wfrp4e.config.characteristics[ch].toLowerCase(), this.actor.characteristics[ch].bonus);
formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase() + " bonus", this.actor.characteristics[ch].bonus);
formula = formula.replace("bonus de " + game.wfrp4e.config.characteristics[ch].toLowerCase(), this.actor.characteristics[ch].bonus);
formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase() + " bonus", this.actor.characteristics[ch].bonus);
}
else
formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase(), this.actor.characteristics[ch].value);
formula = formula.replace(game.wfrp4e.config.characteristics[ch].toLowerCase(), this.actor.characteristics[ch].value);
}
}
}
@ -135,69 +131,69 @@ Hooks.once('init', () => {
// If AoE - wrap with AoE ( )
if (aoe)
formula = "AoE (" + formula.capitalize() + ")";
//console.log("calculateSpellAttributes -> " + formula );
return formula.capitalize();
}
/*---------------------------------------------------------------------*/
// Converters area
if(typeof Babele !== 'undefined') {
Babele.get().register({
module: 'wh4-fr-translation',
lang: 'fr',
dir: 'compendium'
})
if (typeof Babele !== 'undefined') {
Babele.get().register({
module: 'wh4-fr-translation',
lang: 'fr',
dir: 'compendium'
})
Babele.get().registerConverters({
"career_skills": (skills_list) => {
//console.log( "Thru here ...", compendium, skills_list);
if ( skills_list ) {
if (skills_list) {
var i;
var len = skills_list.length;
var re = /(.*)\((.*)\)/i;
var re = /(.*)\((.*)\)/i;
for (i = 0; i < len; i++) {
skills_list[i] = skills_list[i].trim();
var transl = game.babele.translate(compmod+'.skills', { name: skills_list[i] }, true ).name;
var transl = game.babele.translate('wfrp4e-core.skills', { name: skills_list[i] }, true).name;
if (!transl) transl = skills_list[i]
//console.log("List ...", skills_list[i]);
if ( transl == skills_list[i] ) {
var res = re.exec( skills_list[i] );
if (res) {
if (transl == skills_list[i]) {
var res = re.exec(skills_list[i]);
if (res) {
//console.log("Matched/split:", res[1], res[2]);
var subword = game.i18n.localize(res[2].trim() );
var subword = game.i18n.localize(res[2].trim());
var s1 = res[1].trim() + " ()";
var translw = game.babele.translate(compmod+'.skills', { name: s1}, true ).name;
var translw = game.babele.translate('wfrp4e-core.skills', { name: s1 }, true).name;
if (translw != s1) {
var res2 = re.exec(translw);
transl = res2[1] + "(" + subword + ")";
transl = res2[1] + "(" + subword + ")";
} else {
s1 = res[1].trim() + " ( )";
translw = game.babele.translate(compmod+'.skills', { name: s1}, true ).name;
translw = game.babele.translate('wfrp4e-core.skills', { name: s1 }, true).name;
var res2 = re.exec(translw);
transl = res2[1] + "(" + subword + ")";
}
transl = res2[1] + "(" + subword + ")";
}
}
}
skills_list[i] = transl;
}
}
return skills_list;
return skills_list;
},
"resultConverter": (results, translated) => {
//console.log("STUF PARSING", results, translated)
if (translated) {
for (let data of results) {
if ( translated[`${data.range[0]}-${data.range[1]}`] ) {
if (translated[`${data.range[0]}-${data.range[1]}`]) {
data.text = translated[`${data.range[0]}-${data.range[1]}`]
}
}
return results
}
if ( results[0].text.includes("wfrp4e-core.journal-entries") ) {
if (results[0].text.includes("wfrp4e-core.journal-entries")) {
for (let data of results) {
let career = data.text.match(/{(.*)}/)
//console.log(">>>>>", career)
@ -207,7 +203,7 @@ Hooks.once('init', () => {
}
}
}
if ( results[0].documentCollection ) {
if (results[0].documentCollection) {
return Babele.instance.converters.tableResults(results)
}
return results
@ -216,174 +212,173 @@ Hooks.once('init', () => {
"npc_details": (details) => {
//console.log("DETAILS: ", details);
let newDetails = duplicate(details);
if (details.species && details.species.value )
if (details.species && details.species.value)
newDetails.species.value = game.i18n.localize(details.species.value);
if (details.gender && details.gender.value )
newDetails.gender.value = game.i18n.localize(details.gender.value);
if (details.class && details.class.value )
newDetails.class.value = game.i18n.localize(details.class.value);
if (details.gender && details.gender.value)
newDetails.gender.value = game.i18n.localize(details.gender.value);
if (details.class && details.class.value)
newDetails.class.value = game.i18n.localize(details.class.value);
return newDetails;
},
"career_talents": (talents_list) => {
var compendium = game.packs.find(p => p.collection === compmod+'.talents');
"career_talents": (talents_list) => {
var compendium = game.packs.find(p => p.collection === 'wfrp4e-core.talents');
var i;
if ( talents_list ) {
if (talents_list) {
var len = talents_list.length;
var re = /(.*)\((.*)\)/i;
var re = /(.*)\((.*)\)/i;
for (i = 0; i < len; i++) {
var transl = game.babele.translate(compmod+'.talents', { name: talents_list[i]}, true ).name;
var transl = game.babele.translate('wfrp4e-core.talents', { name: talents_list[i] }, true).name;
if (!transl) transl = talents_list[i]
if ( transl == talents_list[i] ) {
var res = re.exec( talents_list[i]);
if (res) {
if (transl == talents_list[i]) {
var res = re.exec(talents_list[i]);
if (res) {
//console.log("Matched/split:", res[1], res[2]);
var subword = game.i18n.localize(res[2].trim() );
var subword = game.i18n.localize(res[2].trim());
var s1 = res[1].trim(); // No () in talents table
var translw = game.babele.translate(compmod+'.talents', { name: s1 }, true ).name;
var translw = game.babele.translate('wfrp4e-core.talents', { name: s1 }, true).name;
if (translw != s1) {
transl = translw + " (" + subword + ")";
transl = translw + " (" + subword + ")";
} else {
s1 = res[1].trim() + " ( )";
translw = game.babele.translate(compmod+'.talents', { name: s1 }, true ).name;
translw = game.babele.translate('wfrp4e-core.talents', { name: s1 }, true).name;
var res2 = re.exec(translw);
transl = res2[1] + " (" + subword + ")";
}
transl = res2[1] + " (" + subword + ")";
}
}
}
talents_list[i] = transl;
}
}
return talents_list;
return talents_list;
},
"npc_characteristics": (chars) => { // Auto-convert char names in the sheet
for (var key in chars) {
var char = chars[key];
var char = chars[key];
//console.log("Was here !", key, char );
var abrev = char["abrev"];
let toTransl = "CHAR." + abrev;
if ( game.i18n.localize( toTransl ) != toTransl) { // Manages unknown language
char["label"] = game.i18n.localize( "CHAR." + abrev );
char["abrev"] = game.i18n.localize( "CHARAbbrev." + abrev );
if (game.i18n.localize(toTransl) != toTransl) { // Manages unknown language
char["label"] = game.i18n.localize("CHAR." + abrev);
char["abrev"] = game.i18n.localize("CHARAbbrev." + abrev);
}
}
return chars;
},
"bestiary_traits": (beast_traits, translations) => {
if ( !beast_traits) {
"bestiary_traits": (beast_traits, translations) => {
if (!beast_traits) {
console.log("No beast traits found here ...")
return beast_traits
}
for (let trait_en of beast_traits)
{
for (let trait_en of beast_traits) {
var special = "";
var nbt = "";
var name_en = trait_en.name.trim(); // strip \r in some traits name
if (!trait_en.name || trait_en.name.length == 0) {
console.log("Wrong item name found!!!!")
continue
}
}
//console.log(">>>>>>>> Parsing", trait_en.name)
if ( trait_en.type == "trait") {
if (trait_en.type == "trait") {
//console.log("Trait translation", compmod, trait_en)
if ( name_en.includes("Tentacles") ) { // Process specific Tentacles case
var re = /(.d*)x Tentacles/i;
var res = re.exec( name_en );
if ( res && res[1] )
if (name_en.includes("Tentacles")) { // Process specific Tentacles case
var re = /(.d*)x Tentacles/i;
var res = re.exec(name_en);
if (res && res[1])
nbt = res[1] + "x ";
name_en = "Tentacles";
} else if ( name_en.includes("(") && name_en.includes(")") ) { // Then process specific traits name with (xxxx) inside
var re = /(.*) \((.*)\)/i;
var res = re.exec( name_en );
} else if (name_en.includes("(") && name_en.includes(")")) { // Then process specific traits name with (xxxx) inside
var re = /(.*) \((.*)\)/i;
var 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
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
}
var trait_fr = game.babele.translate( compmod+'.traits', { name: name_en }, true );
var trait_fr = game.babele.translate('wfrp4e-core.traits', { name: name_en }, true);
//console.log(">>>>> Trait ?", name_en, nbt, trait_fr, trait_fr.name, special);
trait_fr.name = trait_fr.name || trait_en.name
trait_en.name = nbt + trait_fr.name + special;
if ( trait_fr.system && trait_fr.system.description && trait_fr.system.description.value ) {
if (trait_fr.system && trait_fr.system.description && trait_fr.system.description.value) {
trait_en.system.description.value = trait_fr.system.description.value;
} else if (game.modules.get('wfrp4e-eis')) { // No description in the FR compendium -> test other compendium if presenr
trait_fr = game.babele.translate('wfrp4e-eis.eisitems', { name: name_en }, true);
trait_en.name = nbt + trait_fr.name + special;
if (trait_fr.system && trait_fr.system.description && trait_fr.system.description.value)
trait_en.system.description.value = trait_fr.system.description.value;
} else if ( game.modules.get( 'wfrp4e-eis') ) { // No description in the FR compendium -> test other compendium if presenr
trait_fr = game.babele.translate( 'wfrp4e-eis.eisitems', { name: name_en }, true);
trait_en.name = nbt + trait_fr.name + special;
if ( trait_fr.system && trait_fr.system.description && trait_fr.system.description.value )
trait_en.system.description.value = trait_fr.system.description.value;
}
if ( trait_en.system && 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);
trait_en.system.specification.value = game.i18n.localize( trait_en.system.specification.value.trim() );
}
} else if ( trait_en.type == "skill") {
if ( name_en.includes("(") && name_en.includes(")") ) { // Then process specific skills name with (xxxx) inside
var re = /(.*) +\((.*)\)/i;
var 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
}
var trait_fr = game.babele.translate( compmod+'.skills', { name: name_en }, true );
if (trait_en.system && 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);
trait_en.system.specification.value = game.i18n.localize(trait_en.system.specification.value.trim());
}
} else if (trait_en.type == "skill") {
if (name_en.includes("(") && name_en.includes(")")) { // Then process specific skills name with (xxxx) inside
var re = /(.*) +\((.*)\)/i;
var 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
}
var trait_fr = game.babele.translate('wfrp4e-core.skills', { name: name_en }, true);
//console.log(">>>>> Skill ?", name_en, special, trait_fr.name, trait_fr);
trait_fr.name = trait_fr.name || name_en
if (trait_fr.name != name_en) { // Translation OK
trait_en.name = trait_fr.name + special;
if ( trait_fr.system ) {
if (trait_fr.system) {
trait_en.system.description.value = trait_fr.system.description.value;
}
}
} else if ( trait_en.type == "prayer") {
var trait_fr = game.babele.translate( compmod+'.prayers', { name: name_en }, true);
} else if (trait_en.type == "prayer") {
var trait_fr = game.babele.translate('wfrp4e-core.prayers', { name: name_en }, true);
//console.log(">>>>> Prayer ?", name_en, special, trait_fr.name );
trait_fr.name = trait_fr.name || name_en
trait_en.name = trait_fr.name + special;
if ( trait_fr.system && trait_fr.system.description && trait_fr.system.description.value )
trait_en.system.description.value = trait_fr.system.description.value;
} else if ( trait_en.type == "spell") {
var trait_fr = game.babele.translate( compmod+'.spells', { name: name_en }, true)
if ( trait_fr.name == name_en ) { // If no translation, test eisspells
trait_fr = game.babele.translate( 'wfrp4e-eis.eisspells', { name: name_en }, true);
if (trait_fr.system && trait_fr.system.description && trait_fr.system.description.value)
trait_en.system.description.value = trait_fr.system.description.value;
} else if (trait_en.type == "spell") {
var trait_fr = game.babele.translate('wfrp4e-core.spells', { name: name_en }, true)
if (trait_fr.name == name_en) { // If no translation, test eisspells
trait_fr = game.babele.translate('wfrp4e-eis.eisspells', { name: name_en }, true);
}
if ( trait_fr.name == name_en ) { // If no translation, test unofficial grimoire
trait_fr = game.babele.translate( 'wfrp4e-unofficial-grimoire.ug-spells', { name: name_en }, true);
if (trait_fr.name == name_en) { // If no translation, test unofficial grimoire
trait_fr = game.babele.translate('wfrp4e-unofficial-grimoire.ug-spells', { name: name_en }, true);
}
trait_fr.name = trait_fr.name || name_en
//console.log(">>>>> Spell ?", name_en, special, trait_fr.name );
trait_en.name = trait_fr.name + special;
if ( trait_fr.system && trait_fr.system.description && trait_fr.system.description.value )
trait_en.system.description.value = trait_fr.system.description.value;
} else if ( trait_en.type == "talent") {
if ( name_en.includes("(") && name_en.includes(")") ) { // Then process specific skills name with (xxxx) inside
var re = /(.*) +\((.*)\)/i;
var res = re.exec( name_en );
if (trait_fr.system && trait_fr.system.description && trait_fr.system.description.value)
trait_en.system.description.value = trait_fr.system.description.value;
} else if (trait_en.type == "talent") {
if (name_en.includes("(") && name_en.includes(")")) { // Then process specific skills name with (xxxx) inside
var re = /(.*) +\((.*)\)/i;
var 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
special = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
}
var trait_fr = game.babele.translate( compmod+'.talents', { name: name_en }, true )
var trait_fr = game.babele.translate('wfrp4e-core.talents', { name: name_en }, true)
trait_fr.name = trait_fr.name || name_en // Security since babele v10
//console.log(">>>>> Talent ?", trait_fr, name_en, special, trait_fr.name);
if ( trait_fr.name != "Sprinter" && trait_fr.name == name_en) { // If no translation, test ugtalents
trait_fr = game.babele.translate( 'wfrp4e-unofficial-grimoire.ug-careerstalentstraits', { name: name_en }, true );
if (trait_fr.name != "Sprinter" && trait_fr.name == name_en) { // If no translation, test ugtalents
trait_fr = game.babele.translate('wfrp4e-unofficial-grimoire.ug-careerstalentstraits', { name: name_en }, true);
trait_fr.name = trait_fr.name || name_en // Security since babele v10
}
if ( trait_fr.name && (trait_fr.name == "Sprinter" || trait_fr.name != name_en)) { // Talent translated!
if (trait_fr.name && (trait_fr.name == "Sprinter" || trait_fr.name != name_en)) { // Talent translated!
trait_en.name = trait_fr.name.trim() + special
if ( trait_fr.system ) { // Why ???
if (trait_fr.system) { // Why ???
trait_en.system.description.value = trait_fr.system.description.value;
}
}
} else if ( trait_en.type == "career") {
var career_fr = game.babele.translate( compmod+'.careers', trait_en, true );
} else if (trait_en.type == "career") {
var career_fr = game.babele.translate('wfrp4e-core.careers', trait_en, true);
career_fr.name = career_fr.name || trait_en.name
//console.log(">>>>> Career ?", career_fr.name );
trait_en.system = duplicate(career_fr.system);
} else if ( trait_en.type == "trapping" || trait_en.type == "weapon" || trait_en.type == "armour" || trait_en.type == "container" || trait_en.type == "money") {
var trapping_fr = game.babele.translate( compmod+'.trappings', trait_en, true );
} else if (trait_en.type == "trapping" || trait_en.type == "weapon" || trait_en.type == "armour" || trait_en.type == "container" || trait_en.type == "money") {
var trapping_fr = game.babele.translate('wfrp4e-core.trappings', trait_en, true);
//console.log(">>>>> Trapping ?", name_en, trapping_fr.name);
trapping_fr.name = trapping_fr.name || trait_en.name
if ( trapping_fr.system) {
trait_en.system.description = trapping_fr.system.description;
if (trapping_fr.system) {
trait_en.system.description = trapping_fr.system.description;
}
}
}
@ -391,65 +386,66 @@ Hooks.once('init', () => {
return beast_traits
},
// To avoid duplicateing class for all careers
"generic_localization": (value) => {
"generic_localization": (value) => {
let ret = value
if ( value ) {
ret = game.i18n.localize( value.trim() );
if (value) {
ret = game.i18n.localize(value.trim());
if (!ret) ret = value
}
return ret
},
},
"trapping_qualities_flaws": (value) => {
if ( value ) {
if (value) {
let newQF = [];
//console.log("ATOUTS", value, typeof(value));
let list = value
if (typeof(value) == "string") {
if (typeof (value) == "string") {
let myList = value.split(",")
list = []
for (let l of myList) {
list.push( { name: l.trim() } )
list.push({ name: l.trim() })
}
}
for (let i=0; i<list.length; i++) {
newQF[i] = duplicate(list[i] )
if ( newQF[i].name == "Trap Blade") {
for (let i = 0; i < list.length; i++) {
newQF[i] = duplicate(list[i])
if (newQF[i].name == "Trap Blade") {
newQF[i].name = "TrapBlade"; // Auto-patch, without space!
//console.log("PATCHED", trim);
}
let oldName = newQF[i].name
newQF[i].name = game.i18n.localize( oldName )
newQF[i].name = game.i18n.localize(oldName)
if (!newQF[i].name) newQF[i].name = oldName
}
return newQF;
}
},
// Search back in careers the translated name of the groupe (as it is the name of the level career itself)
"career_careergroup": (value) => {
"career_careergroup": (value) => {
// Manage exception - Dirty hack
if ( value == 'Slayer' ) {
if (value == 'Slayer') {
return "Tueur";
}
if ( value == 'Druidic Priest' ) {
if (value == 'Druidic Priest') {
return "Druide";
}
//console.log("Carre groupe : ", value )
// Per default
var compendium = game.packs.find(p => p.collection === compmod+'.careers');
if ( compendium ) {
let newName = game.babele.translate(compmod+'.careers', { name: value } ).name
var compendium = game.packs.find(p => p.collection === 'wfrp4e-core.careers');
if (compendium) {
let newName = game.babele.translate('wfrp4e-core.careers', { name: value }).name
if (!newName) newName = value
return newName
} else {
ui.notifications.error("Impossible de trouver la carrière " + value + ". Elle n'est probablement pas traduite.", { permanent: true })
} else {
ui.notifications.error("Impossible de trouver la carrière " + value + ". Elle n'est probablement pas traduite.", { permanent: true })
}
return value
},
"mutations_modifier": (value) => { // This is really UGLYYYY i know, but i started like this and discovered afterward that many strings were not easy to automate... Sorry :)
//console.log("Parsing mutation :", value);
value = value.toLowerCase();
value = value.toLowerCase();
value = value.replace("gain a broken condition if you fail a test derived from ", "Gagnez un état Brisé si vous échouez à un test dérivé de ");
value = value.replace("weapon skill" ,"Capacité de Combat");
value = value.replace("weapon skill", "Capacité de Combat");
value = value.replace("ballistic skill", "Capacité de Tir");
value = value.replace("strength", "Force");
value = value.replace("toughness", "Endurance");
@ -476,79 +472,79 @@ Hooks.once('init', () => {
"talent_name": (name, translation) => {
console.log("NAME !!!", name, translation)
},
"effects": (effects, translations) => {
if ( !effects) return;
if ( !translations) return;
for (let i=0; i<effects.length; i++) {
"effects": (effects, translations) => {
if (!effects) return;
if (!translations) return;
for (let i = 0; i < effects.length; i++) {
let effect = effects[i];
//console.log("EFFECT LABEL1:", effect );
effect.label = translations['label'+i];
effect.label = translations['label' + i];
}
return effects
},
"diseases_effects": (effects, translations) => {
if ( !effects) return;
for (let i=0; i<effects.length; i++) {
"diseases_effects": (effects, translations) => {
if (!effects) return;
for (let i = 0; i < effects.length; i++) {
let effect = effects[i];
let label = effect.label;
let gravity = "";
if ( label.includes("(") && label.includes(")") ) { // Then process specific skills name with (xxxx) inside
var re = /(.*) +\((.*)\)/i;
var res = re.exec( label );
if (label.includes("(") && label.includes(")")) { // Then process specific skills name with (xxxx) inside
var re = /(.*) +\((.*)\)/i;
var res = re.exec(label);
label = res[1].trim(); // Get the gravity
gravity = " (" + game.i18n.localize( res[2].trim() ) + ")"; // And the special keyword
gravity = " (" + game.i18n.localize(res[2].trim()) + ")"; // And the special keyword
}
effect.label = game.i18n.localize( label ) + gravity;
effect.label = game.i18n.localize(label) + gravity;
}
},
// Auto-translate duration
"spells_duration_range_target_damage": (value) => {
//console.log("Spell duration/range/damage/target :", value);
if ( value == "" ) return ""; // Hop !
if ( value == "Touch" ) return "Contact"; // Hop !
if ( value == "You" ) return "Vous"; // Hop !
if ( value == "Instant" ) return "Instantané"; // Hop !
if (value == "") return ""; // Hop !
if (value == "Touch") return "Contact"; // Hop !
if (value == "You") return "Vous"; // Hop !
if (value == "Instant") return "Instantané"; // Hop !
var translw = value;
var re = /(.*) Bonus (\w*)/i;
var res = re.exec( value );
var re = /(.*) Bonus (\w*)/i;
var res = re.exec(value);
var unit = "";
if ( res ) { // Test "<charac> Bonus <unit>" pattern
if ( res[1] ) { // We have char name, then convert it
translw = "Bonus de " + game.i18n.localize( res[1].trim() );
}
if (res) { // Test "<charac> Bonus <unit>" pattern
if (res[1]) { // We have char name, then convert it
translw = "Bonus de " + game.i18n.localize(res[1].trim());
}
unit = res[2];
} else {
} else {
re = /(\d+) (\w+)/i;
res = re.exec( value );
res = re.exec(value);
if (res) { // Test : "<number> <unit>" pattern
translw = res[1];
translw = res[1];
unit = res[2];
} else { // Test
re = /(\w+) (\w+)/i;
res = re.exec( value );
res = re.exec(value);
if (res) { // Test : "<charac> <unit>" pattern
translw = game.i18n.localize( res[1].trim() );
translw = game.i18n.localize(res[1].trim());
unit = res[2];
}
}
}
}
if ( unit == "hour") unit = "heure";
if ( unit == "hours") unit = "heures";
if ( unit == "days") unit = "jours";
if ( unit == "yard") unit = "mètre";
if ( unit == "yards") unit = "mètres";
}
if (unit == "hour") unit = "heure";
if (unit == "hours") unit = "heures";
if (unit == "days") unit = "jours";
if (unit == "yard") unit = "mètre";
if (unit == "yards") unit = "mètres";
translw += " " + unit;
return translw;
return translw;
}
});
});
}
} );
});
/* -------------------------------------------- */
// Register world usage statistics
function registerUsageCount( registerKey ) {
if ( game.user.isGM ) {
function registerUsageCount(registerKey) {
if (game.user.isGM) {
game.settings.register(registerKey, "world-key", {
name: "Unique world key",
scope: "world",
@ -558,9 +554,9 @@ function registerUsageCount( registerKey ) {
});
let worldKey = game.settings.get(registerKey, "world-key")
if ( worldKey == undefined || worldKey == "" ) {
if (worldKey == undefined || worldKey == "") {
worldKey = randomID(32)
game.settings.set(registerKey, "world-key", worldKey )
game.settings.set(registerKey, "world-key", worldKey)
}
// Simple API counter
let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.version}"`
@ -571,7 +567,7 @@ function registerUsageCount( registerKey ) {
/*---------------------------------------------------------------------*/
Hooks.once('ready', () => {
registerUsageCount("wh4-fr-translation")
});

View File

@ -1,180 +1,291 @@
{
"label": "Items (Archives Vol. I)",
"entries": [
{
"id": "Badger Botherer",
"name": "Badger Botherer",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.AKNVB3Of7B82YFT1]{Badger Rider}</p>"
},
{
"id": "Badger Master",
"name": "Badger Master",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.AKNVB3Of7B82YFT1]{Badger Rider}</p>"
},
{
"id": "Badger Rider",
"name": "Badger Rider",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.AKNVB3Of7B82YFT1]{Badger Rider}</p>"
},
{
"id": "Badger Sergeant",
"name": "Badger Sergeant",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.AKNVB3Of7B82YFT1]{Badger Rider}</p>"
},
{
"id": "Bearded Axe",
"name": "Bearded Axe",
"description": "<p>Favoured by many Dwarfs for use in war, the heads of these axes curve downward toward the haft. This creates a gap between the blade and the haft that is perfect for ripping weapons from unwary enemies.</p>"
},
{
"id": "Blackbriar Javelin",
"name": "Blackbriar Javelin",
"description": "<p>Fashioned from the wood of trees whose spirits have become twisted and malign, these living weapons slowly drip a lethal poison. They are said to bring ill fortune, and this is certainly the case for those who must face them in battle.</p>"
},
{
"id": "Cinderblast Bomb",
"name": "Cinderblast Bomb",
"description": "<p>These lethal weapons are indispensable in the tunnel fighting that goes on deep beneath the Old World as the Dwarfs desperately stave off attacks by Skaven, Goblins, and worse. These bombs are typically tossed into the midst of packed enemy forces, exploding in a blast of flame and shrapnel that is terrifying to behold.</p>"
},
{
"id": "Drakefire Pistol",
"name": "Drakefire Pistol",
"description": "<p>A cunning example of Dwarf artifice, a Drakefire Pistol blasts targets with incendiary shot, often setting them ablaze. The particulars of its design are a carefully guarded secret of the Dwarfs, but it is doubtful if any other species could replicate their&nbsp; intricacies even if the design was understood. They are a favourite of Dwarf 's who face down the Skaven deep beneath the earth, as their foul fur burns very satisfactorily indeed.</p>"
},
{
"id": "Drakefire Shot",
"name": "Drakefire Shot",
"description": "<p>The incendiary ammunition used in Drakefire pistols is both dangerous and rare, and truly only suited for use in the those weapons. However, it may be loaded in to any Blackpowder weapon, which will function exactly once before exploding in the users hands. Resolve this as though a Fumble was rolled on every shot.</p>"
},
{
"label": "Items (Archives Vol. I)",
"mapping": {
"skills": {
"path": "system.skills",
"converter": "career_skills"
},
"talents": {
"path": "system.talents",
"converter": "career_talents"
},
"class": {
"path": "system.class.value",
"converter": "generic_localization"
},
"career_careergroup": "system.careergroup.value",
"trappings": "system.trappings"
},
"entries": [
{
"id": "Dwarf Crossbow",
"name": "Dwarf Crossbow",
"description": "<p>Though the difference between Dwarf and Imperial crossbows is less pronounced that that between their Blackpowder weapons, Dwarf Crossbows are nevertheless built to much tighter tolerances than any human smith could match. As a result, they are more precise weapons.</p>"
},
{
"id": "Dwarf Hammer",
"name": "Dwarf Hammer",
"description": "<p>Dwarfs are known for using the same hammers in the forge during peacetime and on the battlefield in times of war. These heavy tools are perfect for cracking even the thickest Orc skull.</p>"
},
{
"id": "Dwarf Handgun",
"name": "Dwarf Handgun",
"description": "<p>Dwarfs often despair at what passes for gun smithing among the humans, whose weapons are often as dangerous to the bearer as their target. Dwarf blackpowder weapons are finely made and carefully reinforced, making them less prone to misfire and imbuing their projectiles with additional punch.</p>"
},
{
"id": "Dwarf Pistol",
"name": "Dwarf Pistol",
"description": "<p>Dwarfs often despair at what passes for gun smithing among the humans, whose weapons are often as dangerous to the bearer as their target. Dwarf blackpowder weapons are finely made and carefully reinforced, making them less prone to misfire and imbuing their projectiles with additional punch.</p>"
},
{
"id": "Eonir Spear",
"name": "Eonir Spear",
"description": "<p>The bane of mounted forces, these wickedly tipped spears are somewhat lighter than those used in the Empire. Their points are tempered and sharpened by methods known only to the Wood Elves, and they punch through armour with ease.</p>"
},
{
"id": "Eonir War Blade",
"name": "Eonir War Blade",
"description": "<p>The finely made blades of the Eonir are crafted to be somewhat lighter than a typical Empire weapon, but their perfect balance lends itself to swift, precise strikes.</p>"
},
{
"id": "Field Warden",
"name": "Field Warden",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.vnLLLPnNYS97hJVe]{Fieldwarden}</p>"
},
{
"id": "Field Warden Captain",
"name": "Field Warden Captain",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.vnLLLPnNYS97hJVe]{Fieldwarden}</p>"
},
{
"id": "Field Warden Sergeant",
"name": "Field Warden Sergeant",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.vnLLLPnNYS97hJVe]{Fieldwarden}</p>"
},
{
"id": "Forest Ranger",
"name": "Forest Ranger",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.J4o6g4sjXQ8OXjIj]{Ghost Strider}</p>"
},
{
"id": "Forest's Wrath",
"name": "Forest's Wrath",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.J4o6g4sjXQ8OXjIj]{Ghost Strider}</p>"
},
{
"id": "Ghost Strider",
"name": "Ghost Strider",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.J4o6g4sjXQ8OXjIj]{Ghost Strider}</p>"
},
{
"id": "Hold Runner",
"name": "Hold Runner",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.GBhO6rb28jKbYfEk]{Karak Ranger}</p>"
},
{
"id": "Iron Skillet",
"name": "Iron Skillet",
"description": "<p>Despite their smaller stature, the cast iron pots, pans and skillets of the Halflings are fashioned to be heavier than one might think. Some may laugh, but more than one blade has been turned from a fatal blow by a Halfling pan. Such scratched and pitted skillets are always given pride of place in Halfling homes.</p>"
"name": "Arbalète naine",
"description": "<p>Bien que les différences entre les arbalètes naines et impériales soient moins prononcées que celles entre leurs armes à poudre noire, les arbalètes naines fabriquées avec une minutie qu'aucun artisan humain ne saurait égaler, et sont donc plus précises.</p>"
},
{
"id": "Karak Mountain Strider",
"name": "Karak Mountain Strider",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.GBhO6rb28jKbYfEk]{Karak Ranger}</p>"
"name": "Arpenteur des karak",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.GBhO6rb28jKbYfEk]{Patrouilleur des Karak}</p>",
"career_careergroup": "Patrouilleur des karak",
"trappings": [
"4 apprentis Coureurs des forts",
"cartes",
"souvenirs de nombreux voyages"
]
},
{
"id": "Karak Pathkeeper",
"name": "Karak Pathkeeper",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.GBhO6rb28jKbYfEk]{Karak Ranger}</p>"
"id": "Dwarf Handgun",
"name": "Arquebuse naine",
"description": "<p>Les armes à poudre sorties des forges humaines désespèrent souvent les nains, car elles sont souvent aussi dangereuses pour leur porteur que pour sa cible. Les armes à poudre noire des nains sont soigneusement fabriquées et renforcées, les rendant moins susceptibles de râtés et conférant aux projectiles une force supplémentaire.</p>"
},
{
"id": "Karak Ranger",
"name": "Karak Ranger",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.GBhO6rb28jKbYfEk]{Karak Ranger}</p>"
"id": "Cinderblast Bomb",
"name": "Bombe calcinante",
"description": "<p>Ces armes mortelles sont indispensables pour le combat dans les tunnels qui s'enfoncent profondément sous le Vieux Monde, alors que les nains repoussent désespérément les attaques des skavens, des gobelins, et bien pire encore. Ces bombes sont généralement lancées au beau milieu des forces ennemies, explosant en souffles enflammés et éclats, terrifiants à comtempler.</p>"
},
{
"id": "Nan's Cleaver",
"name": "Nan's Cleaver",
"description": "<p>Halfling Cooks care for their kitchenware as carefully as the most diligent warrior cares for their blade. No wonder then that many of these weapons see use in times of war, and more than one Goblin has fallen to a cleaver that was later used to prepare a hearty post-battle stew.</p>"
"id": "Field Warden Captain",
"name": "Capitaine Gardechamps",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.vnLLLPnNYS97hJVe]{Gardechamps}</p>",
"career_careergroup": "Gardechamps",
"trappings": [
"garnison de Sergent Gardechamps",
"respect de la communauté"
]
},
{
"id": "Novice Warden",
"name": "Novice Warden",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.vnLLLPnNYS97hJVe]{Fieldwarden}</p>"
"id": "Drakefire Shot",
"name": "Cartouche Drac de feu",
"description": "<p>Cette munition incendiaire pouvant être utilisée avec les pistolets Drac de feu, est à la fois dangereuse et rare. Elle ne convient vraiment qu'à cette arme spécifique. Néanmoins, elle peut être chargée dans n'importe quelle arme à poudre noire, qui pourra fonctionner ainsi une seule fois avant d'exploser entre les mains de l'utilisateur. Cela se résout comme si un Échec critique avait été obtenu à chaque coup.</p>"
},
{
"id": "Precision Shot and Powder",
"name": "Precision Shot and Powder",
"description": "<p>Expertly prepared powder and carefully smoothed and rounded bullets can be combined to allow for more reliable, precise shots with any suitable Blackpowder weapon.</p>"
"name": "Cartouche et poudre de précision",
"description": "<p>Une poudre préparée par des mains expertes et des balles soigneusement arrondies et lissées peuvent être combinées pour permettre des coups plus précis, plus fiables avec toute arme à poudre noire qui convient.</p>"
},
{
"id": "Slayer's Axe",
"name": "Slayer's Axe",
"description": "<p>Slayers take great pride in their weapons, sharpening them almost ritualistically at every opportunity. The most famous of these have gained reputations almost as formidable as those who bear them. They are devastating weapons, and Slayers who wield them seem able to do so tirelessly despite their size.</p>"
"id": "Badger Rider",
"name": "Chevaucheur de blaireau",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.AKNVB3Of7B82YFT1]{Chevaucheur de blaireau}</p>",
"career_careergroup": "Chevaucheur de blaireau",
"trappings": [
"fontes de selle",
"plastron de cuir",
"arme de lancer ou d'entraves"
]
},
{
"id": "Starfire Shafts",
"name": "Starfire Shafts",
"description": "<p>Wood hewn from the Starfire tree is anathema to corruption, and arrows created from it are imbued with a fierce and blazing spirit. Those struck by arrows are often set ablaze, and their use massed use in warfare is a terrible thing to behold.</p>"
"id": "Hold Runner",
"name": "Coureur des forts",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.GBhO6rb28jKbYfEk]{Patrouilleur des Karak}</p>",
"career_careergroup": "Patrouilleur des karak",
"trappings": [
"sac à dos",
"arme simple",
"veste en cuir",
"outils professionnels (Cartographe)"
]
},
{
"id": "Swiftshiver Shafts",
"name": "Swiftshiver Shafts",
"description": "<p>Cut from a wood so light and strong that they seem to leap from the bow of their own accord, it is a surprisingly easy thing for a skilled archer to knock and shoot more than one of these arrows at once.</p>"
"id": "Forest's Wrath",
"name": "Courrouxde de la forêt",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.J4o6g4sjXQ8OXjIj]{Rôdeur Fantôme}</p>",
"career_careergroup": "Rôdeur fantôme",
"trappings": [
"trophée d'un ennemi légendaire",
"flèche elfique antique (pour proie spéciale)",
"réputation effrayante"
]
},
{
"id": "Wildwood Sword",
"name": "Wildwood Sword",
"description": "<p>A two-handed blade with a haft of living wood, these weapons seem to move with a will of their own, striking more quickly than such a sizable weapon would seem capable of.</p>"
"name": "Épée du Bois sauvage",
"description": "<p>Lames à deux mains dotées d'une poignée de bois vivant, ces armes semblent se mouvoir de leur propre chef, frappant plus rapidement que leur taille ne semble leur permettre.</p>"
},
{
"id": "Windwraith",
"name": "Windwraith",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.J4o6g4sjXQ8OXjIj]{Ghost Strider}</p>"
"name": "Esprit du vent",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.J4o6g4sjXQ8OXjIj]{Rôdeur Fantôme}</p>",
"career_careergroup": "Rôdeur fantôme",
"trappings": [
"arc elfique et armure de cuir avec au moins 1 Atout chacun",
"10 flèches elfiques"
]
},
{
"id": "Starfire Shafts",
"name": "Flèches Lumière des astres",
"description": "<p>Le bois des arbres Lumière des astres est un anathème pour la corruption, et les flèches qui en sont tirées sont imprégnées d'un esprit féroce et flamboyant. Ceux qui sont atteints par ces flèches prennent souvent feu et leur usage massif en temps de guerre est terrifiant à contempler.</p>"
},
{
"id": "Swiftshiver Shafts",
"name": "Flèches Vif Frisson",
"description": "<p>Faites d'un bois si léger et résistant qu'elles semblent jaillir du carquois de leur propre chef, il est aisé pour un archer compétent d'encocher et de tirer plus d'une flèche de ce type à la fois.</p>"
},
{
"id": "Forest Ranger",
"name": "Garde forestier",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.J4o6g4sjXQ8OXjIj]{Rôdeur Fantôme}</p>",
"career_careergroup": "Rôdeur fantôme",
"trappings": [
"sac à dos",
"cape à capuche",
"arc long et 10 flèches",
"outils professionnels (Fabricant d'arcs)"
]
},
{
"id": "Novice Warden",
"name": "Garde novice",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.vnLLLPnNYS97hJVe]{Gardechamps}</p>",
"career_careergroup": "Gardechamps",
"trappings": [
"sac à dos",
"tente",
"carte de la région",
"fronde avec 10 pierres",
"outils professionnels (même spécialisation que Métier)"
]
},
{
"id": "Field Warden",
"name": "Gardechamps",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.vnLLLPnNYS97hJVe]{Gardechamps}</p>",
"career_careergroup": "Gardechamps",
"trappings": [
"veste en cuir",
"arme simple",
"lanterne et huile"
]
},
{
"id": "Karak Pathkeeper",
"name": "Gardien des routes des karak",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.GBhO6rb28jKbYfEk]{Patrouilleur des Karak}</p>",
"career_careergroup": "Patrouilleur des karak",
"trappings": [
"outils (Maçonnerie)"
]
},
{
"id": "Bearded Axe",
"name": "Hache à barbe",
"description": "<p>Prisée par beaucoup de nains durant les combats, la tête de ces haches s'incurve vers le manche, ce qui créé un espace entre le manche et la lame, parfait pour arracher leurs armes aux ennemis peu méfiants.</p>"
},
{
"id": "Slayer's Axe",
"name": "Hache de Tueur",
"description": "<p>Les Tueurs sont extrêmement fiers de leur arme, les affûtant de manière presque rituelle à toute occasion. Les plus célèbres d'entre elles ont gagné une réputation de puissance presque aussi importante que leurs porteurs. Ce sont des armes dévastatrices, et les Tueurs qui les manient ne semblent pas être gênés par leur taille.</p>"
},
{
"id": "Nan's Cleaver",
"name": "Hachoir de Mamie",
"description": "<p>Les cuisiniers halflings sont aussi soigneux avec leurs ustensiles de cuisine que le plus méticuleux des guerriers avec son épée. Il n'est donc pas étonnant que ces armes soient utiles en temps de guerre, et que plus d'un gobelin soit tombé sous les coups d'un hachoir qui avait, juste avant, été utilisé pour préparer un généreux ragoût à déguster après la bataille.</p>"
},
{
"id": "Blackbriar Javelin",
"name": "Javelot Noireronce",
"description": "<p>Taillées dans le bois des arbres dont les esprits ont été tordus et rendus néfastes, ces armes vivantes distillent un poison létal. On prétend qu'elles apportent la malchance, et c'est sûrement le cas pour ceux qui doivent les affronter en combat.</p>"
},
{
"id": "Eonir War Blade",
"name": "Lame de guerre éonir",
"description": "<p>Les lames finement ouvragées des Éonirs sont fabriquées pour être plus légères que les armes types de l'Empire et leur équilibre parfait permet des coups rapides et précis.</p>"
},
{
"id": "Eonir Spear",
"name": "Lance éonir",
"description": "<p>Fléau des forces montées, ces lances à la pointe acérée sont plus légères que les armes types de l'Empire. Leur extrémité est trempée et affûtée par des méthodes connues uniquement des elfes sylvains. Elles transpercent les armures avec aisance.</p>"
},
{
"id": "Badger Master",
"name": "Maître blaireau",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.AKNVB3Of7B82YFT1]{Chevaucheur de blaireau}</p>",
"career_careergroup": "Chevaucheur de blaireau",
"trappings": [
"gros blaireau apprivoisé (blaireau-poney tacheté du Moot)",
"1 écuyer (Taquineur de blaireau)",
"armure de plates",
"sens de l'humour"
]
},
{
"id": "Dwarf Hammer",
"name": "Marteau nain",
"description": "<p>Les nains, de notoriété publique, utilisent les mêmes marteaux dans la forge en temps de paix et sur le champ de bataille en temps de guerre. Ces outils si lourds sont parfaits pour fracasser même le plus dur des crânes orcs.</p>"
},
{
"id": "Karak Ranger",
"name": "Patrouilleur des karak",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.GBhO6rb28jKbYfEk]{Patrouilleur des Karak}</p>",
"career_careergroup": "Patrouilleur des karak",
"trappings": [
"arme à poudre noire avec munitions",
"grappin et corde"
]
},
{
"id": "Drakefire Pistol",
"name": "Pistolet Drac de feu",
"description": "<p>Exemple de l'ingéniosité des nains, ce pistolet Drac de feu balaye les cibles de coups incendiaires, les enflammant souvent. Les particularités de sa conception sont un secret bien gardé des nains et il est peu probable que d'autres races puissent en copier les subtilités, même si le concept venait à en être compris. Elles constituent les armes favorites de tout nain qui tiendrait tête à des skavens, loin sous terre, car voir brûler leur fourrure puante est en soi très satisfaisant.</p>"
},
{
"id": "Dwarf Pistol",
"name": "Pistolet nain",
"description": "<p>Les armes à poudre sorties des forges humaines désespèrent souvent les nains, car elles sont souvent aussi dangereuses pour leur porteur que pour sa cible. Les armes à poudre noire des nains sont soigneusement fabriquées et renforcées, les rendant moins susceptibles de râtés et conférant aux projectiles une force supplémentaire.</p>"
},
{
"id": "Iron Skillet",
"name": "Poêle de fer",
"description": "<p>En dépit de leur petite taille, ces pots, casseroles et poêles à frire des halflings sont fabriqués pour être plus lourds qu'on ne le pense. On pourrait en rire, mais plus d'une lame a été détournée d'un coup fatal par la poêle d'un halfling. Ces ustensiles, grêlés et éraflés, font toujours la fierté des foyers de ce peuple.</p>"
},
{
"id": "Ghost Strider",
"name": "Rôdeur fantôme",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.J4o6g4sjXQ8OXjIj]{Rôdeur Fantôme}</p>",
"career_careergroup": "Rôdeur fantôme",
"trappings": [
"arc elfique et 10 flèches fabriquées par le Personnage",
"assortiment de pièges",
"veste en cuir"
]
},
{
"id": "Youngblood",
"name": "Youngblood",
"description": "<p>Your family are considered newcomers to the Laurelorn and are treated with condescension by Eonir of the older birth kindreds. You are always considered of lower Status than other Eonir, unless they also have the Youngblood Talent. Second generation Youngbloods can lose this Talent by passing a trial to join the Forestborn Kindred.</p>"
"name": "Sang neuf",
"description": "<p>Votre famille est vue comme une nouvelle venue dans la Laurelorn, et est traitée avec condescendance par les Éonirs des autres lignages. Votre Statut est toujours considéré comme plus bas que celui des autres Éonirs, à moins qu'ils aient, eux aussi, le Talent Sang neuf. Un membre du jeune lignage de deuxième génération peut perdre ce Talent s'il réussit une série d'épreuves pour rejoindre 1 lignée des Enfants de la forêt.</p>"
},
{
"id": "Badger Sergeant",
"name": "Sergent blaireau",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.AKNVB3Of7B82YFT1]{Chevaucheur de blaireau}</p>",
"career_careergroup": "Chevaucheur de blaireau",
"trappings": [
"caparaçon pour blaireau (2 PA sur la tête et le torse)",
"arme de corps à corps (base ou cavalerie)"
]
},
{
"id": "Field Warden Sergeant",
"name": "Sergent Gardechamps",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.vnLLLPnNYS97hJVe]{Gardechamps}</p>",
"career_careergroup": "Gardechamps",
"trappings": [
"chemise de mailles de bonne qualité",
"escouade de Gardes novices"
]
},
{
"id": "Badger Botherer",
"name": "Taquineur de blaireau",
"description": "<p>@Compendium[wfrp4e-archives1.archives1-journals.AKNVB3Of7B82YFT1]{Chevaucheur de blaireau}</p>",
"career_careergroup": "Chevaucheur de blaireau",
"trappings": [
"sac à dos",
"veste de cuir",
"fronde",
"blaireau apprivoisé avec selle et harnais"
]
}
]
]
}

View File

@ -0,0 +1,165 @@
{
"label": "Items (Starter Set)",
"entries": [
{
"id": "Ameliorative Elixir",
"name": "Élixir Améliorant",
"description": "<p>Contenant de la mystracine, cette potion épaisse au goût terreux procure une certaine euphorie et des hallucinations agréables. La otion offre un bonus de +10 aux Tests de Force Mentale, mais une pénalité de -10 aux Tests dAgilité, dInitiative et dIntelligence. Durée: [[/r 1d10]] x 10 minutes</p>"
},
{
"id": "Basilisk's Baleful Bile",
"name": "Basilisk's Baleful Bile",
"description": "<p>This poison is created from combining fluids from the eyes and poison sacks of a freshly slain Basilisk. It is a foul tasting poison, and anyone ingesting food or drink laced with Basilisk&rsquo;s Baleful Bile will be called to take an<strong> Easy (+40) Perception</strong> Test. Success indicates they detect the taint of something wrong before suffering the bile&rsquo;s effects, but gain the @Condition[Stunned] Condition for one Round whilst they vomit it up. If ingested, the concoction inflicts 2 @Condition[Poisoned] Conditions, resisted with a <strong>Difficult (-10) Endurance</strong> Test. If the target fails to resist the @Condition[Poisoned] Conditions, they are permanently turned to stone.</p>"
},
{
"id": "Bronze Fever",
"name": "La Fièvre de bronze",
"description": "<p>La Fièvre de bronze est fréquente dans le sud du Vieux Monde, là où le climat est plus chaud et humide, car elle se propage à cause des piqûres dinsectes. La plupart des malades guérissent en quelques jours, mais, en de rares occasions, des complications peuvent mener jusquà la mort.&nbsp;</p>"
},
{
"id": "Bruised",
"name": "Bleus aux côtes",
"description": "<p>Tous les Tests basés sur lAgilité sont effectués avec un malus de -10 pendant [[/r 1d10]] jours.</p>"
},
{
"id": "Clutch of Eyes",
"name": "Pullulement dYeux",
"description": "<p>Des kystes tremblotants bouillonnent sous votre chair, puis la douleur vous transperce alors que des pustules sanglantes émergent et souvrent, révélant une portée de nouveaux yeux horrifiés.</p><p>Jetez @Table[hitloc]{Hit Location} pour déterminer la Localisation de ces nouveaux yeux. Vous pouvez désormais voir depuis cette Localisation.Augmentez votre Caractéristique dInitiative de [[/r 1d10]]. Si vous ne possédiez pas de Caractéristique dInitiative, vous gagnez +[[/r 2d10]] supplémentaires dans celle-ci. Tous les coups qui atteignent la Localisation dotée de votre Pullulement dYeux infligent également un État @Condition[Blinded].</p>"
},
{
"id": "Cracked Bone",
"name": "Os fêlé",
"description": "<p>Gagnez un État @Condition[Stunned]. Tous les Tests subissent un malus de -10 jusquà ce que vous receviez un Test de Soins réussi.</p>"
},
{
"id": "Crippling Wound",
"name": "Blessure incapacitante",
"description": "<p>Gagnez un État @Condition[Prone] qui ne peut être enlevé que grâce à un Test <strong>Simple de Soins</strong> réussi. Tous les Tests subissent un malus de -20 jusquà ce que vous receviez cette Aide Médicale, et passiez au moins une semaine à vous reposer.</p>"
},
{
"id": "Doppelganger",
"name": "Doppelganger",
"description": "<p>le PNJ peut adopter la forme de nimporte quelle créature de Taille Moyenne. Il doit pour cela obtenir au moins 5 DR sur un Test <strong>Étendu de Perception</strong> tout en observant sa cible. Il a ensuite besoin de 2 Rounds pour prendre lapparence de la cible. Les vêtements de la cible et les petits accessoires sont également répliqués; ils font cependant partie de la créature et ne peuvent être retirés. Les objets plus gros, comme les épées et les sacs à dos, ne sont pas copiés. Lorsque ceux qui connaissent la victime rencontrent la créature transformée, ils effectuent un Test <strong>Simple dIntuition Difficile (-20)</strong>. Sils réussissent, ils sentent que quelque chose ne va pas. Sils échouent, ils sont convaincus que la créature est bien la personne quils connaissent.</p>"
},
{
"id": "Flensed Muscle",
"name": "Muscle dépecé",
"description": "<p>Gagnez 4 États @Condition[Bleeding]. Toute nouvelle blessure reçue sur la Localisation affectée au cours des 4 prochaines semaines infligera également 2 États Hémorragiques suite à la réouverture de la plaie.</p><blockquote class=\"foundry-note\"><p>The Active Effect script for this item needs your input. Once applied to an Actor, replace <span style=\"font-family: Courier\">LOCATION_HERE</span> with <span style=\"font-family: Courier New\">head</span>, <span style=\"font-family: Courier New\">body</span>, <span style=\"font-family: Courier\">lArm</span>, <span style=\"font-family: Courier\">rArm</span>, <span style=\"font-family: Courier\">lLeg</span>, or <span style=\"font-family: Courier\">rLeg,</span> matching which location was hit</p></blockquote>"
},
{
"id": "Focusing Philtre",
"name": "Philtre de Concentration",
"description": "<p>Ce Philtre, sombre et amer, permet de focaliser son esprit et aide à se concentrer. Il confère un bonus de +20 aux Tests dIntelligence et dEndurance. Lorsque son effet se dissipe, subissez 1 État @Condition[Fatigued] qui perdurera au moins une journée entière. Durée: [[/r 1d10]] heures.</p>"
},
{
"id": "Fractured Bone",
"name": "Os fracturé",
"description": "<p>Gagnez un État @Condition[Stunned]. Réussissez un Test <strong>Simple de Résistance</strong> ou obtenez également lÉtat @Condition[Prone]. Tous les Tests subissent un malus de -10 pendant les 4 prochaines semaines.</p>"
},
{
"id": "Gaping Wound",
"name": "Blessure béante",
"description": "<p>Gagnez 3 États @Condition[Bleeding]. Toute nouvelle blessure reçue sur la Localisation affectée au cours de la semaine suivante infligera un État Hémorragique supplémentaire, car cette blessure se sera rouverte.</p><blockquote class=\"foundry-note\"><p>The Active Effect script for this item needs your input. Once applied to an Actor, replace <span style=\"font-family: Courier\">LOCATION_HERE</span> avec style=\"font-family: Courier New\">head</span>, <span style=\"font-family: Courier New\">body</span>, <span style=\"font-family: Courier\">lArm</span>, <span style=\"font-family: Courier\">rArm</span>, <span style=\"font-family: Courier\">lLeg</span>, or <span style=\"font-family: Courier\">rLeg,</span> matching which location was hit</p></blockquote>"
},
{
"id": "Gash",
"name": "Rien qu'une égratignure!",
"description": "<p>Gagnez 1 État @Condition[Bleeding].</p>"
},
{
"id": "Gut Blow",
"name": "Coup au ventre",
"description": "<p>Gagnez 1 État @Condition[Stunned].</p>"
},
{
"id": "Itchy Nuisance",
"name": "Démangeaisons",
"description": "<p>Vous agitez les doigts et des spores de champignons irritants sen échappent et se déposent dans les zones sensibles de la cible. Ces spores se développent rapidement en causant de terribles démangeaisons. La cible subit un malus de -10 % à tous les Tests, et diminue de moitié son Mouvement pendant toute la durée du sort.</p>"
},
{
"id": "Katya's Cordial",
"name": "Sirop de Katya",
"description": "<p>Ce mélange diffuse une odeur légèrement sucrée de couleur rose perle au goût épicé. Cette potion augmente le charme de celui qui lingère, avec cependant un effet indésirable. Lorsquelle est sous leffet de la potion, la personne qui la ingérée gagne le Talent @Compendium[wfrp4e-core.talents.6l3jvIAvrKxt0lA9]{Attractive}. Cependant, dès que leffet se dissipe, ce dernier subit une pénalité de -20 à tous les Tests de Sociabilité pendant [[/r 1d10]] jours au cours desquels sa peau et ses yeux dégorgeront des sécrétions jaunâtres à lodeur nauséabonde. Durée : [[/r 1d10]] heures.</p>"
},
{
"id": "Liquor of Luck",
"name": "Liqueur de Chance",
"description": "<p>Ce liquide bleu brillant exhale une légère odeur de réglisse. Le boire confère +1 Point de Chance. De plus, alors que la Liqueur est active, lancez roll [[/r 1d100]] lorsque vous dépensez un Point de Chance. Si vous obtenez un double, vous regagnez un Point de Chance. Lorsque leffet se dissipe, perdez tous les Points de Chance et subissez un État @Condition[Fatigued] qui perdurera au moins une journée entière. Durée : [[/r 1d10]] minutes.</p>"
},
{
"id": "Low Blow!",
"name": "Dans les bijoux de famille",
"description": "<p>Obtenez 1 État @Condition[Stunned]. Réussissez un Test <strong>Simple de Résistance Difficile (-20)</strong> ou gagnez 2 États Sonné supplémentaires.</p>"
},
{
"id": "Massive Intellect",
"name": "Cerveau Massif",
"description": "<p>Du sang frais, des esquilles dos et de la chair martyrisée se déversent par vos orifices pendant que votre ancien cerveau est évacué. Lentement, au fil des semaines, un nouveau grandit à sa place, faisant sétirer douloureusement votre tête grâce à des bandes translucides autour de votre cerveau enflé et luisant. Augmentez votre Caractéristique dIntelligence de [[/r 2d10]]. Si vous naviez pas de Caractéristique de Sociabilité, vous en acquérez une dune valeur égale au résultat de [[/r 2d10]]. De plus, tous les coups à la tête infligent désormais une @Table[crithead]{Blessure Critique} lorsque ce nest pas déjà le cas.</p>"
},
{
"id": "Painful Cut",
"name": "Entaille douloureuse",
"description": "<p>Gagnez 2 États @Condition[Bleeding] et un État @Condition[Stunned]. Réussissez un Test <strong>Simple de Résistance Difficile (-20)</strong> ou obtenez lÉtat @Condition[Unconscious] en vous évanouissant sous la douleur.</p>"
},
{
"id": "Reactionary Restorative",
"name": "Revigorant Réparateur",
"description": "<p>Liquide rouge sang épais au goût répugnant, ce breuvage augmente considérablement les réactions au danger de celui qui lingère. Tant que son effet perdure, vous ne pouvez jamais subir lÉtat @Condition[Surprised]. Lorsque son effet se dissipe, subissez 1 État @Condition[Fatigued] qui perdurera au moins une journée entière. Durée : [[/r 1d10]] heures.</p>"
},
{
"id": "Ruined",
"name": "Anéanti",
"description": "<p>Gagnez un État @Condition[Unconscious] qui ne peut être enlevé que grâce à un Test <strong>Simple de Soins</strong> réussi. La Localisation affectée est inutilisable tant que vous navez pas passé un mois à garder le lit.</p>"
},
{
"id": "Saif al-Janub",
"name": "Saif al-Janub",
"description": "<p>Offert en cadeau à Lohner en remerciement des actions décisives effectuées lors de la défense de Sudenburg contre les morts-vivants en 2498 CI, cette lame courbe a été forgée par le célèbre philosophe-artisan Hataq al-Kundi en 1445 CI. Cette arme exceptionnelle vaut dix fois le prix indiqué en Arabie.</p>"
},
{
"id": "Shattered Bone",
"name": "Os brisé",
"description": "<p>Gagnez un État @Condition[Stunned] qui ne peut être enlevé que grâce à un Test <strong>Simple de Soins</strong> réussi. Tous les Tests subissent un malus de -20 jusquà ce que vous receviez cette Aide Médicale, et passiez au moins une semaine à vous reposer.</p>"
},
{
"id": "Slippery Skin",
"name": "Peau glissante",
"description": "<p>Vous transpirez constamment, votre peau exsudant un mucus fin et visqueux un peu comme celui que produisent les myxines. Cest déplaisant au toucher, cela imbibe vos vêtements en une heure ou deux, et cela rend votre poigne incertaine. Tous les Tests qui nécessitent que vous teniez quelque chose dans vos mains (comme une arme) subissent une pénalité de -20, et vous souffrez également dun malus de -20 aux Tests de Sociabilité. Lorsque vous tentez déchapper à une Empoignade, si vous réussissez, vous pouvez choisir dutiliser soit votre DR, soit le nombre affiché sur le dé des unités. Un jet réussi de 28 peut donc être utilisé pour obtenir +8 DR.</p>"
},
{
"id": "Sneaky Stabbin'",
"name": "Attaque sournoiz",
"description": "<p>Vous enchantez les lames de vos alliés, de façon à ce quelles cherchent le point faible dans larmure de vos adversaires. Les cibles acquièrent immédiatement +1 Avantage, et leurs attaques gagnent la Qualité Pénétrante tant quils ont de lAvantage.</p>"
},
{
"id": "Telepathy",
"name": "Télépathie",
"description": "<p>Votre esprit se libère de ses chaînes matérielles, murmurant de joie alors quil perçoit de nouvelles façons de simposer aux autres. Avec un Test <strong>Simple de Force Mentale</strong> vous pouvez communiquer avec nimporte quelle créature consciente se trouvant dans les Force Mentale en mètres, dans votre ligne de vue. Cela dure pendant un nombre de minutes égal à votre Caractéristique dInitiative. Vous pouvez également lire les pensées superficielles de nimporte quelle créature avec laquelle vous communiquez par télépathie avec un Test <strong>Opposé de Force Mentale</strong>. Si vous ratez le Test, vous ne pouvez plus lire lesprit du sujet pendant les prochains [[/r 1d10]] jours. Lorsque vous utilisez la télépathie, vos yeux luisent étrangement. Chaque fois que cette Mutation est développée, la portée jusquà laquelle vous pouvez utiliser ce pouvoir double.</p><p> </p><p> </p>"
},
{
"id": "The Marvelous Medicinal Mixture",
"name": "Le Merveilleux Mélange Thérapeutique",
"description": "<p>Ce liquide écœurant diffuse une odeur de poisson, et quiconque souhaite ingérer cette décoction doit dans un premier temps réussir un Test Moyen (+20) de Calme. Ensuite, cette personne subit un État @Condition[Fatigued], qui ne disparaîtra quaprès une bonne nuit de repos. La potion ne déclenche aucun autre effet. Cependant, son goût est si abject que les clients de von Holzenauer sont convaincus de son efficacité à guérir nimporte quel malaise</p>"
},
{
"id": "Tonic of Sight Beyond Sight",
"name": "Tonique de Vue au-delà de la Vue",
"description": "<p>Létiquette de la bouteille contenant ce liquide vert foncé est ornée dun grand globe oculaire rouge. Cette potion porte la promesse daméliorer la vision de celui qui la boit. La boire vous conférera lun des Talents suivants, voire plusieurs (lancer [[/r 1d10]]) : 1-2 : @Compendium[wfrp4e-core.talents.9h82z72XGo9tfgQS]{Acute Sense (Sight)}; 3-4 : @Compendium[wfrp4e-core.talents.Nj3tC8A5fZ3zEdMR]{Holy Visions}; 5-6 : @Compendium[wfrp4e-core.talents.6w30u0VPsAicrqb5]{Magical Sense}; 7-8 : @Compendium[wfrp4e-core.talents.OEjUvJKi0xmBwbS2]{Second Sight}; 9-10 : tous les effets ci-dessus. Durée : [[/r 1d10]] minutes</p>"
},
{
"id": "Torn Apart",
"name": "Éventré",
"description": "<p>Vous êtes coupé en deux. La moitié supérieure atterrit à [[/r 1d10]] x 30cm dans une direction aléatoire, et tous les Personnages à proximité sont recouverts de sang.</p>"
},
{
"id": "Torn Flesh",
"name": "Chairs déchirées",
"description": "<p>Gagnez 2 État @Condition[Bleeding].</p>"
},
{
"id": "Winded",
"name": "Soufle coupé",
"description": "Gagnez 2 États @Condition[Stunned]. Réussissez un Test <strong>Simple de Résistance Accessible (+20)</strong> ou obtenez 1 État @Condition[Prone]. Le Mouvement est divisé par deux pendant [[/r 1d10]] Rounds, le temps de récupérer votre souffle.</p>"
}
]
}

View File

@ -8,7 +8,7 @@
}
],
"url": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr",
"version": "6.2.22",
"version": "6.2.23",
"esmodules": [
"babele-register.js",
"addon-register.js",
@ -136,7 +136,7 @@
}
],
"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-6.2.22.zip",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-wh4-lang-fr-fr/archive/foundryvtt-wh4-lang-fr-6.2.23.zip",
"id": "wh4-fr-translation",
"compatibility": {
"minimum": "10",