2020-05-22 22:37:02 +02:00
/* Common useful functions shared between objects */
2020-06-11 00:29:32 +02:00
import { RdDActor } from "./actor.js" ;
2020-05-24 20:19:57 +02:00
const level _category = {
"generale" : "-4" ,
"particuliere" : "-8" ,
"speciale" : "-11" ,
"connaissance" : "-11" ,
"draconic" : "-11" ,
"melee" : "-6" ,
"tir" : "-8" ,
"lancer" : "-8"
}
const carac _array = [ "taille" , "apparence" , "constitution" , "force" , "agilite" , "dexterite" , "vue" , "ouie" , "odoratgout" , "volonte" , "intellect" , "empathie" , "reve" , "chance" , "melee" , "tir" , "lancer" , "derobee" ] ;
const bonusmalus = [ - 10 , - 9 , - 8 , - 7 , - 6 , - 5 , - 4 , - 3 , - 2 , - 1 , 0 , + 1 , + 2 , + 3 , + 4 , + 5 , + 6 , + 7 , + 8 , + 9 , + 10 ] ;
const specialResults = [ { "part" : 0 , "epart" : 0 , "etotal" : 0 } , // 0
{ "part" : 1 , "epart" : 81 , "etotal" : 92 } , // 01-05
{ "part" : 2 , "epart" : 82 , "etotal" : 92 } , // 06-10
{ "part" : 3 , "epart" : 83 , "etotal" : 93 } , // 11-15
{ "part" : 4 , "epart" : 84 , "etotal" : 93 } , // 16-20
{ "part" : 5 , "epart" : 85 , "etotal" : 94 } , // 21-25
{ "part" : 6 , "epart" : 86 , "etotal" : 94 } , // 26-30
{ "part" : 7 , "epart" : 87 , "etotal" : 95 } , // 31-35
{ "part" : 8 , "epart" : 88 , "etotal" : 95 } , // 36-40
{ "part" : 9 , "epart" : 89 , "etotal" : 96 } , // 41-45
{ "part" : 10 , "epart" : 90 , "etotal" : 96 } , // 46-50
{ "part" : 11 , "epart" : 91 , "etotal" : 97 } , // 51-55
{ "part" : 12 , "epart" : 92 , "etotal" : 97 } , // 56-60
{ "part" : 13 , "epart" : 93 , "etotal" : 98 } , // 61-65
{ "part" : 14 , "epart" : 94 , "etotal" : 98 } , // 65-70
{ "part" : 15 , "epart" : 95 , "etotal" : 99 } , // 71-75
{ "part" : 16 , "epart" : 96 , "etotal" : 99 } , // 76-80
{ "part" : 17 , "epart" : 97 , "etotal" : 100 } , // 81-85
{ "part" : 18 , "epart" : 98 , "etotal" : 100 } , // 86-90
{ "part" : 19 , "epart" : 99 , "etotal" : 100 } , // 81-95
{ "part" : 20 , "epart" : 100 , "etotal" : 100 } // 96-00
] ;
const levelDown = [ { "level" : - 11 , "score" : 1 , "part" : 0 , "epart" : 2 , "etotal" : 90 } ,
{ "level" : - 12 , "score" : 1 , "part" : 0 , "epart" : 2 , "etotal" : 70 } ,
{ "level" : - 13 , "score" : 1 , "part" : 0 , "epart" : 2 , "etotal" : 50 } ,
{ "level" : - 14 , "score" : 1 , "part" : 0 , "epart" : 2 , "etotal" : 30 } ,
{ "level" : - 15 , "score" : 1 , "part" : 0 , "epart" : 2 , "etotal" : 10 } ,
2020-05-27 23:47:49 +02:00
{ "level" : - 16 , "score" : 1 , "part" : 0 , "epart" : 2 , "etotal" : 2 }
2020-05-24 20:19:57 +02:00
] ;
2020-05-27 23:47:49 +02:00
const fatigueMatrix = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 , // Dummy filler for the array.
[ 2 , 3 , 3 , 2 , 3 , 3 , 2 , 3 , 3 , 2 , 3 , 3 ] ,
[ 2 , 3 , 3 , 3 , 3 , 3 , 2 , 3 , 3 , 3 , 3 , 3 ] ,
[ 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 ] ,
[ 3 , 3 , 3 , 3 , 3 , 4 , 3 , 3 , 3 , 3 , 3 , 4 ] ,
[ 3 , 3 , 4 , 3 , 3 , 4 , 3 , 3 , 4 , 3 , 3 , 4 ] ,
[ 3 , 3 , 4 , 3 , 4 , 4 , 3 , 3 , 4 , 3 , 4 , 4 ] ,
[ 3 , 4 , 4 , 3 , 4 , 4 , 3 , 4 , 4 , 3 , 4 , 4 ] ,
[ 3 , 4 , 4 , 4 , 4 , 4 , 3 , 4 , 4 , 4 , 4 , 4 ] ,
[ 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 ] ,
[ 4 , 4 , 4 , 4 , 4 , 5 , 4 , 4 , 4 , 4 , 4 , 5 ] ,
[ 4 , 4 , 5 , 4 , 4 , 5 , 4 , 4 , 5 , 4 , 4 , 5 ] ,
[ 4 , 4 , 5 , 4 , 5 , 5 , 4 , 4 , 5 , 4 , 5 , 5 ] ,
[ 4 , 5 , 5 , 4 , 5 , 5 , 4 , 5 , 5 , 4 , 5 , 5 ] ,
[ 4 , 5 , 5 , 5 , 5 , 5 , 4 , 5 , 5 , 5 , 5 , 5 ] ,
[ 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 , 5 ] ] ;
const fatigueMalus = [ 0 , 0 , 0 , - 1 , - 1 , - 1 , - 2 , - 3 , - 4 , - 5 , - 6 , - 7 ] ; // Provides the malus for each segment of fatigue
2020-05-28 23:36:09 +02:00
const fatigueLineSize = [ 3 , 6 , 7 , 8 , 9 , 10 , 11 , 12 ] ;
const fatigueLineMalus = [ 0 , - 1 , - 2 , - 3 , - 4 , - 5 , - 6 , - 7 ] ;
2020-05-31 23:06:25 +02:00
const fatigueMarche = { "aise" : { "4" : 1 , "6" : 2 , "8" : 3 , "10" : 4 , "12" : 6 } ,
"malaise" : { "4" : 2 , "6" : 3 , "8" : 4 , "10" : 6 } ,
"difficile" : { "4" : 3 , "6" : 4 , "8" : 6 } ,
"tresdifficile" : { "4" : 4 , "6" : 6 } }
2020-07-06 09:03:21 +02:00
/* -------------------------------------------- */
const TMRMapping = { A1 : { type : "cite" , label : "Cité VIDE" } , B1 : { type : "plaines" , label : "Plaines d'ASSORH" } , C1 : { type : "necropole" , label : "Nécropole de KROAK" } , D1 : { type : "fleuve" , label : "Fleuve de l'Oubli" } , E1 : { type : "monts" , label : "Monts de KANAI" } ,
F1 : { type : "cite" , label : "Cité GLAUQUE" } , G1 : { type : "desolation" , label : "Désolation de JAMAIS" } , H1 : { type : "lac" , label : "Lac d'ANTI-CALME" } , I1 : { type : "plaines" , label : "Plaines GRISES" } , J1 : { type : "monts" , label : "Monts FAINEANTS" } ,
2020-07-14 22:19:29 +02:00
K1 : { type : "cite" , label : "Cité d'ONKAUS" } , L1 : { type : "fleuve" , label : "Fleuve de l'Oubli" } , M1 : { type : "cite" , label : "Cité JALOUSE" } ,
A2 : { type : "desert" , label : "Désert de MIEUX" } , B2 : { type : "collines" , label : "Collines de DAWELL" } , C2 : { type : "monts" , label : "Monts GLIGNANTS" } , D2 : { type : "cite" , label : "Cité de FROST" } , E2 : { type : "plaines" , label : "Plaines de FIASK" } ,
F2 : { type : "lac" , label : "Lac de MISERE" } , G2 : { type : "marais" , label : "Marais NUISANTS" } , H2 : { type : "collines" , label : "Collines de PARTA" } , I2 : { type : "foret" , label : "Forêt FADE" } , J2 : { type : "desert" , label : "Désert de POLY" } ,
K2 : { type : "foret" , label : "Forêt TAMEE" } , L2 : { type : "fleuve" , label : "Fleuve de l'Oubli" } , M2 : { type : "necropole" , label : "Nécropole de LOGOS" }
2020-07-06 09:03:21 +02:00
}
2020-07-14 22:19:29 +02:00
const rencontresTable = [
{ name : "Messagers des Rêves" , data : { force : "2d4" , ignorer : true , derober : true , refoulement : 1 ,
cite : "01-25" , sanctuaire : "01-25" , plaines : "01-20" , pont : "01-20" , collines : "01-15" , forêt : "01-15" , monts : "01-10" , desert : "01-10" , fleuve : "01-05" ,
lac : "01-05" , marais : "01-02" , gouffre : "01-02" , necropole : "00-00" , desolation : "00-00" } } ,
{ name : "Passeur des Rêves" , data : { force : "2d4" , ignorer : true , derober : true , refoulement : 1 ,
cite : "26-50" , sanctuaire : "26-50" , plaines : "21-40" , pont : "21-40" , collines : "16-30" , forêt : "16-30" , monts : "11-20" , desert : "11-20" , fleuve : "06-10" ,
lac : "06-10" , marais : "03-04" , gouffre : "03-04" , necropole : "00-00" , desolation : "00-00" } } ,
{ name : "Fleur des Rêves" , data : { force : "1d6" , ignorer : true , derober : true , refoulement : 1 ,
cite : "51-65" , sanctuaire : "51-65" , plaines : "41-55" , pont : "41-55" , collines : "31-42" , forêt : "31-42" , monts : "21-26" , desert : "21-26" , fleuve : "11-13" ,
lac : "11-13" , marais : "05-05" , gouffre : "05-05" , necropole : "00-00" , desolation : "00-00" } } ,
{ name : "Mangeur de Rêve" , data : { force : "1d6" , ignorer : false , derober : true , refoulement : 1 ,
cite : "66-70" , sanctuaire : "66-70" , plaines : "56-60" , pont : "56-60" , collines : "43-54" , forêt : "43-54" , monts : "27-44" , desert : "27-44" , fleuve : "14-37" ,
lac : "14-37" , marais : "06-29" , gouffre : "06-29" , necropole : "01-20" , desolation : "01-20" } } ,
{ name : "Changeur de Rêve" , data : { force : "2d6" , ignorer : false , derober : true , refoulement : 1 ,
cite : "71-80" , sanctuaire : "71-80" , plaines : "61-75" , pont : "61-75" , collines : "55-69" , forêt : "55-69" , monts : "45-59" , desert : "45-59" , fleuve : "38-49" ,
lac : "38-49" , marais : "30-39" , gouffre : "30-39" , necropole : "21-30" , desolation : "21-30" } } ,
{ name : "Briseur de Rêve" , data : { force : "2d6" , ignorer : false , derober : true , refoulement : 1 ,
cite : "81-85" , sanctuaire : "81-85" , plaines : "76-82" , pont : "76-82" , collines : "70-82" , forêt : "70-82" , monts : "60-75" , desert : "60-75" , fleuve : "50-65" ,
lac : "50-65" , marais : "40-60" , gouffre : "40-60" , necropole : "31-50" , desolation : "31-50" } } ,
{ name : "Reflet d'ancien Rêve" , data : { force : "2d6" , ignorer : false , derober : true , refoulement : 1 ,
cite : "86-90" , sanctuaire : "86-90" , plaines : "83-88" , pont : "83-88" , collines : "83-88" , forêt : "83-88" , monts : "76-85" , desert : "76-85" , fleuve : "66-79" ,
lac : "66-79" , marais : "61-75" , gouffre : "61-75" , necropole : "51-65" , desolation : "51-65" } } ,
{ name : "Tourbillon blanc" , data : { force : "2d6" , ignorer : false , derober : true , refoulement : 1 ,
cite : "91-94" , sanctuaire : "91-94" , plaines : "89-93" , pont : "89-93" , collines : "89-93" , forêt : "89-93" , monts : "86-92" , desert : "86-92" , fleuve : "80-89" ,
lac : "80-89" , marais : "76-86" , gouffre : "76-86" , necropole : "66-80" , desolation : "66-80" } } ,
{ name : "Tourbillon noir" , data : { force : "2d8" , ignorer : false , derober : true , refoulement : 1 ,
cite : "95-97" , sanctuaire : "95-97" , plaines : "94-97" , pont : "94-97" , collines : "94-97" , forêt : "94-97" , monts : "93-97" , desert : "93-97" , fleuve : "90-97" ,
lac : "90-97" , marais : "87-97" , gouffre : "90-97" , necropole : "81-97" , desolation : "81-97" } } ,
{ name : "Rêve de Dragon" , data : { force : "1d7" , ignorer : false , derober : true , refoulement : 2 ,
cite : "98-00" , sanctuaire : "98-00" , plaines : "98-00" , pont : "98-00" , collines : "98-00" , forêt : "98-00" , monts : "98-00" , desert : "98-00" , fleuve : "98-00" ,
lac : "98-00" , marais : "98-00" , gouffre : "98-00" , necropole : "98-00" , desolation : "98-00" } }
]
2020-07-06 09:03:21 +02:00
/* -------------------------------------------- */
2020-05-22 22:37:02 +02:00
export class RdDUtility {
2020-05-24 20:19:57 +02:00
/* -------------------------------------------- */
static async preloadHandlebarsTemplates ( ) {
const templatePaths = [
//Character Sheets
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html' ,
//Items
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html' ,
2020-06-07 23:16:29 +02:00
'systems/foundryvtt-reve-de-dragon/templates/item-arme-sheet.html' ,
2020-06-23 23:34:12 +02:00
'systems/foundryvtt-reve-de-dragon/templates/item-armure-sheet.html' ,
2020-06-25 23:18:14 +02:00
'systems/foundryvtt-reve-de-dragon/templates/item-objet-sheet.html' ,
'systems/foundryvtt-reve-de-dragon/templates/item-conteneur-sheet.html' ,
2020-06-26 15:47:44 +02:00
'systems/foundryvtt-reve-de-dragon/templates/item-sort-sheet.html' ,
2020-06-29 23:21:15 +02:00
'systems/foundryvtt-reve-de-dragon/templates/item-herbe-sheet.html' ,
'systems/foundryvtt-reve-de-dragon/templates/item-ingredient-sheet.html' ,
'systems/foundryvtt-reve-de-dragon/templates/item-livre-sheet.html' ,
'systems/foundryvtt-reve-de-dragon/templates/item-tache-sheet.html' ,
'systems/foundryvtt-reve-de-dragon/templates/item-potion-sheet.html' ,
2020-07-14 22:19:29 +02:00
'systems/foundryvtt-reve-de-dragon/templates/item-rentontresTMR-sheet.html' ,
2020-05-24 20:19:57 +02:00
'systems/foundryvtt-reve-de-dragon/templates/competence-categorie.html' ,
'systems/foundryvtt-reve-de-dragon/templates/competence-carac-defaut.html' ,
'systems/foundryvtt-reve-de-dragon/templates/competence-base.html' ,
2020-06-07 23:16:29 +02:00
'systems/foundryvtt-reve-de-dragon/templates/arme-competence.html' ,
2020-06-26 15:47:44 +02:00
'systems/foundryvtt-reve-de-dragon/templates/sort-draconic.html' ,
'systems/foundryvtt-reve-de-dragon/templates/sort-tmr.html' ,
2020-05-24 20:19:57 +02:00
// Dialogs
2020-06-12 22:46:04 +02:00
'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html' ,
2020-07-05 21:45:25 +02:00
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html' ,
'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html'
2020-05-24 20:19:57 +02:00
] ;
return loadTemplates ( templatePaths ) ;
}
/* -------------------------------------------- */
static buildResolutionTable ( ) {
let tableRes = [ ]
for ( var j = 0 ; j <= 21 ; j ++ ) {
let subtab = [ ] ;
for ( var i = - 10 ; i <= 22 ; i ++ ) {
var m = ( i + 10 ) * 0.5 ;
var v ;
if ( i == - 9 ) {
v = Math . floor ( j / 2 ) ;
} else if ( i == - 10 ) {
v = Math . floor ( j / 4 ) ;
} else {
if ( j % 2 == 0 ) {
var v = Math . ceil ( j * m ) ;
} else {
var v = Math . floor ( j * m ) ;
}
}
if ( v < 1 ) v = 1 ;
let specResults
if ( v > 100 )
2020-07-14 22:19:29 +02:00
specResults = { part : Math . ceil ( v / 5 ) , epart : 1000 , etotal : 1000 } ;
2020-05-24 20:19:57 +02:00
else
specResults = specialResults [ Math . ceil ( v / 5 ) ] ;
let tabIndex = i + 10 ;
2020-07-14 22:19:29 +02:00
subtab [ tabIndex ] = { niveau : i , score : v , part : specResults . part , epart : specResults . epart , etotal : specResults . etotal }
2020-05-24 20:19:57 +02:00
}
tableRes [ j ] = subtab ;
}
return tableRes ;
}
/* -------------------------------------------- */
static getLevelCategory ( )
{
return level _category ;
}
static getCaracArray ( )
{
return carac _array ;
}
static getBonusMalus ( )
{
return bonusmalus ;
}
/* -------------------------------------------- */
2020-05-27 21:09:37 +02:00
static _ _buildHTMLResolutionHead ( dataRow , minLevel = 0 , maxLevel = 32 ) {
2020-05-24 20:19:57 +02:00
let r = dataRow ;
var row = $ ( "<tr/>" ) ;
2020-05-27 21:09:37 +02:00
for ( var colIndex = minLevel ; colIndex <= maxLevel ; colIndex ++ ) {
let c = dataRow [ colIndex ] ;
2020-05-24 20:19:57 +02:00
let txt = ( c . niveau > 0 ) ? "+" + c . niveau : c . niveau ;
row . append ( $ ( "<th class='table-resolution-level'/>" ) . text ( txt ) ) ;
2020-05-27 21:09:37 +02:00
}
2020-05-24 20:19:57 +02:00
return row ;
}
/* -------------------------------------------- */
2020-05-27 21:09:37 +02:00
static _ _buildHTMLResolutionRow ( dataRow , minLevel = 0 , maxLevel = 32 , rowIndex , caracValue , levelValue ) {
2020-05-24 20:19:57 +02:00
let r = dataRow ;
var row = $ ( "<tr/>" ) ;
2020-05-27 21:09:37 +02:00
for ( var colIndex = minLevel ; colIndex <= maxLevel ; colIndex ++ ) {
let c = dataRow [ colIndex ] ;
if ( rowIndex == caracValue && levelValue + 10 == colIndex ) {
row . append ( $ ( "<td class='table-resolution-target'/>" ) . text ( c . score ) ) ;
} else {
if ( colIndex == 2 )
row . append ( $ ( "<td class='table-resolution-carac'/>" ) . text ( c . score ) ) ;
else
row . append ( $ ( "<td/>" ) . text ( c . score ) ) ;
}
}
2020-05-24 20:19:57 +02:00
return row ;
}
/* -------------------------------------------- */
2020-05-27 21:09:37 +02:00
static makeHTMLResolutionTable ( container , minCarac = 1 , maxCarac = 21 , minLevel = - 10 , maxLevel = 22 , caracValue , levelValue ) {
2020-05-24 20:19:57 +02:00
minCarac = ( minCarac < 1 ) ? 1 : minCarac ;
maxCarac = ( maxCarac > 21 ) ? 21 : maxCarac ;
let data = CONFIG . RDD . resolutionTable ;
var table = $ ( "<table/>" ) . addClass ( 'table-resolution' ) ;
// Build first row of levels
2020-05-27 21:09:37 +02:00
minLevel = ( minLevel < - 10 ) ? 0 : minLevel + 10 ;
maxLevel = ( maxLevel > 22 ) ? 32 : maxLevel + 10 ;
let row = this . _ _buildHTMLResolutionHead ( data [ 0 ] , minLevel , maxLevel ) ;
2020-05-24 20:19:57 +02:00
table . append ( row ) ;
// Then the rest...
for ( var rowIndex = minCarac ; rowIndex <= maxCarac ; rowIndex ++ ) {
2020-05-27 21:09:37 +02:00
let row = this . _ _buildHTMLResolutionRow ( data [ rowIndex ] , minLevel , maxLevel , rowIndex , caracValue , levelValue ) ;
2020-05-24 20:19:57 +02:00
table . append ( row ) ;
}
return container . append ( table ) ;
}
/* -------------------------------------------- */
static getResolutionField ( caracValue , levelValue )
{
if ( levelValue < - 16 ) {
return { "score" : 0 , "part" : 0 , "epart" : 1 , "etotal" : 1 } ;
} if ( levelValue < - 10 ) {
return levelDown . find ( levelData => levelData . level == levelValue ) ;
}
return CONFIG . RDD . resolutionTable [ caracValue ] [ levelValue + 10 ] ;
}
/* -------------------------------------------- */
static computeCarac ( data )
{
let fmax = parseInt ( data . carac . taille . value ) + 4 ;
if ( data . carac . force . value > fmax )
data . carac . force . value = fmax ;
data . carac . derobee . value = Math . floor ( parseInt ( ( ( 21 - data . carac . taille . value ) ) + parseInt ( data . carac . agilite . value ) ) / 2 ) ;
let bonusDomKey = Math . floor ( ( parseInt ( data . carac . force . value ) + parseInt ( data . carac . taille . value ) ) / 2 ) ;
data . attributs . plusdom . value = 2
if ( bonusDomKey < 8 )
data . attributs . plusdom . value = - 1 ;
else if ( bonusDomKey < 12 )
data . attributs . plusdom . value = 0 ;
else if ( bonusDomKey < 14 )
data . attributs . plusdom . value = 1 ;
2020-05-27 21:57:00 +02:00
2020-05-24 20:19:57 +02:00
data . attributs . encombrement . value = ( parseInt ( data . carac . force . value ) + parseInt ( data . carac . taille . value ) ) / 2 ;
data . carac . melee . value = Math . floor ( ( parseInt ( data . carac . force . value ) + parseInt ( data . carac . agilite . value ) ) / 2 ) ;
data . carac . tir . value = Math . floor ( ( parseInt ( data . carac . vue . value ) + parseInt ( data . carac . dexterite . value ) ) / 2 ) ;
data . carac . lancer . value = Math . floor ( ( parseInt ( data . carac . tir . value ) + parseInt ( data . carac . force . value ) ) / 2 ) ;
data . sante . vie . max = Math . ceil ( parseInt ( data . carac . taille . value ) + parseInt ( data . carac . constitution . value ) / 2 ) ;
2020-06-07 23:16:29 +02:00
if ( data . sante . vie . value > data . sante . vie . max )
data . sante . vie . value = data . sante . vie . max ;
2020-05-24 20:19:57 +02:00
let endurance = Math . max ( parseInt ( data . carac . taille . value ) + parseInt ( data . carac . constitution . value ) , parseInt ( data . sante . vie . max ) + parseInt ( data . carac . volonte . value ) ) ;
data . sante . endurance . max = endurance ;
2020-06-07 23:16:29 +02:00
if ( data . sante . endurance . value > endurance )
data . sante . endurance . value = endurance ;
2020-05-29 00:43:16 +02:00
data . sante . fatigue . max = endurance * 2 ;
2020-06-07 23:16:29 +02:00
if ( data . sante . fatigue . value > data . sante . fatigue . max )
data . sante . fatigue . value = data . sante . fatigue . max ;
2020-05-24 20:19:57 +02:00
data . attributs . sconst . value = 5 ; // Max !
if ( data . carac . constitution . value < 9 )
data . attributs . sconst . value = 2 ;
else if ( data . carac . constitution . value < 12 )
data . attributs . sconst . value = 3 ;
else if ( data . carac . constitution . value < 15 )
data . attributs . sconst . value = 4 ;
data . attributs . sust . value = 4 ; // Max !
2020-05-27 21:57:00 +02:00
if ( data . carac . taille . value < 10 )
data . attributs . sust . value = 2 ;
else if ( data . carac . taille . value < 14 )
data . attributs . sust . value = 3 ;
2020-05-29 00:43:16 +02:00
//Compteurs
2020-06-07 23:16:29 +02:00
//data.compteurs.reve.value = data.carac.reve.value;
2020-05-29 00:43:16 +02:00
data . compteurs . reve . max = data . carac . reve . value ;
2020-06-07 23:16:29 +02:00
//data.compteurs.chance.value = data.carac.chance.value;
2020-05-29 00:43:16 +02:00
data . compteurs . chance . max = data . carac . chance . value ;
2020-05-24 20:19:57 +02:00
}
2020-05-27 23:47:49 +02:00
/* -------------------------------------------- */
2020-05-29 00:43:16 +02:00
// Build the nice (?) html table used to manage fatigue.
// max should be the endurance max value
static makeHTMLfatigueMatrix ( value , max )
2020-05-27 23:47:49 +02:00
{
max = ( max < 16 ) ? 16 : max ;
max = ( max > 30 ) ? 30 : max ;
2020-05-29 00:43:16 +02:00
value = ( value > max * 2 ) ? max * 2 : value ;
2020-05-28 23:36:09 +02:00
value = ( value < 0 ) ? 0 : value ;
2020-05-27 23:47:49 +02:00
let fatigueTab = fatigueMatrix [ max ] ;
2020-05-29 00:43:16 +02:00
2020-05-27 23:47:49 +02:00
let table = $ ( "<table/>" ) . addClass ( 'table-fatigue' ) ;
let segmentIdx = 0 ;
2020-05-28 23:36:09 +02:00
let fatigueCount = 0 ;
2020-05-27 23:47:49 +02:00
for ( var line = 0 ; line < fatigueLineSize . length ; line ++ ) {
let row = $ ( "<tr/>" ) ;
let segmentsPerLine = fatigueLineSize [ line ] ;
2020-05-28 23:36:09 +02:00
row . append ( "<td class='fatigue-malus'>" + fatigueLineMalus [ line ] + "</td>" ) ;
2020-05-27 23:47:49 +02:00
while ( segmentIdx < segmentsPerLine ) {
let freeSize = fatigueTab [ segmentIdx ] ;
for ( let col = 0 ; col < 5 ; col ++ ) {
2020-05-28 23:36:09 +02:00
if ( col < freeSize ) {
if ( fatigueCount < value )
row . append ( "<td class='fatigue-used'/>" ) ;
else
row . append ( "<td class='fatigue-free'/>" ) ;
fatigueCount ++ ;
} else {
2020-05-27 23:47:49 +02:00
row . append ( "<td class='fatigue-none'/>" ) ;
2020-05-28 23:36:09 +02:00
}
2020-05-27 23:47:49 +02:00
}
row . append ( "<td class='fatigue-separator'/>" ) ;
segmentIdx = segmentIdx + 1 ;
}
table . append ( row ) ;
}
2020-05-28 23:36:09 +02:00
//console.log("fatigue", table);
2020-05-27 23:47:49 +02:00
return table ;
}
2020-05-31 23:06:25 +02:00
/* -------------------------------------------- */
static getLocalisation ( )
{
let myroll = new Roll ( "d20" ) ;
myroll . roll ( ) ;
let result = myroll . total ;
2020-06-07 23:16:29 +02:00
let txt = ""
if ( result <= 3 ) txt = "Jambe, genou, pied, jarret" ;
else if ( result <= 7 ) txt = "Hanche, cuisse, fesse" ;
else if ( result <= 9 ) txt = "Ventre, reins" ;
else if ( result <= 12 ) txt = "Poitrine, dos" ;
else if ( result <= 14 ) txt = "Avant-bras, main, coude" ;
else if ( result <= 18 ) txt = "Epaule, bras, omoplate" ;
else if ( result == 19 ) txt = "Tête autre" ;
else if ( result == 20 ) txt = "Tête visage" ;
return { result : result , label : txt } ;
2020-05-31 23:06:25 +02:00
}
2020-06-07 23:16:29 +02:00
/* -------------------------------------------- */
static computeBlessuresSante ( degats )
{
console . log ( "Degats !!" , degats ) ;
let result = { "vie" : 0 ,
"endurance" : 0 ,
"legeres" : 0 ,
"graves" : 0 ,
"critiques" : 0
} ;
if ( degats < 11 ) {
result . type = "contusion" ;
let myroll = new Roll ( "1d4" ) ;
myroll . roll ( ) ;
result . endurance = - myroll . result ;
} else if ( degats < 16 ) {
result . type = "blessure légère" ;
let myroll = new Roll ( "1d6" ) ;
myroll . roll ( ) ;
result . endurance = - myroll . result ;
result . legeres = 1
} else if ( degats < 20 ) {
result . type = "blessure grave" ;
let myroll = new Roll ( "2d6" ) ;
myroll . roll ( ) ;
result . endurance = - myroll . result ;
result . vie = - 2 ;
result . graves = 1 ;
} else {
result . type = "critique" ;
result . endurance = - 100 ; // Force endurance to 0
result . vie = - 4 - ( degats - 20 ) ;
result . critiques = 1 ;
}
return result ;
}
2020-05-29 00:43:16 +02:00
/* -------------------------------------------- */
2020-06-12 22:46:04 +02:00
static computeNbBlessures ( blessures , name )
{
let bless = blessures [ name ] ;
console . log ( blessures , name , bless ) ;
let nbBlessures = 0 ;
for ( let k = 0 ; k < bless . liste . length ; k ++ ) {
if ( bless . liste [ k ] . active ) nbBlessures ++ ;
}
return nbBlessures ;
}
/* -------------------------------------------- */
2020-05-29 00:43:16 +02:00
static currentFatigueMalus ( value , max )
{
max = ( max < 16 ) ? 16 : max ;
max = ( max > 30 ) ? 30 : max ;
value = ( value > max * 2 ) ? max * 2 : value ;
value = ( value < 0 ) ? 0 : value ;
let fatigueTab = fatigueMatrix [ max ] ;
let fatigueRem = value ;
for ( let idx = 0 ; idx < fatigueTab . length ; idx ++ ) {
fatigueRem -= fatigueTab [ idx ] ;
if ( fatigueRem <= 0 ) {
return fatigueMalus [ idx ] ;
}
}
return - 7 ; // This is the max !
}
2020-05-24 20:19:57 +02:00
/* -------------------------------------------- */
2020-05-22 22:37:02 +02:00
static findCompetence ( compList , compName )
{
for ( const item of compList ) {
if ( item . name == compName ) {
2020-06-11 00:29:32 +02:00
//console.log("Found item !", item);
2020-05-22 22:37:02 +02:00
return item ;
}
}
}
2020-06-12 11:47:41 +02:00
/* -------------------------------------------- */
static getArmeCategory ( arme )
{
let compname = arme . data . competence . toLowerCase ( ) ;
if ( compname . match ( "hache" ) ) return "hache" ;
if ( compname . match ( "hast" ) ) return "hast" ;
if ( compname . match ( "lance" ) ) return "lance" ;
if ( compname . match ( "bouclier" ) ) return "bouclier" ;
if ( compname . match ( "masse" ) ) return "masse" ;
if ( compname . match ( "fléau" ) ) return "fleau" ;
if ( compname . match ( "epée" ) ) {
let armename = arme . name . toLowerCase ( ) ;
if ( armename == "dague" || armename . match ( "gnome" ) )
return "epee_courte" ;
}
return "epee_longue" ;
}
2020-06-10 08:23:58 +02:00
/* -------------------------------------------- */
static isArmeMelee ( compName )
{
let comp = compName . toLowerCase ( ) ;
if ( comp . match ( "epée" ) || comp . match ( "hache" ) || comp . match ( "fleau" ) || comp . match ( "mass" ) || comp . match ( "lance" ) || comp . match ( "hast" ) || comp == "dague" || comp == "bouclier" )
return true ;
return false ;
}
/* -------------------------------------------- */
static buildDefenseChatCard ( attacker , target , rollData )
{
console . log ( "Target" , target ) ;
let defenseMsg = { title : "Défense en combat" ,
content : "Action de défense en combat!<br><span class='chat-card-button-area'>" +
"<a class='chat-card-button' id='encaisser-button' data-attackerid='" + attacker . data . _id + "' data-defenderid='" + target . actor . data . _id + "'>Encaisser !</a></span>" ,
whisper : ChatMessage . getWhisperRecipients ( target . actor . data . name ) } ;
if ( rollData . competence . data . categorie == "melee" ) { // Melee attack
let defenderArmes = [ ] ;
for ( const arme of target . actor . data . items ) {
2020-06-11 00:29:32 +02:00
if ( arme . type == "arme" && this . isArmeMelee ( arme . data . competence ) ) {
2020-06-10 08:23:58 +02:00
defenderArmes . push ( arme ) ;
2020-06-11 00:29:32 +02:00
defenseMsg . content += "<br><a class='chat-card-button' id='parer-button' data-attackerid='" + attacker . data . _id + "' data-defenderid='" + target . actor . data . _id + "' data-armeid='" + arme . _id + "'>Parer avec " + arme . name + "</a></span>" ;
2020-06-10 08:23:58 +02:00
}
}
2020-06-17 20:31:43 +02:00
defenseMsg . content += "<br><a class='chat-card-button' id='esquiver-button' data-attackerid='" + attacker . data . _id + "' data-defenderid='" + target . actor . data . _id + "'>Esquiver</a></span>" ;
2020-06-10 08:23:58 +02:00
}
2020-06-17 20:31:43 +02:00
if ( rollData . competence . data . categorie == "tir" ) {
for ( const arme of target . actor . data . items ) { // Bouclier for parry
if ( arme . type == "arme" && arme . name . toLowerCase . match ( "bouclier" ) ) {
defenderArmes . push ( arme ) ;
defenseMsg . content += "<br><a class='chat-card-button' id='parer-button' data-attackerid='" + attacker . data . _id + "' data-defenderid='" + target . actor . data . _id + "' data-armeid='" + arme . _id + "'>Parer avec " + arme . name + "</a></span>" ;
}
}
}
if ( rollData . competence . data . categorie == "lancer" ) {
for ( const arme of target . actor . data . items ) { // Bouclier for parry Dodge/Esquive
if ( arme . type == "arme" && arme . name . toLowerCase . match ( "bouclier" ) ) {
defenderArmes . push ( arme ) ;
defenseMsg . content += "<br><a class='chat-card-button' id='parer-button' data-attackerid='" + attacker . data . _id + "' data-defenderid='" + target . actor . data . _id + "' data-armeid='" + arme . _id + "'>Parer avec " + arme . name + "</a></span>" ;
}
}
defenseMsg . content += "<br><a class='chat-card-button' id='esquiver-button' data-attackerid='" + attacker . data . _id + "' data-defenderid='" + target . actor . data . _id + "'>Esquiver</a></span>" ;
}
2020-06-10 08:23:58 +02:00
return defenseMsg ;
}
2020-06-17 20:31:43 +02:00
/* -------------------------------------------- */
2020-06-22 10:18:03 +02:00
static performSocketMesssage ( sockmsg )
2020-06-17 20:31:43 +02:00
{
2020-06-22 10:18:03 +02:00
console . log ( ">>>>> MSG RECV" , sockmsg ) ;
if ( sockmsg . msg == "msg_encaisser" ) {
if ( game . user . isGM ) {
console . log ( "Encaisser ici !!!" ) ;
defenderActor = game . actors . get ( sockmsg . data . defenderid ) ;
defenderActor . encaisserDommages ( sockmsg . data ) ;
}
}
2020-06-17 20:31:43 +02:00
}
2020-06-07 23:16:29 +02:00
/* -------------------------------------------- */
static async chatListeners ( html )
{
html . on ( "click" , '#encaisser-button' , event => {
event . preventDefault ( ) ;
2020-06-17 20:31:43 +02:00
let attackerActor = game . actors . get ( event . currentTarget . attributes [ 'data-attackerid' ] . value ) ;
2020-06-11 00:29:32 +02:00
let rollData = attackerActor . getFlag ( "foundryvtt-reve-de-dragon" , "rollData" ) ;
2020-06-17 20:31:43 +02:00
rollData . attackerid = event . currentTarget . attributes [ 'data-attackerid' ] . value ;
rollData . defenderid = event . currentTarget . attributes [ 'data-defenderid' ] . value ;
2020-06-22 10:18:03 +02:00
let defenderActor = game . actors . get ( rollData . defenderid ) ;
if ( game . user . isGM ) { // Current user is the GM -> direct access
console . log ( "Encaissement direct" , rollData ) ;
defenderActor . encaisserDommages ( rollData ) ;
} else { // Emit message for GM
game . socket . emit ( "system.foundryvtt-reve-de-dragon" , {
msg : "msg_encaisser" ,
data : rollData
} ) ;
}
2020-06-07 23:16:29 +02:00
} ) ;
2020-06-10 08:23:58 +02:00
html . on ( "click" , '#parer-button' , event => {
event . preventDefault ( ) ;
let attackerActor = game . actors . get ( event . currentTarget . attributes [ 'data-attackerid' ] . value ) ;
let defenderActor = game . actors . get ( event . currentTarget . attributes [ 'data-defenderid' ] . value ) ;
let armeId = event . currentTarget . attributes [ 'data-armeid' ] . value ;
2020-06-11 00:29:32 +02:00
let rollData = attackerActor . getFlag ( "foundryvtt-reve-de-dragon" , "rollData" ) ;
defenderActor . parerAttaque ( rollData , armeId ) ;
2020-06-10 08:23:58 +02:00
} ) ;
2020-06-07 23:16:29 +02:00
}
2020-07-06 09:03:21 +02:00
/* -------------------------------------------- */
static convertToTMRCoord ( x , y )
{
y = y + 1
let letterX = String . fromCharCode ( 65 + x ) ;
return letterX + y
}
/* -------------------------------------------- */
static convertToCellCoord ( coordTMR )
{
let x = coordTMR . charCodeAt ( 0 ) - 65 ;
let y = coordTMR . substr ( 1 ) - 1 ;
return { x : x , y : y }
}
/* -------------------------------------------- */
static getTMRDescription ( coordTMR )
{
return TMRMapping [ coordTMR ] ;
}
2020-07-14 22:19:29 +02:00
/* -------------------------------------------- */
static rencontreTMRRoll ( coordTMR , cellDescr )
{
let myroll = new Roll ( "d100" ) ;
myroll . roll ( ) ;
let val = myroll . total ;
//console.log("Rencontre !!!!", val, coordTMR, cellDescr);
for ( let renc of rencontresTable ) {
let scoreDef = renc . data [ cellDescr . type ] ;
let min = scoreDef . substr ( 0 , 2 ) ;
let max = scoreDef . substr ( 3 , 2 ) ;
console . log ( val , scoreDef , min , max ) ;
if ( val >= min && val <= max ) {
return renc ;
}
}
}
2020-05-22 22:37:02 +02:00
}