2020-04-12 08:59:47 +02:00
class ActorWfrp4e _fr extends ActorWfrp4e {
/ * *
* Calculates a weapon ' s range or damage formula .
*
* Takes a weapon formula for Damage or Range ( SB + 4 or SBx3 ) and converts to a numeric value .
*
* @ param { String } formula formula to be processed ( SBx3 => 9 ) .
*
* @ return { Number } Numeric formula evaluation
* /
calculateRangeOrDamage ( formula )
{
//console.log("FR function calculateRangeOrDamage !", formula);
let actorData = this . data
try
{
formula = formula . toLowerCase ( ) ;
// Iterate through characteristics
for ( let ch in actorData . data . characteristics )
{
// Determine if the formula includes the characteristic's abbreviation + B (SB, WPB, etc.)
if ( formula . includes ( ch . concat ( 'b' ) ) )
{
// Replace that abbreviation with the Bonus value
formula = formula . replace ( ch . concat ( 'b' ) , actorData . data . characteristics [ ch ] . bonus . toString ( ) ) ;
}
}
if ( formula . includes ( "yard" ) )
2020-04-20 10:16:26 +02:00
formula = formula . replace ( 'yard' , "mètre" ) ;
2020-04-12 08:59:47 +02:00
if ( formula . includes ( "yds" ) )
2020-04-20 10:16:26 +02:00
formula = formula . replace ( 'yds' , "m." ) ;
2020-04-12 08:59:47 +02:00
// To evaluate multiplication, replace x with *
formula = formula . replace ( 'x' , '*' ) ;
return eval ( formula ) ;
}
catch
{
return formula
}
}
/ * *
* Turns a formula into a processed string for display
*
* Processes damage formula based - same as calculateSpellAttributes , but with additional
* consideration to whether its a magic missile or not
*
* @ param { String } formula Formula to process - "Willpower Bonus + 4"
* @ param { boolean } isMagicMissile Whether or not it ' s a magic missile - used in calculating additional damage
* @ returns { String } Processed formula
* /
calculateSpellDamage ( formula , isMagicMissile )
{
let actorData = this . data
formula = formula . toLowerCase ( ) ;
if ( isMagicMissile ) // If it's a magic missile, damage includes willpower bonus
{
formula += "+ " + actorData . data . characteristics [ "wp" ] . bonus
}
// Specific case, to avoid wrong matching with "Force"
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" , ) ;
else
formula = formula . replace ( "force mentale" , actorData . data . characteristics [ "wp" ] . value ) ;
}
// Iterate through characteristics
for ( let ch in actorData . data . characteristics )
{
// If formula includes characteristic name
while ( formula . includes ( actorData . data . characteristics [ ch ] . label . toLowerCase ( ) ) )
{
// Determine if it's looking for the bonus or the value
if ( formula . includes ( 'bonus' ) )
formula = formula . replace ( "bonus de " + WFRP4E . characteristics [ ch ] . toLowerCase ( ) , actorData . data . characteristics [ ch ] . bonus ) ;
else
formula = formula . replace ( WFRP4E . characteristics [ ch ] . toLowerCase ( ) , actorData . data . characteristics [ ch ] . value ) ;
}
}
//console.log("calculateSpellDamage -> " + formula );
return eval ( formula ) ;
}
/ * *
* Turns a formula into a processed string for display
*
* Turns a spell attribute such as "Willpower Bonus Rounds" into a more user friendly , processed value
* such as "4 Rounds" . If the aoe is checked , it wraps the result in AoE ( Result ) .
*
* @ param { String } formula Formula to process - "Willpower Bonus Rounds"
* @ param { boolean } aoe Whether or not it ' s calculating AoE ( changes string return )
* @ returns { String } formula processed formula
* /
calculateSpellAttributes ( formula , aoe = false )
{
let actorData = this . data
formula = formula . toLowerCase ( ) ;
// Do not process these special values
if ( formula != game . i18n . localize ( "Vous" ) . toLowerCase ( ) && formula != game . i18n . localize ( "Special" ) . toLowerCase ( ) && formula != game . i18n . localize ( "Instantané" ) . toLowerCase ( ) )
{
// Specific case, to avoid wrong matching with "Force"
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" , actorData . data . characteristics [ "wp" ] . bonus ) ;
else
formula = formula . replace ( "force mentale" , actorData . data . characteristics [ "wp" ] . value ) ;
}
if ( formula . includes ( "yard" ) )
2020-04-20 10:16:26 +02:00
formula = formula . replace ( 'yard' , "mètre" ) ;
2020-04-12 08:59:47 +02:00
if ( formula . includes ( "yds" ) )
2020-04-20 10:16:26 +02:00
formula = formula . replace ( 'yds' , "m." ) ;
2020-04-12 08:59:47 +02:00
// Iterate through remaining characteristics
for ( let ch in actorData . data . characteristics )
{
// If formula includes characteristic name
//console.log("Testing :", ch, WFRP4E.characteristics[ch].toLowerCase());
if ( formula . includes ( WFRP4E . characteristics [ ch ] . toLowerCase ( ) ) )
{
// Determine if it's looking for the bonus or the value
if ( formula . includes ( 'bonus' ) )
formula = formula . replace ( "bonus de " + WFRP4E . characteristics [ ch ] . toLowerCase ( ) , actorData . data . characteristics [ ch ] . bonus ) ;
else
formula = formula . replace ( WFRP4E . characteristics [ ch ] . toLowerCase ( ) , actorData . data . characteristics [ ch ] . value ) ;
}
}
}
// If AoE - wrap with AoE ( )
if ( aoe )
formula = "AoE (" + formula . capitalize ( ) + ")" ;
//console.log("calculateSpellAttributes -> " + formula );
return formula . capitalize ( ) ;
}
}
2020-04-23 21:13:56 +02:00
Hooks . on ( "chatMessage" , async ( html , content , msg ) => {
2020-04-23 11:52:39 +02:00
// Split input into arguments
let command = content . split ( " " ) . map ( function ( item ) {
return item . trim ( ) ;
} )
2020-04-23 21:13:56 +02:00
2020-04-23 11:52:39 +02:00
if ( command [ 0 ] == "/auberge" )
{
2020-04-23 21:13:56 +02:00
msg [ "type" ] = 0 ;
msg [ "rollMode" ] = "gmroll" ;
var compendium = game . packs . find ( p => p . collection === 'WH4-fr-translation.plats-dauberges' ) ;
let rollList = [ ] ;
await compendium . getIndex ( ) . then ( index => rollList = index ) ;
//console.log("Got compendium...", rollList.length);
for ( var i = 0 ; i < rollList . length ; i ++ ) {
var rollTab = rollList [ i ] ;
if ( rollTab . name . toLowerCase ( ) . includes ( command [ 1 ] . toLowerCase ( ) ) ) {
let my _rollTable ;
await compendium . getEntity ( rollTab . _id ) . then ( mytab => my _rollTable = mytab ) ;
var result = my _rollTable . roll ( ) ;
console . log ( "RES: " , result [ 0 ] , result [ 1 ] ) ;
msg . content = my _rollTable . name + " : " + result [ 1 ] . text ;
//my_rollTable.draw();
ChatMessage . create ( msg ) ;
return false ;
}
}
msg [ "content" ] = "Syntaxe : /auberge MOT_CLE, avec MOT_CLE parmi:<br>BoissonsBase, BoissonsFortes, Desserts, PlatsCommuns, PlatsExcellents, PlatsMaritimes, PlatsMédiocres, PlatsQualité, PlatsRivières<br>Des raccourcis sont possibles avec une partie du nom : /auberge Base (correspond à BoissonBase) ou /auberge Mari (correspond à PlatsMaritimes), etc."
ChatMessage . create ( msg ) ;
2020-04-23 11:52:39 +02:00
return false ;
}
} ) ;
2020-03-25 20:37:09 +01:00
2020-04-23 21:13:56 +02:00
var _ _mywait = ms => new Promise ( ( r , j ) => setTimeout ( r , ms ) )
2020-03-25 20:37:09 +01:00
Hooks . once ( 'init' , ( ) => {
2020-04-12 08:59:47 +02:00
// Replace to manage specific bonuses/char. computations
CONFIG . Actor . entityClass = ActorWfrp4e _fr ;
2020-04-12 14:40:54 +02:00
WFRP4E . talentBonuses = {
"perspicace" : "int" ,
"affable" : "fel" ,
"tireur de précision" : "bs" ,
"très fort" : "s" ,
"vivacité" : "i" ,
"reflexes foudroyants" : "ag" ,
"imperturbable" : "wp" ,
"très résistant" : "t" ,
"doigts de fée" : "dex" ,
"guerrier né" : "ws"
}
2020-04-23 11:52:39 +02:00
WFRP4E . speciesSkills = {
"human" : [
"Soins aux animaux" ,
"Charme" ,
"Calme" ,
"Evaluation" ,
"Ragot" ,
"Marchandage" ,
"Langue (Bretonnien)" ,
"Langue (Wastelander)" ,
"Commandement" ,
"Savoir (Reikland)" ,
"Corps à corps (Base)" ,
"Projectiles (Arc)"
] ,
"dwarf" : [
"Résistance à l'alcool" ,
"Calme" ,
"Endurance" ,
"Divertissement (Raconter)" ,
"Evaluation" ,
"Intimidation" ,
"Langue (Khazalid)" ,
"Savoir (Nains)" ,
"Savoir (Geologie)" ,
"Savoir (Metallurgie)" ,
"Corps à corps (Base)" ,
"Métier (Au choix)"
] ,
"halfling" : [
"Charme" ,
"Résistance à l'alcool" ,
"Esquive" ,
"Pari" ,
"Marchandage" ,
"Intuition" ,
"Langue (Mootland)" ,
"Savoir (Reikland)" ,
"Perception" ,
"Escamotage" ,
"Discrétion (Au choix)" ,
"Métier (Cuisinier)"
] ,
"helf" : [
"Calme" ,
"Divertissement (Chant)" ,
"Evaluation" ,
"Langue (Eltharin)" ,
"Commandement" ,
"Corps à corps (Base)" ,
"Navigation" ,
"Perception" ,
"Musicien (Au choix)" ,
"Projectiles (Arc)" ,
"Voile" ,
"Natation"
] ,
"welf" : [
"Athlétisme" ,
"Escalade" ,
"Endurance" ,
"Divertissement (Chant)" ,
"Intimidation" ,
"Langue (Eltharin)" ,
"Corps à corps (Base)" ,
"Survie en extérieur" ,
"Perception" ,
"Projectiles (Arc)" ,
"Discrétion (Rural)" ,
"Pistage"
] ,
}
WFRP4E . speciesTalents = {
"human" : [
"Destinée" ,
"Affable, Perspicace" ,
3
] ,
"dwarf" : [
"Résistance à la Magie" ,
"Vision Nocturne" ,
"Lire/Ecrire, Impitoyable" ,
"Déterminé, Obstiné" ,
"Costaud" ,
0
] ,
"halfling" : [
"Sens Aiguisé (Gout)" ,
"Vision Nocturne" ,
"Résistance (Chaos)" ,
"Petit" ,
0
] ,
"helf" : [
"Sens Aiguisé (Vue)" ,
"Imperturbable, Perspicace" ,
"Vision Nocturne" ,
"Seconde Vue, Sixième Sens" ,
"Lire/Ecrire" ,
0
] ,
"welf" : [
"Sens Aiguisé (Sight)" ,
"Dur à cuire, Seconde Vue" ,
"Vision Nocturne" ,
"Seconde Vue, Sixth Sense" ,
"Lire/Ecrire" ,
0
] ,
}
2020-04-23 21:13:56 +02:00
2020-03-25 20:37:09 +01:00
if ( typeof Babele !== 'undefined' ) {
Babele . get ( ) . register ( {
module : 'WH4-fr-translation' ,
lang : 'fr' ,
dir : 'compendium'
} ) ;
2020-03-30 23:23:21 +02:00
Babele . get ( ) . registerConverters ( {
2020-03-31 09:03:19 +02:00
"career_skills" : ( skills _list ) => {
2020-03-30 23:23:21 +02:00
var compendium = game . packs . find ( p => p . collection === 'wfrp4e.skills' ) ;
2020-04-14 17:16:25 +02:00
//console.log( "Thru here ...", compendium, skills_list);
2020-03-30 23:23:21 +02:00
var i ;
var len = skills _list . length ;
var re = /(.*)\((.*)\)/i ;
for ( i = 0 ; i < len ; i ++ ) {
2020-04-14 17:16:25 +02:00
var transl = compendium . i18nName ( { name : skills _list [ i ] } ) ;
//console.log("List ...", skills_list[i]);
2020-03-30 23:23:21 +02:00
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 s1 = res [ 1 ] . trim ( ) + " ()" ;
2020-04-14 17:16:25 +02:00
var translw = compendium . i18nName ( { name : s1 } ) ;
2020-04-10 15:11:26 +02:00
if ( translw != s1 ) {
2020-03-30 23:23:21 +02:00
var res2 = re . exec ( translw ) ;
transl = res2 [ 1 ] + "(" + subword + ")" ;
} else {
s1 = res [ 1 ] . trim ( ) + " ( )" ;
2020-04-14 17:16:25 +02:00
translw = compendium . i18nName ( { name : s1 } ) ;
2020-03-30 23:23:21 +02:00
var res2 = re . exec ( translw ) ;
transl = res2 [ 1 ] + "(" + subword + ")" ;
}
}
}
skills _list [ i ] = transl ;
}
return skills _list ;
} ,
"career_talents" : ( talents _list ) => {
var compendium = game . packs . find ( p => p . collection === 'wfrp4e.talents' ) ;
var i ;
var len = talents _list . length ;
var re = /(.*)\((.*)\)/i ;
for ( i = 0 ; i < len ; i ++ ) {
2020-04-14 17:16:25 +02:00
var transl = compendium . i18nName ( { name : talents _list [ i ] } ) ;
2020-03-30 23:23:21 +02:00
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 ( ) ) ;
2020-03-31 17:44:46 +02:00
var s1 = res [ 1 ] . trim ( ) ; // No () in talents table
2020-04-14 17:16:25 +02:00
var translw = compendium . i18nName ( { name : s1 } ) ;
2020-04-10 15:11:26 +02:00
if ( translw != s1 ) {
2020-03-31 17:44:46 +02:00
transl = translw + "(" + subword + ")" ;
2020-03-30 23:23:21 +02:00
} else {
s1 = res [ 1 ] . trim ( ) + " ( )" ;
2020-04-14 17:16:25 +02:00
translw = compendium . i18nName ( { name : s1 } ) ;
2020-03-30 23:23:21 +02:00
var res2 = re . exec ( translw ) ;
transl = res2 [ 1 ] + "(" + subword + ")" ;
}
}
}
talents _list [ i ] = transl ;
}
return talents _list ;
2020-03-31 09:27:04 +02:00
} ,
2020-04-23 11:52:39 +02:00
"npc_characteristics" : ( chars ) => { // Auto-convert char names in the sheet
for ( var key in chars ) {
//console.log("Was here !", key, chars[key].label);
var char = chars [ key ]
var abrev = char [ "abrev" ] ;
char [ "label" ] = game . i18n . localize ( "CHAR." + abrev ) ;
char [ "abrev" ] = game . i18n . localize ( "CHARAbbrev." + abrev ) ;
}
return chars ;
} ,
2020-04-22 20:22:34 +02:00
"bestiary_traits" : ( beast _traits , translations ) => {
var compendium = game . packs . find ( p => p . collection === 'wfrp4e.traits' ) ;
for ( let trait _en of beast _traits )
{
var nbt = "" ;
var special = "" ;
var name _en = trait _en . name . trim ( ) ; // strip \r in some traits name
if ( name _en . includes ( "Tentacles" ) ) { // Process specific Tentacles case
var re = /(.d*)x Tentacles/i ;
var res = re . exec ( name _en ) ;
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 ) ;
name _en = res [ 1 ] ; // Get the root traits name
special = " (" + res [ 2 ] + ")" ; // And the special keyword
}
var trait _fr = compendium . translate ( { name : name _en } ) ;
//console.log(">>>>> Trait ?", name_en, nbt, trait_fr.name);
trait _en . name = nbt + trait _fr . name + special ;
trait _en . data . description . value = trait _fr . data . description . value ;
if ( isNaN ( trait _en . data . specification . value ) ) { // This is a string, so translate it
//console.log("Translating : ", trait_en.data.specification.value);
2020-04-23 11:52:39 +02:00
trait _en . data . specification . value = game . i18n . localize ( trait _en . data . specification . value . trim ( ) ) ;
2020-04-22 20:22:34 +02:00
}
}
return beast _traits ;
2020-04-21 21:47:05 +02:00
} ,
2020-03-31 09:27:04 +02:00
// To avoid duplicateing class for all careers
2020-03-31 17:44:46 +02:00
"generic_localization" : ( value ) => {
2020-04-01 00:41:20 +02:00
if ( value )
return game . i18n . localize ( value . trim ( ) ) ;
2020-04-10 15:11:26 +02:00
} ,
2020-04-01 00:41:20 +02:00
"trapping_qualities_flaws" : ( value ) => {
if ( value ) {
var list = value . split ( "," ) ;
var i = 0 ;
var re = /(.*) (\d+)/i ;
for ( i = 0 ; i < list . length ; i ++ ) {
var splitted = re . exec ( list [ i ] . trim ( ) ) ;
if ( splitted ) {
//console.log("FOund:", splitted[0], splitted[1], splitted[2] );
list [ i ] = game . i18n . localize ( splitted [ 1 ] ) + " " + splitted [ 2 ] ;
} else {
list [ i ] = game . i18n . localize ( list [ i ] . trim ( ) ) ;
}
2020-03-31 17:44:46 +02:00
}
2020-04-01 00:41:20 +02:00
return list . toString ( ) ;
2020-03-31 17:44:46 +02:00
}
} ,
2020-03-31 09:27:04 +02:00
// Search back in careers the translated name of the groupe (as it is the name of the level career itself)
"career_careergroup" : ( value ) => {
var compendium = game . packs . find ( p => p . collection === 'wfrp4e.careers' ) ;
2020-04-14 17:16:25 +02:00
return compendium . i18nName ( { name : value } ) ;
2020-04-10 15:11:26 +02:00
} ,
// Auto-translate duration
"spells_duration_range_target_damage" : ( value ) => {
2020-04-10 17:36:32 +02:00
//console.log("Spell duration/range/damage/target :", value);
2020-04-10 15:11:26 +02:00
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 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 ( ) ) ;
}
unit = res [ 2 ] ;
} else {
re = /(\d+) (\w+)/i ;
res = re . exec ( value ) ;
if ( res ) { // Test : "<number> <unit>" pattern
translw = res [ 1 ] ;
unit = res [ 2 ] ;
} else { // Test
re = /(\w+) (\w+)/i ;
res = re . exec ( value ) ;
if ( res ) { // Test : "<charac> <unit>" pattern
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" ;
translw += " " + unit ;
return translw ;
2020-03-31 17:44:46 +02:00
}
2020-03-30 23:23:21 +02:00
} ) ;
2020-03-27 23:12:43 +01:00
}
2020-03-25 21:03:36 +01:00
} ) ;
2020-04-12 08:59:47 +02:00