2020-05-22 22:37:02 +02:00
/* Common useful functions shared between objects */
2020-09-13 22:46:42 +02:00
import { TMRUtility } from "./tmr-utility.js" ;
2020-11-11 04:31:17 +01:00
import { RdDRollTables } from "./rdd-rolltables.js" ;
2020-11-24 15:20:05 +01:00
import { ChatUtility } from "./chat-utility.js" ;
2020-12-12 21:58:44 +01:00
import { RdDItemCompetence } from "./item-competence.js" ;
import { RdDCombat } from "./rdd-combat.js" ;
2020-06-11 00:29:32 +02:00
2020-12-02 20:52:37 +01:00
/* -------------------------------------------- */
2020-05-24 20:19:57 +02:00
const level _category = {
"generale" : "-4" ,
"particuliere" : "-8" ,
2020-12-02 20:52:37 +01:00
"specialisee" : "-11" ,
2020-05-24 20:19:57 +02:00
"connaissance" : "-11" ,
"draconic" : "-11" ,
"melee" : "-6" ,
"tir" : "-8" ,
"lancer" : "-8"
}
2020-12-02 20:52:37 +01:00
/* -------------------------------------------- */
const label _category = {
"generale" : "Générales" ,
"particuliere" : "Particulières" ,
"specialisee" : "Spécialisées" ,
"connaissance" : "Connaissances" ,
"draconic" : "Draconics" ,
"melee" : "Mêlée" ,
"tir" : "Tir" ,
"lancer" : "Lancer"
}
/* -------------------------------------------- */
2020-08-13 22:28:56 +02:00
const competenceTroncs = [ [ "Esquive" , "Dague" , "Corps à corps" ] ,
[ "Epée à 1 main" , "Epée à 2 mains" , "Hache à 1 main" , "Hache à 2 mains" , "Lance" , "Masse à 1 main" , "Masse à 2 mains" ] ] ;
const competence _xp = {
"-11" : [ 5 , 10 , 15 , 25 , 35 , 45 , 55 , 70 , 85 , 100 , 115 , 135 , 155 , 175 ] ,
"-8" : [ 10 , 20 , 30 , 40 , 55 , 70 , 85 , 100 , 120 , 140 , 160 ] ,
"-6" : [ 10 , 20 , 35 , 50 , 65 , 80 , 100 , 120 , 140 ] ,
"-4" : [ 15 , 30 , 45 , 60 , 80 , 100 , 120 ]
}
2020-11-12 16:35:51 +01:00
2020-12-02 20:52:37 +01:00
/* -------------------------------------------- */
2020-08-13 22:28:56 +02:00
// This table starts at 0 -> niveau -10
const competence _xp _par _niveau = [ 5 , 5 , 5 , 10 , 10 , 10 , 10 , 15 , 15 , 15 , 15 , 20 , 20 , 20 , 20 , 30 , 30 , 40 , 40 , 60 , 60 , 100 , 100 , 100 , 100 , 100 , 100 , 100 , 100 , 100 ] ;
2020-05-24 20:19:57 +02:00
const carac _array = [ "taille" , "apparence" , "constitution" , "force" , "agilite" , "dexterite" , "vue" , "ouie" , "odoratgout" , "volonte" , "intellect" , "empathie" , "reve" , "chance" , "melee" , "tir" , "lancer" , "derobee" ] ;
2020-11-15 02:07:41 +01:00
const difficultesLibres = [ 0 , - 1 , - 2 , - 3 , - 4 , - 5 , - 6 , - 7 , - 8 , - 9 , - 10 ] ;
const ajustementsConditions = [ - 10 , - 9 , - 8 , - 7 , - 6 , - 5 , - 4 , - 3 , - 2 , - 1 , 0 , + 1 , + 2 , + 3 , + 4 , + 5 , + 6 , + 7 , + 8 , + 9 , + 10 ] ;
2020-12-01 00:05:18 +01:00
const ajustementsEncaissement = [ - 10 , - 9 , - 8 , - 7 , - 6 , - 5 , - 4 , - 3 , - 2 , - 1 , 0 , + 1 , + 2 , + 3 , + 4 , + 5 , + 6 , + 7 , + 8 , + 9 , + 10 , + 11 , + 12 , + 13 , + 14 , + 15 , + 16 , + 17 , + 18 , + 19 , + 20 , + 21 , + 22 , + 23 , + 24 , + 25 ] ;
2020-12-02 20:52:37 +01:00
/* -------------------------------------------- */
2020-11-17 13:08:52 +01:00
function _buildAllSegmentsFatigue ( max ) {
const cycle = [ 5 , 2 , 4 , 1 , 3 , 0 ] ;
let fatigue = [ [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] ] ;
2020-11-18 20:16:59 +01:00
for ( let i = 0 ; i <= max ; i ++ ) {
2020-11-17 13:08:52 +01:00
const ligneFatigue = duplicate ( fatigue [ i ] ) ;
const caseIncrementee = cycle [ i % 6 ] ;
ligneFatigue [ caseIncrementee ] ++ ;
ligneFatigue [ caseIncrementee + 6 ] ++ ;
ligneFatigue . fatigueMax = 2 * ( i + 1 ) ;
fatigue [ i + 1 ] = ligneFatigue ;
2020-11-18 20:16:59 +01:00
2020-11-17 13:08:52 +01:00
}
return fatigue ;
}
2020-12-02 20:52:37 +01:00
/* -------------------------------------------- */
2020-11-18 20:16:59 +01:00
function _cumulSegmentsFatigue ( matrix ) {
let cumulMatrix = [ ] ;
for ( let line of matrix )
{
let cumul = duplicate ( line ) ;
for ( let i = 1 ; i < 12 ; i ++ ) {
cumul [ i ] += cumul [ i - 1 ] ;
}
cumulMatrix . push ( cumul ) ;
}
return cumulMatrix ;
}
2020-11-17 13:08:52 +01:00
2020-12-02 20:52:37 +01:00
/* -------------------------------------------- */
2020-11-17 13:08:52 +01:00
const fatigueMatrix = _buildAllSegmentsFatigue ( 30 ) ;
2020-11-18 20:16:59 +01:00
const cumulFatigueMatrix = _cumulSegmentsFatigue ( fatigueMatrix ) ;
2020-11-17 13:08:52 +01:00
2020-05-27 23:47:49 +02:00
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-12-06 21:11:30 +01:00
/* -------------------------------------------- */
/* Static tables for commands /table */
2020-11-11 04:31:17 +01:00
const table2func = { "queues" : { descr : "queues : Tire une queue de Dragon" , func : RdDRollTables . getQueue } ,
"ombre" : { descr : "ombre: Tire une Ombre de Dragon" , func : RdDRollTables . getOmbre } ,
"tetehr" : { descr : "tetehr: Tire une Tête de Dragon pour Hauts Revants" , fund : RdDRollTables . getTeteHR } ,
"tete" : { descr : "tete: Tire une Tête de Dragon" , func : RdDRollTables . getTete } ,
"souffle" : { descr : "souffle: Tire un Souffle de Dragon" , func : RdDRollTables . getSouffle } ,
"tarot" : { descr : "tarot: Tire une carte de Tarot Dracnique" , func : RdDRollTables . getTarot } } ;
2020-07-14 22:19:29 +02:00
2020-12-02 20:52:37 +01:00
/* -------------------------------------------- */
2020-11-24 18:54:13 +01:00
const definitionsBlessures = [
{ type : "legere" , facteur : 2 } ,
{ type : "grave" , facteur : 4 } ,
{ type : "critique" , facteur : 6 }
]
2020-12-06 21:11:30 +01:00
/* -------------------------------------------- */
const nomEthylisme = [ "Emeché" , "Gris" , "Pinté" , "Pas frais" , "Ivre" , "Bu" , "Complètement fait" , "Ivre mort" ] ;
2020-12-02 20:52:37 +01:00
/* -------------------------------------------- */
2020-11-11 04:21:25 +01:00
const definitionsEncaissement = {
"mortel" : [
{ minimum : undefined , maximum : 0 , endurance : "0" , vie : "0" , legeres : 0 , graves : 0 , critiques : 0 } ,
{ minimum : 1 , maximum : 10 , endurance : "1d4" , vie : "0" , legeres : 0 , graves : 0 , critiques : 0 } ,
{ minimum : 11 , maximum : 15 , endurance : "1d6" , vie : "0" , legeres : 1 , graves : 0 , critiques : 0 } ,
{ minimum : 16 , maximum : 19 , endurance : "2d6" , vie : "2" , legeres : 0 , graves : 1 , critiques : 0 } ,
{ minimum : 20 , maximum : undefined , endurance : "100" , vie : "4 + @over20" , legeres : 0 , graves : 0 , critiques : 1 } ,
] ,
"non-mortel" : [
{ minimum : undefined , maximum : 0 , endurance : "0" , vie : "0" , legeres : 0 , graves : 0 , critiques : 0 } ,
{ minimum : 1 , maximum : 10 , endurance : "1d4" , vie : "0" , legeres : 0 , graves : 0 , critiques : 0 } ,
{ minimum : 11 , maximum : 15 , endurance : "1d6" , vie : "0" , legeres : 0 , graves : 0 , critiques : 0 } ,
{ minimum : 16 , maximum : 19 , endurance : "2d6" , vie : "0" , legeres : 1 , graves : 0 , critiques : 0 } ,
{ minimum : 20 , maximum : undefined , endurance : "100" , vie : "1" , legeres : 1 , graves : 0 , critiques : 0 } ,
] ,
"cauchemar" : [
2020-11-12 00:06:57 +01:00
{ minimum : undefined , maximum : 0 , endurance : "0" , vie : "0" , legeres : 0 , graves : 0 , critiques : 0 } ,
2020-11-11 04:21:25 +01:00
{ minimum : 1 , maximum : 10 , endurance : "1d4" , vie : "0" , legeres : 0 , graves : 0 , critiques : 0 } ,
{ minimum : 11 , maximum : 15 , endurance : "1d6" , vie : "0" , legeres : 0 , graves : 0 , critiques : 0 } ,
{ minimum : 16 , maximum : 19 , endurance : "2d6" , vie : "0" , legeres : 0 , graves : 0 , critiques : 0 } ,
{ minimum : 20 , maximum : undefined , endurance : "3d6 + @over20" , vie : "0" , legeres : 0 , graves : 0 , critiques : 0 } ,
]
} ;
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' ,
2020-11-04 16:29:10 +01:00
'systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html' ,
'systems/foundryvtt-reve-de-dragon/templates/actor-humanoide-sheet.html' ,
2020-11-14 23:24:01 +01:00
'systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html' ,
2020-05-24 20:19:57 +02:00
//Items
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html' ,
2020-09-20 16:36:39 +02:00
'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-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-11-10 13:53:51 +01:00
'systems/foundryvtt-reve-de-dragon/templates/item-rencontresTMR-sheet.html' ,
2020-07-20 12:02:07 +02:00
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html' ,
'systems/foundryvtt-reve-de-dragon/templates/item-souffle-sheet.html' ,
2020-11-09 23:56:25 +01:00
'systems/foundryvtt-reve-de-dragon/templates/item-tarot-sheet.html' ,
2020-07-20 12:02:07 +02:00
'systems/foundryvtt-reve-de-dragon/templates/item-tete-sheet.html' ,
'systems/foundryvtt-reve-de-dragon/templates/item-ombre-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-11-09 23:56:25 +01:00
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html' ,
2020-11-09 22:35:26 +01:00
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie.html' ,
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.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' ,
2020-07-23 22:09:40 +02:00
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html' ,
2020-11-10 13:53:51 +01:00
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html' ,
2020-09-20 16:36:39 +02:00
'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html' ,
2020-11-27 12:20:13 +01:00
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-surenc.html' ,
2020-11-27 15:47:18 +01:00
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-natation.html' ,
2020-12-11 08:29:24 +01:00
'systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html' ,
2020-09-20 16:36:39 +02:00
// Calendrier
2020-11-14 23:24:01 +01:00
'systems/foundryvtt-reve-de-dragon/templates/calendar-template.html' ,
2020-12-08 21:40:41 +01:00
'systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html' ,
'systems/foundryvtt-reve-de-dragon/templates/heures-select-option.html' ,
2020-11-12 14:43:08 +01:00
// Conteneur/item in Actor sheet
2020-12-01 20:52:05 +01:00
'systems/foundryvtt-reve-de-dragon/templates/actor-inventaire-conteneur.html' ,
'systems/foundryvtt-reve-de-dragon/templates/editor-notes-mj.html'
2020-05-24 20:19:57 +02:00
] ;
return loadTemplates ( templatePaths ) ;
}
2020-11-18 16:57:58 +01:00
/* -------------------------------------------- */
static checkNull ( items ) {
if ( items && items . length ) {
return items ;
}
return [ ] ;
}
2020-12-06 20:11:30 +01:00
/* -------------------------------------------- */
2020-12-06 21:11:30 +01:00
static getNomEthylisme ( niveauEthylisme ) {
let index = Math . abs ( niveauEthylisme ) ;
return nomEthylisme [ index ] ;
2020-12-06 20:11:30 +01:00
}
2020-12-06 21:11:30 +01:00
2020-12-01 22:18:15 +01:00
/* -------------------------------------------- */
static initAfficheContenu ( actorId ) { // persistent handling of conteneur show/hide
if ( ! this . afficheContenu )
this . afficheContenu = { } ;
}
/* -------------------------------------------- */
static toggleAfficheContenu ( conteneurId ) {
this . afficheContenu [ conteneurId ] = ! this . afficheContenu [ conteneurId ] ;
}
/* -------------------------------------------- */
static getAfficheContenu ( conteneurId ) {
return this . afficheContenu [ conteneurId ] ;
}
2020-11-18 16:57:58 +01:00
/* -------------------------------------------- */
static filterItemsPerTypeForSheet ( data ) {
data . data . materiel = this . checkNull ( data . itemsByType [ 'objet' ] ) ;
data . data . conteneurs = this . checkNull ( data . itemsByType [ 'conteneur' ] ) ;
data . data . armes = this . checkNull ( data . itemsByType [ 'arme' ] ) ;
data . data . armures = this . checkNull ( data . itemsByType [ 'armure' ] ) ;
data . data . livres = this . checkNull ( data . itemsByType [ 'livre' ] ) ;
2020-11-23 22:10:19 +01:00
data . data . potions = this . checkNull ( data . itemsByType [ 'potion' ] ) ;
2020-11-18 16:57:58 +01:00
data . data . ingredients = this . checkNull ( data . itemsByType [ 'ingredient' ] ) ;
data . data . munitions = this . checkNull ( data . itemsByType [ 'munition' ] ) ;
data . data . herbes = this . checkNull ( data . itemsByType [ 'herbe' ] ) ;
data . data . sorts = this . checkNull ( data . itemsByType [ 'sort' ] ) ;
data . data . queues = this . checkNull ( data . itemsByType [ 'queue' ] ) ;
data . data . souffles = this . checkNull ( data . itemsByType [ 'souffle' ] ) ;
data . data . ombres = this . checkNull ( data . itemsByType [ 'ombre' ] ) ;
data . data . tetes = this . checkNull ( data . itemsByType [ 'tete' ] ) ;
data . data . objets = data . data . conteneurs . concat ( data . data . materiel ) . concat ( data . data . armes ) . concat ( data . data . armures ) . concat ( data . data . munitions ) . concat ( data . data . livres ) . concat ( data . data . potions ) . concat ( data . data . herbes ) . concat ( data . data . ingredients ) ;
}
/* -------------------------------------------- */
2020-11-28 09:59:30 +01:00
static async processItemDropEvent ( actorSheet , event ) {
2020-11-18 16:57:58 +01:00
let dragData = JSON . parse ( event . dataTransfer . getData ( "text/plain" ) ) ;
let dropID = $ ( event . target ) . parents ( ".item" ) . attr ( "data-item-id" ) ; // Only relevant if container drop
if ( dropID ) { // Dropped over an item !!!
let objetId = dragData . id || dragData . data . _id ;
if ( actorSheet . objetVersConteneur [ objetId ] != dropID ) {
if ( actorSheet . actor . testConteneurCapacite ( objetId , dropID ) ) {
2020-11-28 09:59:30 +01:00
await actorSheet . actor . enleverDeConteneur ( objetId , actorSheet . objetVersConteneur [ objetId ] ) ;
await actorSheet . actor . ajouterAConteneur ( objetId , dropID ) ;
2020-11-18 16:57:58 +01:00
} else {
ui . notifications . info ( "Capacité d'encombrement insuffisante dans le conteneur !" ) ;
}
}
}
2020-12-02 14:00:54 +01:00
actorSheet . actor . computeEncombrementTotalEtMalusArmure ( ) ;
2020-11-18 16:57:58 +01:00
}
/* -------------------------------------------- */
static buildArbreDeConteneur ( actorSheet , data ) {
actorSheet . objetVersConteneur = { } ; // Table de hash locale pour recupération rapide du conteneur parent (si existant)
// Attribution des objets aux conteneurs
for ( let conteneur of data . data . conteneurs ) {
conteneur . subItems = [ ] ;
2020-11-27 09:40:48 +01:00
if ( ! conteneur . data . encTotal ) conteneur . data . encTotal = 0 ;
//conteneur.data.encTotal = ; Deja calculé
2020-11-18 16:57:58 +01:00
if ( conteneur . data . contenu ) {
for ( let id of conteneur . data . contenu ) {
let objet = data . data . objets . find ( objet => ( id == objet . _id ) ) ;
if ( objet ) {
2020-11-27 09:40:48 +01:00
if ( ! objet . data . encombrement ) objet . data . encombrement = 0 ; // Auto-fix
objet . estContenu = true ; // Permet de filtrer ce qifui est porté dans le template
2020-11-18 16:57:58 +01:00
actorSheet . objetVersConteneur [ id ] = conteneur . _id ;
2020-11-27 09:40:48 +01:00
conteneur . data . encTotal += Number ( objet . data . encombrement ) * Number ( ( ( objet . data . quantite ) ? objet . data . quantite : 1 ) ) ;
2020-11-18 16:57:58 +01:00
conteneur . subItems . push ( objet ) ;
}
}
}
}
// Construit la liste des conteneurs de niveau 1 (c'est à dire non contenu eux-même dans un conteneur)
let newConteneurs = data . data . conteneurs . filter ( function ( conteneur , index , arr ) { return ! conteneur . estContenu } ) ;
data . data . conteneurs = newConteneurs ;
}
2020-11-12 14:44:42 +01:00
/* -------------------------------------------- */
2020-11-12 15:06:25 +01:00
/ * * C o n s t r u i t l a s t r u c t u r e r é c u r s i v e d e s c o n t e n e u r s , a v e c i m b r i c a t i o n p o t e n t i e l l e
*
* /
2020-11-12 14:43:08 +01:00
static buildConteneur ( objet , niveau ) {
if ( ! niveau ) niveau = 1 ;
2020-12-01 22:18:15 +01:00
objet . niveau = niveau ;
//console.log("OBJ:", objet);
2020-11-12 14:43:08 +01:00
let str = Handlebars . partials [ 'systems/foundryvtt-reve-de-dragon/templates/actor-inventaire-conteneur.html' ] ( { item : objet } ) ;
if ( objet . type == 'conteneur' ) {
2020-12-01 22:18:15 +01:00
//console.log("ITEM DISPLAYED", this.getAfficheContenu(objet._id) );
if ( this . getAfficheContenu ( objet . _id ) ) {
str = str + "<ul class='item-list alterne-list item-display-show list-item-margin" + niveau + "'>" ;
} else {
str = str + "<ul class='item-list alterne-list item-display-hide list-item-margin" + niveau + "'>" ;
}
2020-11-12 14:43:08 +01:00
for ( let subItem of objet . subItems ) {
str = str + this . buildConteneur ( subItem , niveau + 1 ) ;
}
2020-11-27 09:40:48 +01:00
str = str + "</ul>" ;
2020-11-12 14:43:08 +01:00
}
return new Handlebars . SafeString ( str ) ;
}
2020-05-24 20:19:57 +02:00
/* -------------------------------------------- */
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 ;
}
2020-12-02 20:52:37 +01:00
static getLabelCategory ( )
{
return label _category ;
}
2020-05-24 20:19:57 +02:00
static getCaracArray ( )
{
return carac _array ;
}
2020-11-15 02:07:41 +01:00
static getDifficultesLibres ( )
2020-05-24 20:19:57 +02:00
{
2020-11-15 02:07:41 +01:00
return difficultesLibres ;
}
static getAjustementsConditions ( )
{
return ajustementsConditions ;
2020-05-24 20:19:57 +02:00
}
2020-12-01 00:05:18 +01:00
static getAjustementsEncaissement ( )
{
return ajustementsEncaissement ;
}
2020-05-24 20:19:57 +02:00
2020-11-24 18:54:13 +01:00
static getDefinitionsBlessures ( ) {
return definitionsBlessures ;
}
2020-08-13 22:28:56 +02:00
/* -------------------------------------------- */
static isTronc ( compName )
{
for ( let troncList of competenceTroncs ) {
for ( let troncName of troncList ) {
if ( troncName == compName )
return troncList ;
}
}
return false ;
}
/* -------------------------------------------- */
static computeCompetenceXPCost ( competence )
{
let minLevel = competence . data . base ;
if ( minLevel == competence . data . niveau ) return 0 ;
if ( competence . data . niveau < - 10 ) return 0 ;
let xp = 0 ;
for ( let i = minLevel + 1 ; i <= competence . data . niveau ; i ++ ) {
xp += competence _xp _par _niveau [ i + 10 ] ;
//console.log(i, i+10, competence_xp_par_niveau[i+10]);
}
return xp ;
}
2020-05-24 20:19:57 +02:00
/* -------------------------------------------- */
2020-08-14 22:24:35 +02:00
static computeCompetenceTroncXP ( competenceList )
{
let xp = 0 ;
for ( let troncList of competenceTroncs ) {
2020-12-06 23:57:08 +01:00
let minNiveau = 0 ;
2020-08-14 22:24:35 +02:00
for ( let troncName of troncList ) {
let comp = RdDUtility . findCompetence ( competenceList , troncName ) ;
2020-12-06 23:57:08 +01:00
if ( comp ) {
minNiveau = Math . min ( comp . data . niveau , minNiveau ) ;
}
2020-08-14 22:24:35 +02:00
}
2020-12-06 23:57:08 +01:00
minNiveau = Math . max ( minNiveau , 0 ) ; // Clamp à 0, pour le tronc commun
2020-08-14 22:24:35 +02:00
let minNiveauXP = competence _xp _par _niveau [ minNiveau + 10 ] ;
xp += minNiveauXP ;
for ( let troncName of troncList ) {
let comp = RdDUtility . findCompetence ( competenceList , troncName ) ;
2020-12-06 23:57:08 +01:00
if ( comp ) {
xp += competence _xp _par _niveau [ comp . data . niveau + 10 ] - minNiveauXP ;
}
2020-08-14 22:24:35 +02:00
}
}
return xp ;
}
2020-11-24 16:41:15 +01:00
/* -------------------------------------------- */
/** Retourne une liste triée d'armes avec le split arme1 main / arme 2 main */
2020-12-05 21:24:31 +01:00
static finalizeArmeList ( armeList , competenceList , carac ) {
2020-11-24 16:41:15 +01:00
// Gestion des armes 1/2 mains
let arme2mains = [ ] ; // Tableau contenant la duplication des armes 1m/2m
for ( const arme of armeList ) {
2020-12-05 21:24:31 +01:00
let comp = competenceList . find ( c => c . name == arme . data . competence ) ;
2020-12-09 00:36:38 +01:00
arme . data . initiative = RdDUtility . calculInitiative ( arme . data . niveau , carac [ comp . data . defaut _carac ] . value ) ;
2020-11-24 16:41:15 +01:00
// Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence
if ( arme . data . unemain && arme . data . deuxmains ) {
let arme2main = duplicate ( arme ) ;
arme2main . data . dommages = arme2main . data . dommages . split ( "/" ) [ 1 ] ; // Existence temporaire uniquement dans la liste des armes, donc OK
arme2main . data . competence = arme2main . data . competence . replace ( " 1 main" , " 2 mains" ) ; // Replace !
2020-12-05 21:24:31 +01:00
let comp = competenceList . find ( c => c . name == arme2main . data . competence ) ;
arme2main . data . niveau = comp . data . niveau ;
2020-12-09 00:36:38 +01:00
arme2main . data . initiative = RdDUtility . calculInitiative ( arme2main . data . niveau , carac [ comp . data . defaut _carac ] . value ) ;
2020-11-24 16:41:15 +01:00
arme2mains . push ( arme2main ) ;
}
}
armeList = armeList . concat ( arme2mains ) ; // Merge all cases
armeList = armeList . sort ( ( a , b ) => { if ( a . name > b . name ) return 1 ; else return - 1 ; } ) ;
return armeList
}
2020-12-09 00:36:38 +01:00
static calculInitiative ( niveau , caracValue ) {
let base = niveau + Math . floor ( caracValue / 2 ) ;
return "1d6" + ( base >= 0 ? "+" : "" ) + base ;
}
2020-08-14 22:24:35 +02:00
/* -------------------------------------------- */
2020-05-24 20:19:57 +02:00
static computeCarac ( data )
{
2020-11-17 13:08:52 +01:00
data . carac . force . value = Math . min ( data . carac . force . value , parseInt ( data . carac . taille . value ) + 4 ) ;
2020-05-24 20:19:57 +02:00
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 ) ;
2020-11-17 13:08:52 +01:00
// TODO: gérer table des bonus dommages (et autres) des créatures
2020-05-24 20:19:57 +02:00
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 ) ;
2020-09-05 22:56:33 +02:00
data . sante . vie . max = Math . ceil ( ( parseInt ( data . carac . taille . value ) + parseInt ( data . carac . constitution . value ) ) / 2 ) ;
2020-11-17 13:08:52 +01:00
data . sante . vie . value = Math . min ( data . sante . vie . value , data . sante . vie . max )
data . sante . endurance . max = 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 . value = Math . min ( data . sante . endurance . value , data . sante . endurance . max ) ;
data . sante . fatigue . max = data . sante . endurance . max * 2 ;
data . sante . fatigue . value = Math . min ( 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-07-17 22:04:35 +02:00
data . reve . reve . max = data . carac . reve . value ;
2020-06-07 23:16:29 +02:00
//data.compteurs.chance.value = data.carac.chance.value;
2020-07-17 22:04:35 +02:00
data . compteurs . chance . max = data . carac . chance . value ;
2020-05-24 20:19:57 +02:00
}
2020-11-17 13:08:52 +01:00
2020-11-24 16:41:15 +01:00
/* -------------------------------------------- */
2020-11-18 20:16:59 +01:00
static getSegmentsFatigue ( maxEnd ) {
maxEnd = Math . max ( maxEnd , 1 ) ;
maxEnd = Math . min ( maxEnd , fatigueMatrix . length ) ;
return fatigueMatrix [ maxEnd ] ;
2020-11-17 13:08:52 +01:00
}
2020-11-24 16:41:15 +01:00
/* -------------------------------------------- */
2020-11-18 20:16:59 +01:00
static calculMalusFatigue ( fatigue , maxEnd )
{
maxEnd = Math . max ( maxEnd , 1 ) ;
maxEnd = Math . min ( maxEnd , cumulFatigueMatrix . length ) ;
let segments = cumulFatigueMatrix [ maxEnd ] ;
for ( let i = 0 ; i < 12 ; i ++ ) {
if ( fatigue <= segments [ i ] ) {
return fatigueMalus [ i ]
}
2020-11-17 13:08:52 +01:00
}
2020-11-18 20:16:59 +01:00
return - 7 ;
2020-11-17 13:08:52 +01: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.
2020-11-17 13:08:52 +01:00
// max should be the endurance max value
static makeHTMLfatigueMatrix ( fatigue , maxEndurance ) {
let segments = this . getSegmentsFatigue ( maxEndurance ) ;
return this . makeHTMLfatigueMatrixForSegment ( fatigue , segments ) ;
}
2020-05-29 00:43:16 +02:00
2020-11-17 13:08:52 +01:00
static makeHTMLfatigueMatrixForSegment ( fatigue , segments ) {
fatigue = Math . max ( fatigue , 0 ) ;
fatigue = Math . min ( fatigue , segments . fatigueMax ) ;
let table = $ ( "<table/>" ) . addClass ( 'table-fatigue' ) ;
2020-05-27 23:47:49 +02:00
let segmentIdx = 0 ;
2020-05-28 23:36:09 +02:00
let fatigueCount = 0 ;
2020-11-17 13:08:52 +01:00
for ( var line = 0 ; line < fatigueLineSize . length ; line ++ ) {
2020-05-27 23:47:49 +02:00
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 ) {
2020-11-17 13:08:52 +01:00
let freeSize = segments [ segmentIdx ] ;
for ( let col = 0 ; col < 5 ; col ++ ) {
if ( col < freeSize ) {
if ( fatigueCount < fatigue )
2020-12-11 19:14:24 +01:00
row . append ( "<td class='fatigue-used'>X</td>" ) ;
2020-11-17 13:08:52 +01:00
2020-05-28 23:36:09 +02:00
else
row . append ( "<td class='fatigue-free'/>" ) ;
fatigueCount ++ ;
2020-11-17 13:08:52 +01:00
} 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 ) ;
}
return table ;
}
2020-11-17 13:08:52 +01:00
2020-05-31 23:06:25 +02:00
/* -------------------------------------------- */
static getLocalisation ( )
{
2020-12-04 20:52:04 +01:00
let result = new Roll ( "1d20" ) . roll ( ) . 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" ;
2020-11-18 23:49:05 +01:00
else if ( result == 19 ) txt = "Tête" ;
else if ( result == 20 ) txt = "Tête (visage)" ;
2020-06-07 23:16:29 +02:00
return { result : result , label : txt } ;
2020-05-31 23:06:25 +02:00
}
2020-11-11 04:21:25 +01:00
2020-11-11 10:38:27 +01:00
/* -------------------------------------------- */
2020-12-15 02:20:24 +01:00
static computeBlessuresSante ( degats , mortalite , loc ) {
2020-11-11 04:21:25 +01:00
let encaissement = RdDUtility . selectEncaissement ( degats , mortalite )
2020-12-06 21:31:41 +01:00
let over20 = Math . max ( degats - 20 , 0 ) ;
encaissement . endurance = - RdDUtility . _evaluatePerte ( encaissement . endurance , over20 ) ;
encaissement . vie = - RdDUtility . _evaluatePerte ( encaissement . vie , over20 ) ;
2020-12-15 02:20:24 +01:00
encaissement . locName = loc ? loc . label : "Corps" ;
2020-11-11 04:21:25 +01:00
return encaissement ;
}
2020-11-11 10:38:27 +01:00
/* -------------------------------------------- */
2020-11-11 04:21:25 +01:00
static selectEncaissement ( degats , mortalite ) {
const table = definitionsEncaissement [ mortalite ] === undefined ? definitionsEncaissement [ "mortel" ] : definitionsEncaissement [ mortalite ] ;
for ( let encaissement of table ) {
if ( ( encaissement . minimum === undefined || encaissement . minimum <= degats )
&& ( encaissement . maximum === undefined || degats <= encaissement . maximum ) ) {
return duplicate ( encaissement ) ;
}
2020-06-07 23:16:29 +02:00
}
2020-11-11 04:21:25 +01:00
return duplicate ( table [ 0 ] ) ;
}
2020-11-11 10:38:27 +01:00
/* -------------------------------------------- */
2020-11-11 04:21:25 +01:00
static _evaluatePerte ( formula , over20 ) {
console . log ( "_evaluatePerte" , formula , over20 )
let perte = new Roll ( formula , { over20 : over20 } )
perte . evaluate ( )
return perte . total
2020-06-07 23:16:29 +02:00
}
2020-06-12 22:46:04 +02:00
/* -------------------------------------------- */
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-08-29 22:52:41 +02:00
/* -------------------------------------------- */
2020-05-22 22:37:02 +02:00
static findCompetence ( compList , compName )
{
2020-11-12 23:50:37 +01:00
compName = compName . toLowerCase ( ) ;
return compList . find ( item => item . name . toLowerCase ( ) == compName && ( item . type == "competence" || item . type == "competencecreature" ) )
2020-05-22 22:37:02 +02:00
}
2020-12-12 21:58:44 +01:00
2020-06-10 08:23:58 +02:00
/* -------------------------------------------- */
static buildDefenseChatCard ( attacker , target , rollData )
{
2020-12-02 00:09:47 +01:00
console . log ( "Attacker.defense" , attacker , target , target . actor . isToken , attacker . data . _id , rollData . competence . data . categorie ) ;
2020-07-27 18:58:10 +02:00
let myTarget = target . actor ;
2020-06-10 08:23:58 +02:00
let defenseMsg = { title : "Défense en combat" ,
2020-07-27 18:58:10 +02:00
content : "<strong>" + myTarget . name + "</strong> doit se défendre : <br><span class='chat-card-button-area'>" +
2020-12-12 21:58:44 +01:00
"<a class='chat-card-button' id='encaisser-button' data-attackerId='" + attacker . data . _id + "' data-defenderTokenId='" + target . data . _id + "'>Encaisser !</a></span>" ,
2020-07-28 09:20:01 +02:00
whisper : ChatMessage . getWhisperRecipients ( myTarget . name ) ,
2020-12-12 21:58:44 +01:00
attackerId : attacker . data . _id ,
2020-12-02 00:09:47 +01:00
defenderTokenId : target . data . _id ,
2020-07-28 09:20:01 +02:00
rollMode : true
} ;
2020-06-10 08:23:58 +02:00
2020-12-08 22:27:28 +01:00
if ( rollData . competence . data . categorie == 'melee' || rollData . competence . data . categorie == 'competencecreature' ) { // Melee attack or creature
2020-06-10 08:23:58 +02:00
let defenderArmes = [ ] ;
2020-07-27 18:58:10 +02:00
for ( const arme of myTarget . data . items ) {
2020-12-12 21:58:44 +01:00
if ( arme . type == "arme" && RdDItemCompetence . isCompetenceMelee ( arme . data . competence ) ) {
2020-06-10 08:23:58 +02:00
defenderArmes . push ( arme ) ;
2020-12-12 21:58:44 +01:00
defenseMsg . content += "<br><a class='chat-card-button' id='parer-button' data-attackerId='" + attacker . data . _id + "' data-defenderTokenId='" + target . data . _id + "' data-armeid='" + arme . _id + "'>Parer avec " + arme . name + "</a></span>" ;
2020-06-10 08:23:58 +02:00
}
2020-12-08 22:27:28 +01:00
if ( arme . type == "competencecreature" && arme . data . isparade ) {
defenderArmes . push ( arme ) ;
2020-12-12 21:58:44 +01:00
defenseMsg . content += "<br><a class='chat-card-button' id='parer-button' data-attackerId='" + attacker . data . _id + "' data-defenderTokenId='" + target . data . _id + "' data-armeid='" + arme . _id + "'>Parer avec " + arme . name + "</a></span>" ;
2020-12-08 22:27:28 +01:00
}
2020-06-10 08:23:58 +02:00
}
2020-12-12 21:58:44 +01:00
defenseMsg . content += "<br><a class='chat-card-button' id='esquiver-button' data-attackerId='" + attacker . data . _id + "' data-defenderTokenId='" + target . 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" ) {
2020-07-27 18:58:10 +02:00
for ( const arme of myTarget . data . items ) { // Bouclier for parry
2020-06-17 20:31:43 +02:00
if ( arme . type == "arme" && arme . name . toLowerCase . match ( "bouclier" ) ) {
defenderArmes . push ( arme ) ;
2020-12-12 21:58:44 +01:00
defenseMsg . content += "<br><a class='chat-card-button' id='parer-button' data-attackerId='" + attacker . data . _id + "' data-defenderTokenId='" + target . data . _id + "' data-armeid='" + arme . _id + "'>Parer avec " + arme . name + "</a></span>" ;
2020-06-17 20:31:43 +02:00
}
}
}
if ( rollData . competence . data . categorie == "lancer" ) {
2020-07-27 18:58:10 +02:00
for ( const arme of myTarget . data . items ) { // Bouclier for parry Dodge/Esquive
2020-06-17 20:31:43 +02:00
if ( arme . type == "arme" && arme . name . toLowerCase . match ( "bouclier" ) ) {
defenderArmes . push ( arme ) ;
2020-12-12 21:58:44 +01:00
defenseMsg . content += "<br><a class='chat-card-button' id='parer-button' data-attackerId='" + attacker . data . _id + "' data-defenderTokenId='" + target . data . _id + "' data-armeid='" + arme . _id + "'>Parer avec " + arme . name + "</a></span>" ;
2020-06-17 20:31:43 +02:00
}
}
2020-12-12 21:58:44 +01:00
defenseMsg . content += "<br><a class='chat-card-button' id='esquiver-button' data-attackerId='" + attacker . data . _id + "' data-defenderTokenId='" + target . data . _id + "'>Esquiver</a></span>" ;
2020-06-17 20:31:43 +02:00
}
2020-07-28 09:20:01 +02:00
2020-11-12 23:50:37 +01:00
defenseMsg . toSocket = true ; // True per default for all players
if ( game . user . isGM ) { // In GM case, only if target is a player
defenseMsg . toSocket = myTarget . hasPlayerOwner ;
}
2020-07-28 09:20:01 +02:00
2020-06-10 08:23:58 +02:00
return defenseMsg ;
}
2020-12-12 23:31:19 +01:00
/* -------------------------------------------- */
2020-12-13 23:11:58 +01:00
static async responseNombreAstral ( data ) {
2020-12-12 23:31:19 +01:00
let actor = game . actors . get ( data . id ) ;
2020-12-13 23:11:58 +01:00
actor . ajouteNombreAstral ( data ) ;
2020-12-12 23:31:19 +01:00
}
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 ) ;
2020-11-24 15:20:05 +01:00
switch ( sockmsg . msg ) {
case "msg_encaisser" :
return RdDUtility . _handleMsgEncaisser ( sockmsg . data ) ;
case "msg_defense" :
return RdDUtility . _handleMsgDefense ( sockmsg . data ) ;
case "msg_gm_chat_message" :
return ChatUtility . handleGMChatMessage ( sockmsg . data ) ;
2020-12-08 21:40:41 +01:00
case "msg_sync_time" :
return game . system . rdd . calendrier . syncPlayerTime ( sockmsg . data ) ;
2020-12-12 23:31:19 +01:00
case "msg_request_nombre_astral" :
return game . system . rdd . calendrier . requestNombreAstral ( sockmsg . data ) ;
case "msg_response_nombre_astral" :
return RdDUtility . responseNombreAstral ( sockmsg . data ) ;
2020-11-24 15:20:05 +01:00
}
}
2020-11-29 18:21:34 +01:00
/* -------------------------------------------- */
2020-11-24 15:20:05 +01:00
static _handleMsgDefense ( data ) {
2020-12-02 00:09:47 +01:00
let defenderToken = canvas . tokens . get ( data . defenderTokenId ) ;
if ( defenderToken ) {
2020-12-04 10:15:55 +01:00
if ( ! game . user . isGM && game . user . character == undefined ) { // vérification / sanity check
ui . notifications . error ( "Le joueur " + game . user . name + " n'est connecté à aucun personnage. Impossible de continuer." ) ;
return ;
}
2020-12-02 00:09:47 +01:00
if ( ( game . user . isGM && ! defenderToken . actor . hasPlayerOwner ) || ( defenderToken . actor . hasPlayerOwner && ( game . user . character . id == defenderToken . actor . data . _id ) ) ) {
2020-11-24 15:20:05 +01:00
console . log ( "User is pushing message..." , game . user . name ) ;
2020-12-12 21:58:44 +01:00
game . system . rdd . rollDataHandler [ data . attackerId ] = duplicate ( data . rollData ) ;
2020-11-24 15:20:05 +01:00
data . whisper = [ game . user ] ;
data . blind = true ;
data . rollMode = "blindroll" ;
ChatMessage . create ( data ) ;
2020-07-28 09:20:01 +02:00
}
2020-06-22 10:18:03 +02:00
}
2020-06-17 20:31:43 +02:00
}
2020-11-24 16:41:15 +01:00
/* -------------------------------------------- */
static buildItemsClassification ( items ) {
let itemsByType = { } ;
for ( const item of items ) {
let list = itemsByType [ item . type ] ;
if ( ! list ) {
list = [ ] ;
itemsByType [ item . type ] = list ;
}
list . push ( item ) ;
}
return itemsByType ;
}
/* -------------------------------------------- */
static rollInitiativeCompetence ( combatantId , arme ) {
const combatant = game . combat . getCombatant ( combatantId ) ;
2020-11-24 17:41:14 +01:00
const actor = combatant . actor ;
2020-11-24 17:47:35 +01:00
if ( arme . name == "Autre action" ) {
game . combat . rollInitiative ( combatantId , "1d6" ) ;
} else if ( arme . name == "Draconic" ) {
game . combat . rollInitiative ( combatantId , "1d6+200" ) ;
2020-11-24 17:41:14 +01:00
} else {
2020-11-24 17:47:35 +01:00
let initOffset = 0 ;
let caracForInit = 0 ;
let competence = RdDUtility . findCompetence ( combatant . actor . data . items , arme . data . competence ) ;
if ( actor . data . type == 'creature' || actor . data . type == 'entite' ) {
caracForInit = competence . data . carac _value ;
2020-11-24 17:41:14 +01:00
} else {
2020-11-24 17:47:35 +01:00
caracForInit = actor . data . data . carac [ competence . data . defaut _carac ] . value ;
if ( competence . data . categorie == "lancer" ) { // Offset de principe pour les armes de jet
initOffset = 40 ;
}
if ( competence . data . categorie == "tir" ) { // Offset de principe pour les armes de jet
initOffset = 80 ;
}
2020-11-24 17:41:14 +01:00
}
2020-11-24 17:47:35 +01:00
// Cas des créatures et entités vs personnages
2020-12-09 00:36:38 +01:00
let rollFormula = RdDUtility . calculInitiative ( competence . data . niveau , caracForInit ) + "+" + initOffset ;
2020-11-24 17:47:35 +01:00
game . combat . rollInitiative ( combatantId , rollFormula ) ;
2020-11-24 17:41:14 +01:00
}
2020-11-24 16:41:15 +01:00
}
/* -------------------------------------------- */
2020-12-05 00:04:40 +01:00
static buildArmeList ( combatant ) {
const actor = combatant . actor ; // Easy access
2020-11-24 17:41:14 +01:00
let armesList = [ ] ;
if ( actor . data . type == 'creature' || actor . data . type == 'entite' ) {
for ( const competenceItem of actor . data . items ) {
2020-12-05 00:04:40 +01:00
if ( competenceItem . data . iscombat ) { // Seul un item de type arme
2020-11-24 17:41:14 +01:00
armesList . push ( { name : competenceItem . name , data : { niveau : competenceItem . data . niveau , competence : competenceItem . name } } ) ;
}
}
} else {
// Recupération des items 'arme'
let itemsByType = RdDUtility . buildItemsClassification ( combatant . actor . data . items ) ;
armesList = itemsByType [ 'arme' ] ;
// Force corps à corps et Draconic
let cc = RdDUtility . findCompetence ( combatant . actor . data . items , "Corps à corps" ) ;
armesList . push ( { name : "Corps à corps" , data : { niveau : cc . data . niveau , description : "" , force : 6 , competence : "Corps à corps" , dommages : combatant . actor . data . data . attributs . plusdom . value } } ) ;
2020-12-05 21:24:31 +01:00
armesList . push ( { name : "Draconic" , data : { initOnly : true , competence : "Draconic" } } ) ;
2020-11-24 17:41:14 +01:00
}
2020-12-05 21:24:31 +01:00
armesList . push ( { name : "Autre action" , data : { initOnly : true , competence : "Autre action" } } ) ;
2020-12-05 00:04:40 +01:00
return armesList ;
}
/* -------------------------------------------- */
static displayInitiativeMenu ( html , combatantId ) {
const combatant = game . combat . getCombatant ( combatantId ) ;
let armesList = this . buildArmeList ( combatant ) ;
2020-11-24 17:41:14 +01:00
// Build the relevant submenu
if ( armesList ) {
2020-11-24 16:41:15 +01:00
let menuItems = [ ] ;
for ( let arme of armesList ) {
menuItems . push ( {
name : arme . data . competence ,
icon : "<i class='fas fa-dice-d6'></i>" ,
callback : target => { RdDUtility . rollInitiativeCompetence ( combatantId , arme ) } } ) ;
}
2020-11-24 17:41:14 +01:00
new ContextMenu ( html , ".directory-list" , menuItems ) . render ( ) ;
2020-11-24 16:41:15 +01:00
}
}
/* -------------------------------------------- */
static pushInitiativeOptions ( html , options ) {
options . push (
{
name : "Sélectionner l'initiative..." ,
condition : true ,
icon : '<i class="far fa-question-circle"></i>' ,
callback : target => {
RdDUtility . displayInitiativeMenu ( html , target . data ( 'combatant-id' ) ) ;
}
2020-11-24 16:43:54 +01:00
} ) ;
}
/* -------------------------------------------- */
2020-11-24 15:20:05 +01:00
static _handleMsgEncaisser ( data ) {
if ( game . user . isGM ) { // Seul le GM effectue l'encaissement sur la fiche
2020-12-15 02:20:24 +01:00
let attackerRoll = game . system . rdd . rollDataHandler [ data . attackerId ] ; // Retrieve the rolldata from the store
2020-12-02 00:09:47 +01:00
let defenderToken = canvas . tokens . get ( data . defenderTokenId ) ;
2020-12-15 02:20:24 +01:00
defenderToken . actor . encaisserDommages ( attackerRoll ) ;
2020-11-24 15:20:05 +01:00
}
2020-11-24 16:41:15 +01:00
}
2020-06-07 23:16:29 +02:00
/* -------------------------------------------- */
static async chatListeners ( html )
{
2020-12-12 21:58:44 +01:00
RdDCombat . registerChatCallbacks ( html ) ;
2020-06-07 23:16:29 +02:00
html . on ( "click" , '#encaisser-button' , event => {
event . preventDefault ( ) ;
2020-12-12 21:58:44 +01:00
if ( RdDCombat . isActive ( ) ) return ;
let attackerId = event . currentTarget . attributes [ 'data-attackerId' ] . value ;
let defenderTokenId = event . currentTarget . attributes [ 'data-defenderTokenId' ] . value ;
2020-06-22 10:18:03 +02:00
if ( game . user . isGM ) { // Current user is the GM -> direct access
2020-12-12 21:58:44 +01:00
let rollData = game . system . rdd . rollDataHandler [ attackerId ] ;
rollData . attackerId = attackerId ;
2020-12-02 00:09:47 +01:00
rollData . defenderTokenId = defenderTokenId ;
let defenderToken = canvas . tokens . get ( defenderTokenId ) ;
2020-12-12 21:58:44 +01:00
defenderToken . actor . encaisserDommages ( rollData , game . actors . get ( attackerId ) ) ;
2020-06-22 10:18:03 +02:00
} else { // Emit message for GM
game . socket . emit ( "system.foundryvtt-reve-de-dragon" , {
msg : "msg_encaisser" ,
2020-12-12 21:58:44 +01:00
data : { attackerId : attackerId , defenderTokenId : defenderTokenId }
2020-06-22 10:18:03 +02:00
} ) ;
}
2020-07-27 18:58:10 +02:00
} ) ;
2020-06-10 08:23:58 +02:00
html . on ( "click" , '#parer-button' , event => {
event . preventDefault ( ) ;
2020-12-12 21:58:44 +01:00
if ( RdDCombat . isActive ( ) ) return ;
let attackerId = event . currentTarget . attributes [ 'data-attackerId' ] . value ;
2020-12-02 00:09:47 +01:00
let defenderToken = canvas . tokens . get ( event . currentTarget . attributes [ 'data-defenderTokenId' ] . value ) ;
2020-06-10 08:23:58 +02:00
let armeId = event . currentTarget . attributes [ 'data-armeid' ] . value ;
2020-12-12 21:58:44 +01:00
let rollData = game . system . rdd . rollDataHandler [ attackerId ] ;
defenderToken . actor . parerAttaque ( rollData , armeId , game . actors . get ( attackerId ) ) ;
2020-07-27 18:58:10 +02:00
} ) ;
2020-12-12 21:58:44 +01:00
2020-07-27 18:58:10 +02:00
html . on ( "click" , '#esquiver-button' , event => {
event . preventDefault ( ) ;
2020-12-12 21:58:44 +01:00
if ( RdDCombat . isActive ( ) ) return ;
let attackerId = event . currentTarget . attributes [ 'data-attackerId' ] . value ;
2020-12-02 00:09:47 +01:00
let defenderToken = canvas . tokens . get ( event . currentTarget . attributes [ 'data-defenderTokenId' ] . value ) ;
2020-12-12 21:58:44 +01:00
let rollData = game . system . rdd . rollDataHandler [ attackerId ] ;
2020-11-14 21:53:46 +01:00
//console.log("Esquive !", rollData, defenderActor);
2020-12-12 21:58:44 +01:00
defenderToken . actor . esquiverAttaque ( rollData , game . actors . get ( attackerId ) ) ;
2020-06-10 08:23:58 +02:00
} ) ;
2020-12-12 21:58:44 +01:00
2020-11-14 21:22:29 +01:00
html . on ( "click" , '#particuliere-attaque' , event => {
event . preventDefault ( ) ;
2020-12-12 21:58:44 +01:00
if ( RdDCombat . isActive ( ) ) return ;
let attackerId = event . currentTarget . attributes [ 'data-attackerId' ] . value ;
let attackerActor = game . actors . get ( event . currentTarget . attributes [ 'data-attackerId' ] . value ) ;
let rollData = game . system . rdd . rollDataHandler [ attackerId ] ;
rollData . particuliereAttaque = event . currentTarget . attributes [ 'data-mode' ] . value ;
2020-11-14 21:53:46 +01:00
//console.log("Particulère !", rollData);
2020-11-14 21:22:29 +01:00
attackerActor . continueRoll ( rollData ) ;
} ) ;
2020-12-12 21:58:44 +01:00
2020-11-17 16:30:03 +01:00
html . on ( "click" , '.tmr-passeur-coord a' , event => {
2020-11-17 18:08:19 +01:00
let coord = event . currentTarget . attributes [ 'data-tmr-coord' ] . value ;
let actorId = event . currentTarget . attributes [ 'data-actor-id' ] . value ;
let actor = game . actors . get ( actorId ) ;
actor . tmrApp . forceDemiRevePosition ( coord ) ;
} ) ;
2020-06-07 23:16:29 +02:00
}
2020-09-13 22:46:42 +02:00
/* -------------------------------------------- */
/* Display help for /table */
static displayHelpTable ( msg )
{
msg . content = "" ;
for ( let [ name , tableData ] of Object . entries ( table2func ) ) {
msg . content += "<br>" + tableData . descr ;
}
ChatMessage . create ( msg ) ;
}
/* -------------------------------------------- */
/* Manage chat commands */
2020-12-12 21:58:44 +01:00
static processChatCommand ( commands , content , msg ) {
2020-09-13 22:46:42 +02:00
// Setup new message's visibility
let rollMode = game . settings . get ( "core" , "rollMode" ) ;
2020-11-03 09:14:14 +01:00
if ( [ "gmroll" , "blindroll" ] . includes ( rollMode ) ) msg [ "whisper" ] = ChatMessage . getWhisperRecipients ( "GM" ) ;
2020-09-13 22:46:42 +02:00
if ( rollMode === "blindroll" ) msg [ "blind" ] = true ;
msg [ "type" ] = 0 ;
let command = commands [ 0 ] ;
// Roll on a table
if ( command === "/table" ) {
if ( commands [ 1 ] ) {
let tableName = commands [ 1 ] . toLowerCase ( ) ;
2020-11-03 09:14:14 +01:00
table2func [ tableName ] . func ( ) ;
2020-09-13 22:46:42 +02:00
} else {
this . displayHelpTable ( msg ) ;
}
return false
} else if ( command === "/tmrr" ) {
TMRUtility . getRencontre ( commands [ 1 ] , commands [ 2 ] )
return false
2020-09-13 23:08:52 +02:00
} else if ( command === "/tmra" ) {
TMRUtility . getTMRAleatoire ( )
return false
}
2020-09-13 22:46:42 +02:00
return true ;
}
2020-05-22 22:37:02 +02:00
}