2021-01-02 04:28:43 +01:00
import { ChatUtility } from "./chat-utility.js" ;
2020-11-15 02:07:41 +01:00
import { Misc } from "./misc.js" ;
2020-11-16 03:54:43 +01:00
import { RdDDice } from "./rdd-dice.js" ;
2021-10-09 22:02:13 +02:00
import { ReglesOptionelles } from "./regles-optionelles.js" ;
2020-11-11 22:39:36 +01:00
2020-11-12 16:35:51 +01:00
/ * *
* difficultés au delà de - 10
* /
const levelDown = [
2021-10-30 02:20:16 +02:00
{ level : - 11 , score : 1 , norm : 1 , sign : 0 , part : 0 , epart : 2 , etotal : 90 } ,
{ level : - 12 , score : 1 , norm : 1 , sign : 0 , part : 0 , epart : 2 , etotal : 70 } ,
{ level : - 13 , score : 1 , norm : 1 , sign : 0 , part : 0 , epart : 2 , etotal : 50 } ,
{ level : - 14 , score : 1 , norm : 1 , sign : 0 , part : 0 , epart : 2 , etotal : 30 } ,
{ level : - 15 , score : 1 , norm : 1 , sign : 0 , part : 0 , epart : 2 , etotal : 10 } ,
{ level : - 16 , score : 1 , norm : 1 , sign : 0 , part : 0 , epart : 0 , etotal : 2 }
2020-11-12 16:35:51 +01:00
] ;
2021-10-30 02:20:16 +02:00
const levelImpossible = { score : 0 , norm : 0 , sign : 0 , part : 0 , epart : 0 , etotal : 1 } ;
2020-11-12 16:35:51 +01:00
const reussites = [
2020-12-12 21:58:44 +01:00
{ code : "etotal" , isPart : false , isSign : false , isSuccess : false , isEchec : true , isEPart : true , isETotal : true , ptTache : - 4 , ptQualite : - 6 , quality : "Echec total" , condition : ( target , roll ) => roll >= target . etotal && roll <= 100 } ,
{ code : "epart" , isPart : false , isSign : false , isSuccess : false , isEchec : true , isEPart : true , isETotal : false , ptTache : - 2 , ptQualite : - 4 , quality : "Echec particulier" , condition : ( target , roll ) => ( roll >= target . epart && roll < target . etotal ) } ,
2021-01-02 19:25:03 +01:00
{ code : "echec" , isPart : false , isSign : false , isSuccess : false , isEchec : true , isEPart : false , isETotal : false , ptTache : 0 , ptQualite : - 2 , quality : "Echec normal" , condition : ( target , roll ) => ( roll > target . norm && roll < target . etotal ) } ,
{ code : "norm" , isPart : false , isSign : false , isSuccess : true , isEchec : false , isEPart : false , isETotal : false , ptTache : 1 , ptQualite : 0 , quality : "Réussite normale" , condition : ( target , roll ) => ( roll > target . sign && roll <= target . norm ) } ,
2020-12-12 21:58:44 +01:00
{ code : "sign" , isPart : false , isSign : true , isSuccess : true , isEchec : false , isEPart : false , isETotal : false , ptTache : 2 , ptQualite : 1 , quality : "Réussite significative" , condition : ( target , roll ) => ( roll > target . part && roll <= target . sign ) } ,
{ code : "part" , isPart : true , isSign : true , isSuccess : true , isEchec : false , isEPart : false , isETotal : false , ptTache : 3 , ptQualite : 2 , quality : "Réussite Particulière!" , condition : ( target , roll ) => ( roll > 0 && roll <= target . part ) } ,
{ code : "error" , isPart : false , isSign : false , isSuccess : false , isEchec : true , isEPart : true , isETotal : true , ptTache : 0 , ptQualite : 0 , quality : "Jet de dés invalide" , condition : ( target , roll ) => ( roll <= 0 || roll > 100 ) }
2020-11-12 16:35:51 +01:00
] ;
2021-04-03 23:59:29 +02:00
const reussiteInsuffisante = { code : "notSign" , isPart : false , isSign : false , isSuccess : false , isEchec : true , isEPart : false , isETotal : false , ptTache : 0 , ptQualite : - 2 , quality : "Réussite insuffisante" , condition : ( target , roll ) => false }
2020-12-05 00:04:40 +01:00
/* -------------------------------------------- */
2020-12-06 23:31:23 +01:00
const caracMaximumResolution = 60 ;
2020-12-05 00:04:40 +01:00
/* -------------------------------------------- */
2020-11-11 22:39:36 +01:00
export class RdDResolutionTable {
static resolutionTable = this . build ( )
/* -------------------------------------------- */
static build ( ) {
let table = [ ]
2020-12-06 23:31:23 +01:00
for ( var caracValue = 0 ; caracValue <= caracMaximumResolution ; caracValue ++ ) {
2020-11-25 00:46:11 +01:00
table [ caracValue ] = this . _computeRow ( caracValue ) ;
2020-11-11 22:39:36 +01:00
}
return table ;
}
2020-11-15 16:38:45 +01:00
/* -------------------------------------------- */
2020-11-16 03:54:43 +01:00
static getResultat ( code ) {
2020-12-31 02:20:52 +01:00
let resultat = reussites . find ( r => code == r . code ) ;
2020-11-16 03:54:43 +01:00
if ( resultat == undefined ) {
2020-11-14 03:16:03 +01:00
resultat = reussites . find ( r => r . code == "error" ) ;
}
return resultat ;
}
2020-11-15 16:38:45 +01:00
2020-12-04 20:52:04 +01:00
/* -------------------------------------------- */
2020-11-16 03:54:43 +01:00
static explain ( rolled ) {
2020-12-06 19:31:11 +01:00
let message = "<br>Jet : <strong>" + rolled . roll + "</strong> sur " + rolled . score + "% " ;
2022-11-05 18:06:30 +01:00
if ( rolled . caracValue != undefined && rolled . finalLevel != undefined ) {
2021-01-13 03:42:13 +01:00
message += ( rolled . diviseurSignificative > 1 ? ` (1/ ${ rolled . diviseurSignificative } de ` : "(" )
2020-12-12 21:58:44 +01:00
+ rolled . caracValue + " à " + Misc . toSignedString ( rolled . finalLevel ) + ") " ;
2020-11-16 03:54:43 +01:00
}
2020-12-06 23:31:23 +01:00
message += '<strong>' + rolled . quality + '</strong>'
2020-11-16 03:54:43 +01:00
return message ;
2020-12-18 23:48:41 +01:00
}
2020-11-16 03:54:43 +01:00
2021-01-03 15:40:48 +01:00
/* -------------------------------------------- */
2021-01-05 18:43:13 +01:00
static async displayRollData ( rollData , actor = undefined , template = 'chat-resultat-general.html' ) {
2022-01-29 18:50:37 +01:00
return await ChatUtility . createChatWithRollMode ( actor ? . userName ? ? game . user . name , {
2021-01-09 19:36:19 +01:00
content : await RdDResolutionTable . buildRollDataHtml ( rollData , actor , template )
} ) ;
2020-12-31 02:08:58 +01:00
}
2021-01-05 18:43:13 +01:00
/* -------------------------------------------- */
static async buildRollDataHtml ( rollData , actor , template = 'chat-resultat-general.html' ) {
rollData . show = rollData . show || { } ;
return await renderTemplate ( ` systems/foundryvtt-reve-de-dragon/templates/ ${ template } ` , rollData ) ;
2020-11-12 16:35:51 +01:00
}
2020-12-04 20:52:04 +01:00
2020-11-15 16:38:45 +01:00
/* -------------------------------------------- */
2020-12-12 21:58:44 +01:00
static async rollData ( rollData ) {
2021-06-13 21:56:01 +02:00
rollData . rolled = await this . roll ( rollData . caracValue , rollData . finalLevel , rollData ) ;
2020-12-17 00:44:32 +01:00
return rollData ;
2020-12-06 19:29:10 +01:00
}
2020-12-08 23:07:41 +01:00
2020-12-04 20:52:04 +01:00
/* -------------------------------------------- */
2021-06-13 21:56:01 +02:00
static async roll ( caracValue , finalLevel , rollData = { } ) {
2020-11-25 00:46:11 +01:00
let chances = this . computeChances ( caracValue , finalLevel ) ;
2021-10-30 02:21:41 +02:00
this . _updateChancesWithBonus ( chances , rollData . bonus , finalLevel ) ;
2021-06-13 21:56:01 +02:00
this . _updateChancesFactor ( chances , rollData . diviseurSignificative ) ;
chances . showDice = rollData . showDice ;
chances . rollMode = rollData . rollMode ;
2020-12-12 21:58:44 +01:00
2021-06-28 20:19:02 +02:00
let rolled = await this . rollChances ( chances , rollData . diviseurSignificative , rollData . forceDiceResult ) ;
2020-11-25 00:46:11 +01:00
rolled . caracValue = caracValue ;
2020-11-16 03:54:43 +01:00
rolled . finalLevel = finalLevel ;
2021-06-13 21:56:01 +02:00
rolled . bonus = rollData . bonus ;
rolled . factorHtml = Misc . getFractionHtml ( rollData . diviseurSignificative ) ;
2021-10-09 22:02:13 +02:00
if ( ReglesOptionelles . isUsing ( "afficher-colonnes-reussite" ) ) {
rolled . niveauNecessaire = this . findNiveauNecessaire ( caracValue , rolled . roll ) ;
rolled . ajustementNecessaire = rolled . niveauNecessaire - finalLevel ;
}
2020-11-16 03:54:43 +01:00
return rolled ;
2020-11-15 16:38:45 +01:00
}
2020-11-12 16:35:51 +01:00
2021-05-28 09:12:18 +02:00
/* -------------------------------------------- */
static findNiveauNecessaire ( caracValue , rollValue ) {
for ( let cell of this . resolutionTable [ caracValue ] ) {
if ( rollValue <= cell . norm ) {
return cell . niveau ;
}
}
return 16 ; // Dummy default
}
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
2021-01-02 04:28:43 +01:00
static _updateChancesFactor ( chances , diviseur ) {
2021-02-25 02:03:45 +01:00
if ( chances . level > - 11 && diviseur && diviseur > 1 ) {
2021-01-07 00:32:22 +01:00
let newScore = Math . floor ( chances . score / diviseur ) ;
2022-11-05 18:06:30 +01:00
mergeObject ( chances , this . _computeCell ( undefined , newScore ) , { overwrite : true } ) ;
2020-12-12 21:58:44 +01:00
}
}
/* -------------------------------------------- */
2021-10-30 02:21:41 +02:00
static _updateChancesWithBonus ( chances , bonus , finalLevel ) {
if ( bonus && finalLevel > - 11 ) {
2021-01-22 14:35:14 +01:00
let newScore = Number ( chances . score ) + bonus ;
2022-11-05 18:06:30 +01:00
mergeObject ( chances , this . _computeCell ( undefined , newScore ) , { overwrite : true } ) ;
2020-12-12 21:58:44 +01:00
}
}
2021-02-12 12:50:17 +01:00
2021-05-28 09:12:18 +02:00
/* -------------------------------------------- */
2021-01-23 18:36:30 +01:00
static significativeRequise ( chances ) {
2021-01-09 19:33:19 +01:00
chances . roll = Math . floor ( chances . score / 2 ) ;
2021-01-07 00:32:22 +01:00
mergeObject ( chances , reussites . find ( x => x . code == 'sign' ) , { overwrite : true } ) ;
}
2020-12-12 21:58:44 +01:00
2021-05-28 09:12:18 +02:00
/* -------------------------------------------- */
2021-02-12 12:50:17 +01:00
static succesRequis ( chances ) {
chances . roll = chances . score ;
mergeObject ( chances , reussites . find ( x => x . code == 'norm' ) , { overwrite : true } ) ;
}
2020-11-15 16:38:45 +01:00
/* -------------------------------------------- */
2021-06-28 20:19:02 +02:00
static async rollChances ( chances , diviseur , forceDiceResult = - 1 ) {
2022-10-08 17:36:11 +02:00
chances . forceDiceResult = forceDiceResult <= 0 || forceDiceResult > 100 ? undefined : { total : forceDiceResult } ;
chances . roll = await RdDDice . rollTotal ( "1d100" , chances ) ;
2021-04-03 23:59:29 +02:00
mergeObject ( chances , this . computeReussite ( chances , chances . roll , diviseur ) , { overwrite : true } ) ;
2020-11-12 16:35:51 +01:00
return chances ;
}
2020-11-15 16:38:45 +01:00
/* -------------------------------------------- */
2020-11-25 00:46:11 +01:00
static computeChances ( caracValue , difficulte ) {
2020-11-12 16:35:51 +01:00
if ( difficulte < - 16 ) {
return duplicate ( levelImpossible ) ;
}
if ( difficulte < - 10 ) {
return duplicate ( levelDown . find ( levelData => levelData . level == difficulte ) ) ;
}
2021-01-02 14:10:43 +01:00
return duplicate ( RdDResolutionTable . resolutionTable [ caracValue ] [ difficulte + 10 ] ) ;
2020-11-12 16:35:51 +01:00
}
2021-01-04 22:03:00 +01:00
/* -------------------------------------------- */
2020-12-31 02:08:58 +01:00
static isAjustementAstrologique ( rollData ) {
2021-01-05 18:43:13 +01:00
if ( rollData . selectedCarac ? . label . toLowerCase ( ) . includes ( 'chance' ) ) {
2020-12-31 02:08:58 +01:00
return true ;
}
2022-09-07 09:01:23 +02:00
if ( rollData . selectedSort ? . system . isrituel ) {
2020-12-31 02:08:58 +01:00
return true ;
}
return false ;
}
2020-11-15 16:38:45 +01:00
/* -------------------------------------------- */
2020-12-12 21:58:44 +01:00
static isEchec ( rollData ) {
2020-12-15 02:20:24 +01:00
switch ( rollData . surprise ) {
case 'demi' : return ! rollData . rolled . isSign ;
case 'totale' : return true ;
}
return rollData . rolled . isEchec ;
2020-12-12 21:58:44 +01:00
}
2020-12-15 02:20:24 +01:00
2020-12-15 23:54:09 +01:00
/* -------------------------------------------- */
2020-12-12 21:58:44 +01:00
static isEchecTotal ( rollData ) {
2020-12-15 02:20:24 +01:00
if ( rollData . arme && rollData . surprise == 'demi' ) {
return rollData . rolled . isEchec ;
}
return rollData . rolled . isETotal ;
2020-12-12 21:58:44 +01:00
}
2020-12-18 23:48:41 +01:00
2020-12-15 23:54:09 +01:00
/* -------------------------------------------- */
2020-12-12 21:58:44 +01:00
static isParticuliere ( rollData ) {
2020-12-15 02:20:24 +01:00
if ( rollData . arme && rollData . surprise ) {
return false ;
}
return rollData . rolled . isPart ;
2020-12-12 21:58:44 +01:00
}
2020-12-15 02:20:24 +01:00
2020-12-15 23:54:09 +01:00
/* -------------------------------------------- */
2020-12-12 21:58:44 +01:00
static isReussite ( rollData ) {
2020-12-15 02:20:24 +01:00
switch ( rollData . surprise ) {
case 'demi' : return rollData . rolled . isSign ;
case 'totale' : return false ;
}
return rollData . rolled . isSuccess ;
2020-11-12 16:35:51 +01:00
}
/* -------------------------------------------- */
2021-04-03 23:59:29 +02:00
static computeReussite ( chances , roll , diviseur ) {
const reussite = reussites . find ( x => x . condition ( chances , roll ) ) ;
if ( diviseur > 1 && reussite . code == 'norm' ) {
return reussiteInsuffisante ;
}
return reussite ;
2020-11-12 16:35:51 +01:00
}
2020-11-16 23:28:18 +01:00
/* -------------------------------------------- */
2020-11-25 00:46:11 +01:00
static _computeRow ( caracValue ) {
2020-11-11 22:39:36 +01:00
let dataRow = [
2020-11-25 00:46:11 +01:00
this . _computeCell ( - 10 , Math . max ( Math . floor ( caracValue / 4 ) , 1 ) ) ,
this . _computeCell ( - 9 , Math . max ( Math . floor ( caracValue / 2 ) , 1 ) )
2020-11-11 22:39:36 +01:00
]
for ( var diff = - 8 ; diff <= 22 ; diff ++ ) {
2020-11-25 00:46:11 +01:00
dataRow [ diff + 10 ] = this . _computeCell ( diff , Math . max ( Math . floor ( caracValue * ( diff + 10 ) / 2 ) , 1 ) ) ;
2020-11-11 22:39:36 +01:00
}
return dataRow ;
}
2020-11-16 23:28:18 +01:00
/* -------------------------------------------- */
2020-11-12 16:35:51 +01:00
static _computeCell ( niveau , percentage ) {
2020-11-11 22:39:36 +01:00
return {
2020-11-12 16:35:51 +01:00
niveau : niveau ,
score : percentage ,
2021-01-02 19:25:03 +01:00
norm : Math . min ( 99 , percentage ) ,
2020-11-12 16:35:51 +01:00
sign : this . _reussiteSignificative ( percentage ) ,
part : this . _reussitePart ( percentage ) ,
epart : this . _echecParticulier ( percentage ) ,
etotal : this . _echecTotal ( percentage )
2021-01-02 19:25:03 +01:00
} ;
2020-11-11 22:39:36 +01:00
}
2020-11-16 23:28:18 +01:00
/* -------------------------------------------- */
2021-01-02 19:25:03 +01:00
static _reussiteSignificative ( percentage ) {
return Math . floor ( percentage / 2 ) ;
2020-11-11 22:39:36 +01:00
}
2020-11-16 23:28:18 +01:00
/* -------------------------------------------- */
2021-01-02 19:25:03 +01:00
static _reussitePart ( percentage ) {
return Math . ceil ( percentage / 5 ) ;
2020-11-11 22:39:36 +01:00
}
2020-11-16 23:28:18 +01:00
/* -------------------------------------------- */
2021-01-02 19:25:03 +01:00
static _echecParticulier ( percentage ) {
const epart = Math . ceil ( percentage / 5 ) + 80 ;
return epart >= 100 ? 101 : epart ;
2020-11-11 22:39:36 +01:00
}
2020-11-16 23:28:18 +01:00
/* -------------------------------------------- */
2021-01-02 19:25:03 +01:00
static _echecTotal ( percentage ) {
const etotal = Math . ceil ( percentage / 10 ) + 91 ;
return percentage >= 100 ? 101 : Math . min ( etotal , 100 ) ;
2020-11-11 22:39:36 +01:00
}
2020-12-15 23:54:09 +01:00
/* -------------------------------------------- */
2020-12-18 23:48:41 +01:00
static buildHTMLResults ( caracValue , levelValue ) {
2021-04-03 23:59:29 +02:00
if ( caracValue == undefined || isNaN ( caracValue ) ) caracValue = 10 ;
if ( levelValue == undefined || isNaN ( levelValue ) ) levelValue = 0 ;
2020-12-18 23:48:41 +01:00
let cell = this . computeChances ( caracValue , levelValue ) ;
2021-01-05 18:43:13 +01:00
cell . epart = cell . epart > 99 ? 'N/A' : cell . epart ;
cell . etotal = cell . etotal > 100 ? 'N/A' : cell . etotal ;
2021-01-02 19:27:15 +01:00
cell . score = Math . min ( cell . score , 99 ) ;
return `
2021-04-03 23:59:29 +02:00
< span class = "table-proba-reussite competence-label" >
Particulière : < span class = "rdd-roll-part" > $ { cell . part } < / s p a n >
- Significative : < span class = "rdd-roll-sign" > $ { cell . sign } < / s p a n >
- Réussite : < span class = "rdd-roll-norm" > $ { cell . score } < / s p a n >
- Echec Particulier : < span class = "rdd-roll-epart" > $ { cell . epart } < / s p a n >
- Echec Total : < span class = "rdd-roll-etotal" > $ { cell . etotal } < / s p a n >
< / s p a n >
`
2020-12-15 23:54:09 +01:00
}
2020-11-11 22:39:36 +01:00
/* -------------------------------------------- */
2020-11-12 23:37:12 +01:00
static buildHTMLTableExtract ( caracValue , levelValue ) {
return this . buildHTMLTable ( caracValue , levelValue , caracValue - 2 , caracValue + 2 , levelValue - 5 , levelValue + 5 )
}
2020-11-11 22:39:36 +01:00
static buildHTMLTable ( caracValue , levelValue , minCarac = 1 , maxCarac = 21 , minLevel = - 10 , maxLevel = 11 ) {
return this . _buildHTMLTable ( caracValue , levelValue , minCarac , maxCarac , minLevel , maxLevel )
}
/* -------------------------------------------- */
static _buildHTMLTable ( caracValue , levelValue , minCarac , maxCarac , minLevel , maxLevel ) {
2020-11-14 15:57:42 +01:00
let countColonnes = maxLevel - minLevel ;
2020-11-11 22:39:36 +01:00
minCarac = Math . max ( minCarac , 1 ) ;
2020-12-06 23:31:23 +01:00
maxCarac = Math . min ( maxCarac , caracMaximumResolution ) ;
2020-11-11 22:39:36 +01:00
minLevel = Math . max ( minLevel , - 10 ) ;
2020-11-14 15:57:42 +01:00
maxLevel = Math . max ( Math . min ( maxLevel , 22 ) , minLevel + countColonnes ) ;
2020-11-11 22:39:36 +01:00
2020-11-12 23:37:12 +01:00
let table = $ ( "<table class='table-resolution'/>" )
2021-01-02 14:10:43 +01:00
. append ( this . _buildHTMLHeader ( RdDResolutionTable . resolutionTable [ 0 ] , minLevel , maxLevel ) ) ;
2020-11-11 22:39:36 +01:00
2020-11-25 23:17:13 +01:00
for ( var rowIndex = minCarac ; rowIndex <= maxCarac ; rowIndex ++ ) {
2021-01-02 14:10:43 +01:00
table . append ( this . _buildHTMLRow ( RdDResolutionTable . resolutionTable [ rowIndex ] , rowIndex , caracValue , levelValue , minLevel , maxLevel ) ) ;
2020-11-11 22:39:36 +01:00
}
2020-12-15 23:37:35 +01:00
table . append ( "</table>" ) ;
2020-11-11 22:39:36 +01:00
return table ;
}
2020-12-04 20:52:04 +01:00
/* -------------------------------------------- */
2020-11-11 22:39:36 +01:00
static _buildHTMLHeader ( dataRow , minLevel , maxLevel ) {
2020-11-12 23:37:12 +01:00
let tr = $ ( "<tr/>" ) ;
if ( minLevel > - 8 ) {
tr . append ( $ ( "<th class='table-resolution-level'/>" ) . text ( "-8" ) )
}
if ( minLevel > - 7 ) {
tr . append ( $ ( "<th class='table-resolution-level'/>" ) . text ( "..." ) ) ;
}
2020-11-14 15:57:42 +01:00
for ( let difficulte = minLevel ; difficulte <= maxLevel ; difficulte ++ ) {
2020-11-15 02:07:41 +01:00
tr . append ( $ ( "<th class='table-resolution-level'/>" ) . text ( Misc . toSignedString ( difficulte ) ) ) ;
2020-11-11 22:39:36 +01:00
}
return tr ;
}
2020-12-04 20:52:04 +01:00
/* -------------------------------------------- */
2020-11-11 22:39:36 +01:00
static _buildHTMLRow ( dataRow , rowIndex , caracValue , levelValue , minLevel , maxLevel ) {
2020-11-12 23:37:12 +01:00
let tr = $ ( "<tr/>" ) ;
let max = maxLevel ;
if ( minLevel > - 8 ) {
let score = dataRow [ - 8 + 10 ] . score ;
tr . append ( $ ( "<td class='table-resolution-carac'/>" ) . text ( score ) )
}
if ( minLevel > - 7 ) {
tr . append ( $ ( "<td/>" ) )
}
for ( let difficulte = minLevel ; difficulte <= max ; difficulte ++ ) {
let td = $ ( "<td/>" ) ;
2020-11-11 22:39:36 +01:00
let score = dataRow [ difficulte + 10 ] . score ;
if ( rowIndex == caracValue && levelValue == difficulte ) {
td . addClass ( 'table-resolution-target' ) ;
} else if ( difficulte == - 8 ) {
td . addClass ( 'table-resolution-carac' ) ;
}
tr . append ( td . text ( score ) ) ;
}
return tr ;
}
}