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" ;
2023-06-20 23:43:24 +02:00
import { ReglesOptionnelles } from "./settings/regles-optionnelles.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
] ;
2022-12-06 01:30:12 +01: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
/* -------------------------------------------- */
2023-11-04 03:42:39 +01:00
const CARAC _MAXIMUM _RESOLUTION = 40 ;
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 = [ ]
2023-11-04 03:42:39 +01:00
for ( var caracValue = 0 ; caracValue <= CARAC _MAXIMUM _RESOLUTION ; caracValue ++ ) {
2020-11-25 00:46:11 +01:00
table [ caracValue ] = this . _computeRow ( caracValue ) ;
2020-11-11 22:39:36 +01:00
}
return table ;
}
2022-12-06 01:30:12 +01:00
/* -------------------------------------------- */
static computeChances ( carac , level ) {
if ( level < - 16 ) {
return levelImpossible ;
}
if ( level < - 10 ) {
return levelDown . find ( it => it . level == level ) ;
}
const percentage = RdDResolutionTable . computePercentage ( carac , level ) ;
return this . _computeCell ( level , percentage ) ;
}
/* -------------------------------------------- */
static _computeRow ( caracValue ) {
let dataRow = [
this . _computeCell ( - 10 , Math . max ( Math . floor ( caracValue / 4 ) , 1 ) ) ,
this . _computeCell ( - 9 , Math . max ( Math . floor ( caracValue / 2 ) , 1 ) )
]
for ( var diff = - 8 ; diff <= 22 ; diff ++ ) {
dataRow [ diff + 10 ] = this . _computeCell ( diff , RdDResolutionTable . computePercentage ( caracValue , diff ) ) ;
}
return dataRow ;
}
/* -------------------------------------------- */
static _computeCell ( niveau , percentage ) {
return {
niveau : niveau ,
score : percentage ,
norm : Math . min ( 99 , percentage ) ,
sign : this . _reussiteSignificative ( percentage ) ,
part : this . _reussitePart ( percentage ) ,
epart : this . _echecParticulier ( percentage ) ,
etotal : this . _echecTotal ( percentage )
} ;
}
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
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' ) {
2023-06-14 22:25:11 +02:00
return await ChatUtility . createChatWithRollMode ( RdDResolutionTable . actorChatName ( actor ) , {
content : await RdDResolutionTable . buildRollDataHtml ( rollData , template )
2021-01-09 19:36:19 +01:00
} ) ;
2020-12-31 02:08:58 +01:00
}
2023-06-14 22:25:11 +02:00
static actorChatName ( actor ) {
2024-08-31 00:46:20 +02:00
return actor ? . name ? ? game . user . name ;
2023-06-14 22:25:11 +02:00
}
2021-01-05 18:43:13 +01:00
/* -------------------------------------------- */
2023-06-14 22:25:11 +02:00
static async buildRollDataHtml ( rollData , template = 'chat-resultat-general.html' ) {
2021-01-05 18:43:13 +01:00
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
/* -------------------------------------------- */
2022-12-06 01:30:12 +01:00
static async roll ( caracValue , finalLevel , rollData = { } ) {
2024-05-02 14:08:02 +02:00
let chances = foundry . utils . duplicate ( 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
2023-06-20 23:43:24 +02:00
if ( ReglesOptionnelles . isUsing ( "afficher-colonnes-reussite" ) ) {
2021-10-09 22:02:13 +02:00
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
/* -------------------------------------------- */
2022-12-06 01:30:12 +01:00
static findNiveauNecessaire ( carac , rolled ) {
if ( carac == 0 ) {
return NaN ;
}
if ( rolled >= carac ) {
const upper = Math . ceil ( rolled / carac ) ;
return 2 * upper - 10
}
if ( rolled > Math . floor ( carac / 2 ) ) {
return - 8
}
if ( rolled > Math . floor ( carac / 4 ) ) {
return - 9
2021-05-28 09:12:18 +02:00
}
2022-12-06 01:30:12 +01:00
if ( rolled > 1 ) {
return - 10
}
return - 11 ;
2021-05-28 09:12:18 +02:00
}
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 ) ;
2024-05-01 09:13:21 +02:00
foundry . utils . 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 ) {
2022-12-06 01:30:12 +01:00
if ( bonus && finalLevel > - 11 ) {
2021-01-22 14:35:14 +01:00
let newScore = Number ( chances . score ) + bonus ;
2024-05-01 09:13:21 +02:00
foundry . utils . 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 ) ;
2024-05-01 09:13:21 +02:00
foundry . utils . mergeObject ( chances , reussites . find ( x => x . code == 'sign' ) , { overwrite : true } ) ;
2021-01-07 00:32:22 +01:00
}
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 ;
2024-05-01 09:13:21 +02:00
foundry . utils . mergeObject ( chances , reussites . find ( x => x . code == 'norm' ) , { overwrite : true } ) ;
2021-02-12 12:50:17 +01:00
}
2020-11-15 16:38:45 +01:00
/* -------------------------------------------- */
2021-06-28 20:19:02 +02:00
static async rollChances ( chances , diviseur , forceDiceResult = - 1 ) {
2022-12-06 01:30:12 +01:00
chances . forceDiceResult = forceDiceResult <= 0 || forceDiceResult > 100 ? undefined : { total : forceDiceResult } ;
chances . roll = await RdDDice . rollTotal ( "1d100" , chances ) ;
2024-05-01 09:13:21 +02:00
foundry . utils . 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
/* -------------------------------------------- */
2022-12-06 01:30:12 +01:00
static computePercentage ( carac , diff ) {
if ( diff < - 16 ) return 0
if ( diff < - 10 ) return 1
if ( diff == - 10 ) return Math . max ( Math . floor ( carac / 4 ) , 1 )
if ( diff == - 9 ) return Math . max ( Math . floor ( carac / 2 ) , 1 )
return Math . max ( Math . floor ( carac * ( diff + 10 ) / 2 ) , 1 ) ;
2020-11-12 16:35:51 +01:00
}
2021-01-04 22:03:00 +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
/* -------------------------------------------- */
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
/* -------------------------------------------- */
2022-12-06 01:30:12 +01:00
static subTable ( carac , level , delta = { carac : 2 , level : 5 } ) {
return {
carac ,
level ,
minCarac : carac - ( delta ? . carac ? ? 2 ) ,
maxCarac : carac + ( delta ? . carac ? ? 2 ) ,
minLevel : level - ( delta ? . level ? ? 5 ) ,
maxLevel : level + ( delta ? . level ? ? 5 )
} ;
2020-11-11 22:39:36 +01:00
}
/* -------------------------------------------- */
2022-12-06 01:30:12 +01:00
static async buildHTMLTable ( { carac : carac , level : level , minCarac = 1 , maxCarac = 21 , minLevel = - 10 , maxLevel = 11 } ) {
let colonnes = maxLevel - minLevel ;
2020-11-11 22:39:36 +01:00
minCarac = Math . max ( minCarac , 1 ) ;
2022-12-06 01:30:12 +01:00
maxCarac = Math . min ( maxCarac , minCarac + 20 ) ;
2020-11-11 22:39:36 +01:00
minLevel = Math . max ( minLevel , - 10 ) ;
2022-12-06 01:30:12 +01:00
maxLevel = Math . max ( Math . min ( maxLevel , 30 ) , minLevel + colonnes ) ;
return await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/resolution-table.html' , {
carac : carac ,
difficulte : level ,
min : minLevel ,
2023-03-08 02:00:38 +01:00
rows : Misc . intArray ( minCarac , maxCarac + 1 ) ,
cols : Misc . intArray ( minLevel , maxLevel + 1 )
2022-12-06 01:30:12 +01:00
} ) ;
2020-11-11 22:39:36 +01:00
}
}