2020-05-22 22:37:02 +02:00
import { RdDUtility } from "./rdd-utility.js" ;
2020-07-25 10:29:28 +02:00
import { TMRUtility } from "./tmr-utility.js" ;
2020-12-06 20:11:30 +01:00
import { RdDRollDialogEthylisme } from "./rdd-roll-ethylisme.js" ;
2020-12-06 19:29:10 +01:00
import { RdDRoll } from "./rdd-roll.js" ;
2020-07-05 21:45:25 +02:00
import { RdDTMRDialog } from "./rdd-tmr-dialog.js" ;
2020-11-14 03:16:03 +01:00
import { Misc } from "./misc.js" ;
2020-12-11 08:29:24 +01:00
import { RdDAstrologieJoueur } from "./rdd-astrologie-joueur.js" ;
2020-11-12 16:35:51 +01:00
import { RdDResolutionTable } from "./rdd-resolution-table.js" ;
2020-11-16 04:32:42 +01:00
import { RdDDice } from "./rdd-dice.js" ;
import { RdDRollTables } from "./rdd-rolltables.js" ;
2020-11-24 15:20:05 +01:00
import { ChatUtility } from "./chat-utility.js" ;
2020-12-04 20:52:04 +01:00
import { RdDItemSort } from "./item-sort.js" ;
2020-12-08 03:04:00 +01:00
import { Grammar } from "./grammar.js" ;
2020-12-27 19:55:51 +01:00
import { RdDEncaisser } from "./rdd-roll-encaisser.js" ;
2020-12-12 21:58:44 +01:00
import { RdDCombat } from "./rdd-combat.js" ;
2020-12-31 11:53:41 +01:00
import { DeDraconique } from "./de-draconique.js" ;
2021-01-02 00:04:27 +01:00
import { RdDAudio } from "./rdd-audio.js" ;
2021-01-01 22:25:32 +01:00
import { RdDItemCompetence } from "./item-competence.js" ;
2021-01-04 00:17:22 +01:00
import { RdDItemArme } from "./item-arme.js" ;
2021-01-07 20:04:10 +01:00
import { RdDAlchimie } from "./rdd-alchimie.js" ;
2021-01-13 03:42:13 +01:00
import { StatusEffects } from "./status-effects.js" ;
2021-01-13 23:47:12 +01:00
import { RdDItemCompetenceCreature } from "./item-competencecreature.js" ;
2021-01-13 03:42:13 +01:00
2020-05-22 22:37:02 +02:00
2020-12-31 00:55:02 +01:00
/* -------------------------------------------- */
2020-12-15 23:54:05 +01:00
/ * *
* Extend the base Actor entity by defining a custom roll data structure which is ideal for the Simple system .
* @ extends { Actor }
* /
2020-05-22 00:48:43 +02:00
export class RdDActor extends Actor {
2021-01-10 00:30:37 +01:00
/* -------------------------------------------- */
static init ( ) {
2021-01-13 03:42:13 +01:00
Hooks . on ( "deleteActiveEffect" , ( actor , effect , options ) => actor . onDeleteActiveEffect ( effect , options ) ) ;
Hooks . on ( "createActiveEffect" , ( actor , effect , options ) => actor . onCreateActiveEffect ( effect , options ) ) ;
2021-01-10 00:30:37 +01:00
}
2021-01-13 03:42:13 +01:00
2020-05-24 20:19:57 +02:00
/* -------------------------------------------- */
/ * *
* Override the create ( ) function to provide additional RdD functionality .
*
* This overrided create ( ) function adds initial items
* Namely : Basic skills , money ,
*
* @ param { Object } data Barebones actor data which this function adds onto .
* @ param { Object } options ( Unused ) Additional options which customize the creation workflow .
*
* /
2021-01-09 19:33:19 +01:00
2020-05-24 20:19:57 +02:00
static async create ( data , options ) {
2021-01-09 19:33:19 +01:00
2020-11-18 16:33:12 +01:00
// Case of compendium global import
2020-12-01 17:36:13 +01:00
if ( data instanceof Array ) {
2020-11-18 16:33:12 +01:00
return super . create ( data , options ) ;
2020-12-01 17:36:13 +01:00
}
2020-05-24 20:19:57 +02:00
// If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic
if ( data . items ) {
2021-01-08 22:23:50 +01:00
let actor = super . create ( data , options ) ;
2021-01-05 11:47:22 +01:00
if ( data . type == "personnage" ) {
2021-01-09 19:33:19 +01:00
await actor . checkMonnaiePresence ( data . items ) ;
2021-01-05 11:47:22 +01:00
}
2021-01-08 22:23:50 +01:00
return actor ;
2020-05-24 20:19:57 +02:00
}
2021-01-09 19:33:19 +01:00
2021-01-10 22:12:07 +01:00
let compendiumName ;
2020-11-14 23:24:01 +01:00
if ( data . type == "personnage" ) {
2020-09-20 17:38:21 +02:00
compendiumName = "foundryvtt-reve-de-dragon.competences" ;
2020-11-14 23:24:01 +01:00
} else if ( data . type == "creature" ) {
2020-09-20 17:38:21 +02:00
compendiumName = "foundryvtt-reve-de-dragon.competences-creatures" ;
2020-11-14 23:24:01 +01:00
} else if ( data . type == "entite" ) {
compendiumName = "foundryvtt-reve-de-dragon.competences-entites" ;
2020-06-22 10:18:03 +02:00
}
2021-01-10 22:12:07 +01:00
if ( compendiumName ) {
2021-01-12 13:18:29 +01:00
data . items = await RdDUtility . loadCompendium ( compendiumName ) ;
2021-01-10 22:12:07 +01:00
}
2020-12-31 00:55:02 +01:00
// Ajout monnaie
2021-01-12 13:18:29 +01:00
if ( data . type == "personnage" && data . items ) {
2021-01-09 19:33:19 +01:00
await RdDActor . ajouterMonnaie ( data . items ) ;
}
2020-12-31 00:55:02 +01:00
2020-09-27 22:33:02 +02:00
return super . create ( data , options ) ;
2020-09-20 16:36:39 +02:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-05-22 00:48:43 +02:00
prepareData ( ) {
super . prepareData ( ) ;
2020-05-21 21:48:20 +02:00
2020-05-22 00:48:43 +02:00
const actorData = this . data ;
2020-05-22 19:28:01 +02:00
2020-11-11 14:42:11 +01:00
// Dynamic computing fields
2020-12-20 21:54:09 +01:00
this . encTotal = 0 ;
2020-11-11 14:42:11 +01:00
2020-12-04 10:15:55 +01:00
/ *
// Auto-resize token
if ( this . isToken ) {
let tokenSize = actorData . data . carac . taille . value / 10 ;
this . token . update ( { height : tokenSize , width : tokenSize } ) ;
} * /
2021-01-09 19:33:19 +01:00
2020-05-22 00:48:43 +02:00
// Make separate methods for each Actor type (character, npc, etc.) to keep
// things organized.
if ( actorData . type === 'personnage' ) this . _prepareCharacterData ( actorData ) ;
2021-01-08 16:57:10 +01:00
if ( actorData . type === 'creature' ) this . prepareCreatureData ( actorData ) ;
2021-01-10 22:12:07 +01:00
if ( actorData . type === 'vehicule' ) this . prepareVehiculeData ( actorData ) ;
2021-01-08 16:57:10 +01:00
}
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
prepareCreatureData ( actorData ) {
2021-01-08 16:57:10 +01:00
this . computeEncombrementTotalEtMalusArmure ( ) ;
this . computeEtatGeneral ( ) ;
2020-05-22 00:48:43 +02:00
}
2021-01-10 22:12:07 +01:00
/* -------------------------------------------- */
prepareVehiculeData ( actorData ) {
this . computeEncombrementTotalEtMalusArmure ( ) ;
}
2020-06-03 21:35:18 +02:00
/* -------------------------------------------- */
2020-05-22 00:48:43 +02:00
/ * *
* Prepare Character type specific data
* /
2021-01-01 21:11:56 +01:00
async _prepareCharacterData ( actorData ) {
2020-05-24 20:19:57 +02:00
// Initialize empty items
RdDUtility . computeCarac ( actorData . data ) ;
2020-12-02 14:00:54 +01:00
this . computeEncombrementTotalEtMalusArmure ( ) ;
2020-06-07 23:16:29 +02:00
this . computeEtatGeneral ( ) ;
2021-01-05 11:25:28 +01:00
// Sanity check
2021-01-07 11:42:36 +01:00
await this . checkMonnaiePresence ( actorData . items ) ;
2020-05-22 00:48:43 +02:00
}
2020-12-31 00:55:02 +01:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async checkMonnaiePresence ( items ) { // Ajout opportuniste si les pièces n'existent pas.
if ( ! items ) return ; // Sanity check during import
let piece = items . find ( item => item . type == 'monnaie' && Number ( item . data . valeur _deniers ) == 1 ) ;
2021-01-07 11:42:36 +01:00
let newMonnaie = [ ] ;
2020-12-31 10:55:40 +01:00
if ( ! piece ) {
2021-01-09 19:33:19 +01:00
newMonnaie . push ( RdDUtility . createMonnaie ( "Etain (1 denier)" , 1 , "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp" ) ) ;
2020-12-31 10:55:40 +01:00
}
2021-01-09 19:33:19 +01:00
piece = items . find ( item => item . type == 'monnaie' && Number ( item . data . valeur _deniers ) == 10 ) ;
2020-12-31 10:55:40 +01:00
if ( ! piece ) {
2021-01-09 19:33:19 +01:00
newMonnaie . push ( RdDUtility . createMonnaie ( "Bronze (10 deniers)" , 10 , "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp" ) ) ;
2020-12-31 10:55:40 +01:00
}
2021-01-09 19:33:19 +01:00
piece = items . find ( item => item . type == 'monnaie' && Number ( item . data . valeur _deniers ) == 100 ) ;
2020-12-31 10:55:40 +01:00
if ( ! piece ) {
2021-01-07 11:42:36 +01:00
newMonnaie . push ( RdDUtility . createMonnaie ( "Argent (1 sol)" , 100 , "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp" ) ) ;
2020-12-31 10:55:40 +01:00
}
2021-01-09 19:33:19 +01:00
piece = items . find ( item => item . type == 'monnaie' && Number ( item . data . valeur _deniers ) == 1000 ) ;
2020-12-31 10:55:40 +01:00
if ( ! piece ) {
2021-01-09 19:33:19 +01:00
newMonnaie . push ( RdDUtility . createMonnaie ( "Or (10 sols)" , 1000 , "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp" ) ) ;
2021-01-07 11:42:36 +01:00
}
2021-01-09 19:33:19 +01:00
if ( newMonnaie . length > 0 ) {
await this . createOwnedItem ( newMonnaie ) ;
2020-12-31 10:55:40 +01:00
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
static async ajouterMonnaie ( items ) { // Creation auto à la création du personnage
2021-01-05 11:59:03 +01:00
let etain = RdDUtility . createMonnaie ( "Etain (1 denier)" , 1 , "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp" ) ;
2020-12-31 10:55:40 +01:00
items . push ( etain ) ;
2021-01-09 19:33:19 +01:00
2021-01-05 11:47:22 +01:00
let bronze = RdDUtility . createMonnaie ( "Bronze (10 deniers)" , 10 , "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp" ) ;
2020-12-31 10:55:40 +01:00
items . push ( bronze ) ;
2021-01-09 19:33:19 +01:00
2021-01-05 11:47:22 +01:00
let argent = RdDUtility . createMonnaie ( "Argent (1 sol)" , 100 , "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp" ) ;
2020-12-31 10:55:40 +01:00
items . push ( argent ) ;
2021-01-09 19:33:19 +01:00
2021-01-05 11:47:22 +01:00
let or = RdDUtility . createMonnaie ( "Or (10 sols)" , 1000 , "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp" ) ;
2020-12-31 10:55:40 +01:00
items . push ( or ) ;
}
2021-01-09 19:33:19 +01:00
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
isCreature ( ) {
return this . data . type == 'creature' || this . data . type == 'entite' ;
}
2020-12-15 23:54:05 +01:00
2020-12-18 23:57:28 +01:00
/* -------------------------------------------- */
isPersonnage ( ) {
return this . data . type == 'personnage' ;
}
2020-07-14 22:19:29 +02:00
/* -------------------------------------------- */
2020-11-16 04:01:36 +01:00
getReveActuel ( ) {
2021-01-23 18:36:30 +01:00
return Misc . toInt ( this . data . data . reve ? . reve ? . value ? ? this . data . data . carac . reve . value ) ;
2020-07-14 22:19:29 +02:00
}
2021-01-23 18:36:30 +01:00
/* -------------------------------------------- */
2020-12-06 19:29:10 +01:00
getChanceActuel ( ) {
2021-01-23 18:36:30 +01:00
return Misc . toInt ( this . data . data . compteurs . chance ? . value ? ? 10 ) ;
2020-12-06 19:29:10 +01:00
}
2020-12-15 02:20:24 +01:00
/* -------------------------------------------- */
2021-01-23 18:36:30 +01:00
getTaille ( ) {
return Misc . toInt ( this . data . data . carac . taille ? . value ) ;
}
/* -------------------------------------------- */
getForce ( ) {
if ( this . isEntiteCauchemar ( ) ) {
return Misc . toInt ( this . data . data . carac . reve ? . value ) ;
}
return Misc . toInt ( this . data . data . carac . force ? . value ) ;
}
/* -------------------------------------------- */
getAgilite ( ) {
switch ( this . data . type ) {
case 'personnage' : return Misc . toInt ( this . data . data . carac . agilite ? . value ) ;
case 'creature' : return Misc . toInt ( this . data . data . carac . force ? . value ) ;
case 'entite' : return Misc . toInt ( this . data . data . carac . reve ? . value ) ;
}
return 10 ;
2021-01-05 18:43:13 +01:00
}
getMoralTotal ( ) {
2021-01-23 18:36:30 +01:00
return Misc . toInt ( this . data . data . compteurs . moral ? . value ) ;
2020-12-12 21:58:44 +01:00
}
2020-12-15 02:20:24 +01:00
/* -------------------------------------------- */
getBonusDegat ( ) {
2020-12-16 23:02:15 +01:00
// TODO: gérer séparation et +dom créature/entité indépendament de la compétence
2020-12-15 18:36:18 +01:00
return Misc . toInt ( this . data . data . attributs . plusdom . value ) ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-12-15 18:36:18 +01:00
getProtectionNaturelle ( ) {
return Misc . toInt ( this . data . data . attributs . protection . value ) ;
2020-12-15 02:20:24 +01:00
}
2021-01-13 16:34:24 +01:00
/* -------------------------------------------- */
2021-01-05 18:43:13 +01:00
getEtatGeneral ( ) {
2021-01-23 18:36:30 +01:00
return Misc . toInt ( this . data . data . compteurs . etat ? . value ) ;
2021-01-05 18:43:13 +01:00
}
getMalusArmure ( ) {
2021-01-23 18:36:30 +01:00
return Misc . toInt ( this . data . data . attributs ? . malusarmure ? . value ) ;
2021-01-05 18:43:13 +01:00
}
getEncTotal ( ) {
return Math . floor ( this . encTotal ? ? 0 ) ;
}
2021-01-09 19:33:19 +01:00
getSurenc ( ) {
2021-01-23 18:36:30 +01:00
return Misc . toInt ( this . data . data . compteurs . surenc ? . value ) ;
2021-01-05 18:43:13 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2021-01-08 22:23:50 +01:00
loadCompendiumNames ( ) {
2021-01-09 19:33:19 +01:00
return this . data . items . filter ( ( item ) => item . type == 'competence' ) ;
}
2020-12-12 21:58:44 +01:00
/* -------------------------------------------- */
getCompetence ( compName ) {
2021-01-08 22:23:50 +01:00
return RdDItemCompetence . findCompetence ( this . data . items , compName ) ;
2021-01-09 19:33:19 +01:00
}
2021-01-05 18:43:13 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
getTache ( id ) {
return this . data . items . find ( item => item . type == 'tache' && item . _id == id ) ;
2021-01-05 18:43:13 +01:00
}
2021-01-09 19:33:19 +01:00
getMeditation ( id ) {
return this . data . items . find ( item => item . type == 'meditation' && item . _id == id ) ;
2020-12-12 21:58:44 +01:00
}
2020-07-14 22:19:29 +02:00
/* -------------------------------------------- */
getBestDraconic ( ) {
2021-01-09 19:33:19 +01:00
const list = this . getDraconicList ( ) . sort ( ( a , b ) => b . data . niveau - a . data . niveau ) ;
if ( list . length == 0 ) {
2020-11-12 14:20:10 +01:00
return { name : "none" , niveau : - 11 } ;
2021-01-09 19:33:19 +01:00
}
2020-11-12 14:20:10 +01:00
return duplicate ( list [ 0 ] ) ;
2021-01-09 19:33:19 +01:00
}
2021-01-02 04:28:43 +01:00
2020-07-26 18:44:03 +02:00
/* -------------------------------------------- */
2020-12-30 19:18:07 +01:00
async deleteSortReserve ( sortReserve ) {
2020-07-26 18:44:03 +02:00
let reserve = duplicate ( this . data . data . reve . reserve ) ;
let len = reserve . list . length ;
let i = 0 ;
let newTable = [ ] ;
2021-01-09 19:33:19 +01:00
for ( i = 0 ; i < len ; i ++ ) {
if ( reserve . list [ i ] . coord != sortReserve . coord && reserve . list [ i ] . sort . name != sortReserve . sort . name )
newTable . push ( reserve . list [ i ] ) ;
2020-07-26 18:44:03 +02:00
}
2021-01-09 19:33:19 +01:00
if ( newTable . length != len ) {
2020-07-26 18:44:03 +02:00
reserve . list = newTable ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.reve.reserve" : reserve } ) ;
2020-07-26 18:44:03 +02:00
}
}
2021-01-09 19:33:19 +01:00
2020-12-14 10:38:43 +01:00
/* -------------------------------------------- */
2021-01-13 03:42:13 +01:00
getSurprise ( isCombat = true ) {
let niveauSurprise = Array . from ( this . effects ? . values ( ) ? ? [ ] )
. map ( effect => StatusEffects . valeurSurprise ( effect . data , isCombat ) )
. reduce ( ( a , b ) => a + b , 0 ) ;
if ( niveauSurprise > 1 ) {
return 'totale' ;
}
if ( niveauSurprise == 1 || this . getSonne ( ) ) {
2020-12-12 21:58:44 +01:00
return 'demi' ;
}
return '' ;
}
2020-12-04 20:52:04 +01:00
/* -------------------------------------------- */
2020-11-24 18:54:13 +01:00
async dormirChateauDormant ( ) {
2021-01-09 19:33:19 +01:00
let message = {
whisper : ChatUtility . getWhisperRecipientsAndGMs ( this . name ) ,
content : ""
2020-11-24 18:54:13 +01:00
} ;
2020-12-19 01:14:02 +01:00
2020-11-24 18:54:13 +01:00
const blessures = duplicate ( this . data . data . blessures ) ;
console . log ( "dormirChateauDormant" , blessures )
await this . _recupererBlessures ( message , "legere" , blessures . legeres . liste . filter ( b => b . active ) , [ ] ) ;
await this . _recupererBlessures ( message , "grave" , blessures . graves . liste . filter ( b => b . active ) , blessures . legeres . liste ) ;
2020-12-27 20:23:14 +01:00
await this . _recupererBlessures ( message , "critique" , blessures . critiques . liste . filter ( b => b . active ) , blessures . graves . liste ) ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.blessures" : blessures } ) ;
2020-11-24 18:54:13 +01:00
await this . _recupererVie ( message ) ;
await this . transformerStress ( message ) ;
await this . retourSeuilDeReve ( message ) ;
2021-01-09 19:33:19 +01:00
message . content = ` A la fin Chateau Dormant, ${ message . content } <br>Un nouveau jour se lève ` ;
ChatMessage . create ( message ) ;
2020-11-24 18:54:13 +01:00
}
2020-12-04 20:52:04 +01:00
/* -------------------------------------------- */
2020-11-24 18:54:13 +01:00
async _recupererBlessures ( message , type , liste , moindres ) {
let count = 0 ;
const definitions = RdDUtility . getDefinitionsBlessures ( ) ;
2021-01-09 19:33:19 +01:00
let definition = definitions . find ( d => d . type == type ) ;
2020-11-24 18:54:13 +01:00
for ( let blessure of liste ) {
if ( blessure . jours >= definition . facteur ) {
let rolled = await this . _jetRecuperationConstitution ( Misc . toInt ( blessure . soins _complets ) , message ) ;
blessure . soins _complets = 0 ;
if ( rolled . isSuccess && this . _retrograderBlessure ( type , blessure , moindres ) ) {
2021-01-09 19:33:19 +01:00
message . content += ` -- une blessure ${ type } cicatrise ` ;
count ++ ;
2020-11-24 18:54:13 +01:00
}
else if ( rolled . isETotal ) {
2021-01-09 19:33:19 +01:00
message . content += ` -- une blessure ${ type } s'infecte (temps de guérison augmenté de ${ definition . facteur } jours, perte de vie) ` ;
blessure . jours = 0 ;
await this . santeIncDec ( "vie" , - 1 ) ;
2020-11-24 18:54:13 +01:00
}
else {
2021-01-09 19:33:19 +01:00
message . content += ` -- une blessure ${ type } reste stable ` ;
2020-11-24 18:54:13 +01:00
}
}
else {
blessure . jours ++ ;
}
}
}
2020-12-05 21:24:31 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
_retrograderBlessure ( type , blessure , blessuresMoindres ) {
2020-11-24 18:54:13 +01:00
if ( type != "legere" ) {
let retrograde = blessuresMoindres . find ( b => ! b . active ) ;
if ( ! retrograde ) {
return false ;
}
2020-12-15 02:20:24 +01:00
mergeObject ( retrograde , { "active" : true , "premiers_soins" : 0 , "soins_complets" : 0 , "jours" : 0 , "loc" : blessure . loc } ) ;
2020-11-24 18:54:13 +01:00
}
2020-12-01 01:17:18 +01:00
this . _supprimerBlessure ( blessure ) ;
2020-11-24 18:54:13 +01:00
return true ;
}
2021-01-09 19:33:19 +01:00
2020-12-05 21:24:31 +01:00
/* -------------------------------------------- */
2020-12-01 01:17:18 +01:00
_supprimerBlessure ( blessure ) {
2020-12-15 02:20:24 +01:00
mergeObject ( blessure , { "active" : false , "premiers_soins" : 0 , "soins_complets" : 0 , "jours" : 0 , "loc" : "" } ) ;
2020-12-01 01:17:18 +01:00
}
2020-12-05 21:24:31 +01:00
/* -------------------------------------------- */
2020-11-24 18:54:13 +01:00
async _recupererVie ( message ) {
let blessures = [ ] . concat ( this . data . data . blessures . legeres . liste ) . concat ( this . data . data . blessures . graves . liste ) . concat ( this . data . data . blessures . critiques . liste ) ;
let nbBlessures = blessures . filter ( b => b . active ) ;
let vieManquante = this . data . data . sante . vie . max - this . data . data . sante . vie . value ;
2021-01-09 19:33:19 +01:00
if ( nbBlessures == 0 && vieManquante > 0 ) {
2020-11-24 18:54:13 +01:00
let bonusSoins = 0 ;
2021-01-09 19:33:19 +01:00
for ( let b of blessures ) {
2020-11-24 18:54:13 +01:00
bonusSoins = Math . max ( bonusSoins , Misc . toInt ( b . soins _complets ) ) ;
}
let rolled = await this . _jetRecuperationConstitution ( bonusSoins , message )
if ( rolled . isSuccess ) {
const gain = Math . min ( rolled . isPart ? 2 : 1 , vieManquante ) ;
2021-01-09 19:33:19 +01:00
message . content += " -- récupération de vie: " + gain ;
2020-11-24 18:54:13 +01:00
await this . santeIncDec ( "vie" , gain ) ;
}
else if ( rolled . isETotal ) {
message . content += " -- perte de vie: 1" ;
await this . santeIncDec ( "vie" , - 1 ) ;
}
2021-01-09 19:33:19 +01:00
else {
message . content += " -- vie stationnaire " ;
2020-11-24 18:54:13 +01:00
}
}
}
2020-12-05 21:24:31 +01:00
/* -------------------------------------------- */
2020-11-24 18:54:13 +01:00
async _jetRecuperationConstitution ( bonusSoins , message = undefined ) {
let difficulte = Misc . toInt ( bonusSoins ) + Math . min ( 0 , this . data . data . sante . vie . value - this . data . data . sante . vie . max ) ;
let rolled = await RdDResolutionTable . roll ( this . data . data . carac . constitution . value , difficulte ) ;
if ( message ) {
message . content += RdDResolutionTable . explain ( rolled ) . replace ( /Jet :/ , "Constitution :" ) ;
}
return rolled ;
}
2020-12-05 21:24:31 +01:00
/* -------------------------------------------- */
2020-12-01 01:17:18 +01:00
async remiseANeuf ( ) {
2021-01-09 19:33:19 +01:00
let message = {
whisper : ChatUtility . getWhisperRecipientsAndGMs ( this . name ) ,
content : "Remise à neuf de " + this . name
2020-12-01 01:17:18 +01:00
} ;
2020-12-27 22:21:08 +01:00
if ( this . isEntiteCauchemar ( ) ) {
await this . santeIncDec ( "endurance" , this . data . data . sante . endurance . max - this . data . data . sante . endurance . value ) ;
}
else {
2021-01-09 19:33:19 +01:00
if ( this . data . data . blessures ) {
2020-12-27 19:55:51 +01:00
const blessures = duplicate ( this . data . data . blessures ) ;
for ( let listeBlessures of [ blessures . legeres . liste , blessures . graves . liste , blessures . critiques . liste ] ) {
for ( let blessure of listeBlessures ) {
this . _supprimerBlessure ( blessure ) ;
}
2020-12-15 02:20:24 +01:00
}
2021-01-09 19:33:19 +01:00
await this . update ( { "data.blessures" : blessures } ) ;
2020-12-01 01:17:18 +01:00
}
2021-01-19 22:32:08 +01:00
if ( this . isPersonnage ( ) ) {
await this . setEthylisme ( 1 ) ;
}
2020-12-29 01:34:15 +01:00
2020-12-27 19:55:51 +01:00
await this . santeIncDec ( "vie" , this . data . data . sante . vie . max - this . data . data . sante . vie . value ) ;
2020-12-27 22:21:08 +01:00
await this . santeIncDec ( "endurance" , this . data . data . sante . endurance . max - this . data . data . sante . endurance . value ) ;
2021-01-09 19:33:19 +01:00
if ( this . data . data . sante . fatigue ) {
2020-12-27 19:55:51 +01:00
let fatigue = duplicate ( this . data . data . sante . fatigue )
fatigue . value = 0 ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.sante.fatigue" : fatigue } ) ;
2020-12-27 19:55:51 +01:00
}
2020-12-15 02:20:24 +01:00
}
2021-01-09 19:33:19 +01:00
ChatMessage . create ( message ) ;
2020-12-01 01:17:18 +01:00
}
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async dormir ( heures = 1 ) {
let message = {
whisper : ChatUtility . getWhisperRecipientsAndGMs ( this . name ) ,
2021-01-15 19:09:44 +01:00
content : this . name + ": Vous dormez " + heures + " heure" + ( heures > 1 ? "s" : "" )
2020-11-24 15:43:03 +01:00
} ;
2020-11-20 11:38:27 +01:00
await this . recupereEndurance ( message ) ;
2021-01-09 19:33:19 +01:00
for ( let i = 0 ; i < heures ; i ++ ) {
2020-12-19 01:14:02 +01:00
await this . _recupererEthylisme ( message ) ;
2020-11-20 11:38:27 +01:00
await this . recupererFatigue ( message ) ;
await this . recuperationReve ( message ) ;
2020-11-16 04:32:42 +01:00
}
2021-01-09 19:33:19 +01:00
ChatMessage . create ( message ) ;
2020-11-16 04:32:42 +01:00
}
2021-01-11 20:42:10 +01:00
/* -------------------------------------------- */
2020-12-19 01:14:02 +01:00
async _recupererEthylisme ( message ) {
let ethylisme = duplicate ( this . data . data . compteurs . ethylisme ) ;
2020-12-29 01:34:15 +01:00
ethylisme . nb _doses = 0 ;
ethylisme . jet _moral = false ;
2021-01-09 19:33:19 +01:00
if ( ethylisme . value < 1 ) {
2020-12-19 01:14:02 +01:00
ethylisme . value = Math . min ( ethylisme . value + 1 , 1 ) ;
if ( ethylisme . value <= 0 ) {
message . content += ` <br>Vous dégrisez un peu ( ${ RdDUtility . getNomEthylisme ( ethylisme . value ) } ) ` ;
}
}
2020-12-29 01:34:15 +01:00
await this . update ( { "data.compteurs.ethylisme" : ethylisme } ) ;
2020-12-19 01:14:02 +01:00
}
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
2020-11-20 11:38:27 +01:00
async recupereEndurance ( message ) {
const manquant = this . _computeEnduranceMax ( ) - this . data . data . sante . endurance . value ;
if ( manquant > 0 ) {
await this . santeIncDec ( "endurance" , manquant ) ;
message . content += "<br>Vous récuperez " + manquant + " points d'endurance" ;
2020-11-17 13:08:52 +01:00
}
}
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
2020-11-20 11:38:27 +01:00
async recupererFatigue ( message ) {
2020-11-17 13:08:52 +01:00
let fatigue = duplicate ( this . data . data . sante . fatigue )
2020-11-20 11:38:27 +01:00
const fatigueMin = this . _computeFatigueMin ( ) ;
if ( fatigue . value <= fatigueMin ) {
2020-11-17 13:08:52 +01:00
message . content += "<br>Vous êtes déjà reposé" ;
return ;
}
2020-11-20 11:38:27 +01:00
fatigue . value = Math . max ( fatigueMin , this . _calculRecuperationSegment ( fatigue . value ) ) ;
console . log ( "recupererFatigue" , fatigue )
2021-01-09 19:33:19 +01:00
await this . update ( { "data.sante.fatigue" : fatigue } ) ;
if ( fatigue . value == 0 ) {
2020-11-20 11:38:27 +01:00
message . content += "<br>Vous êtes bien reposé" ;
}
}
2020-11-21 08:27:28 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
_calculRecuperationSegment ( actuel ) {
2020-11-17 13:08:52 +01:00
const segments = RdDUtility . getSegmentsFatigue ( this . data . data . sante . endurance . max ) ;
let cumul = 0 ;
let i ;
2021-01-09 19:33:19 +01:00
for ( i = 0 ; i < 11 ; i ++ ) {
2020-11-17 13:08:52 +01:00
cumul += segments [ i ] ;
2020-11-20 11:38:27 +01:00
let diff = cumul - actuel ;
2021-01-09 19:33:19 +01:00
if ( diff >= 0 ) {
2020-11-17 13:08:52 +01:00
const limit2Segments = Math . floor ( segments [ i ] / 2 ) ;
if ( diff > limit2Segments && i > 0 ) {
2021-01-09 19:33:19 +01:00
cumul -= segments [ i - 1 ] ; // le segment est à moins de la moitié, il est récupéré
2020-11-16 04:32:42 +01:00
}
2020-11-17 13:08:52 +01:00
cumul -= segments [ i ] ;
break ;
}
2020-11-20 11:38:27 +01:00
} ;
return cumul ;
2020-11-17 13:08:52 +01:00
}
2020-11-24 15:45:41 +01:00
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async recuperationReve ( message ) {
2020-11-17 13:08:52 +01:00
const seuil = this . data . data . reve . seuil . value ;
2020-11-25 00:49:21 +01:00
const reveActuel = this . getReveActuel ( ) ;
if ( reveActuel >= seuil ) {
2021-01-02 19:57:38 +01:00
message . content += ` <br>Vous avez suffisament rêvé (seuil ${ seuil } , rêve actuel ${ reveActuel } ) ` ;
2020-11-17 13:08:52 +01:00
}
else {
2021-01-02 19:57:38 +01:00
let deRecuperation = ( await DeDraconique . ddr ( "selfroll" ) ) . total ;
2020-11-17 13:08:52 +01:00
console . log ( "recuperationReve" , deRecuperation ) ;
2021-01-09 19:33:19 +01:00
if ( deRecuperation >= 7 ) {
2020-11-17 13:08:52 +01:00
// Rêve de Dragon !
2021-01-02 19:57:38 +01:00
message . content += ` <br>Vous faites un <strong>Rêve de Dragon</strong> de ${ deRecuperation } Points de rêve ` ;
2020-11-25 00:49:21 +01:00
message . content += await this . combattreReveDeDragon ( deRecuperation ) ;
2020-11-16 04:32:42 +01:00
}
2021-01-09 19:33:19 +01:00
else {
2021-01-02 19:57:38 +01:00
message . content += ` <br>Vous récupérez ${ deRecuperation } Points de rêve ` ;
2020-11-25 00:49:21 +01:00
await this . reveActuelIncDec ( deRecuperation ) ;
2020-11-17 13:08:52 +01:00
}
}
2020-11-16 04:32:42 +01:00
}
2020-12-05 21:24:31 +01:00
/* -------------------------------------------- */
2020-11-24 18:54:13 +01:00
async retourSeuilDeReve ( message ) {
const seuil = this . data . data . reve . seuil . value ;
const reveActuel = this . getReveActuel ( ) ;
if ( reveActuel > seuil ) {
2021-01-09 19:33:19 +01:00
message . content += ` <br>Votre rêve redescend vers son seuil naturel ( ${ seuil } , nouveau rêve actuel ${ ( reveActuel - 1 ) } ) ` ;
2020-11-24 18:54:13 +01:00
await this . reveActuelIncDec ( - 1 ) ;
}
}
2020-11-16 04:32:42 +01:00
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async combattreReveDeDragon ( force ) {
2020-11-16 04:32:42 +01:00
let draconic = this . getBestDraconic ( ) ;
let niveau = Math . max ( 0 , draconic . data . niveau ) ;
2021-01-05 18:43:13 +01:00
let etat = this . getEtatGeneral ( ) ;
2020-11-16 04:32:42 +01:00
let difficulte = niveau - etat - force ;
let reveActuel = this . getReveActuel ( ) ;
2020-11-21 09:10:31 +01:00
let rolled = await RdDResolutionTable . roll ( reveActuel , difficulte ) ;
2020-11-17 13:08:52 +01:00
// TODO: xp particulière
2021-01-09 19:33:19 +01:00
console . log ( "combattreReveDeDragon" , rolled ) ;
2020-11-25 23:41:08 +01:00
return await this . appliquerReveDeDragon ( rolled , force ) ;
2020-11-16 04:32:42 +01:00
}
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
2020-11-25 23:41:08 +01:00
async appliquerReveDeDragon ( roll , force ) {
2020-11-16 04:32:42 +01:00
let message = "" ;
if ( roll . isSuccess ) {
message += "<br>Vous gagnez " + force + " points de Rêve" ;
2020-11-25 23:41:08 +01:00
await this . updatePointDeSeuil ( ) ;
await this . reveActuelIncDec ( force ) ;
2020-11-16 04:32:42 +01:00
}
if ( roll . isPart ) {
// TODO: Dialog pour choix entre HR opu général?
2021-01-15 08:27:21 +01:00
message += "<br>Vous gagnez une Tête de dragon: Demander à votre MJ d'effectuer un tirage sur la table des Hauts Rêvants ou des Vrais Rêvants, selon votre choix." ;
2020-11-16 04:32:42 +01:00
}
if ( roll . isEchec ) {
2020-12-17 02:20:03 +01:00
message += "<br>Vous subissez une Queue de Dragon: " + await this . ajouterQueue ( ) ;
2020-11-16 04:32:42 +01:00
}
if ( roll . isETotal ) {
2020-12-17 02:20:03 +01:00
message += "<br>A cause de votre échec total, vous subissez une deuxième Queue de Dragon: " + await this . ajouterQueue ( ) ;
2020-11-16 04:32:42 +01:00
}
return message ;
}
2020-11-15 11:15:36 +01:00
/* -------------------------------------------- */
2020-11-14 03:16:03 +01:00
async sortMisEnReserve ( rollData , sort ) {
let reserve = duplicate ( this . data . data . reve . reserve ) ;
2020-12-31 02:20:52 +01:00
reserve . list . push ( { coord : rollData . coord , sort : sort , draconic : duplicate ( rollData . competence ) } ) ;
2020-11-14 03:16:03 +01:00
await this . update ( { "data.reve.reserve" : reserve } ) ;
this . currentTMR . updateSortReserve ( ) ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async updateCarac ( caracName , caracValue ) {
2020-06-07 23:16:29 +02:00
let caracpath = "data.carac." + caracName + ".value"
2021-01-14 20:51:32 +01:00
if ( caracName == "force" ) {
2021-01-23 18:36:30 +01:00
if ( Number ( caracValue ) > this . getTaille ( ) + 4 ) {
2021-01-14 20:51:32 +01:00
ui . notifications . warn ( "Votre FORCE doit être au maximum de TAILLE+4" ) ;
return ;
}
}
2020-11-18 18:38:21 +01:00
if ( caracName == "reve" ) {
2020-11-16 04:32:42 +01:00
if ( caracValue > Misc . toInt ( this . data . data . reve . seuil . value ) ) {
2020-11-18 18:38:21 +01:00
this . setPointsDeSeuil ( caracValue ) ;
2020-11-16 04:32:42 +01:00
}
}
2021-01-11 17:54:24 +01:00
if ( caracName == "chance" ) {
if ( caracValue > Misc . toInt ( this . data . data . compteurs . chance . value ) ) {
this . setPointsDeChance ( caracValue ) ;
}
}
2021-01-09 19:33:19 +01:00
await this . update ( { [ caracpath ] : caracValue } ) ;
2020-05-24 20:19:57 +02:00
}
2021-01-03 18:19:18 +01:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async updateCaracXP ( caracName , caracXP ) {
2021-01-23 18:36:30 +01:00
if ( caracName == 'Taille' ) {
return ;
}
2021-01-09 19:33:19 +01:00
let caracpath = "data.carac." + caracName + ".xp" ;
await this . update ( { [ caracpath ] : caracXP } ) ;
this . checkCaracXP ( caracName ) ;
2021-01-03 18:19:18 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async updateCreatureCompetence ( compName , fieldName , compValue ) {
2020-12-12 21:58:44 +01:00
let comp = this . getCompetence ( compName ) ;
2021-01-09 19:33:19 +01:00
console . log ( comp ) ;
if ( comp ) {
const update = { _id : comp . _id }
2020-09-20 17:38:21 +02:00
if ( fieldName == "niveau" )
2020-09-20 19:17:31 +02:00
update [ 'data.niveau' ] = compValue ;
2020-09-20 17:38:21 +02:00
else if ( fieldName == "dommages" )
2020-09-20 19:17:31 +02:00
update [ 'data.dommages' ] = compValue ;
2021-01-09 19:33:19 +01:00
else
2020-09-20 19:17:31 +02:00
update [ 'data.carac_value' ] = compValue ;
console . log ( update ) ;
2020-09-20 17:38:21 +02:00
const updated = await this . updateEmbeddedEntity ( "OwnedItem" , update ) ; // Updates one EmbeddedEntity
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async updateCompetence ( compName , compValue ) {
2020-12-12 21:58:44 +01:00
let comp = this . getCompetence ( compName ) ;
2021-01-09 19:33:19 +01:00
if ( comp ) {
2021-01-14 23:59:57 +01:00
let troncList = RdDItemCompetence . isTronc ( compName ) ;
2020-08-13 22:28:56 +02:00
let maxNiveau = compValue ;
2021-01-09 19:33:19 +01:00
if ( troncList ) {
2020-09-05 22:56:33 +02:00
let message = "Vous avez modifié une compétence 'tronc'. Vérifiez que les compétences suivantes évoluent ensemble jusqu'au niveau 0 : " ;
2021-01-09 19:33:19 +01:00
for ( let troncName of troncList ) {
2020-09-05 22:56:33 +02:00
message += "<br>" + troncName ;
2020-08-13 22:28:56 +02:00
}
2021-01-09 19:33:19 +01:00
ChatMessage . create ( {
whisper : ChatMessage . getWhisperRecipients ( game . user . name ) ,
content : message
} ) ;
2020-08-13 22:28:56 +02:00
}
2021-01-09 19:33:19 +01:00
const update = { _id : comp . _id , 'data.niveau' : maxNiveau } ;
2020-06-01 23:50:10 +02:00
const updated = await this . updateEmbeddedEntity ( "OwnedItem" , update ) ; // Updates one EmbeddedEntity
2020-06-12 22:46:04 +02:00
} else {
console . log ( "Competence not found" , compName ) ;
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async updateCompetenceXP ( compName , compValue ) {
2020-12-12 21:58:44 +01:00
let comp = this . getCompetence ( compName ) ;
2021-01-09 19:33:19 +01:00
if ( comp ) {
2021-01-14 15:29:47 +01:00
this . checkCompetenceXP ( compName , compValue ) ;
2021-01-09 19:33:19 +01:00
const update = { _id : comp . _id , 'data.xp' : compValue } ;
2020-06-12 22:46:04 +02:00
const updated = await this . updateEmbeddedEntity ( "OwnedItem" , update ) ; // Updates one EmbeddedEntity
2020-06-01 23:50:10 +02:00
} else {
console . log ( "Competence not found" , compName ) ;
}
}
2021-01-03 19:19:02 +01:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async updateCompetenceArchetype ( compName , compValue ) {
2021-01-03 19:19:02 +01:00
let comp = this . getCompetence ( compName ) ;
2021-01-09 19:33:19 +01:00
if ( comp ) {
const update = { _id : comp . _id , 'data.niveau_archetype' : compValue } ;
2021-01-03 19:19:02 +01:00
const updated = await this . updateEmbeddedEntity ( "OwnedItem" , update ) ; // Updates one EmbeddedEntity
} else {
console . log ( "Competence not found" , compName ) ;
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async updateCompteurValue ( fieldName , fieldValue ) {
2020-08-29 22:52:41 +02:00
//console.log("Update", fieldName, fieldValue);
let compteurs = duplicate ( this . data . data . compteurs ) ;
2021-01-09 19:33:19 +01:00
compteurs [ fieldName ] . value = fieldValue ;
await this . update ( { "data.compteurs" : compteurs } ) ;
2020-08-29 22:52:41 +02:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async updateProtectionValue ( fieldName , fieldValue ) {
2020-12-18 01:10:03 +01:00
let attributs = duplicate ( this . data . data . attributs ) ;
attributs [ fieldName ] . value = fieldValue ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.attributs" : attributs } ) ;
2020-12-18 01:10:03 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
validateConteneur ( itemId , conteneurId ) {
let conteneurDest = this . items . find ( conteneur => conteneurId == conteneur . _id ) ; // recup conteneur
let conteneurSrc = this . items . find ( conteneur => itemId == conteneur . _id && conteneur . type == 'conteneur' ) ;
if ( conteneurSrc ) { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant
for ( let id of conteneurSrc . data . data . contenu ) {
let subObjet = this . items . find ( subobj => id == subobj . _id ) ;
if ( subObjet && subObjet . _id == conteneurDest . _id ) {
2021-01-08 09:58:15 +01:00
ui . notifications . warn ( "Impossible de déplacer un conteneur parent dans son fils !" ) ;
return false ; // Loop detected !
}
2021-01-09 19:33:19 +01:00
if ( subObjet && subObjet . type == 'conteneur' ) {
return this . validateConteneur ( subObjet . _id , conteneurId ) ;
2021-01-08 09:58:15 +01:00
}
}
}
return true ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-11-15 09:35:05 +01:00
/ * * T e s t e s i l e c o n t e n e u r d e d e s t i n a t i o n a s u f f i s a m e n t d e c a p a c i t é
* pour recevoir le nouvel objet
* /
2021-01-09 19:33:19 +01:00
testConteneurCapacite ( itemId , conteneurId ) {
if ( ! conteneurId ) return true ; // pas de conteneur (porté sur soi), donc toujours OK.
let conteneur = this . items . find ( conteneur => conteneurId == conteneur . _id ) ; // recup conteneur
2020-11-15 09:35:05 +01:00
//console.log("Conteneur trouvé : ", conteneur);
2021-01-09 19:33:19 +01:00
if ( conteneur && conteneur . type == "conteneur" ) {
2020-11-15 09:35:05 +01:00
let currentEnc = 0 ; // Calculer le total actuel des contenus
for ( let id of conteneur . data . data . contenu ) {
2021-01-09 19:33:19 +01:00
let objet = this . items . find ( objet => ( id == objet . _id ) ) ;
2020-11-15 09:35:05 +01:00
currentEnc += ( objet ) ? objet . data . data . encombrement : 0 ;
2021-01-09 19:33:19 +01:00
}
2020-11-15 09:35:05 +01:00
// Et gérer le nouvel objet
2021-01-09 19:33:19 +01:00
let nouvelObjet = this . items . find ( objet => ( itemId == objet . _id ) ) ;
2021-01-10 11:35:11 +01:00
if ( nouvelObjet && currentEnc + nouvelObjet . data . data . encombrement > Number ( conteneur . data . data . capacite ) ) {
2021-01-08 09:58:15 +01:00
ui . notifications . warn ( "Capacité d'encombrement insuffisante dans le conteneur !" ) ;
2020-11-15 09:35:05 +01:00
return false ;
2021-01-08 09:58:15 +01:00
}
2020-11-15 09:35:05 +01:00
}
return true ;
}
2021-01-10 02:28:45 +01:00
/* -------------------------------------------- */
buildSubConteneurObjetList ( conteneurId , deleteList ) {
let conteneur = this . items . find ( conteneur => conteneurId == conteneur . _id ) ; // recup conteneur
if ( conteneur && conteneur . type == 'conteneur' ) { // Si présent
for ( let subId of conteneur . data . data . contenu ) {
let subObj = this . items . find ( subobjet => subId == subobjet . _id ) ; // recup conteneur
if ( subObj && subObj . type == 'conteneur' ) {
this . buildSubConteneurObjetList ( subId , deleteList ) ;
2021-01-08 18:58:37 +01:00
}
2021-01-09 09:54:08 +01:00
if ( subObj ) // Robust...
2021-01-10 11:35:11 +01:00
deleteList . push ( { id : subId , conteneurId : conteneurId } ) ;
2021-01-08 18:58:37 +01:00
}
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async deleteAllConteneur ( itemId ) {
2021-01-08 18:58:37 +01:00
let list = [ ] ;
2021-01-10 11:35:11 +01:00
list . push ( { id : itemId , conteneurId : undefined } ) ; // Init list
2021-01-09 19:33:19 +01:00
this . buildSubConteneurObjetList ( itemId , list ) ;
2021-01-08 18:58:37 +01:00
//console.log("List to delete", list);
2021-01-10 11:35:11 +01:00
for ( let item of list ) {
await this . deleteOwnedItem ( item . id ) ;
2021-01-08 18:58:37 +01:00
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-11-12 14:43:08 +01:00
/ * * S u p p r i m e u n i t e m d ' u n c o n t e n e u r , s u r l a b a s e
* de leurs ID * /
2021-01-09 19:33:19 +01:00
async enleverDeConteneur ( itemId , conteneurId ) {
if ( ! conteneurId ) return ; // pas de conteneur (porté sur soi)
let conteneur = this . items . find ( conteneur => conteneurId == conteneur . _id ) ; // recup conteneur
if ( conteneur ) { // Si présent
2020-11-28 09:59:30 +01:00
let data2use = duplicate ( conteneur . data ) ;
2020-11-12 14:43:08 +01:00
//console.log("Suppression du conteneur1", conteneurId, itemId, conteneur.data.data.contenu);
2020-11-28 09:59:30 +01:00
let contenu = data2use . data . contenu ;
2020-11-28 10:05:53 +01:00
let index = contenu . indexOf ( itemId ) ;
while ( index >= 0 ) { // Force cleanup, itemId is unique
contenu . splice ( index , 1 ) ;
index = contenu . indexOf ( itemId ) ;
}
2021-01-09 19:33:19 +01:00
await this . updateEmbeddedEntity ( "OwnedItem" , data2use ) ;
2020-11-12 14:43:08 +01:00
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-11-12 14:43:08 +01:00
/ * * A j o u t e u n i t e m d a n s u n c o n t e n e u r , s u r l a b a s e
* de leurs ID * /
2021-01-09 19:33:19 +01:00
async ajouterAConteneur ( itemId , conteneurId ) {
if ( ! conteneurId ) return ; // pas de conteneur (porté sur soi)
let conteneur = this . items . find ( conteneur => conteneurId == conteneur . _id ) ;
if ( conteneur && conteneur . type == 'conteneur' ) {
2020-11-28 09:59:30 +01:00
let data2use = duplicate ( conteneur . data ) ;
2021-01-09 19:33:19 +01:00
data2use . data . contenu . push ( itemId ) ;
await this . updateEmbeddedEntity ( "OwnedItem" , data2use ) ;
2020-11-12 14:43:08 +01:00
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2021-01-08 11:56:10 +01:00
/** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */
2021-01-09 19:33:19 +01:00
async nettoyerConteneurs ( ) {
let conteneurList = this . items . filter ( conteneur => conteneur . type == 'conteneur' ) ;
2021-01-08 11:56:10 +01:00
let conteneurFixedList = [ ] ;
for ( let conteneur of conteneurList ) {
2021-01-09 19:33:19 +01:00
if ( conteneur . data . data . contenu . length > 0 ) {
conteneurFixedList . push ( { _id : conteneur . _id , 'data.contenu' : [ ] } ) ;
2021-01-08 11:56:10 +01:00
}
}
2021-01-09 19:33:19 +01:00
if ( conteneurFixedList . length > 0 )
await this . updateOwnedItem ( conteneurFixedList ) ;
2021-01-08 11:56:10 +01:00
}
2021-01-10 02:28:45 +01:00
/* -------------------------------------------- */
async moveItemsBetweenActors ( itemId , sourceActorId ) {
2021-01-09 09:54:08 +01:00
let itemsList = [ ]
let sourceActor = game . actors . get ( sourceActorId ) ;
2021-01-10 11:35:11 +01:00
itemsList . push ( { id : itemId , conteneurId : undefined } ) ; // Init list
2021-01-09 09:54:08 +01:00
sourceActor . buildSubConteneurObjetList ( itemId , itemsList ) ; // Get itemId list
2021-01-10 11:35:11 +01:00
2021-01-22 10:05:30 +01:00
let itemMap = { } ;
2021-01-10 11:35:11 +01:00
for ( let item of itemsList ) {
2021-01-22 10:05:30 +01:00
let srcItem = sourceActor . data . items . find ( subItem => subItem . _id == item . id ) ;
let newItem = await this . createOwnedItem ( duplicate ( srcItem ) ) ;
console . log ( 'New object' , newItem , srcItem ) ;
itemMap [ srcItem . _id ] = newItem . _id ; // Pour garder le lien ancien / nouveau
}
for ( let item of itemsList ) { // Second boucle pour traiter la remise en conteneurs
2021-01-10 11:35:11 +01:00
// gestion conteneur/contenu
if ( item . conteneurId ) { // l'Objet était dans un conteneur
2021-01-22 10:05:30 +01:00
let newConteneurId = itemMap [ item . conteneurId ] ; // Get conteneur
2021-01-10 11:35:11 +01:00
let newConteneur = this . data . items . find ( subItem => subItem . _id == newConteneurId ) ;
2021-01-22 10:05:30 +01:00
let newItemId = itemMap [ item . id ] ; // Get newItem
console . log ( 'New conteneur filling!' , newConteneur , newItemId , item ) ;
2021-01-10 11:35:11 +01:00
let contenu = duplicate ( newConteneur . data . contenu ) ;
2021-01-22 10:05:30 +01:00
contenu . push ( newItemId ) ;
2021-01-10 11:35:11 +01:00
await this . updateOwnedItem ( { _id : newConteneurId , 'data.contenu' : contenu } ) ;
}
2021-01-09 09:54:08 +01:00
}
2021-01-10 11:35:11 +01:00
for ( let item of itemsList ) {
await sourceActor . deleteOwnedItem ( item . id ) ;
2021-01-09 09:54:08 +01:00
}
}
2021-01-10 02:28:45 +01:00
/* -------------------------------------------- */
detectSurEncombrement ( ) {
2021-01-10 22:12:07 +01:00
let maxEnc = 0 ;
if ( this . data . type == 'vehicule' )
maxEnc = this . data . data . capacite _encombrement ;
else
maxEnc = this . data . data . attributs . encombrement . value ;
let diffEnc = Number ( this . encTotal ) - Number ( maxEnc ) ;
2021-01-05 18:43:13 +01:00
return Math . max ( 0 , Math . ceil ( diffEnc ) ) ;
2020-11-11 14:42:11 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async computeEncombrementTotalEtMalusArmure ( ) {
2020-12-20 21:54:09 +01:00
let encTotal = 0 ;
2021-01-10 22:12:07 +01:00
let malusArmureData = ( this . data . data . attributs && this . data . data . attributs . malusarmure ) ? duplicate ( this . data . data . attributs . malusarmure ) : { } ;
2021-01-09 19:33:19 +01:00
let newMalusArmure = 0 ;
2020-11-11 11:43:13 +01:00
for ( const item of this . data . items ) {
2021-01-09 19:33:19 +01:00
if ( item . type == 'armure' && item . data . equipe ) { // Armure équipée, intégration du malus armure total
2020-12-02 14:00:54 +01:00
newMalusArmure += item . data . malus ;
}
// Calcul encombrement
2021-01-09 19:33:19 +01:00
if ( item . data && item . data . encombrement != undefined ) {
if ( ! Number ( item . data . encombrement ) ) item . data . encombrement = 0 ; // Auto-fix
if ( item . data . quantite == undefined ) item . data . quantite = 1 ; // Auto-fix
if ( item . data . quantite < 0 ) item . data . quantite = 0 ; // Auto-fix
2020-11-27 09:40:48 +01:00
item . data . encTotal = Number ( item . data . encombrement ) * Number ( item . data . quantite ) ;
//console.log("Enc:", item.name, item.data.encombrement, item.data.quantite, item.data.encTotal);
2020-12-20 21:54:09 +01:00
encTotal += item . data . encTotal ;
2020-11-27 09:40:48 +01:00
} else {
item . data . encTotal = 0 ; // Force default enc
2020-11-11 11:43:13 +01:00
}
}
2020-12-02 14:00:54 +01:00
// Mise à jour valeur totale et états
2020-12-20 21:54:09 +01:00
this . encTotal = encTotal ;
2020-11-11 14:42:11 +01:00
this . detectSurEncombrement ( ) ;
2020-12-02 14:00:54 +01:00
// Mise à jour éventuelle du malus armure
2021-01-10 22:12:07 +01:00
if ( this . data . data . attributs && this . data . data . attributs . malusarmure && newMalusArmure != malusArmureData . value ) {
2020-12-02 14:00:54 +01:00
malusArmureData . value = newMalusArmure ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.attributs.malusarmure" : malusArmureData } ) ;
2020-12-02 14:00:54 +01:00
}
2020-11-11 11:43:13 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-12-05 02:22:37 +01:00
computeResumeBlessure ( blessures = this . data . data . blessures ) {
2021-01-09 19:33:19 +01:00
let nbLegeres = this . countBlessures ( blessures . legeres . liste ) ;
let nbGraves = this . countBlessures ( blessures . graves . liste ) ;
let nbCritiques = this . countBlessures ( blessures . critiques . liste ) ;
2020-12-05 02:22:37 +01:00
let resume = "Blessures:" ;
if ( nbCritiques > 0 || nbGraves > 0 || nbLegeres > 0 ) {
if ( nbLegeres > 0 ) {
resume += " " + nbLegeres + " légères" ;
}
if ( nbGraves > 0 ) {
if ( nbLegeres > 0 )
resume += "," ;
resume += " " + nbGraves + " graves" ;
}
if ( nbCritiques > 0 ) {
if ( nbGraves > 0 || nbLegeres > 0 )
resume += "," ;
resume += " une CRITIQUE !" ;
}
}
else {
resume += " aucune" ;
}
return resume ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
computeEtatGeneral ( ) {
2020-05-29 00:43:16 +02:00
let data = this . data . data ;
2020-11-15 11:15:36 +01:00
// Pas d'état général pour les entités forçage à 0
2021-01-09 19:33:19 +01:00
if ( this . data . type == 'entite' ) {
2020-11-15 11:15:36 +01:00
data . compteurs . etat . value = 0 ;
return ;
}
// Pour les autres
2020-12-19 01:14:02 +01:00
let state = - ( data . sante . vie . max - data . sante . vie . value ) ;
2021-01-09 19:33:19 +01:00
if ( data . sante . fatigue ) {
2021-01-04 14:10:21 +01:00
// Creatures n'ont pas de fatigue
2020-12-19 01:14:02 +01:00
state += RdDUtility . currentFatigueMalus ( data . sante . fatigue . value , data . sante . endurance . max ) ;
2021-01-09 19:33:19 +01:00
}
2021-01-04 14:10:21 +01:00
// Ajout de l'éthylisme
2021-01-13 16:34:24 +01:00
state += Math . min ( 0 , ( data . compteurs . ethylisme ? . value ? ? 0 ) ) ;
2021-01-04 14:10:21 +01:00
2021-01-09 19:33:19 +01:00
data . compteurs . etat . value = state ;
if ( data . compteurs && data . compteurs . surenc ) {
2020-12-19 01:14:02 +01:00
data . compteurs . surenc . value = - this . detectSurEncombrement ( ) ;
2020-12-08 21:40:41 +01:00
}
2020-05-29 00:43:16 +02:00
}
2021-01-10 22:12:07 +01:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async ajouterRefoulement ( value = 1 ) {
2020-07-17 22:04:35 +02:00
let ret = "none" ;
2021-01-09 19:33:19 +01:00
2020-07-17 22:04:35 +02:00
let refoulement = duplicate ( this . data . data . reve . refoulement ) ;
refoulement . value = refoulement . value + value ;
2020-11-14 03:16:03 +01:00
2020-12-04 20:52:04 +01:00
let total = new Roll ( "1d20" ) . roll ( ) . total ;
2021-01-09 19:33:19 +01:00
if ( total <= refoulement . value ) {
2020-07-17 22:04:35 +02:00
refoulement . value = 0 ;
2021-01-09 19:33:19 +01:00
this . ajouterSouffle ( { chat : true } ) ;
2020-07-17 22:04:35 +02:00
ret = "souffle" ;
}
2020-11-14 03:16:03 +01:00
2021-01-09 19:33:19 +01:00
await this . update ( { "data.reve.refoulement" : refoulement } ) ;
return ret ;
2020-07-17 22:04:35 +02:00
}
2020-11-16 04:32:42 +01:00
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async ajouterSouffle ( options = { chat : false } ) {
2020-12-30 11:50:18 +01:00
let souffle = await RdDRollTables . getSouffle ( ) ;
2020-12-17 02:20:03 +01:00
await this . createOwnedItem ( souffle ) ;
2021-01-09 19:33:19 +01:00
if ( options . chat ) {
2020-12-17 02:20:03 +01:00
ChatMessage . create ( {
2021-01-15 08:27:21 +01:00
whisper : ChatMessage . getWhisperRecipients ( [ "GM" , game . user . name ] ) ,
2020-12-17 02:20:03 +01:00
content : this . name + " subit un Souffle de Dragon : " + souffle . name
} ) ;
}
return souffle ;
2020-11-16 04:32:42 +01:00
}
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async ajouterQueue ( options = { chat : false } ) {
2020-11-16 04:32:42 +01:00
// TODO: Déterminer si Thanatos a été utilisé? => laisser le joueur ne pas choisir Thanatos => choisir sa voie?
let utiliseThanatos = false ;
let queue ;
if ( utiliseThanatos ) {
queue = await RdDRollTables . getOmbre ( ) ;
// mettre à jour: plus d'ombre en vue
}
else {
queue = await RdDRollTables . getQueue ( ) ;
}
2020-12-17 02:20:03 +01:00
await this . createOwnedItem ( queue ) ;
2021-01-09 19:33:19 +01:00
if ( options . chat ) {
2020-12-17 02:20:03 +01:00
ChatMessage . create ( {
2021-01-15 08:27:21 +01:00
whisper : ChatMessage . getWhisperRecipients ( [ "GM" , game . user . name ] ) ,
2020-12-17 02:20:03 +01:00
content : this . name + " subit une Queue de Dragon : " + queue . name
} ) ;
}
2021-01-02 19:57:38 +01:00
return queue . name ;
2020-11-16 04:32:42 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
displayTMRQueueSouffleInformation ( ) {
for ( let item of this . data . items ) {
2020-12-30 16:33:56 +01:00
let content
if ( item . type == 'queue' ) {
2021-01-09 19:33:19 +01:00
if ( item . name . toLowerCase ( ) == 'conquête' ) {
2020-12-30 16:33:56 +01:00
content = "RAPPEL ! Vous souffrez d'une <strong>Conquête</strong> : " + item . data . description ;
2021-01-09 19:33:19 +01:00
}
else if ( item . name . toLowerCase ( ) == 'pélerinage' ) {
2020-12-30 16:33:56 +01:00
content = "RAPPEL ! Vous souffrez d'un <strong>Pélerinage</strong> : " + item . data . description ;
2020-12-30 15:56:17 +01:00
}
2021-01-09 19:33:19 +01:00
else if ( item . name . toLowerCase ( ) == 'urgence draconique' ) {
2020-12-30 16:33:56 +01:00
content = "RAPPEL ! Vous souffrez d'une <strong>Urgence Draconique</strong> : " + item . data . description ;
}
2021-01-09 19:33:19 +01:00
} else if ( item . type == 'souffle' ) {
if ( item . name . toLowerCase ( ) == 'périple' ) {
2020-12-30 16:33:56 +01:00
content = "RAPPEL ! Vous souffrez du Souffle <strong>Périple</strong>. Vous devez gérer manuellement le détail du Périple.<br>" + item . data . description ;
2021-01-09 19:33:19 +01:00
} else if ( item . name . toLowerCase ( ) == 'fermeture des cités' ) {
2020-12-30 16:33:56 +01:00
content = "RAPPEL ! Vous souffrez du Souffle <strong>Fermeture des Cités</strong>. Vous devez gérer manuellement le détail des Citées ré-ouvertes.<br>" + item . data . description ;
2021-01-09 19:33:19 +01:00
} else if ( item . name . toLowerCase ( ) == 'désorientation' ) {
2020-12-30 16:33:56 +01:00
content = "RAPPEL ! Vous souffrez du Souffle <strong>Désorientation</strong>. Vous devez gérer avec votre MJ les effets de ce souffle.<br>" + item . data . description ;
2021-01-09 19:33:19 +01:00
} else if ( item . name . toLowerCase ( ) == 'double résistance du fleuve' ) {
2020-12-30 16:33:56 +01:00
content = "RAPPEL ! Vous souffrez du Souffle <strong>Double Résistance du Fleuve</strong>. Vous devez gérer avec votre MJ les effets de ce souffle.<br>" + item . data . description ;
2020-12-30 15:56:17 +01:00
}
}
2020-12-30 16:33:56 +01:00
if ( content ) {
ChatMessage . create ( {
2021-01-15 08:27:21 +01:00
whisper : ChatMessage . getWhisperRecipients ( [ "GM" , game . user . name ] ) ,
2020-12-30 16:33:56 +01:00
content : content
} ) ;
2021-01-09 19:33:19 +01:00
}
2020-12-30 15:56:17 +01:00
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async deleteTMRRencontreAtPosition ( ) {
2020-07-21 23:51:24 +02:00
let rencontres = duplicate ( this . data . data . reve . rencontre ) ;
let len = rencontres . list . length ;
let i = 0 ;
//console.log("List", rencontres, len);
let newTable = [ ] ;
2021-01-09 19:33:19 +01:00
for ( i = 0 ; i < len ; i ++ ) {
if ( rencontres . list [ i ] . coord != this . data . data . reve . tmrpos . coord )
2020-07-21 23:51:24 +02:00
newTable . push ( rencontres . list [ i ] ) ;
}
2021-01-09 19:33:19 +01:00
if ( newTable . length != len ) {
2020-07-21 23:51:24 +02:00
rencontres . list = newTable ;
//console.log("Result: ", rencontres);
2021-01-09 19:33:19 +01:00
await this . update ( { "data.reve.rencontre" : rencontres } ) ;
2020-07-21 23:51:24 +02:00
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async addTMRRencontre ( currentRencontre ) {
2020-07-21 23:51:24 +02:00
let rencontres = duplicate ( this . data . data . reve . rencontre ) ;
let len = rencontres . list . length ;
let i = 0 ;
let already = false ;
2021-01-09 19:33:19 +01:00
for ( i = 0 ; i < len ; i ++ ) {
if ( rencontres . list [ i ] . coord == this . data . data . reve . tmrpos . coord )
2020-07-21 23:51:24 +02:00
already = true ;
}
2021-01-09 19:33:19 +01:00
if ( ! already ) {
rencontres . list . push ( { coord : this . data . data . reve . tmrpos . coord , rencontre : currentRencontre } ) ;
await this . update ( { "data.reve.rencontre" : rencontres } ) ;
2020-07-21 23:51:24 +02:00
}
}
2020-11-17 16:30:03 +01:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async updateCoordTMR ( coord ) {
let tmrPos = duplicate ( this . data . data . reve . tmrpos ) ;
2020-11-17 16:30:03 +01:00
tmrPos . coord = coord ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.reve.tmrpos" : tmrPos } ) ;
2020-11-17 16:30:03 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async reveActuelIncDec ( value ) {
2020-07-17 22:04:35 +02:00
let reve = duplicate ( this . data . data . reve . reve ) ;
2020-11-14 03:16:03 +01:00
reve . value = Math . max ( reve . value + value , 0 ) ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.reve.reve" : reve } ) ;
2020-07-17 22:04:35 +02:00
}
2021-01-09 19:33:19 +01:00
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async updatePointDeSeuil ( value = 1 ) {
2020-11-16 03:52:34 +01:00
const seuil = Misc . toInt ( this . data . data . reve . seuil . value ) ;
const reve = Misc . toInt ( this . data . data . carac . reve . value ) ;
if ( seuil < reve ) {
2021-01-09 19:33:19 +01:00
await this . setPointsDeSeuil ( Math . min ( seuil + value , reve ) ) ;
2020-11-16 03:52:34 +01:00
}
}
2021-01-09 19:33:19 +01:00
2020-11-17 16:30:03 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async setPointsDeSeuil ( value ) {
2020-11-16 03:52:34 +01:00
let seuil = duplicate ( this . data . data . reve . seuil ) ;
seuil . value = value ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.reve.seuil" : seuil } ) ;
2020-11-16 03:52:34 +01:00
}
2021-01-11 17:54:24 +01:00
/* -------------------------------------------- */
async setPointsDeChance ( value ) {
let chance = duplicate ( this . data . data . compteurs . chance ) ;
chance . value = value ;
await this . update ( { "data.compteurs.chance" : chance } ) ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2021-01-03 15:40:48 +01:00
getSonne ( ) {
2021-01-09 19:33:19 +01:00
return ! this . isEntiteCauchemar ( ) && ( this . data . data . sante . sonne ? . value ? ? false ) ;
2021-01-03 15:40:48 +01:00
}
2021-01-13 03:42:13 +01:00
async setSonne ( sonne = true ) {
if ( this . isEntiteCauchemar ( ) ) {
return ;
}
await this . setStatusSonne ( sonne ) ;
await this . setStateSonne ( sonne ) ;
}
async setStateSonne ( sonne ) {
if ( this . isEntiteCauchemar ( ) ) {
return ;
}
await this . update ( { "data.sante.sonne.value" : sonne } ) ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2021-01-03 15:40:48 +01:00
getSConst ( ) {
2021-01-13 03:42:13 +01:00
if ( this . isEntiteCauchemar ( ) ) {
return 0 ;
2021-01-03 15:40:48 +01:00
}
2021-01-13 03:42:13 +01:00
return this . data . data . attributs ? . sconst ? . value ? ? 0 ;
2021-01-03 15:40:48 +01:00
}
2021-01-09 19:38:24 +01:00
/* -------------------------------------------- */
2021-01-13 03:42:13 +01:00
async testSiSonne ( sante , endurance ) {
2021-01-09 19:38:24 +01:00
const roll = new Roll ( "1d20" ) . roll ( ) ;
roll . showDice = true ;
RdDDice . show ( roll ) ;
let result = {
roll : roll ,
sonne : roll . total > endurance || roll . total == 20
}
if ( roll . total == 1 ) {
let xp = Misc . toInt ( this . data . data . carac . constitution . xp ) + 1 ;
this . update ( { "data.carac.constitution.xp" : xp } ) ; // +1 XP !
2020-06-07 23:16:29 +02:00
// TODO : Output to chat
2020-05-31 23:06:25 +02:00
}
2021-01-09 19:38:24 +01:00
if ( result . sonne ) {
// 20 is always a failure
2021-01-13 03:42:13 +01:00
await this . setSonne ( ) ;
2021-01-09 19:38:24 +01:00
sante . sonne . value = true ;
}
return result ;
2020-05-31 23:06:25 +02:00
}
2020-07-27 16:27:41 +02:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
countBlessures ( blessuresListe ) {
2020-11-25 00:50:20 +01:00
return blessuresListe . filter ( b => b . active ) . length
2020-07-27 16:27:41 +02:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
countBlessuresByName ( name ) {
return this . countBlessures ( this . data . data . blessures [ name ] . liste ) ;
2021-01-03 15:40:48 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-12-06 21:39:55 +01:00
async jetVie ( ) {
let myRoll = new Roll ( "1d20" ) . roll ( ) ;
myRoll . showDice = true ;
await RdDDice . show ( myRoll ) ;
let msgText = "Jet de Vie : " + myRoll . total + " / " + this . data . data . sante . vie . value + "<br>" ;
2021-01-09 19:33:19 +01:00
if ( myRoll . total <= this . data . data . sante . vie . value ) {
2020-12-06 21:39:55 +01:00
msgText += "Jet réussi, pas de perte de point de vie (prochain jet dans 1 round pour 1 critique, SC minutes pour une grave)" ;
2021-01-09 19:33:19 +01:00
if ( myRoll . total == 1 ) {
2020-12-06 21:39:55 +01:00
msgText += "La durée entre 2 jets de vie est multipliée par 20 (20 rounds pour une critique, SCx20 minutes pour une grave)" ;
}
} else {
msgText += "Jet échoué, vous perdez 1 point de vie" ;
await this . santeIncDec ( "vie" , - 1 ) ;
2021-01-09 19:33:19 +01:00
if ( myRoll . total == 20 ) {
2020-12-06 21:39:55 +01:00
msgText += "Votre personnage est mort !!!!!" ;
}
}
const message = {
content : msgText ,
whisper : ChatMessage . getWhisperRecipients ( game . user . name )
} ;
2021-01-09 19:33:19 +01:00
ChatMessage . create ( message ) ;
2020-12-06 21:39:55 +01:00
}
2020-08-29 22:52:41 +02:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-12-01 00:21:53 +01:00
async santeIncDec ( name , inc , isCritique = false ) {
2021-01-09 19:33:19 +01:00
2020-06-07 23:16:29 +02:00
const sante = duplicate ( this . data . data . sante ) ;
2021-01-13 03:04:33 +01:00
let compteur = sante [ name ] ;
if ( ! compteur ) {
2021-01-19 23:01:14 +01:00
return ;
2020-12-01 17:36:13 +01:00
}
2021-01-09 19:38:24 +01:00
let result = {
sonne : false ,
} ;
2020-11-21 23:24:00 +01:00
let minValue = 0 ;
2020-12-01 00:21:53 +01:00
if ( this . type == 'personnage' ) {
// TODO: les animaux/humanoïdes on théoriquement aussi un sconst, mais la SPA n'est pas passé par là
minValue = name == "vie" ? - Number ( this . data . data . attributs . sconst . value ) : 0 ;
}
2021-01-13 03:04:33 +01:00
result . newValue = Math . max ( minValue , Math . min ( compteur . value + inc , compteur . max ) ) ;
2021-01-09 19:38:24 +01:00
//console.log("New value ", inc, minValue, result.newValue);
2021-01-13 03:04:33 +01:00
let fatigue = 0 ;
2021-01-09 19:38:24 +01:00
if ( name == "endurance" && this . data . type != 'entite' ) {
if ( ! isCritique && result . newValue == 0 && inc < 0 ) { // perte endurance et endurance devient 0 -> -1 vie sauf si coup critique
2020-06-07 23:16:29 +02:00
sante . vie . value = sante . vie . value - 1 ;
2020-05-31 23:06:25 +02:00
}
2021-01-09 19:38:24 +01:00
result . newValue = Math . max ( 0 , result . newValue ) ;
if ( inc > 0 ) { // le max d'endurance s'applique seulement à la récupération
2021-01-10 02:28:45 +01:00
result . newValue = Math . min ( result . newValue , this . _computeEnduranceMax ( ) )
2020-11-20 11:38:27 +01:00
}
2021-01-13 03:04:33 +01:00
const perte = compteur . value - result . newValue ;
if ( perte > 1 ) {
2021-01-09 19:38:24 +01:00
// Peut-être sonné si 2 points d'endurance perdus d'un coup
2021-01-13 03:42:13 +01:00
const testIsSonne = await this . testSiSonne ( sante , result . newValue ) ;
2021-01-09 19:38:24 +01:00
result . sonne = testIsSonne . sonne ;
result . jetEndurance = testIsSonne . roll . total ;
2021-01-13 03:04:33 +01:00
} else if ( inc > 0 ) {
await this . setSonne ( false ) ;
}
if ( sante . fatigue && inc < 0 ) { // Each endurance lost -> fatigue lost
fatigue = perte ;
2020-05-31 23:06:25 +02:00
}
}
2021-01-13 03:04:33 +01:00
compteur . value = result . newValue ;
2021-01-09 19:38:24 +01:00
//console.log(name, inc, data.value, result.newValue, minValue, data.max);
2021-01-13 03:04:33 +01:00
// If endurance lost, then the same amount of fatigue cannot be recovered
2021-01-13 23:46:12 +01:00
if ( sante . fatigue && fatigue > 0 ) {
sante . fatigue . value = Math . max ( sante . fatigue . value + fatigue , this . _computeFatigueMin ( ) ) ;
}
2021-01-09 19:38:24 +01:00
await this . update ( { "data.sante" : sante } ) ;
return result ;
2020-06-07 23:16:29 +02:00
}
2020-08-29 22:52:41 +02:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-11-20 11:38:27 +01:00
_computeFatigueMin ( ) {
return this . data . data . sante . endurance . max - this . data . data . sante . endurance . value ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-11-20 11:38:27 +01:00
_computeEnduranceMax ( ) {
let blessures = this . data . data . blessures ;
let diffVie = this . data . data . sante . vie . max - this . data . data . sante . vie . value ;
let maxEndVie = this . data . data . sante . endurance . max - ( diffVie * 2 ) ;
2020-11-25 00:50:20 +01:00
let nbGraves = this . countBlessures ( blessures . graves . liste ) ;
let nbCritiques = this . countBlessures ( blessures . critiques . liste ) ;
2020-11-20 11:38:27 +01:00
let maxEndGraves = Math . floor ( this . data . data . sante . endurance . max / ( 2 * nbGraves ) ) ;
let maxEndCritiques = nbCritiques > 0 ? 1 : this . data . data . sante . endurance . max ;
return Math . max ( 0 , Math . min ( maxEndVie , maxEndGraves , maxEndCritiques ) ) ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async manageBlessureFromSheet ( bType , index , active ) {
let bList = duplicate ( this . data . data . blessures ) ;
let blessure = bList [ bType + "s" ] . liste [ index ] ;
2020-07-20 12:02:07 +02:00
blessure . active = ! blessure . active ;
2021-01-09 19:33:19 +01:00
if ( ! blessure . active ) {
2020-07-27 16:27:41 +02:00
blessure . premiers _soins = 0 ;
blessure . soins _complets = 0 ;
blessure . jours = 0 ;
2021-01-09 19:33:19 +01:00
blessure . loc = "" ;
2020-07-27 16:27:41 +02:00
}
//console.log("Blessure update", bType, index, blessure, bList );
2021-01-09 19:33:19 +01:00
await this . update ( { 'data.blessures' : bList } ) ;
2020-07-20 12:02:07 +02:00
}
2020-07-27 16:27:41 +02:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async setDataBlessureFromSheet ( bType , index , psoins , pcomplets , jours , loc ) {
let bList = duplicate ( this . data . data . blessures ) ;
let blessure = bList [ bType + "s" ] . liste [ index ] ;
2020-07-27 16:27:41 +02:00
blessure . premiers _soins = psoins ;
blessure . soins _complets = pcomplets ;
blessure . jours = jours ;
2020-12-15 02:20:24 +01:00
blessure . loc = loc ;
2021-01-09 19:33:19 +01:00
await this . update ( { 'data.blessures' : bList } ) ;
2020-07-27 16:27:41 +02:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-12-16 02:54:28 +01:00
async jetDeMoral ( situation ) {
let jetMoral = new Roll ( "1d20" ) . roll ( ) ;
RdDDice . show ( jetMoral ) ;
2020-12-29 01:34:15 +01:00
let moralActuel = Misc . toInt ( this . data . data . compteurs . moral . value ) ;
const difficulte = 10 + moralActuel ;
2020-12-21 22:13:13 +01:00
const succes = jetMoral . total <= difficulte ;
2020-12-29 01:34:15 +01:00
let ajustementMoral = this . _calculAjustementMoral ( succes , moralActuel , situation ) ;
2021-01-09 19:33:19 +01:00
2020-12-29 01:34:15 +01:00
await this . moralIncDec ( ajustementMoral ) ;
ChatMessage . create ( {
whisper : ChatUtility . getWhisperRecipientsAndGMs ( game . user . name ) ,
2021-01-09 19:33:19 +01:00
content : ` Jet de moral ${ succes ? "réussi" : "manqué" } en situation ${ situation } ( ${ jetMoral . total } / ${ difficulte } ), vous ${ ajustementMoral > 0 ? "gagnez du moral" : ajustementMoral < 0 ? "perdez du moral" : "gardez votre moral" } `
2020-12-29 01:34:15 +01:00
} ) ;
return ajustementMoral ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-12-29 01:34:15 +01:00
async moralIncDec ( ajustementMoral ) {
let compteurs = duplicate ( this . data . data . compteurs ) ;
compteurs . moral . value = Misc . toInt ( compteurs . moral . value ) ; ;
2020-12-16 02:54:28 +01:00
if ( ajustementMoral != 0 ) {
compteurs . moral . value += ajustementMoral ;
2020-12-29 01:34:15 +01:00
if ( compteurs . moral . value > 3 ) {
2020-12-16 02:54:28 +01:00
// exaltation
2020-12-29 01:34:15 +01:00
compteurs . moral . value -- ;
2020-12-16 02:54:28 +01:00
compteurs . exaltation . value = Misc . toInt ( compteurs . exaltation . value ) + 1 ;
}
2020-12-29 01:34:15 +01:00
if ( compteurs . moral . value < - 3 ) {
2020-12-16 02:54:28 +01:00
// dissolution
2020-12-29 01:34:15 +01:00
compteurs . moral . value ++ ;
2020-12-16 02:54:28 +01:00
compteurs . dissolution . value = Misc . toInt ( compteurs . dissolution . value ) + 1 ;
}
2020-12-29 01:34:15 +01:00
await this . update ( { 'data.compteurs' : compteurs } ) ;
2020-12-16 02:54:28 +01:00
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-12-21 22:13:13 +01:00
_calculAjustementMoral ( succes , moral , situation ) {
2020-12-16 02:54:28 +01:00
switch ( situation ) {
2020-12-21 22:13:13 +01:00
case 'heureuse' : return succes ? 1 : 0 ;
case 'malheureuse' : return succes ? 0 : - 1 ;
2020-12-16 02:54:28 +01:00
case 'neutre' :
if ( succes && moral <= 0 ) return 1 ;
if ( ! succes && moral > 0 ) return - 1 ;
}
return 0 ;
}
2021-01-03 18:19:18 +01:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-12-29 01:34:15 +01:00
async setEthylisme ( degre ) {
let ethylisme = duplicate ( this . data . data . compteurs . ethylisme ) ;
ethylisme . value = degre ;
ethylisme . nb _doses = 0 ;
if ( degre == 1 ) {
ethylisme . jet _moral = false ;
}
2021-01-09 19:33:19 +01:00
await this . update ( { "data.compteurs.ethylisme" : ethylisme } ) ;
2020-12-29 01:34:15 +01:00
}
2020-12-06 20:11:30 +01:00
/* -------------------------------------------- */
async ethylismeTest ( ) {
2021-01-09 19:33:19 +01:00
let rollData = {
2020-12-06 20:11:30 +01:00
vieValue : this . data . data . sante . vie . value ,
2021-01-05 18:43:13 +01:00
etat : this . getEtatGeneral ( ) - Math . min ( 0 , this . data . data . compteurs . ethylisme . value ) , // Pour les jets d'Ethylisme, on ignore le degré d'éthylisme (p.162)
2020-12-29 01:34:15 +01:00
diffNbDoses : - Number ( this . data . data . compteurs . ethylisme . nb _doses || 0 ) ,
2020-12-06 20:11:30 +01:00
finalLevel : 0 ,
diffConditions : 0 ,
ajustementsConditions : CONFIG . RDD . ajustementsConditions ,
forceAlcool : 0
}
let html = await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ethylisme.html' , rollData ) ;
2021-01-09 19:33:19 +01:00
new RdDRollDialogEthylisme ( html , rollData , this ) . render ( true ) ;
2020-12-06 20:11:30 +01:00
}
2021-01-09 19:33:19 +01:00
2020-12-06 20:11:30 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async performEthylisme ( rollData ) {
2020-12-06 20:11:30 +01:00
let ethylisme = duplicate ( this . data . data . compteurs . ethylisme ) ;
2021-01-09 19:33:19 +01:00
2020-12-06 21:11:30 +01:00
// Je d'ethylisme
2021-01-09 19:33:19 +01:00
let rollEthylisme = await RdDResolutionTable . roll ( rollData . vieValue , rollData . finalLevel ) ;
2020-12-06 21:11:30 +01:00
let msgText = RdDResolutionTable . explain ( rollEthylisme ) + "<br>" ;
2021-01-09 19:33:19 +01:00
if ( rollEthylisme . isSuccess ) {
ethylisme . nb _doses ++ ;
2020-12-19 01:14:02 +01:00
msgText += ` Vous avez réussi votre jet d'éthylisme, vous avez consommé ${ ethylisme . nb _doses } doses sans effet. ` ;
2020-12-06 21:11:30 +01:00
} else {
2021-01-09 19:33:19 +01:00
ethylisme . value = Math . max ( ethylisme . value - 1 , - 7 ) ;
2020-12-29 01:34:15 +01:00
ethylisme . nb _doses = 0 ;
2020-12-06 21:11:30 +01:00
let enduranceLost = new Roll ( "1d6" ) . roll ( ) . total ;
await this . santeIncDec ( "endurance" , - enduranceLost ) ;
2020-12-19 01:14:02 +01:00
const ajustementEthylique = ethylisme . value ;
2020-12-06 21:11:30 +01:00
// Qui a bu boira (p 164)
2021-01-09 19:33:19 +01:00
let rollVolonte = await RdDResolutionTable . roll ( this . data . data . carac . volonte . value , Math . min ( ajustementEthylique , 0 ) + this . data . data . compteurs . moral . value ) ;
2020-12-19 01:14:02 +01:00
msgText += ` Vous avez échoué à votre jet d'éthylisme, vous êtes maintenant ${ RdDUtility . getNomEthylisme ( ajustementEthylique ) } ( ${ ajustementEthylique } ). `
2020-12-06 21:11:30 +01:00
msgText += "<br>" + RdDResolutionTable . explain ( rollVolonte ) + "<br>" ;
2021-01-09 19:33:19 +01:00
msgText += "Qui a bu boira : " + ( rollVolonte . isSuccess
2020-12-19 01:14:02 +01:00
? "vous êtes libre de continuer à boire ou pas."
: "vous avez une envie irrépréssible de reprendre un verre." ) ;
2020-12-29 01:34:15 +01:00
}
2020-12-19 01:14:02 +01:00
2020-12-29 01:34:15 +01:00
ChatMessage . create ( {
content : msgText ,
whisper : ChatUtility . getWhisperRecipientsAndGMs ( game . user . name )
2021-01-09 19:33:19 +01:00
} ) ;
2020-12-29 01:34:15 +01:00
if ( rollEthylisme . isEchec ) {
await this . _jetDeMoralEthylique ( ethylisme ) ;
}
2021-01-09 19:33:19 +01:00
await this . update ( { 'data.compteurs.ethylisme' : ethylisme } ) ;
2020-12-29 01:34:15 +01:00
}
2021-01-09 19:33:19 +01:00
2020-12-29 01:34:15 +01:00
/* -------------------------------------------- */
async _jetDeMoralEthylique ( ethylisme ) {
if ( ethylisme . value >= - 1 && ! ethylisme . jet _moral ) {
let adjust = await this . jetDeMoral ( 'heureuse' ) ;
if ( adjust > 0 || ethylisme . value == - 1 ) {
ethylisme . jet _moral = true ;
2020-12-19 01:14:02 +01:00
}
2020-12-29 01:34:15 +01:00
if ( ethylisme . value == - 1 && adjust <= 0 ) {
// alcool triste
ChatMessage . create ( {
content : "Décidément, vous avez l'alcool triste, vous perdez finalement un point de moral!" ,
whisper : ChatUtility . getWhisperRecipientsAndGMs ( game . user . name )
2021-01-09 19:33:19 +01:00
} ) ;
2020-12-29 01:34:15 +01:00
this . moralIncDec ( - 1 ) ;
2020-12-19 01:14:02 +01:00
}
2020-12-29 01:34:15 +01:00
}
2020-12-06 20:11:30 +01:00
}
2020-11-12 16:35:51 +01:00
/* -------------------------------------------- */
async stressTest ( ) {
2020-11-24 18:54:13 +01:00
const message = {
content : "" ,
2020-12-29 01:34:15 +01:00
whisper : ChatUtility . getWhisperRecipientsAndGMs ( game . user . name )
2020-11-24 18:54:13 +01:00
} ;
await this . transformerStress ( message ) ;
ChatMessage . create ( message ) ;
}
2020-12-06 20:11:30 +01:00
/* -------------------------------------------- */
2020-11-24 18:54:13 +01:00
async transformerStress ( message ) {
2020-12-19 01:45:03 +01:00
let compteurs = duplicate ( this . data . data . compteurs ) ;
const stress = Misc . toInt ( compteurs . stress . value ) ;
2021-01-09 19:33:19 +01:00
if ( stress <= 0 ) {
2021-01-11 20:42:10 +01:00
return false ;
2020-11-24 18:54:13 +01:00
}
2021-01-09 19:33:19 +01:00
2020-11-24 18:54:13 +01:00
let stressRoll = await this . _stressRoll ( ) ;
let convertis = Math . floor ( stress * stressRoll . factor ) ;
compteurs . stress . value = Math . max ( stress - convertis - 1 , 0 ) ;
2021-01-09 19:33:19 +01:00
2020-12-19 01:45:03 +01:00
let dissolution = Math . max ( 0 , Misc . toInt ( compteurs . dissolution . value ) ) ;
let exaltation = Math . max ( 0 , Misc . toInt ( compteurs . exaltation . value ) ) ;
const annule = Math . min ( dissolution , exaltation ) ;
dissolution -= annule ;
exaltation -= annule ;
2021-01-09 19:33:19 +01:00
if ( dissolution > 0 ) {
2020-12-19 01:45:03 +01:00
const perdus = Math . min ( dissolution , convertis ) ;
convertis -= perdus ;
dissolution -= perdus ;
}
compteurs . experience . value += convertis + exaltation ;
compteurs . dissolution . value = dissolution ;
compteurs . exaltation . value = 0 ;
2020-11-24 18:54:13 +01:00
message . content += "<br>Vous transformez " + convertis + " points de Stress en Expérience" + stressRoll . comment ;
2021-01-11 20:42:10 +01:00
await this . update ( { "data.compteurs" : compteurs } ) ;
return true ;
2020-08-29 22:52:41 +02:00
}
2020-11-14 21:34:34 +01:00
/* -------------------------------------------- */
2020-11-21 09:10:31 +01:00
async _stressRoll ( ) {
2020-11-25 00:49:21 +01:00
let reveActuel = this . getReveActuel ( ) ;
let result = await RdDResolutionTable . roll ( reveActuel , 0 ) ;
2020-11-17 16:30:03 +01:00
console . log ( "_stressRoll" , result ) ;
switch ( result . code ) {
case "sign" : return { factor : 0.75 , comment : " (75%): " + result . quality + " - " + result . roll + " sur " + result . score + "%" }
case "norm" : return { factor : 0.5 , comment : " (50%): " + result . quality + " - " + result . roll + " sur " + result . score + "%" }
case "echec" : return { factor : 0.2 , comment : " (20%): " + result . quality + " - " + result . roll + " sur " + result . score + "%" }
case "epart" : return { factor : 0.1 , comment : " (10%): " + result . quality + " - " + result . roll + " sur " + result . score + "%" }
case "etotal" : return { factor : 0 , comment : " (0%): " + result . quality + " - " + result . roll + " sur " + result . score + "%" }
case "part" :
{
2020-11-25 00:49:21 +01:00
let second = await RdDResolutionTable . roll ( reveActuel , 0 ) ;
2020-11-17 16:30:03 +01:00
console . log ( "_stressRoll" , second ) ;
switch ( second . code ) {
case "part" : case "sign" :
return { factor : 1.5 , comment : " (150%): Double Particulière - " + result . roll + " puis " + second . roll + " sur " + result . score + "%" }
default :
2021-01-15 00:28:39 +01:00
return { factor : 1 , comment : " (100%): " + result . quality + " - " + result . roll + " puis " + second . roll + " sur " + result . score + "%" }
2020-11-17 16:30:03 +01:00
}
2020-11-17 11:35:05 +01:00
}
2020-11-17 16:30:03 +01:00
}
2020-11-12 16:35:51 +01:00
}
2020-11-17 11:35:05 +01:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-12-12 21:58:44 +01:00
createCallbackExperience ( ) {
2020-12-06 23:31:23 +01:00
return {
condition : r => r . rolled . isPart && r . finalLevel < 0 && game . settings . get ( "core" , "rollMode" ) != 'selfroll' ,
2020-12-31 03:34:37 +01:00
action : r => this . _appliquerAjoutExperience ( r , game . settings . get ( "core" , "rollMode" ) != 'blindroll' )
2020-12-06 23:31:23 +01:00
} ;
}
2020-12-18 00:45:20 +01:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async checkCaracXP ( caracName ) {
2021-01-03 18:19:18 +01:00
let carac = this . data . data . carac [ caracName ] ;
if ( carac && carac . xp > 0 ) {
2021-01-15 00:20:11 +01:00
let xpNeeded = RdDUtility . getCaracNextXp ( carac . value + 1 ) ;
2021-01-09 19:33:19 +01:00
if ( carac . xp >= xpNeeded ) {
2021-01-03 18:19:18 +01:00
carac = duplicate ( carac ) ;
carac . value = Number ( carac . value ) + 1 ;
2021-01-09 19:33:19 +01:00
let xpData = {
alias : this . name ,
2021-01-03 18:19:18 +01:00
carac : caracName ,
value : carac . value ,
xp : carac . xp
}
2021-01-09 19:36:19 +01:00
ChatUtility . createChatMessage ( this . name , "default" , {
content : await renderTemplate ( ` systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html ` , xpData )
} ) ;
2021-01-03 18:19:18 +01:00
}
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2021-01-14 15:29:47 +01:00
async checkCompetenceXP ( compName , newXP = undefined ) {
2021-01-09 19:33:19 +01:00
let competence = RdDItemCompetence . findCompetence ( this . data . items , compName ) ;
2021-01-14 15:29:47 +01:00
if ( competence && newXP && newXP == competence . data . xp ) { // Si édition, mais sans changement XP
return ;
}
newXP = ( newXP ) ? newXP : competence . data . xp ;
if ( competence && newXP > 0 ) {
2021-01-15 00:20:11 +01:00
let xpNeeded = RdDItemCompetence . getCompetenceNextXp ( competence . data . niveau + 1 ) ;
2021-01-14 15:29:47 +01:00
if ( newXP >= xpNeeded ) {
2021-01-14 10:32:15 +01:00
let newCompetence = duplicate ( competence ) ;
newCompetence . data . niveau += 1 ;
2021-01-14 15:29:47 +01:00
newCompetence . data . xp = newXP ;
2021-01-14 20:51:32 +01:00
2021-01-09 19:33:19 +01:00
let xpData = {
alias : this . name ,
2021-01-14 10:32:15 +01:00
competence : newCompetence . name ,
niveau : newCompetence . data . niveau ,
xp : newCompetence . data . xp ,
archetype : newCompetence . data . niveau _archetype ,
archetypeWarning : newCompetence . data . niveau > competence . data . niveau _archetype
2021-01-03 18:19:18 +01:00
}
2021-01-09 19:36:19 +01:00
ChatUtility . createChatMessage ( this . name , "default" , {
content : await renderTemplate ( ` systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html ` , xpData )
} ) ;
2021-01-03 18:19:18 +01:00
}
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async _appliquerAjoutExperience ( rollData , display = true ) {
2021-01-05 18:43:13 +01:00
if ( ! this . isPersonnage ( ) ) return ;
2021-01-09 19:33:19 +01:00
let xpResult = this . appliquerExperience ( rollData . rolled , rollData . selectedCarac . label , rollData . competence ) ;
if ( display && xpResult . result ) {
2020-12-14 10:38:43 +01:00
let xpmsg = "<br>Points d'expérience gagnés ! Carac: " + xpResult . xpCarac + ", Comp: " + xpResult . xpCompetence ;
2021-01-14 21:58:00 +01:00
let message = {
whisher : ChatMessage . getWhisperRecipients ( [ "GM" , this . name ] ) ,
content : "<strong>" + rollData . selectedCarac . label + "</strong>" + xpmsg ,
}
2020-12-14 10:38:43 +01:00
ChatMessage . create ( message ) ;
}
2021-01-09 19:33:19 +01:00
if ( xpResult && xpResult . xpComp > 0 && rollData . competence ) {
this . checkCompetenceXP ( rollData . competence . name ) ;
2021-01-03 18:19:18 +01:00
}
2021-01-09 19:33:19 +01:00
if ( xpResult && xpResult . xpCarac > 0 && rollData . selectedCarac ) {
this . checkCaracXP ( rollData . selectedCarac . name ) ;
2021-01-03 18:19:18 +01:00
}
2020-12-06 23:31:23 +01:00
}
2020-12-08 23:07:41 +01:00
/* -------------------------------------------- */
async rollUnSort ( coord ) {
let sortList = duplicate ( this . getSortList ( ) ) ; // Duplication car les pts de reve sont modifiés dans le sort
2021-01-09 19:33:19 +01:00
if ( ! sortList || sortList . length == 0 ) {
2020-12-08 23:07:41 +01:00
ui . notifications . info ( "Aucun sort disponible!" ) ;
return ;
}
2021-01-09 19:33:19 +01:00
if ( this . currentTMR ) this . currentTMR . minimize ( ) ; // Hide
let rollData = {
2020-12-08 23:07:41 +01:00
selectedCarac : this . data . data . carac . reve ,
draconicList : this . getDraconicList ( ) ,
sortList : sortList ,
2020-12-31 02:20:52 +01:00
competence : this . getBestDraconic ( ) ,
2020-12-08 23:07:41 +01:00
selectedSort : sortList [ 0 ] ,
coord : coord ,
2021-01-09 19:33:19 +01:00
coordLabel : TMRUtility . getTMRDescription ( coord ) . label ,
2020-12-08 23:07:41 +01:00
diffLibre : sortList [ 0 ] . data . difficulte , // Per default at startup
coutreve : Array ( 20 ) . fill ( ) . map ( ( item , index ) => 1 + index )
}
2020-12-28 10:11:47 +01:00
if ( this . currentTMR ) this . currentTMR . minimize ( ) ; // Hide
2020-12-08 23:07:41 +01:00
const dialog = await RdDRoll . create ( this , rollData ,
2020-12-28 10:11:47 +01:00
{ html : 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html' ,
2020-12-28 10:17:40 +01:00
close : html => { this . currentTMR . maximize ( ) } // Re-display TMR
} ,
2020-12-08 23:07:41 +01:00
{
name : 'lancer-un-sort' ,
label : 'Lancer un sort' ,
callbacks : [
2020-12-12 21:58:44 +01:00
this . createCallbackExperience ( ) ,
2020-12-08 23:07:41 +01:00
{ action : r => this . _rollUnSortResult ( r , false ) }
]
} ,
{
name : 'mettre-en-reserve' ,
label : 'Mettre un sort en réserve' ,
callbacks : [
2020-12-12 21:58:44 +01:00
this . createCallbackExperience ( ) ,
2021-01-09 19:33:19 +01:00
{ action : r => this . _rollUnSortResult ( r , true ) }
2020-12-08 23:07:41 +01:00
]
2020-12-28 10:11:47 +01:00
} ,
2020-12-08 23:07:41 +01:00
) ;
dialog . render ( true ) ;
}
2020-12-30 15:18:58 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
isRencontreSpeciale ( ) { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective'
2020-12-30 16:33:56 +01:00
let addMsg = "" ;
2021-01-09 19:33:19 +01:00
let rencSpecial = this . data . items . find ( item => ( item . type == 'queue' || item . type == 'souffle' ) && item . name . toLowerCase ( ) . includes ( 'mauvaise rencontre' ) ) ;
if ( rencSpecial ) {
2020-12-30 15:18:58 +01:00
rencSpecial = duplicate ( rencSpecial ) ; // To keep it
2021-01-09 19:33:19 +01:00
if ( rencSpecial . type == 'queue' ) {
this . deleteOwnedItem ( rencSpecial . _id ) ; // Suppression dans la liste des queues
2020-12-30 16:33:56 +01:00
addMsg = " La queue a été supprimée de votre fiche automatiquement" ;
} else {
addMsg = " Vous devez gérer manuellement le décompte de mauvaises rencontres manuellement." ;
2021-01-09 19:33:19 +01:00
}
ChatMessage . create ( {
2020-12-30 16:33:56 +01:00
content : "Vous êtes sous le coup d'une Mauvaise Rencontre en Persective." + addMsg ,
2021-01-09 19:33:19 +01:00
whisper : ChatMessage . getWhisperRecipients ( game . user . name )
} ) ;
2020-12-30 15:18:58 +01:00
}
return rencSpecial ;
}
2020-12-30 15:31:43 +01:00
/* -------------------------------------------- */
getTMRFatigue ( ) { // Pour l'instant uniquement Inertie Draconique
2021-01-09 19:33:19 +01:00
let inertieDraconique = this . data . items . find ( item => item . type == 'queue' && item . name . toLowerCase ( ) . includes ( 'inertie draconique' ) ) ;
if ( inertieDraconique ) {
ChatMessage . create ( {
2020-12-30 15:56:17 +01:00
content : "Vous êtes sous le coup d'une Inertie Draconique : vous perdez 2 cases de Fatigue par déplacement au lieu d'1." ,
2021-01-09 19:33:19 +01:00
whisper : ChatMessage . getWhisperRecipients ( game . user . name )
} ) ;
2020-12-30 15:31:43 +01:00
return 2 ;
}
return 1 ;
}
2020-12-30 21:11:01 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
isConnaissanceFleuve ( ) {
return this . data . items . find ( item => item . type == 'tete' && item . name . toLowerCase ( ) . includes ( 'connaissance du fleuve' ) ) ;
2020-12-30 21:11:01 +01:00
}
2020-12-31 00:55:02 +01:00
2020-12-30 19:18:07 +01:00
/* -------------------------------------------- */
isReserveEnSecurite ( ) {
2021-01-09 19:33:19 +01:00
let reserveSecurite = this . data . items . find ( item => item . type == 'tete' && item . name . toLowerCase ( ) . includes ( ' en sécurité' ) ) ;
2020-12-30 19:18:07 +01:00
return reserveSecurite ;
}
2020-12-30 16:49:07 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
isDoubleResistanceFleuve ( ) {
let resistFleuve = this . data . items . find ( item => item . type == 'souffle' && item . name . toLowerCase ( ) . includes ( 'résistance du fleuve' ) ) ;
if ( resistFleuve ) {
ChatMessage . create ( {
2020-12-30 16:49:07 +01:00
content : "Vous êtes sous le coup d'une Double Résistance du Fleuve : vous devez maîtriser 2 fois chaque case humide, un second jet est donc effectué." ,
2021-01-09 19:33:19 +01:00
whisper : ChatMessage . getWhisperRecipients ( game . user . name )
} ) ;
2020-12-30 16:49:07 +01:00
return true ;
}
return false ;
}
2020-12-30 16:57:47 +01:00
/* -------------------------------------------- */
async checkSoufflePeage ( cellDescr ) {
2021-01-09 19:33:19 +01:00
let peage = this . data . items . find ( item => item . type == 'souffle' && item . name . toLowerCase ( ) . includes ( 'péage' ) ) ;
if ( peage && ( cellDescr . type == 'pont' || cellDescr . type == 'cite' ) ) {
await this . reveActuelIncDec ( - 1 ) ;
ChatMessage . create ( {
2020-12-30 16:57:47 +01:00
content : "Vous êtes sous le coup d'un Péage : l'entrée sur cette case vous coûte 1 Point de Rêve (déduit automatiquement)." ,
2021-01-09 19:33:19 +01:00
whisper : ChatMessage . getWhisperRecipients ( game . user . name )
} ) ;
2020-12-30 16:57:47 +01:00
}
}
2020-12-30 21:11:01 +01:00
/* -------------------------------------------- */
checkTeteDeplacementAccelere ( ) {
2021-01-09 19:33:19 +01:00
let deplAccelere = this . data . items . find ( item => item . type == 'tete' && item . name . toLowerCase ( ) . includes ( ' déplacement accéléré' ) ) ;
if ( deplAccelere ) {
2020-12-30 21:11:01 +01:00
return true ;
}
return false ;
}
2020-12-30 16:33:56 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
checkIsAdditionnalHumide ( cellDescr , coordTMR ) {
let pontHumide = this . data . items . find ( item => item . type == 'souffle' && item . name . toLowerCase ( ) . includes ( ' des ponts' ) ) ;
if ( pontHumide && cellDescr . type == 'pont' ) {
ChatMessage . create ( {
2020-12-30 16:33:56 +01:00
content : "Vous êtes sous le coup d'une Impraticabilité des Ponts : ils doivent être maîtrisés comme des cases humides." ,
2021-01-09 19:33:19 +01:00
whisper : ChatMessage . getWhisperRecipients ( game . user . name )
} ) ;
2020-12-30 16:33:56 +01:00
return true ;
}
2020-12-30 19:27:35 +01:00
// Débordement ?
2021-01-09 19:33:19 +01:00
let debordementList = this . data . items . filter ( item => item . type == 'casetmr' && item . data . specific == 'debordement' ) ;
2020-12-30 19:27:35 +01:00
for ( let caseTMR of debordementList ) {
2021-01-09 19:33:19 +01:00
if ( caseTMR . data . coord == coordTMR )
2020-12-30 19:27:35 +01:00
return true ;
}
2021-01-09 19:33:19 +01:00
2020-12-30 16:33:56 +01:00
return false ;
}
2020-12-17 09:29:09 +01:00
/* -------------------------------------------- */
2020-12-08 23:07:41 +01:00
async _rollUnSortResult ( rollData , isSortReserve = false ) {
let rolled = rollData . rolled ;
2020-12-31 02:20:52 +01:00
let selectedSort = rollData . selectedSort ;
let closeTMR = ! isSortReserve ;
if ( selectedSort . data . isrituel && isSortReserve ) {
ui . notifications . error ( "Impossible de mettre le rituel '" + selectedSort . name + "' en réserve" ) ;
2020-12-11 20:37:00 +01:00
this . currentTMR . close ( ) ; // Close TMR !
return ;
2021-01-09 19:33:19 +01:00
}
2020-12-31 02:20:52 +01:00
rollData . isSortReserve = isSortReserve ;
rollData . show = { }
rollData . depenseReve = Number ( selectedSort . data . ptreve _reel ) ;
2020-12-11 20:37:00 +01:00
2020-12-08 23:07:41 +01:00
let myReve = duplicate ( this . data . data . reve . reve ) ;
if ( rolled . isSuccess ) { // Réussite du sort !
if ( rolled . isPart ) {
2020-12-31 02:20:52 +01:00
rollData . depenseReve = Math . max ( Math . floor ( rollData . depenseReve / 2 ) , 1 ) ;
2020-12-08 23:07:41 +01:00
}
if ( rollData . isSortReserve ) {
2020-12-31 02:20:52 +01:00
rollData . depenseReve ++ ;
2020-12-08 23:07:41 +01:00
}
2020-12-31 02:20:52 +01:00
if ( myReve . value > rollData . depenseReve ) {
2020-12-08 23:07:41 +01:00
// Incrémenter/gére le bonus de case
2020-12-31 02:20:52 +01:00
RdDItemSort . incrementBonusCase ( this , selectedSort , rollData . coord ) ;
2021-01-09 19:33:19 +01:00
2020-12-08 23:07:41 +01:00
if ( rollData . isSortReserve ) {
2020-12-31 02:20:52 +01:00
await this . sortMisEnReserve ( rollData , selectedSort ) ;
2020-12-08 23:07:41 +01:00
closeTMR = false ;
}
}
else {
2020-12-31 02:20:52 +01:00
rollData . depenseReve = 0 ;
rollData . show . reveInsuffisant = true ;
2021-01-09 19:33:19 +01:00
mergeObject ( rollData . rolled , RdDResolutionTable . getResultat ( "echec" ) , { overwrite : true } ) ;
2020-12-08 23:07:41 +01:00
}
} else {
if ( rolled . isETotal ) { // Echec total !
2020-12-31 02:20:52 +01:00
rollData . depenseReve = Math . min ( myReve . value , Math . floor ( rollData . depenseReve * 1.5 ) )
2020-12-08 23:07:41 +01:00
// TODO: mise en réserve d'un échec total...
} else {
2020-12-31 02:20:52 +01:00
rollData . depenseReve = 0
2020-12-08 23:07:41 +01:00
}
}
2020-12-31 02:20:52 +01:00
myReve . value = Math . max ( myReve . value - rollData . depenseReve , 0 ) ;
2020-12-08 23:07:41 +01:00
await this . update ( { "data.reve.reve" : myReve } ) ;
2021-01-09 19:33:19 +01:00
2020-12-08 23:07:41 +01:00
if ( closeTMR ) {
this . currentTMR . close ( ) ; // Close TMR !
} else {
this . currentTMR . maximize ( ) ; // Re-display TMR
}
// Final chat message
2021-01-05 18:43:13 +01:00
RdDResolutionTable . displayRollData ( rollData , this , 'chat-resultat-sort.html' ) ;
2020-12-31 02:20:52 +01:00
if ( myReve . value == 0 ) { // 0 points de reve
ChatMessage . create ( { content : this . name + " est réduit à 0 Points de Rêve, et tombe endormi !" } ) ;
closeTMR = true ;
}
2020-12-08 23:07:41 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async rollCarac ( caracName ) {
2021-01-02 14:10:43 +01:00
let rollData = { selectedCarac : this . getCaracByName ( caracName ) } ;
2020-12-06 23:31:23 +01:00
const dialog = await RdDRoll . create ( this , rollData ,
2021-01-09 19:33:19 +01:00
{ html : 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html' } ,
2020-12-06 23:31:23 +01:00
{
2021-01-09 19:33:19 +01:00
name : 'jet-' + caracName ,
2020-12-08 03:04:00 +01:00
label : 'Jet ' + Grammar . apostrophe ( 'de' , rollData . selectedCarac . label ) ,
2020-12-06 23:31:23 +01:00
callbacks : [
2020-12-12 21:58:44 +01:00
this . createCallbackExperience ( ) ,
2021-01-05 18:43:13 +01:00
{ action : r => this . _onRollCaracResult ( r ) }
2020-12-06 23:31:23 +01:00
]
}
) ;
dialog . render ( true ) ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2021-01-02 04:28:43 +01:00
async _onRollCaracResult ( rollData ) {
2020-12-06 23:31:23 +01:00
// Final chat message
2021-01-05 18:43:13 +01:00
RdDResolutionTable . displayRollData ( rollData , this , 'chat-resultat-general.html' ) ;
2020-12-06 18:41:54 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async rollCompetence ( name ) {
2021-01-02 14:10:43 +01:00
let rollData = { competence : this . getCompetence ( name ) }
2021-01-19 23:39:35 +01:00
2020-12-08 03:04:00 +01:00
if ( rollData . competence . type == 'competencecreature' ) {
2021-01-19 23:39:35 +01:00
if ( rollData . competence . data . iscombat ) {
const arme = RdDItemCompetenceCreature . toArme ( competence ) ;
RdDCombat . createUsingTarget ( this ) . attaque ( competence , arme ) ;
return ;
}
2020-12-08 03:04:00 +01:00
// Fake competence pour créature
2021-01-13 23:47:12 +01:00
RdDItemCompetenceCreature . setRollDataCreature ( rollData ) ;
2020-12-08 03:04:00 +01:00
}
2021-01-01 22:25:32 +01:00
else {
2020-12-08 03:04:00 +01:00
rollData . carac = this . data . data . carac ;
}
2020-12-12 21:58:44 +01:00
console . log ( "rollCompetence !!!" , rollData ) ;
2020-12-08 03:04:00 +01:00
2021-01-09 19:33:19 +01:00
const dialog = await RdDRoll . create ( this , rollData , { html : 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html' } , {
name : 'jet-competence' ,
label : 'Jet ' + Grammar . apostrophe ( 'de' , name ) ,
callbacks : [
this . createCallbackExperience ( ) ,
{ action : r => this . _competenceResult ( r ) }
]
} ) ;
dialog . render ( true ) ;
}
/* -------------------------------------------- */
async creerTacheDepuisLivre ( item ) {
let tache = {
name : "Lire " + item . name , type : 'tache' ,
data : {
carac : 'intellect' ,
competence : 'Ecriture' ,
difficulte : item . data . data . difficulte ,
periodicite : "60 minutes" ,
fatigue : 2 ,
points _de _tache : item . data . data . points _de _tache ,
points _de _tache _courant : 0 ,
description : "Lecture du livre " + item . name +
" - XP : " + item . data . data . xp + " - Compétences : " + item . data . data . competence
}
}
await this . createOwnedItem ( tache , { renderSheet : true } ) ;
}
/* -------------------------------------------- */
async rollTache ( id ) {
let tache = duplicate ( this . getTache ( id ) ) ;
2020-12-15 08:37:52 +01:00
let competence = duplicate ( this . getCompetence ( tache . data . competence ) ) ;
competence . data . defaut _carac = tache . data . carac ; // Patch !
let rollData = {
2021-01-09 19:33:19 +01:00
competence : competence ,
2020-12-15 08:37:52 +01:00
tache : tache ,
diffConditions : tache . data . difficulte ,
2021-01-13 03:11:03 +01:00
use : { libre : false , conditions : false } ,
2021-01-09 19:33:19 +01:00
carac : { }
2021-01-02 14:10:43 +01:00
} ;
2020-12-15 08:37:52 +01:00
rollData . carac [ tache . data . carac ] = duplicate ( this . data . data . carac [ tache . data . carac ] ) ; // Single carac
2021-01-02 14:10:43 +01:00
console . log ( "rollTache !!!" , rollData ) ;
2020-12-15 08:37:52 +01:00
2021-01-09 19:33:19 +01:00
const dialog = await RdDRoll . create ( this , rollData , { html : 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html' } , {
name : 'jet-competence' ,
label : 'Jet de Tâche ' + tache . name ,
callbacks : [
this . createCallbackExperience ( ) ,
{ condition : r => r . rolled . isETotal , action : r => this . _tacheETotal ( r ) } ,
{ action : r => this . _tacheResult ( r ) }
]
} ) ;
2020-12-15 21:28:55 +01:00
dialog . render ( true ) ;
2020-12-15 08:37:52 +01:00
}
/* -------------------------------------------- */
2021-01-01 03:25:48 +01:00
async _tacheResult ( rollData ) {
2020-12-15 21:28:55 +01:00
// Mise à jour de la tache
rollData . tache . data . points _de _tache _courant += rollData . rolled . ptTache ;
2021-01-09 19:33:19 +01:00
this . updateEmbeddedEntity ( "OwnedItem" , rollData . tache ) ;
this . santeIncDec ( "fatigue" , rollData . tache . data . fatigue ) ;
2020-12-15 21:28:55 +01:00
2021-01-05 18:43:13 +01:00
RdDResolutionTable . displayRollData ( rollData , this , 'chat-resultat-tache.html' ) ;
2020-12-15 08:37:52 +01:00
}
2020-12-30 10:41:02 +01:00
/* -------------------------------------------- */
2020-12-18 00:45:20 +01:00
_tacheETotal ( rollData ) {
2020-12-30 10:41:02 +01:00
rollData . tache . data . difficulte -- ;
2021-01-09 19:33:19 +01:00
this . updateEmbeddedEntity ( "OwnedItem" , rollData . tache ) ;
2020-12-18 00:45:20 +01:00
}
2021-01-04 22:03:00 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async rollMeditation ( id ) {
2021-01-05 18:43:13 +01:00
let meditation = duplicate ( this . getMeditation ( id ) ) ;
2021-01-04 22:03:00 +01:00
let competence = duplicate ( this . getCompetence ( meditation . data . competence ) ) ;
competence . data . defaut _carac = "intellect" ; // Meditation = tjs avec intellect
let meditationData = {
2021-01-05 18:43:13 +01:00
competence : competence ,
2021-01-04 22:03:00 +01:00
meditation : meditation ,
2021-01-05 18:43:13 +01:00
conditionMeditation : {
isHeure : false ,
isVeture : false ,
isComportement : false ,
isPurification : false ,
} ,
2021-01-04 22:03:00 +01:00
diffConditions : 0 ,
2021-01-13 03:11:03 +01:00
use : { libre : false , conditions : true , } ,
2021-01-09 19:33:19 +01:00
carac : { }
2021-01-04 22:03:00 +01:00
} ;
2021-01-09 19:33:19 +01:00
meditationData . carac [ "intellect" ] = duplicate ( this . data . data . carac [ "intellect" ] ) ;
2021-01-04 22:03:00 +01:00
2021-01-05 18:43:13 +01:00
console . log ( "rollMeditation !!!" , meditationData ) ;
2021-01-04 22:03:00 +01:00
2021-01-09 19:33:19 +01:00
const dialog = await RdDRoll . create ( this , meditationData , { html : 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html' } , {
name : 'jet-meditation' ,
label : 'Jet de Meditation ' + meditation . name ,
height : 600 ,
callbacks : [
this . createCallbackExperience ( ) ,
{ condition : r => r . rolled . isETotal , action : r => this . _meditationETotal ( r ) } ,
{ action : r => this . _meditationResult ( r ) }
]
} ) ;
2021-01-04 22:03:00 +01:00
dialog . render ( true ) ;
}
/* -------------------------------------------- */
async _meditationResult ( meditationData ) {
2021-01-09 19:33:19 +01:00
this . santeIncDec ( "fatigue" , 2 ) ;
2021-01-04 22:03:00 +01:00
meditationData . diffLecture = - 7 ;
2021-01-09 19:33:19 +01:00
if ( meditationData . rolled . isPart )
2021-01-04 22:03:00 +01:00
meditationData . diffLecture = 0 ;
2021-01-09 19:33:19 +01:00
else if ( meditationData . rolled . isSign )
2021-01-04 22:03:00 +01:00
meditationData . diffLecture = - 3 ;
RdDResolutionTable . displayRollData ( meditationData , this . name , 'chat-resultat-meditation.html' ) ;
}
2021-01-09 19:33:19 +01:00
2021-01-04 22:03:00 +01:00
/* -------------------------------------------- */
_meditationETotal ( meditationData ) {
meditationData . meditation . data . malus -- ;
2021-01-09 19:33:19 +01:00
this . updateEmbeddedEntity ( "OwnedItem" , meditationData . meditation ) ;
2021-01-04 22:03:00 +01:00
}
2021-01-09 19:33:19 +01:00
2020-12-11 08:29:24 +01:00
/* -------------------------------------------- */
2021-01-01 03:25:48 +01:00
async _competenceResult ( rollData ) {
2021-01-05 18:43:13 +01:00
RdDResolutionTable . displayRollData ( rollData , this , 'chat-resultat-competence.html' )
2020-12-08 03:04:00 +01:00
}
2020-12-06 23:31:23 +01:00
2020-12-06 21:11:30 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async rollAppelChance ( onSuccess = ( ) => { } , onEchec = ( ) => { } ) {
2021-01-02 14:10:43 +01:00
let rollData = { selectedCarac : this . getCaracByName ( 'chance-actuelle' ) , surprise : '' } ;
2020-12-06 23:31:23 +01:00
const dialog = await RdDRoll . create ( this , rollData ,
2021-01-09 19:33:19 +01:00
{ html : 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html' } ,
2020-11-15 02:07:41 +01:00
{
2020-12-06 19:29:10 +01:00
name : 'appelChance' ,
label : 'Appel à la chance' ,
callbacks : [
2020-12-12 21:58:44 +01:00
this . createCallbackExperience ( ) ,
2021-01-07 01:54:38 +01:00
{ action : r => this . _appelChanceResult ( r , onSuccess , onEchec ) } ,
2020-12-06 19:29:10 +01:00
]
2020-11-15 02:07:41 +01:00
}
2021-01-09 19:33:19 +01:00
) ;
dialog . render ( true ) ;
}
/* -------------------------------------------- */
async _appelChanceResult ( rollData , onSuccess = ( ) => { } , onEchec = ( ) => { } ) {
await RdDResolutionTable . displayRollData ( rollData , this , 'chat-resultat-appelchance.html' )
if ( rollData . rolled . isSuccess ) {
await this . chanceActuelleIncDec ( - 1 )
onSuccess ( ) ;
}
else {
onEchec ( ) ;
2020-11-15 02:07:41 +01:00
}
2020-12-06 19:29:10 +01:00
}
2021-01-09 19:33:19 +01:00
2020-12-06 21:11:30 +01:00
/* -------------------------------------------- */
2020-12-06 19:29:10 +01:00
async chanceActuelleIncDec ( value ) {
let chance = duplicate ( this . data . data . compteurs . chance ) ;
chance . value = Math . max ( chance . value + value , 0 ) ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.compteurs.chance" : chance } ) ;
2020-12-06 19:29:10 +01:00
}
2021-01-09 19:33:19 +01:00
2021-01-07 00:29:38 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async appelDestinee ( onSuccess = ( ) => { } , onEchec = ( ) => { } ) {
if ( this . data . data . compteurs . destinee ? . value ? ? 0 > 0 ) {
ChatMessage . create ( { content : ` <span class="rdd-roll-part"> ${ this . name } a fait appel à la Destinée !</span> ` } ) ;
2021-01-07 00:29:38 +01:00
let destinee = duplicate ( this . data . data . compteurs . destinee ) ;
destinee . value = destinee . value - 1 ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.compteurs.destinee" : destinee } ) ;
2021-01-07 00:29:38 +01:00
onSuccess ( ) ;
}
else {
onEchec ( ) ;
}
}
2020-12-06 19:29:10 +01:00
2020-12-06 21:11:30 +01:00
/* -------------------------------------------- */
2020-12-06 19:29:10 +01:00
ajustementAstrologique ( ) {
2020-12-15 02:20:24 +01:00
if ( this . isCreature ( ) ) {
return 0 ;
}
2020-12-11 03:23:34 +01:00
// selon l'heure de naissance...
2020-12-15 23:28:59 +01:00
return game . system . rdd . calendrier . getAjustementAstrologique ( this . data . data . heure , this . data . name ) ;
2020-12-06 19:29:10 +01:00
}
2020-12-13 23:32:16 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
checkDesirLancinant ( ) {
let queue = this . data . items . filter ( ( item ) => item . name . toLowerCase ( ) . includes ( 'lancinant' ) ) ;
2020-12-14 10:38:43 +01:00
return ( queue . length > 0 ) ;
}
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async appliquerExperience ( rolled , caracName , competence = undefined ) {
2021-01-23 18:36:30 +01:00
if ( this . isCreature ( ) ) {
return ;
}
2021-01-09 19:33:19 +01:00
if ( rolled . isPart && rolled . finalLevel < 0 ) {
2020-12-14 10:38:43 +01:00
// Cas de désir lancinant, pas d'expérience sur particulière
2021-01-09 19:33:19 +01:00
if ( this . checkDesirLancinant ( ) ) {
ChatMessage . create ( {
content : ` Vous souffrez au moins d'un Désir Lancinant, vous ne pouvez pas gagner d'expérience sur une Particulière tant que le désir n'est pas assouvi ` ,
whisper : ChatMessage . getWhisperRecipients ( game . user . name )
} ) ;
return { result : false , xpcarac : 0 , xpCompetence : 0 } ;
2020-12-14 10:38:43 +01:00
}
2020-12-12 21:58:44 +01:00
if ( caracName == 'derobee' ) caracName = 'agilite' ;
let xp = Math . abs ( rolled . finalLevel ) ;
let xpCarac = Math . floor ( xp / 2 ) ; // impair: arrondi inférieur en carac
2020-12-15 08:40:07 +01:00
let xpComp = 0 ;
2021-01-09 19:33:19 +01:00
if ( competence ) {
2020-12-15 08:40:07 +01:00
xpComp = xp - xpCarac ;
2021-01-09 19:33:19 +01:00
competence = duplicate ( competence ) ;
2020-12-31 03:34:37 +01:00
competence . data . xp = Misc . toInt ( competence . data . xp ) + xpComp ;
2021-01-09 19:33:19 +01:00
await this . updateEmbeddedEntity ( "OwnedItem" , competence ) ;
2020-12-15 08:37:52 +01:00
} else {
2020-12-15 08:40:07 +01:00
xpCarac = Math . max ( xpCarac , 1 ) ;
2021-01-09 19:33:19 +01:00
}
2020-12-31 03:34:37 +01:00
if ( xpCarac > 0 ) {
let carac = duplicate ( this . data . data . carac ) ;
let selectedCarac = RdDActor . _findCaracByName ( carac , caracName ) ;
2021-01-09 19:33:19 +01:00
if ( ! selectedCarac . derivee ) {
2020-12-31 03:34:37 +01:00
selectedCarac . xp = Misc . toInt ( selectedCarac . xp ) + xpCarac ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.carac" : carac } ) ;
2020-12-31 03:34:37 +01:00
} else {
2021-01-09 19:33:19 +01:00
ChatMessage . create ( {
content : ` Vous avez ${ xpCarac } à répartir pour la caractérisque dérivée ${ caracName } . Vous devez le faire manuellement. ` ,
whisper : ChatMessage . getWhisperRecipients ( game . user . name )
} ) ;
2020-12-31 03:34:37 +01:00
}
2020-12-13 23:32:16 +01:00
}
2021-01-09 19:33:19 +01:00
return { result : true , xpCarac : xpCarac , xpCompetence : xpComp } ; //XP
2020-12-13 23:32:16 +01:00
}
2021-01-09 19:33:19 +01:00
return { result : false , xpCarac : 0 , xpCompetence : 0 } ; // Pas d'XP
2020-12-13 23:32:16 +01:00
}
2021-01-09 19:33:19 +01:00
2020-12-13 23:11:58 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async ajouteNombreAstral ( data ) {
2020-12-13 23:32:16 +01:00
// Gestion expérience (si existante)
2021-01-09 19:33:19 +01:00
data . competence = RdDItemCompetence . findCompetence ( this . data . items , "astrologie" ) ;
2021-01-03 18:19:18 +01:00
data . selectedCarac = this . data . data . carac [ "vue" ] ;
2021-01-09 19:33:19 +01:00
this . _appliquerAjoutExperience ( data ) ;
2020-12-13 23:32:16 +01:00
2020-12-13 23:11:58 +01:00
// Ajout du nombre astral
2021-01-09 19:33:19 +01:00
const item = {
name : "Nombre Astral" , type : "nombreastral" , data :
{ value : data . nbAstral , istrue : data . isvalid , jourindex : Number ( data . date ) , jourlabel : game . system . rdd . calendrier . getDateFromIndex ( Number ( data . date ) ) }
} ;
2020-12-13 23:11:58 +01:00
await this . createEmbeddedEntity ( "OwnedItem" , item ) ;
2021-01-09 19:33:19 +01:00
2020-12-13 23:11:58 +01:00
// Suppression des anciens nombres astraux
2021-01-09 19:33:19 +01:00
let toDelete = this . data . items . filter ( ( item ) => item . data . jourindex < game . system . rdd . calendrier . getCurrentDayIndex ( ) ) ;
2020-12-13 23:11:58 +01:00
const deletions = toDelete . map ( i => i . _id ) ;
await this . deleteEmbeddedEntity ( "OwnedItem" , deletions ) ;
// Affichage Dialog
this . astrologieNombresAstraux ( ) ;
2021-01-09 19:33:19 +01:00
}
2020-12-06 19:29:10 +01:00
2020-12-11 08:29:24 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async astrologieNombresAstraux ( ) {
2020-12-11 08:29:24 +01:00
// Afficher l'interface spéciale
2021-01-09 19:33:19 +01:00
const astrologieDialog = await RdDAstrologieJoueur . create ( this , { } ) ;
2020-12-13 23:11:58 +01:00
astrologieDialog . render ( true ) ;
2020-12-11 08:29:24 +01:00
}
2020-12-06 21:11:30 +01:00
/* -------------------------------------------- */
2020-12-06 18:41:54 +01:00
getCaracByName ( caracName ) {
2021-01-09 19:33:19 +01:00
switch ( caracName ) {
2020-12-31 03:51:53 +01:00
case 'reve-actuel' : case 'Rêve actuel' :
2020-12-06 18:41:54 +01:00
return {
2020-12-31 03:51:53 +01:00
label : 'Rêve actuel' ,
2020-12-06 18:41:54 +01:00
value : this . getReveActuel ( ) ,
2021-01-05 18:43:13 +01:00
type : "number"
2020-12-06 18:41:54 +01:00
} ;
2020-12-31 03:34:37 +01:00
case 'chance-actuelle' : case 'Chance actuelle' :
2020-12-06 18:41:54 +01:00
return {
label : 'Chance actuelle' ,
2020-12-31 03:34:37 +01:00
value : this . getChanceActuel ( ) ,
2021-01-05 18:43:13 +01:00
type : "number"
2020-12-06 18:41:54 +01:00
} ;
2020-11-15 02:07:41 +01:00
}
2020-12-31 03:34:37 +01:00
return RdDActor . _findCaracByName ( this . data . data . carac , caracName ) ;
}
static _findCaracByName ( carac , name ) {
name = name . toLowerCase ( ) ;
2021-01-09 19:33:19 +01:00
switch ( name ) {
2020-12-31 03:34:37 +01:00
case 'reve-actuel' : case 'rêve actuel' :
return carac . reve ;
case 'chance-actuelle' : case 'chance actuelle' :
return carac . chance ;
}
for ( const [ key , value ] of Object . entries ( carac ) ) {
if ( name == key || name == value . label . toLowerCase ( ) ) {
return carac [ key ] ;
}
}
return carac [ name ] ; // Per default
2020-12-06 18:41:54 +01:00
}
/* -------------------------------------------- */
getSortList ( ) {
return this . data . items . filter ( item => item . type == "sort" ) ;
}
2021-01-09 19:33:19 +01:00
2020-12-06 18:41:54 +01:00
/* -------------------------------------------- */
getDraconicList ( ) {
return this . data . items . filter ( item => item . data . categorie == 'draconic' )
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
checkMonteeLaborieuse ( ) { // Return +1 si la queue Montée Laborieuse est présente, 0 sinon
let monteLaborieuse = this . data . items . find ( item => ( item . type == 'queue' || item . type == 'souffle' ) && item . name . toLowerCase ( ) . includes ( 'montée laborieuse' ) ) ;
if ( monteLaborieuse ) {
ChatMessage . create ( {
2020-12-30 15:56:17 +01:00
content : "Vous êtes sous le coup d'une Montée Laborieuse : vos montées en TMR coûtent 1 Point de Rêve de plus." ,
2021-01-09 19:33:19 +01:00
whisper : ChatMessage . getWhisperRecipients ( game . user . name )
} ) ;
2020-12-30 15:56:17 +01:00
return 1 ;
}
return 0 ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async displayTMR ( mode = "normal" ) {
let isRapide = mode == "rapide" ;
if ( mode != "visu" ) {
2020-12-06 18:41:54 +01:00
let minReveValue = ( isRapide ) ? 3 : 2 ;
2021-01-09 19:33:19 +01:00
if ( this . getReveActuel ( ) < minReveValue ) {
ChatMessage . create ( {
2020-12-06 18:41:54 +01:00
content : "Vous n'avez plus assez de Points de Reve pour monter dans les Terres Médianes" ,
2021-01-09 19:33:19 +01:00
whisper : ChatMessage . getWhisperRecipients ( game . user . name )
} ) ;
2020-12-06 18:41:54 +01:00
return ;
2021-01-09 19:33:19 +01:00
}
2020-09-20 19:17:31 +02:00
}
2021-01-09 19:33:19 +01:00
2021-01-20 19:29:02 +01:00
if ( mode != 'visu' ) {
// Notification au MJ
ChatMessage . create ( { content : this . name + " est monté dans les TMR en mode : " + mode , whisper : ChatMessage . getWhisperRecipients ( "GM" ) } ) ;
}
2020-12-06 18:41:54 +01:00
let data = {
fatigue : {
2021-01-09 19:33:19 +01:00
malus : RdDUtility . calculMalusFatigue ( this . data . data . sante . fatigue . value , this . data . data . sante . endurance . max ) ,
html : "<table class='table-fatigue'>" + RdDUtility . makeHTMLfatigueMatrix ( this . data . data . sante . fatigue . value , this . data . data . sante . endurance . max ) . html ( ) + "</table>"
2020-12-06 18:41:54 +01:00
} ,
draconic : this . getDraconicList ( ) ,
sort : this . getSortList ( ) ,
caracReve : this . data . data . carac . reve . value ,
pointsReve : this . getReveActuel ( ) ,
isRapide : isRapide
2021-01-09 19:33:19 +01:00
}
let html = await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html' , data ) ;
2020-12-06 18:41:54 +01:00
this . currentTMR = new RdDTMRDialog ( html , this , data , mode ) ;
this . currentTMR . render ( true ) ;
}
2020-12-08 03:04:00 +01:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2021-01-04 00:17:22 +01:00
rollArme ( compName , armeName = undefined ) {
2021-01-14 00:35:55 +01:00
let arme = armeName ? this . data . items . find ( item => item . name == armeName && RdDItemArme . isArme ( item ) ) : undefined ;
2021-01-04 00:17:22 +01:00
let competence = this . getCompetence ( compName ) ;
2021-01-09 19:33:19 +01:00
2021-01-04 00:17:22 +01:00
if ( arme || armeName || ( competence . type == 'competencecreature' && competence . data . iscombat ) ) {
RdDCombat . createUsingTarget ( this ) . attaque ( competence , arme ) ;
2020-12-06 18:41:54 +01:00
} else {
2021-01-09 19:33:19 +01:00
this . rollCompetence ( competence . name ) ;
2020-12-06 18:41:54 +01:00
}
}
2020-12-01 17:36:13 +01:00
2020-12-17 09:29:09 +01:00
/* -------------------------------------------- */
2020-12-06 18:41:54 +01:00
_getTarget ( ) {
2020-12-01 17:36:13 +01:00
if ( game . user . targets && game . user . targets . size == 1 ) {
for ( let target of game . user . targets ) {
return target ;
}
}
return undefined ;
}
2021-01-09 19:33:19 +01:00
2021-01-14 00:35:55 +01:00
getArmeParade ( armeParadeId ) {
const item = armeParadeId ? this . getOwnedItem ( armeParadeId ) : undefined ;
return RdDItemArme . getArmeData ( item ) ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async equiperObjet ( itemID ) {
2020-06-23 23:34:12 +02:00
let item = this . getOwnedItem ( itemID ) ;
2021-01-09 19:33:19 +01:00
if ( item && item . data . data ) {
let update = { _id : item . _id , "data.equipe" : ! item . data . data . equipe } ;
await this . updateEmbeddedEntity ( "OwnedItem" , update ) ;
2020-12-02 14:00:54 +01:00
this . computeEncombrementTotalEtMalusArmure ( ) ; // Mise à jour encombrement
2020-06-24 00:22:40 +02:00
}
2020-06-23 23:34:12 +02:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
computeArmure ( attackerRoll ) {
2021-01-19 22:50:02 +01:00
let dmg = ( attackerRoll . dmg . dmgArme ? ? 0 ) + ( attackerRoll . dmg . dmgActor ? ? 0 ) ;
2021-01-09 19:33:19 +01:00
let arme = attackerRoll . arme ;
2020-06-23 23:34:12 +02:00
let protection = 0 ;
2021-01-19 22:50:02 +01:00
const armures = this . data . items . filter ( it => it . type == "armure" && it . data . equipe ) ;
for ( const item of armures ) {
protection += new Roll ( item . data . protection . toString ( ) ) . roll ( ) . total ;
if ( dmg > 0 ) {
this . _deteriorerArmure ( item , dmg ) ;
dmg = 0 ;
2020-06-23 23:34:12 +02:00
}
}
2021-01-19 22:50:02 +01:00
// TODO: max armure sur chutes...
2020-12-18 01:10:03 +01:00
const penetration = arme ? Misc . toInt ( arme . data . penetration ) : 0 ;
protection = Math . max ( protection - penetration , 0 ) ;
2020-12-15 18:36:18 +01:00
protection += this . getProtectionNaturelle ( ) ;
2020-06-23 23:34:12 +02:00
console . log ( "Final protect" , protection ) ;
return protection ;
2020-06-07 23:16:29 +02:00
}
2020-11-11 04:21:25 +01:00
2021-01-19 22:50:02 +01:00
_deteriorerArmure ( item , dmg ) {
let update = duplicate ( item ) ;
update . data . deterioration = ( update . data . deterioration ? ? 0 ) + dmg ;
if ( update . data . deterioration >= 10 ) {
update . data . deterioration = 0 ;
let res = /\d+/ . exec ( update . data . protection ) ;
if ( ! res ) {
update . data . protection = "1d" + update . data . protection ;
}
else if ( res = /(\d+d\d+)(\-\d+)?/ . exec ( update . data . protection ) ) {
let malus = Misc . toInt ( res [ 2 ] ) - 1 ;
update . data . protection = res [ 1 ] + malus ;
}
else {
ui . notifications . warn ( ` La valeur d'armure de votre ${ item . name } est incorrecte ` ) ;
}
ChatMessage . create ( { content : "Votre armure s'est détériorée, elle protège maintenant de " + update . data . protection } ) ;
}
this . updateEmbeddedEntity ( "OwnedItem" , update ) ;
}
2020-12-27 22:21:08 +01:00
/* -------------------------------------------- */
2021-01-09 19:33:19 +01:00
async encaisser ( ) {
2020-12-27 22:21:08 +01:00
let data = { ajustementsEncaissement : RdDUtility . getAjustementsEncaissement ( ) } ;
2021-01-09 19:33:19 +01:00
let html = await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html' , data ) ;
2020-12-27 22:21:08 +01:00
new RdDEncaisser ( html , this ) . render ( true ) ;
}
2020-11-11 04:21:25 +01:00
/* -------------------------------------------- */
2021-01-23 18:36:30 +01:00
async encaisserDommages ( rollData , attacker = undefined , defenderRoll = undefined ) {
2020-12-01 17:36:13 +01:00
if ( attacker && ! await attacker . accorder ( this , 'avant-encaissement' ) ) {
return ;
}
2021-01-10 00:30:37 +01:00
console . log ( "encaisserDommages" , rollData )
2020-12-15 02:20:24 +01:00
2021-01-09 19:38:24 +01:00
let santeOrig = duplicate ( this . data . data . sante ) ;
2021-01-10 00:30:37 +01:00
let encaissement = this . jetEncaissement ( rollData ) ;
2021-01-06 16:24:05 +01:00
this . ajouterBlessure ( encaissement ) ; // Will upate the result table
2021-01-19 23:01:14 +01:00
const perteVie = this . isEntiteCauchemar ( )
? { newValue : 0 }
: await this . santeIncDec ( "vie" , - encaissement . vie ) ;
2021-01-09 19:38:24 +01:00
const perteEndurance = await this . santeIncDec ( "endurance" , - encaissement . endurance , ( encaissement . critiques > 0 ) ) ;
2021-01-10 02:28:45 +01:00
2020-06-07 23:16:29 +02:00
this . computeEtatGeneral ( ) ;
2021-01-04 00:42:04 +01:00
this . sheet . render ( false ) ;
2021-01-10 02:28:45 +01:00
2021-01-23 18:36:30 +01:00
mergeObject ( encaissement , {
alias : this . data . name ,
hasPlayerOwner : this . hasPlayerOwner ,
resteEndurance : this . data . data . sante . endurance . value ,
sonne : perteEndurance . sonne ,
jetEndurance : perteEndurance . jetEndurance ,
endurance : santeOrig . endurance . value - perteEndurance . newValue ,
vie : this . isEntiteCauchemar ( ) ? 0 : ( santeOrig . vie . value - perteVie . newValue ) ,
show : defenderRoll ? . show ? ? { }
} ) ;
2021-01-10 02:28:45 +01:00
2021-01-09 19:38:24 +01:00
ChatUtility . createChatWithRollMode ( this . name , {
2021-01-10 02:28:45 +01:00
roll : encaissement . roll ,
content : await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html' , encaissement )
} ) ;
2021-01-09 19:38:24 +01:00
if ( ! encaissement . hasPlayerOwner && encaissement . endurance != 0 ) {
encaissement = duplicate ( encaissement ) ;
encaissement . isGM = true ;
ChatMessage . create ( {
whisper : ChatMessage . getWhisperRecipients ( "GM" ) ,
content : await renderTemplate ( 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html' , encaissement )
} ) ;
}
2020-06-07 23:16:29 +02:00
}
2020-11-07 21:06:37 +01:00
2021-01-06 16:24:05 +01:00
/* -------------------------------------------- */
jetEncaissement ( rollData ) {
2021-01-09 19:38:24 +01:00
const roll = new Roll ( "2d10" ) . roll ( ) ;
roll . showDice = true ;
2021-01-06 16:24:05 +01:00
RdDDice . show ( roll , game . settings . get ( "core" , "rollMode" ) ) ;
2021-01-09 19:38:24 +01:00
const armure = this . computeArmure ( rollData ) ;
const jetTotal = roll . total + rollData . dmg . total - armure ;
let encaissement = RdDUtility . selectEncaissement ( jetTotal , rollData . dmg . mortalite )
let over20 = Math . max ( jetTotal - 20 , 0 ) ;
encaissement . dmg = rollData . dmg ;
encaissement . dmg . loc = rollData . dmg . loc ? ? RdDUtility . getLocalisation ( ) ;
encaissement . dmg . loc . label = encaissement . dmg . loc . label ? ? 'Corps;'
2021-01-06 16:24:05 +01:00
encaissement . roll = roll ;
2021-01-09 19:38:24 +01:00
encaissement . armure = armure ;
encaissement . total = jetTotal ;
encaissement . vie = RdDUtility . _evaluatePerte ( encaissement . vie , over20 ) ;
encaissement . endurance = RdDUtility . _evaluatePerte ( encaissement . endurance , over20 ) ;
encaissement . penetration = rollData . arme ? . data . penetration ? ? 0 ;
2021-01-06 16:24:05 +01:00
return encaissement ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
ajouterBlessure ( encaissement ) {
2021-01-06 16:24:05 +01:00
// Fast exit
2021-01-09 19:33:19 +01:00
if ( this . data . type == 'entite' ) return ; // Une entité n'a pas de blessures
if ( encaissement . legeres + encaissement . graves + encaissement . critiques == 0 ) return ;
2021-01-06 16:24:05 +01:00
const endActuelle = Number ( this . data . data . sante . endurance . value ) ;
let blessures = duplicate ( this . data . data . blessures ) ;
let count = encaissement . legeres ;
// Manage blessures
while ( count > 0 ) {
let legere = blessures . legeres . liste . find ( it => ! it . active ) ;
if ( legere ) {
this . _setBlessure ( legere , encaissement ) ;
count -- ;
}
else {
encaissement . graves += count ;
encaissement . legeres -= count ;
break ;
}
}
2021-01-09 19:33:19 +01:00
2021-01-06 16:24:05 +01:00
count = encaissement . graves ;
while ( count > 0 ) {
let grave = blessures . graves . liste . find ( it => ! it . active ) ;
if ( grave ) {
this . _setBlessure ( grave , encaissement ) ;
count -- ;
}
2021-01-09 19:33:19 +01:00
else {
2021-01-06 16:24:05 +01:00
encaissement . critiques += count ;
encaissement . graves -= count ;
encaissement . endurance = - endActuelle ;
encaissement . vie = - 4 ;
break ;
}
}
2021-01-09 19:33:19 +01:00
2021-01-06 16:24:05 +01:00
count = encaissement . critique ;
2021-01-09 19:33:19 +01:00
while ( count > 0 ) {
2021-01-06 16:24:05 +01:00
let critique = blessures . critiques . liste [ 0 ] ;
2021-01-09 19:33:19 +01:00
if ( ! critique . active ) {
2021-01-06 16:24:05 +01:00
this . _setBlessure ( critique , encaissement ) ;
count -- ;
} else {
// TODO: status effect dead
2021-01-09 19:33:19 +01:00
ChatMessage . create ( { content : ` <strong> ${ this . name } vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !</strong> ` } ) ;
2021-01-06 16:24:05 +01:00
encaissement . critique -= count ;
break ;
}
}
encaissement . endurance = Math . max ( encaissement . endurance , - endActuelle ) ;
2021-01-09 19:33:19 +01:00
this . update ( { "data.blessures" : blessures } ) ;
2021-01-06 16:24:05 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2021-01-06 16:24:05 +01:00
_setBlessure ( blessure , encaissement ) {
blessure . active = true ;
blessure . loc = encaissement . locName ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-05-21 21:48:20 +02:00
/** @override */
getRollData ( ) {
const data = super . getRollData ( ) ;
return data ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
2020-12-01 17:36:13 +01:00
/* -- entites -- */
/* retourne true si on peut continuer, false si on ne peut pas continuer */
2021-01-09 19:33:19 +01:00
async targetEntiteNonAccordee ( target , when = 'avant-encaissement' ) {
if ( target ) {
2020-12-01 17:36:13 +01:00
return ! await this . accorder ( target . actor , when ) ;
}
return false ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async accorder ( entite , when = 'avant-encaissement' ) {
2020-12-01 17:36:13 +01:00
if ( when != game . settings . get ( "foundryvtt-reve-de-dragon" , "accorder-entite-cauchemar" )
2021-01-09 19:33:19 +01:00
|| ! entite . isEntiteCauchemar ( )
|| entite . isEntiteCauchemarAccordee ( this ) ) {
2020-12-01 17:36:13 +01:00
return true ;
}
2021-01-09 19:33:19 +01:00
let rolled = await RdDResolutionTable . roll ( this . getReveActuel ( ) , - Number ( entite . data . data . carac . niveau . value ) ) ;
2021-01-02 20:56:31 +01:00
const rollData = {
alias : this . name ,
rolled : rolled ,
entite : entite . name ,
2021-01-09 19:33:19 +01:00
selectedCarac : this . data . data . carac . reve
2020-12-01 17:36:13 +01:00
} ;
2021-01-09 19:33:19 +01:00
2020-12-01 17:36:13 +01:00
if ( rolled . isSuccess ) {
await entite . setEntiteReveAccordee ( this ) ;
}
2021-01-09 19:33:19 +01:00
2021-01-05 18:43:13 +01:00
await RdDResolutionTable . displayRollData ( rollData , this , 'chat-resultat-accorder-cauchemar.html' ) ;
2021-01-02 20:56:31 +01:00
if ( rolled . isPart ) {
await this . _appliquerAjoutExperience ( rollData , true ) ;
2020-12-01 17:36:13 +01:00
}
return rolled . isSuccess ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
isEntiteCauchemar ( ) {
2020-12-01 17:36:13 +01:00
return this . data . type == 'entite' ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
isEntiteCauchemarAccordee ( attaquant ) {
2020-12-01 17:36:13 +01:00
if ( ! this . isEntiteCauchemar ( ) ) { return true ; }
let resonnance = this . data . data . sante . resonnance ;
return ( resonnance . actors . find ( it => it == attaquant . _id ) ) ;
}
2020-11-14 03:16:03 +01:00
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async setEntiteReveAccordee ( attaquant ) {
2020-12-01 17:36:13 +01:00
if ( ! this . isEntiteCauchemar ( ) ) {
ui . notifications . error ( "Impossible de s'accorder à " + this . name + ": ce n'est pas une entite de cauchemer/rêve" ) ;
return ;
}
let resonnance = duplicate ( this . data . data . sante . resonnance ) ;
2021-01-09 19:33:19 +01:00
if ( resonnance . actors . find ( it => it == attaquant . _id ) ) {
2020-12-01 17:36:13 +01:00
// déjà accordé
return ;
}
resonnance . actors . push ( attaquant . _id ) ;
2021-01-09 19:33:19 +01:00
await this . update ( { "data.sante.resonnance" : resonnance } ) ;
2020-12-01 17:36:13 +01:00
return ;
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async optimizeArgent ( sumDenier ) {
2020-12-31 00:55:02 +01:00
let sols = Math . floor ( sumDenier / 100 ) ;
2021-01-09 19:33:19 +01:00
let deniers = sumDenier - ( sols * 100 ) ;
2020-12-31 00:55:02 +01:00
let nbOr = Math . floor ( sols / 10 ) ;
2021-01-09 19:33:19 +01:00
let nbArgent = sols - ( nbOr * 10 ) ;
let nbBronze = Math . floor ( deniers / 10 ) ;
let nbEtain = deniers - ( nbBronze * 10 ) ;
2020-12-31 00:55:02 +01:00
// console.log("ARGENT", nbOr, nbArgent, nbBronze, nbEtain);
2021-01-09 19:33:19 +01:00
let piece = this . data . items . find ( item => item . type == 'monnaie' && item . data . valeur _deniers == 1000 ) ;
if ( piece ) {
let update = { _id : piece . _id , 'data.quantite' : nbOr } ;
const updated = await this . updateEmbeddedEntity ( "OwnedItem" , update ) ;
2020-12-31 00:55:02 +01:00
}
2021-01-09 19:33:19 +01:00
piece = this . data . items . find ( item => item . type == 'monnaie' && item . data . valeur _deniers == 100 ) ;
if ( piece ) {
let update = { _id : piece . _id , 'data.quantite' : nbArgent } ;
const updated = await this . updateEmbeddedEntity ( "OwnedItem" , update ) ;
2020-12-31 00:55:02 +01:00
}
2021-01-09 19:33:19 +01:00
piece = this . data . items . find ( item => item . type == 'monnaie' && item . data . valeur _deniers == 10 ) ;
if ( piece ) {
let update = { _id : piece . _id , 'data.quantite' : nbBronze } ;
const updated = await this . updateEmbeddedEntity ( "OwnedItem" , update ) ;
2020-12-31 00:55:02 +01:00
}
2021-01-09 19:33:19 +01:00
piece = this . data . items . find ( item => item . type == 'monnaie' && item . data . valeur _deniers == 1 ) ;
if ( piece ) {
let update = { _id : piece . _id , 'data.quantite' : nbEtain } ;
const updated = await this . updateEmbeddedEntity ( "OwnedItem" , update ) ;
2020-12-31 00:55:02 +01:00
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async payerDenier ( sumDenier , dataObj = undefined ) {
2020-12-31 00:55:02 +01:00
sumDenier = Number ( sumDenier ) ;
let denierDisponible = 0 ;
2021-01-02 00:04:27 +01:00
2021-01-09 19:33:19 +01:00
let monnaie = this . data . items . filter ( item => item . type == 'monnaie' ) ;
for ( let piece of monnaie ) {
denierDisponible += piece . data . valeur _deniers * Number ( piece . data . quantite ) ;
2020-12-31 00:55:02 +01:00
}
console . log ( "DENIER" , game . user . character , sumDenier , denierDisponible ) ;
2021-01-01 21:11:56 +01:00
let msg = "" ;
2021-01-22 10:05:30 +01:00
let isPayed = false ;
2021-01-09 19:33:19 +01:00
if ( denierDisponible >= sumDenier ) {
2020-12-31 00:55:02 +01:00
denierDisponible -= sumDenier ;
this . optimizeArgent ( denierDisponible ) ;
2021-01-01 21:11:56 +01:00
msg = ` Vous avez payé <strong> ${ sumDenier } Deniers</strong>, qui ont été soustraits de votre argent. ` ;
2021-01-09 19:33:19 +01:00
RdDAudio . PlayContextAudio ( "argent" ) ; // Petit son
2021-01-22 10:05:30 +01:00
isPayed = true ;
2020-12-31 00:55:02 +01:00
} else {
2021-01-09 19:33:19 +01:00
msg = "Vous n'avez pas assez d'argent pour paye cette somme !" ;
2020-12-31 00:55:02 +01:00
}
2021-01-01 21:11:56 +01:00
2021-01-22 10:05:30 +01:00
if ( dataObj && isPayed ) {
2021-01-01 21:11:56 +01:00
dataObj . payload . data . cout = sumDenier / 100 ; // Mise à jour du prix en sols , avec le prix acheté
2021-01-09 19:33:19 +01:00
await this . createOwnedItem ( dataObj . payload ) ;
2021-01-01 21:11:56 +01:00
msg += ` <br>Et l'objet <strong> ${ dataObj . payload . name } </strong> a été ajouté à votre inventaire. ` ;
}
2021-01-09 19:33:19 +01:00
let message = {
whisper : ChatUtility . getWhisperRecipientsAndGMs ( this . name ) ,
content : msg
2021-01-01 21:11:56 +01:00
} ;
2021-01-09 19:33:19 +01:00
ChatMessage . create ( message ) ;
2020-12-31 00:55:02 +01:00
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async monnaieIncDec ( id , value ) {
let monnaie = this . data . items . find ( item => item . type == 'monnaie' && item . _id == id ) ;
if ( monnaie ) {
2020-12-31 00:55:02 +01:00
monnaie . data . quantite += value ;
2021-01-09 19:33:19 +01:00
if ( monnaie . data . quantite < 0 ) monnaie . data . quantite = 0 ; // Sanity check
const update = { _id : monnaie . _id , 'data.quantite' : monnaie . data . quantite } ;
const updated = await this . updateEmbeddedEntity ( "OwnedItem" , update ) ;
2020-12-31 00:55:02 +01:00
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
async effectuerTacheAlchimie ( recetteId , alchimieName , alchimieData ) {
let recette = this . data . items . find ( item => item . type == 'recettealchimique' && item . _id == recetteId ) ;
if ( recette ) {
let competence = this . data . items . find ( item => item . type == 'competence' && item . name . toLowerCase ( ) == "alchimie" ) ;
2021-01-07 20:04:10 +01:00
let diffAlchimie = RdDAlchimie . getDifficulte ( alchimieData ) ;
2021-01-09 19:33:19 +01:00
let rollData = {
2021-01-22 02:07:21 +01:00
recette : recette ,
2021-01-07 20:04:10 +01:00
competence : competence ,
diffLibre : diffAlchimie // Per default at startup
}
2021-01-09 19:33:19 +01:00
if ( alchimieName == "couleur" ) {
2021-01-07 20:04:10 +01:00
rollData . selectedCarac = this . data . data . carac . vue ,
2021-01-09 19:33:19 +01:00
rollData . alchimieTexte = ` Couleurs ${ alchimieData } ( ${ diffAlchimie } ) (Malus de -4 si vous ne possédez pas de Cristal Alchimique) ` ;
2021-01-07 20:04:10 +01:00
} else {
2021-01-09 19:33:19 +01:00
rollData . selectedCarac = this . data . data . carac . dexterite ,
rollData . alchimieTexte = ` Consistances ${ alchimieData } ( ${ diffAlchimie } ) ` ;
2021-01-07 20:04:10 +01:00
}
2021-01-09 19:33:19 +01:00
2021-01-07 20:04:10 +01:00
const dialog = await RdDRoll . create ( this , rollData ,
2021-01-09 19:33:19 +01:00
{
html : 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html' ,
2021-01-07 20:04:10 +01:00
} ,
{
name : 'tache-alchimique' ,
label : 'Tache Alchimique' ,
callbacks : [
this . createCallbackExperience ( ) ,
{ action : r => this . _alchimieResult ( r , false ) }
]
}
) ;
dialog . render ( true ) ;
}
}
2021-01-09 19:33:19 +01:00
/* -------------------------------------------- */
_alchimieResult ( rollData ) {
2021-01-07 20:04:10 +01:00
RdDResolutionTable . displayRollData ( rollData , this , 'chat-resultat-alchimie.html' ) ;
}
2021-01-11 16:29:41 +01:00
/* -------------------------------------------- */
buildVehiculesList ( ) {
2021-01-22 02:08:49 +01:00
return this . _buildActorLinksList (
this . data . data . subacteurs ? . vehicules ? ? [ ] ,
vehicle => { return { id : vehicle . id , name : vehicle . data . name , categorie : vehicle . data . data . categorie ,
structure : vehicle . data . data . structure , img : vehicle . data . img } ; } ) ;
2021-01-11 16:29:41 +01:00
}
/* -------------------------------------------- */
buildSuivantsList ( ) {
2021-01-22 02:08:49 +01:00
return this . _buildActorLinksList ( this . data . data . subacteurs ? . suivants ? ? [ ] ) ;
2021-01-11 16:29:41 +01:00
}
/* -------------------------------------------- */
buildMonturesList ( ) {
2021-01-22 02:08:49 +01:00
return this . _buildActorLinksList ( this . data . data . subacteurs ? . montures ? ? [ ] ) ;
2021-01-11 16:29:41 +01:00
}
2021-01-22 02:08:49 +01:00
_buildActorLinksList ( links , actorTransformation = it => { return { id : it . id , name : it . data . name , img : it . data . img } ; } ) {
return links . map ( link => game . actors . get ( link . id ) )
. filter ( it => it != null )
. map ( actorTransformation ) ;
}
2021-01-11 16:29:41 +01:00
/* -------------------------------------------- */
async pushSubacteur ( actor , dataArray , dataPath , dataName ) {
let alreadyPresent = dataArray . find ( attached => attached . id == actor . data . _id ) ;
if ( ! alreadyPresent ) {
let newArray = duplicate ( dataArray ) ;
newArray . push ( { id : actor . data . _id } ) ;
await this . update ( { [ dataPath ] : newArray } ) ;
} else {
ui . notifications . warn ( dataName + " est déja attaché à ce Personnage." ) ;
}
}
/* -------------------------------------------- */
addSubacteur ( actorId ) {
let actor = game . actors . get ( actorId ) ;
//console.log("Ajout acteur : ", actor, this);
if ( actor && actor . owner ) {
if ( actor . data . type == 'vehicule' ) {
this . pushSubacteur ( actor , this . data . data . subacteurs . vehicules , 'data.subacteurs.vehicules' , 'Ce Véhicule' ) ;
} else if ( actor . data . type == 'creature' ) {
this . pushSubacteur ( actor , this . data . data . subacteurs . montures , 'data.subacteurs.montures' , 'Cette Monture' ) ;
} else if ( actor . data . type == 'personnage' ) {
this . pushSubacteur ( actor , this . data . data . subacteurs . suivants , 'data.subacteurs.suivants' , 'Ce Suivant' ) ;
}
} else {
ui . notifications . warn ( "Vous n'avez pas les droits sur l'acteur que vous attachez." )
}
}
/* -------------------------------------------- */
async removeSubacteur ( actorId ) {
let newVehicules = this . data . data . subacteurs . vehicules . filter ( function ( obj , index , arr ) { return obj . id != actorId } ) ;
let newSuivants = this . data . data . subacteurs . suivants . filter ( function ( obj , index , arr ) { return obj . id != actorId } ) ;
let newMontures = this . data . data . subacteurs . montures . filter ( function ( obj , index , arr ) { return obj . id != actorId } ) ;
await this . update ( { 'data.subacteurs.vehicules' : newVehicules } ) ;
await this . update ( { 'data.subacteurs.suivants' : newSuivants } ) ;
await this . update ( { 'data.subacteurs.montures' : newMontures } ) ;
}
2021-01-13 03:42:13 +01:00
/* -------------------------------------------- */
async onCreateActiveEffect ( effect , options ) {
switch ( StatusEffects . statusId ( effect ) ) {
case 'sonne' :
await this . setStateSonne ( true ) ;
return ;
}
}
/* -------------------------------------------- */
async onDeleteActiveEffect ( effect , options ) {
switch ( StatusEffects . statusId ( effect ) ) {
case 'sonne' :
await this . setStateSonne ( false ) ;
return ;
}
}
/* -------------------------------------------- */
enleverTousLesEffets ( ) {
this . deleteEmbeddedEntity ( 'ActiveEffect' , Array . from ( this . effects ? . keys ( ) ? ? [ ] ) ) ;
}
/* -------------------------------------------- */
listeEffets ( matching = it => true ) {
const all = Array . from ( this . effects ? . values ( ) ? ? [ ] ) ;
const filtered = all . filter ( it => matching ( it . data ) ) ;
return filtered ;
}
/* -------------------------------------------- */
async setStatusDemiReve ( status ) {
const options = { renderSheet : true /*, noHook: from == 'hook' */ } ;
if ( status ) {
await this . addEffect ( StatusEffects . demiReve ( ) , options )
}
else {
this . deleteEffect ( StatusEffects . demiReve ( ) , options )
}
}
/* -------------------------------------------- */
async setStatusSonne ( sonne ) {
if ( this . isEntiteCauchemar ( ) ) {
return ;
}
const id = 'sonne' ;
const options = { renderSheet : true /*, noHook: from == 'hook' */ } ;
if ( sonne ) {
await this . addById ( id , options ) ;
}
else /* if (!sonne)*/ {
this . deleteById ( id , options )
}
}
2020-11-14 03:16:03 +01:00
2021-01-13 03:42:13 +01:00
/* -------------------------------------------- */
deleteById ( id , options ) {
const effects = Array . from ( this . effects ? . values ( ) )
. filter ( it => it . data . flags . core ? . statusId == id ) ;
this . _deleteAll ( effects , options ) ;
}
/* -------------------------------------------- */
deleteEffect ( effect , options ) {
const toDelete = Array . from ( this . effects ? . values ( ) )
. filter ( it => StatusEffects . statusId ( it . data ) == StatusEffects . statusId ( effect ) ) ;
this . _deleteAll ( toDelete , options ) ;
}
2020-11-14 03:16:03 +01:00
2021-01-13 03:42:13 +01:00
/* -------------------------------------------- */
_deleteAll ( effects , options ) {
this . _deleteAllIds ( effects . map ( it => it . id ) , options ) ;
}
/* -------------------------------------------- */
_deleteAllIds ( effectIds , options ) {
this . deleteEmbeddedEntity ( 'ActiveEffect' , effectIds , options ) ;
this . applyActiveEffects ( ) ;
}
/* -------------------------------------------- */
async addById ( id , options ) {
const statusEffect = CONFIG . statusEffects . find ( it => it . id == id ) ;
await this . addEffect ( statusEffect , options ) ;
}
/* -------------------------------------------- */
async addEffect ( statusEffect , options ) {
this . deleteById ( statusEffect . id , options ) ;
const effet = duplicate ( statusEffect ) ;
effet [ "flags.core.statusId" ] = effet . id ;
await this . createEmbeddedEntity ( 'ActiveEffect' , effet , options ) ;
this . applyActiveEffects ( ) ;
}
2021-01-14 15:29:47 +01:00
/* -------------------------------------------- */
async updateEmbeddedEntity ( embeddedName , data , options ) {
if ( data && data [ 'data.defaut_carac' ] && data [ 'data.xp' ] ) { // C'est une compétence
this . checkCompetenceXP ( data [ 'name' ] , data [ 'data.xp' ] ) ;
}
return super . updateEmbeddedEntity ( embeddedName , data , options ) ;
}
2021-01-13 03:42:13 +01:00
}