diff --git a/module/actor.js b/module/actor.js index 3d084731..c8deb06f 100644 --- a/module/actor.js +++ b/module/actor.js @@ -37,9 +37,9 @@ export class RdDActor extends Actor { * @param {Object} options (Unused) Additional options which customize the creation workflow. * */ - + static async create(data, options) { - + // Case of compendium global import if (data instanceof Array) { return super.create(data, options); @@ -48,11 +48,11 @@ export class RdDActor extends Actor { if (data.items) { let actor = super.create(data, options); if (data.type == "personnage") { - await actor.checkMonnaiePresence( data.items ); + await actor.checkMonnaiePresence(data.items); } return actor; } - + let compendiumName = ""; if (data.type == "personnage") { compendiumName = "foundryvtt-reve-de-dragon.competences"; @@ -63,14 +63,14 @@ export class RdDActor extends Actor { } data.items = RdDUtility.loadCompendium(compendiumName); // Ajout monnaie - if (data.type == "personnage" ) { - await RdDActor.ajouterMonnaie( data.items ); - } + if (data.type == "personnage") { + await RdDActor.ajouterMonnaie(data.items); + } return super.create(data, options); } - - /* -------------------------------------------- */ + + /* -------------------------------------------- */ prepareData() { super.prepareData(); @@ -85,7 +85,7 @@ export class RdDActor extends Actor { let tokenSize = actorData.data.carac.taille.value/10; this.token.update({height: tokenSize, width: tokenSize } ); }*/ - + // Make separate methods for each Actor type (character, npc, etc.) to keep // things organized. if (actorData.type === 'personnage') this._prepareCharacterData(actorData); @@ -93,7 +93,7 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - prepareCreatureData(actorData) { + prepareCreatureData(actorData) { this.computeEncombrementTotalEtMalusArmure(); this.computeEtatGeneral(); } @@ -111,46 +111,46 @@ export class RdDActor extends Actor { await this.checkMonnaiePresence(actorData.items); } - /* -------------------------------------------- */ - 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); + /* -------------------------------------------- */ + 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); let newMonnaie = []; if (!piece) { - newMonnaie.push( RdDUtility.createMonnaie("Etain (1 denier)", 1, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp" ) ); + newMonnaie.push(RdDUtility.createMonnaie("Etain (1 denier)", 1, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp")); } - piece = items.find( item => item.type =='monnaie' && Number(item.data.valeur_deniers) == 10); + piece = items.find(item => item.type == 'monnaie' && Number(item.data.valeur_deniers) == 10); if (!piece) { - newMonnaie.push(RdDUtility.createMonnaie("Bronze (10 deniers)", 10, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp") ); + newMonnaie.push(RdDUtility.createMonnaie("Bronze (10 deniers)", 10, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp")); } - piece = items.find( item => item.type =='monnaie' && Number(item.data.valeur_deniers) == 100); + piece = items.find(item => item.type == 'monnaie' && Number(item.data.valeur_deniers) == 100); if (!piece) { newMonnaie.push(RdDUtility.createMonnaie("Argent (1 sol)", 100, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp")); } - piece = items.find( item => item.type =='monnaie' && Number(item.data.valeur_deniers) == 1000); + piece = items.find(item => item.type == 'monnaie' && Number(item.data.valeur_deniers) == 1000); if (!piece) { - newMonnaie.push(RdDUtility.createMonnaie("Or (10 sols)", 1000, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp") ); + newMonnaie.push(RdDUtility.createMonnaie("Or (10 sols)", 1000, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp")); } - if ( newMonnaie.length > 0) { - await this.createOwnedItem( newMonnaie ); + if (newMonnaie.length > 0) { + await this.createOwnedItem(newMonnaie); } } - /* -------------------------------------------- */ - static async ajouterMonnaie( items ) { // Creation auto à la création du personnage + /* -------------------------------------------- */ + static async ajouterMonnaie(items) { // Creation auto à la création du personnage let etain = RdDUtility.createMonnaie("Etain (1 denier)", 1, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp"); items.push(etain); - + let bronze = RdDUtility.createMonnaie("Bronze (10 deniers)", 10, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp"); items.push(bronze); - + let argent = RdDUtility.createMonnaie("Argent (1 sol)", 100, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp"); items.push(argent); - + let or = RdDUtility.createMonnaie("Or (10 sols)", 1000, "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp"); items.push(or); } - + /* -------------------------------------------- */ isCreature() { return this.data.type == 'creature' || this.data.type == 'entite'; @@ -181,7 +181,7 @@ export class RdDActor extends Actor { // TODO: gérer séparation et +dom créature/entité indépendament de la compétence return Misc.toInt(this.data.data.attributs.plusdom.value); } - /* -------------------------------------------- */ + /* -------------------------------------------- */ getProtectionNaturelle() { return Misc.toInt(this.data.data.attributs.protection.value); } @@ -194,34 +194,33 @@ export class RdDActor extends Actor { getEncTotal() { return Math.floor(this.encTotal ?? 0); } - getSurenc(){ + getSurenc() { return this.data.data.compteurs?.surenc?.value ?? 0; } - /* -------------------------------------------- */ + /* -------------------------------------------- */ loadCompendiumNames() { - return this.data.items.filter( (item) => item.type == 'competence'); - } + return this.data.items.filter((item) => item.type == 'competence'); + } /* -------------------------------------------- */ getCompetence(compName) { return RdDItemCompetence.findCompetence(this.data.items, compName); - } - /* -------------------------------------------- */ - getTache( id ) { - return this.data.items.find( item => item.type=='tache' && item._id == id ); } - getMeditation( id ) { - return this.data.items.find( item => item.type=='meditation' && item._id == id ); + /* -------------------------------------------- */ + getTache(id) { + return this.data.items.find(item => item.type == 'tache' && item._id == id); + } + getMeditation(id) { + return this.data.items.find(item => item.type == 'meditation' && item._id == id); } /* -------------------------------------------- */ getBestDraconic() { - const list = this.getDraconicList().sort((a, b) => b.data.niveau - a.data.niveau); - if (list.length==0) - { + const list = this.getDraconicList().sort((a, b) => b.data.niveau - a.data.niveau); + if (list.length == 0) { return { name: "none", niveau: -11 }; - } + } return duplicate(list[0]); - } + } /* -------------------------------------------- */ async deleteSortReserve(sortReserve) { @@ -229,23 +228,20 @@ export class RdDActor extends Actor { let len = reserve.list.length; let i = 0; let newTable = []; - 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]); + 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]); } - if ( newTable.length != len ) { + if (newTable.length != len) { reserve.list = newTable; - await this.update( {"data.reve.reserve": reserve } ); + await this.update({ "data.reve.reserve": reserve }); } } - + /* -------------------------------------------- */ getSurprise() { - if (this.isEntiteCauchemar()) { - return ''; - } // TODO: gérer une liste de flags demi-surprise (avec icône sur le token)? - if ( this.data.data.sante.sonne && this.data.data.sante.sonne.value) { + if (this.getSonne()) { return 'demi'; } return ''; @@ -263,9 +259,9 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async dormirChateauDormant() { - let message = { - whisper: ChatUtility.getWhisperRecipientsAndGMs( this.name ), - content : "" + let message = { + whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), + content: "" }; const blessures = duplicate(this.data.data.blessures); @@ -273,34 +269,34 @@ export class RdDActor extends Actor { 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); await this._recupererBlessures(message, "critique", blessures.critiques.liste.filter(b => b.active), blessures.graves.liste); - await this.update( {"data.blessures": blessures } ); + await this.update({ "data.blessures": blessures }); await this._recupererVie(message); await this.transformerStress(message); await this.retourSeuilDeReve(message); - message.content = "A la fin Chateau Dormant, " + message.content +"
Un nouveau jour se lève"; - ChatMessage.create( message ); + message.content = `A la fin Chateau Dormant, ${message.content}
Un nouveau jour se lève`; + ChatMessage.create(message); } /* -------------------------------------------- */ async _recupererBlessures(message, type, liste, moindres) { let count = 0; const definitions = RdDUtility.getDefinitionsBlessures(); - let definition = definitions.find( d => d.type == type); + let definition = definitions.find(d => d.type == type); 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)) { - message.content += " -- une blessure " + type + " cicatrise"; - count++; + message.content += ` -- une blessure ${type} cicatrise`; + count++; } else if (rolled.isETotal) { - 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); + 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); } else { - message.content += " -- une blessure " + type + " reste stable"; + message.content += ` -- une blessure ${type} reste stable`; } } else { @@ -310,8 +306,7 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - _retrograderBlessure(type, blessure, blessuresMoindres) - { + _retrograderBlessure(type, blessure, blessuresMoindres) { if (type != "legere") { let retrograde = blessuresMoindres.find(b => !b.active); if (!retrograde) { @@ -322,7 +317,7 @@ export class RdDActor extends Actor { this._supprimerBlessure(blessure); return true; } - + /* -------------------------------------------- */ _supprimerBlessure(blessure) { mergeObject(blessure, { "active": false, "premiers_soins": 0, "soins_complets": 0, "jours": 0, "loc": "" }); @@ -333,24 +328,23 @@ export class RdDActor extends Actor { 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; - if (nbBlessures == 0 && vieManquante>0) { + if (nbBlessures == 0 && vieManquante > 0) { let bonusSoins = 0; - for (let b of blessures) - { + for (let b of blessures) { 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); - message.content += " -- récupération de vie: " + gain; + message.content += " -- récupération de vie: " + gain; await this.santeIncDec("vie", gain); } else if (rolled.isETotal) { message.content += " -- perte de vie: 1"; await this.santeIncDec("vie", -1); } - else{ - message.content +=" -- vie stationnaire "; + else { + message.content += " -- vie stationnaire "; } } } @@ -367,59 +361,58 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async remiseANeuf() { - let message = { - whisper: ChatUtility.getWhisperRecipientsAndGMs( this.name ), - content : "Remise à neuf de " + this.name + let message = { + whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), + content: "Remise à neuf de " + this.name }; if (this.isEntiteCauchemar()) { await this.santeIncDec("endurance", this.data.data.sante.endurance.max - this.data.data.sante.endurance.value); } else { - if (this.data.data.blessures){ + if (this.data.data.blessures) { 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); } } - await this.update( {"data.blessures": blessures } ); + await this.update({ "data.blessures": blessures }); } await this.setEthylisme(1); await this.santeIncDec("vie", this.data.data.sante.vie.max - this.data.data.sante.vie.value); await this.santeIncDec("endurance", this.data.data.sante.endurance.max - this.data.data.sante.endurance.value); - if (this.data.data.sante.fatigue){ + if (this.data.data.sante.fatigue) { let fatigue = duplicate(this.data.data.sante.fatigue) fatigue.value = 0; - await this.update( {"data.sante.fatigue": fatigue } ); + await this.update({ "data.sante.fatigue": fatigue }); } } - ChatMessage.create( message ); + ChatMessage.create(message); } /* -------------------------------------------- */ - async dormir(heures=1) { - let message = { - whisper: ChatUtility.getWhisperRecipientsAndGMs( this.name ), - content : "Vous dormez " + heures + " heure" + (heures > 1 ? "s": "") + async dormir(heures = 1) { + let message = { + whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), + content: "Vous dormez " + heures + " heure" + (heures > 1 ? "s" : "") }; await this.recupereEndurance(message); - for (let i=0; iVous dégrisez un peu (${RdDUtility.getNomEthylisme(ethylisme.value)})`; @@ -447,27 +440,24 @@ export class RdDActor extends Actor { } fatigue.value = Math.max(fatigueMin, this._calculRecuperationSegment(fatigue.value)); console.log("recupererFatigue", fatigue) - await this.update( {"data.sante.fatigue": fatigue } ); - if (fatigue.value == 0) - { + await this.update({ "data.sante.fatigue": fatigue }); + if (fatigue.value == 0) { message.content += "
Vous êtes bien reposé"; } } /* -------------------------------------------- */ - _calculRecuperationSegment(actuel) - { + _calculRecuperationSegment(actuel) { const segments = RdDUtility.getSegmentsFatigue(this.data.data.sante.endurance.max); let cumul = 0; let i; - for (i=0; i <11; i++) { + for (i = 0; i < 11; i++) { cumul += segments[i]; let diff = cumul - actuel; - if (diff >= 0) - { + if (diff >= 0) { const limit2Segments = Math.floor(segments[i] / 2); if (diff > limit2Segments && i > 0) { - cumul -= segments[i-1]; // le segment est à moins de la moitié, il est récupéré + cumul -= segments[i - 1]; // le segment est à moins de la moitié, il est récupéré } cumul -= segments[i]; break; @@ -477,7 +467,7 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async recuperationReve(message) { + async recuperationReve(message) { const seuil = this.data.data.reve.seuil.value; const reveActuel = this.getReveActuel(); if (reveActuel >= seuil) { @@ -486,13 +476,12 @@ export class RdDActor extends Actor { else { let deRecuperation = (await DeDraconique.ddr("selfroll")).total; console.log("recuperationReve", deRecuperation); - if (deRecuperation>=7) - { + if (deRecuperation >= 7) { // Rêve de Dragon ! message.content += `
Vous faites un Rêve de Dragon de ${deRecuperation} Points de rêve`; message.content += await this.combattreReveDeDragon(deRecuperation); } - else{ + else { message.content += `
Vous récupérez ${deRecuperation} Points de rêve`; await this.reveActuelIncDec(deRecuperation); } @@ -504,13 +493,13 @@ export class RdDActor extends Actor { const seuil = this.data.data.reve.seuil.value; const reveActuel = this.getReveActuel(); if (reveActuel > seuil) { - message.content += `
Votre rêve redescend vers son seuil naturel (${seuil}, nouveau rêve actuel ${(reveActuel-1)})`; + message.content += `
Votre rêve redescend vers son seuil naturel (${seuil}, nouveau rêve actuel ${(reveActuel - 1)})`; await this.reveActuelIncDec(-1); } } /* -------------------------------------------- */ - async combattreReveDeDragon(force){ + async combattreReveDeDragon(force) { let draconic = this.getBestDraconic(); let niveau = Math.max(0, draconic.data.niveau); let etat = this.getEtatGeneral(); @@ -518,7 +507,7 @@ export class RdDActor extends Actor { let reveActuel = this.getReveActuel(); let rolled = await RdDResolutionTable.roll(reveActuel, difficulte); // TODO: xp particulière - console.log("combattreReveDeDragon", rolled ); + console.log("combattreReveDeDragon", rolled); return await this.appliquerReveDeDragon(rolled, force); } @@ -552,144 +541,137 @@ export class RdDActor extends Actor { this.currentTMR.updateSortReserve(); } - /* -------------------------------------------- */ - async updateCarac( caracName, caracValue ) - { + /* -------------------------------------------- */ + async updateCarac(caracName, caracValue) { let caracpath = "data.carac." + caracName + ".value" if (caracName == "reve") { if (caracValue > Misc.toInt(this.data.data.reve.seuil.value)) { this.setPointsDeSeuil(caracValue); } } - await this.update( { [caracpath]: caracValue } ); + await this.update({ [caracpath]: caracValue }); } - /* -------------------------------------------- */ - async updateCaracXP( caracName, caracXP ) - { - let caracpath = "data.carac."+caracName+".xp"; - await this.update( { [caracpath]: caracXP } ); - this.checkCaracXP( caracName ); + /* -------------------------------------------- */ + async updateCaracXP(caracName, caracXP) { + let caracpath = "data.carac." + caracName + ".xp"; + await this.update({ [caracpath]: caracXP }); + this.checkCaracXP(caracName); } - /* -------------------------------------------- */ - async updateCreatureCompetence( compName, fieldName, compValue ) - { + /* -------------------------------------------- */ + async updateCreatureCompetence(compName, fieldName, compValue) { let comp = this.getCompetence(compName); - console.log( comp ); - if ( comp ) { - const update = {_id: comp._id } + console.log(comp); + if (comp) { + const update = { _id: comp._id } if (fieldName == "niveau") update['data.niveau'] = compValue; else if (fieldName == "dommages") update['data.dommages'] = compValue; - else + else update['data.carac_value'] = compValue; console.log(update); const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity } } - /* -------------------------------------------- */ - async updateCompetence( compName, compValue ) - { + /* -------------------------------------------- */ + async updateCompetence(compName, compValue) { let comp = this.getCompetence(compName); - if ( comp ) { - let troncList = RdDUtility.isTronc( compName ); + if (comp) { + let troncList = RdDUtility.isTronc(compName); let maxNiveau = compValue; - if ( troncList ) { + if (troncList) { let message = "Vous avez modifié une compétence 'tronc'. Vérifiez que les compétences suivantes évoluent ensemble jusqu'au niveau 0 : "; - for(let troncName of troncList) { + for (let troncName of troncList) { message += "
" + troncName; } - ChatMessage.create( { - whisper: ChatMessage.getWhisperRecipients(game.user.name), - content: message } ); + ChatMessage.create({ + whisper: ChatMessage.getWhisperRecipients(game.user.name), + content: message + }); } - const update = {_id: comp._id, 'data.niveau': maxNiveau }; - const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity - } else { - console.log("Competence not found", compName); - } - } - - /* -------------------------------------------- */ - async updateCompetenceXP( compName, compValue ) - { - let comp = this.getCompetence(compName); - if ( comp ) { - const update = {_id: comp._id, 'data.xp': compValue }; + const update = { _id: comp._id, 'data.niveau': maxNiveau }; const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity } else { console.log("Competence not found", compName); } } - /* -------------------------------------------- */ - async updateCompetenceArchetype( compName, compValue ) - { + /* -------------------------------------------- */ + async updateCompetenceXP(compName, compValue) { let comp = this.getCompetence(compName); - if ( comp ) { - const update = {_id: comp._id, 'data.niveau_archetype': compValue }; + if (comp) { + const update = { _id: comp._id, 'data.xp': compValue }; const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity } else { console.log("Competence not found", compName); } } - - /* -------------------------------------------- */ - async updateCompteurValue( fieldName, fieldValue ) - { + + /* -------------------------------------------- */ + async updateCompetenceArchetype(compName, compValue) { + let comp = this.getCompetence(compName); + if (comp) { + const update = { _id: comp._id, 'data.niveau_archetype': compValue }; + const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity + } else { + console.log("Competence not found", compName); + } + } + + /* -------------------------------------------- */ + async updateCompteurValue(fieldName, fieldValue) { //console.log("Update", fieldName, fieldValue); let compteurs = duplicate(this.data.data.compteurs); - compteurs[fieldName].value = fieldValue; - await this.update( {"data.compteurs": compteurs } ); + compteurs[fieldName].value = fieldValue; + await this.update({ "data.compteurs": compteurs }); } - /* -------------------------------------------- */ - async updateProtectionValue( fieldName, fieldValue ) - { + /* -------------------------------------------- */ + async updateProtectionValue(fieldName, fieldValue) { let attributs = duplicate(this.data.data.attributs); attributs[fieldName].value = fieldValue; - await this.update( {"data.attributs": attributs } ); + await this.update({ "data.attributs": attributs }); } - /* -------------------------------------------- */ - 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 ) { + /* -------------------------------------------- */ + 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) { ui.notifications.warn("Impossible de déplacer un conteneur parent dans son fils !"); return false; // Loop detected ! } - if ( subObjet && subObjet.type == 'conteneur') { - return this.validateConteneur( subObjet._id, conteneurId); + if (subObjet && subObjet.type == 'conteneur') { + return this.validateConteneur(subObjet._id, conteneurId); } } } return true; } - /* -------------------------------------------- */ + /* -------------------------------------------- */ /** Teste si le conteneur de destination a suffisament de capacité * pour recevoir le nouvel objet */ - 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 + 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 //console.log("Conteneur trouvé : ", conteneur); - if ( conteneur && conteneur.type == "conteneur" ) { + if (conteneur && conteneur.type == "conteneur") { let currentEnc = 0; // Calculer le total actuel des contenus for (let id of conteneur.data.data.contenu) { - let objet = this.items.find( objet => (id == objet._id) ); + let objet = this.items.find(objet => (id == objet._id)); currentEnc += (objet) ? objet.data.data.encombrement : 0; - } + } // Et gérer le nouvel objet - let nouvelObjet = this.items.find( objet => (itemId == objet._id) ); - if ( currentEnc + nouvelObjet.data.data.encombrement > Number(conteneur.data.data.capacite) ) { + let nouvelObjet = this.items.find(objet => (itemId == objet._id)); + if (currentEnc + nouvelObjet.data.data.encombrement > Number(conteneur.data.data.capacite)) { ui.notifications.warn("Capacité d'encombrement insuffisante dans le conteneur !"); return false; } @@ -710,26 +692,26 @@ export class RdDActor extends Actor { deleteList.push( subId ); } } - deleteList.push( conteneurId ); + deleteList.push(conteneurId); } - /* -------------------------------------------- */ - async deleteAllConteneur( itemId ) { + /* -------------------------------------------- */ + async deleteAllConteneur(itemId) { let list = []; - this.buildSubConteneurObjetList( itemId, list ); + this.buildSubConteneurObjetList(itemId, list); //console.log("List to delete", list); - for( let id of list) { - await this.deleteOwnedItem( id ); + for (let id of list) { + await this.deleteOwnedItem(id); } } - /* -------------------------------------------- */ + /* -------------------------------------------- */ /** Supprime un item d'un conteneur, sur la base * de leurs ID */ - 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 + 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 let data2use = duplicate(conteneur.data); //console.log("Suppression du conteneur1", conteneurId, itemId, conteneur.data.data.contenu); let contenu = data2use.data.contenu; @@ -738,35 +720,35 @@ export class RdDActor extends Actor { contenu.splice(index, 1); index = contenu.indexOf(itemId); } - await this.updateEmbeddedEntity("OwnedItem", data2use); + await this.updateEmbeddedEntity("OwnedItem", data2use); } } - /* -------------------------------------------- */ + /* -------------------------------------------- */ /** Ajoute un item dans un conteneur, sur la base * de leurs ID */ - 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' ) { + 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') { let data2use = duplicate(conteneur.data); - data2use.data.contenu.push( itemId ); - await this.updateEmbeddedEntity("OwnedItem", data2use ); + data2use.data.contenu.push(itemId); + await this.updateEmbeddedEntity("OwnedItem", data2use); } } - /* -------------------------------------------- */ + /* -------------------------------------------- */ /** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */ - async nettoyerConteneurs( ) { - let conteneurList = this.items.filter( conteneur => conteneur.type == 'conteneur'); + async nettoyerConteneurs() { + let conteneurList = this.items.filter(conteneur => conteneur.type == 'conteneur'); let conteneurFixedList = []; for (let conteneur of conteneurList) { - if ( conteneur.data.data.contenu.length > 0 ) { - conteneurFixedList.push( { _id: conteneur._id, 'data.contenu': [] }); + if (conteneur.data.data.contenu.length > 0) { + conteneurFixedList.push({ _id: conteneur._id, 'data.contenu': [] }); } } - if ( conteneurFixedList.length > 0) - await this.updateOwnedItem( conteneurFixedList ) ; + if (conteneurFixedList.length > 0) + await this.updateOwnedItem(conteneurFixedList); } /* -------------------------------------------- */ @@ -789,20 +771,20 @@ export class RdDActor extends Actor { return Math.max(0, Math.ceil(diffEnc)); } - /* -------------------------------------------- */ - async computeEncombrementTotalEtMalusArmure( ) { + /* -------------------------------------------- */ + async computeEncombrementTotalEtMalusArmure() { let encTotal = 0; let malusArmureData = (this.data.data.attributs.malusarmure) ? duplicate(this.data.data.attributs.malusarmure) : {}; - let newMalusArmure = 0; + let newMalusArmure = 0; for (const item of this.data.items) { - if ( item.type == 'armure' && item.data.equipe ) { // Armure équipée, intégration du malus armure total + if (item.type == 'armure' && item.data.equipe) { // Armure équipée, intégration du malus armure total newMalusArmure += item.data.malus; } // Calcul encombrement - 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 + 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 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); encTotal += item.data.encTotal; @@ -817,15 +799,15 @@ export class RdDActor extends Actor { // Mise à jour éventuelle du malus armure if (this.data.data.attributs.malusarmure && newMalusArmure != malusArmureData.value) { malusArmureData.value = newMalusArmure; - await this.update( {"data.attributs.malusarmure": malusArmureData } ); + await this.update({ "data.attributs.malusarmure": malusArmureData }); } } - /* -------------------------------------------- */ + /* -------------------------------------------- */ computeResumeBlessure(blessures = this.data.data.blessures) { - let nbLegeres = this.countBlessures(blessures.legeres.liste ); - let nbGraves = this.countBlessures(blessures.graves.liste ); - let nbCritiques = this.countBlessures(blessures.critiques.liste ); + let nbLegeres = this.countBlessures(blessures.legeres.liste); + let nbGraves = this.countBlessures(blessures.graves.liste); + let nbCritiques = this.countBlessures(blessures.critiques.liste); let resume = "Blessures:"; if (nbCritiques > 0 || nbGraves > 0 || nbLegeres > 0) { @@ -849,60 +831,59 @@ export class RdDActor extends Actor { return resume; } - /* -------------------------------------------- */ + /* -------------------------------------------- */ getEtatGeneral() { return this.data.data.compteurs?.etat?.value ?? 0; } - /* -------------------------------------------- */ - computeEtatGeneral( ) - { + /* -------------------------------------------- */ + computeEtatGeneral() { let data = this.data.data; // Pas d'état général pour les entités forçage à 0 - if ( this.data.type == 'entite') { + if (this.data.type == 'entite') { data.compteurs.etat.value = 0; return; } // Pour les autres let state = - (data.sante.vie.max - data.sante.vie.value); - if (data.sante.fatigue){ + if (data.sante.fatigue) { // Creatures n'ont pas de fatigue state += RdDUtility.currentFatigueMalus(data.sante.fatigue.value, data.sante.endurance.max); - } + } // Ajout de l'éthylisme - state += Math.min(0, (data.compteurs?.ethylisme?.value ??0)); + state += Math.min(0, (data.compteurs?.ethylisme?.value ?? 0)); - data.compteurs.etat.value = state; - if ( data.compteurs && data.compteurs.surenc) { + data.compteurs.etat.value = state; + if (data.compteurs && data.compteurs.surenc) { data.compteurs.surenc.value = - this.detectSurEncombrement(); } } - - /* -------------------------------------------- */ - async ajouterRefoulement( value=1) { + + /* -------------------------------------------- */ + async ajouterRefoulement(value = 1) { let ret = "none"; - + let refoulement = duplicate(this.data.data.reve.refoulement); refoulement.value = refoulement.value + value; let total = new Roll("1d20").roll().total; - if ( total <= refoulement.value ) { + if (total <= refoulement.value) { refoulement.value = 0; - this.ajouterSouffle({chat: true}); + this.ajouterSouffle({ chat: true }); ret = "souffle"; } - await this.update( {"data.reve.refoulement": refoulement } ); - return ret; + await this.update({ "data.reve.refoulement": refoulement }); + return ret; } /* -------------------------------------------- */ - async ajouterSouffle(options = {chat : false}) { + async ajouterSouffle(options = { chat: false }) { let souffle = await RdDRollTables.getSouffle(); await this.createOwnedItem(souffle); - if (options.chat){ + if (options.chat) { ChatMessage.create({ - whisper: ChatUtility.getWhisperRecipientsAndGMs( this.name ), + whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), content: this.name + " subit un Souffle de Dragon : " + souffle.name }); } @@ -910,7 +891,7 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async ajouterQueue(options = {chat : false}) { + async ajouterQueue(options = { chat: false }) { // TODO: Déterminer si Thanatos a été utilisé? => laisser le joueur ne pas choisir Thanatos => choisir sa voie? let utiliseThanatos = false; let queue; @@ -922,173 +903,173 @@ export class RdDActor extends Actor { queue = await RdDRollTables.getQueue(); } await this.createOwnedItem(queue); - if (options.chat){ + if (options.chat) { ChatMessage.create({ - whisper: ChatUtility.getWhisperRecipientsAndGMs( this.name ), + whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), content: this.name + " subit une Queue de Dragon : " + queue.name }); } return queue.name; } - - /* -------------------------------------------- */ - displayTMRQueueSouffleInformation( ) { - for ( let item of this.data.items) { + + /* -------------------------------------------- */ + displayTMRQueueSouffleInformation() { + for (let item of this.data.items) { let content if (item.type == 'queue') { - if ( item.name.toLowerCase() == 'conquête' ) { + if (item.name.toLowerCase() == 'conquête') { content = "RAPPEL ! Vous souffrez d'une Conquête : " + item.data.description; - } - else if ( item.name.toLowerCase() == 'pélerinage' ) { + } + else if (item.name.toLowerCase() == 'pélerinage') { content = "RAPPEL ! Vous souffrez d'un Pélerinage : " + item.data.description; } - else if ( item.name.toLowerCase() == 'urgence draconique' ) { + else if (item.name.toLowerCase() == 'urgence draconique') { content = "RAPPEL ! Vous souffrez d'une Urgence Draconique : " + item.data.description; } - } else if ( item.type == 'souffle') { - if ( item.name.toLowerCase() == 'périple' ) { + } else if (item.type == 'souffle') { + if (item.name.toLowerCase() == 'périple') { content = "RAPPEL ! Vous souffrez du Souffle Périple. Vous devez gérer manuellement le détail du Périple.
" + item.data.description; - } else if ( item.name.toLowerCase() == 'fermeture des cités' ) { + } else if (item.name.toLowerCase() == 'fermeture des cités') { content = "RAPPEL ! Vous souffrez du Souffle Fermeture des Cités. Vous devez gérer manuellement le détail des Citées ré-ouvertes.
" + item.data.description; - } else if ( item.name.toLowerCase() == 'désorientation' ) { + } else if (item.name.toLowerCase() == 'désorientation') { content = "RAPPEL ! Vous souffrez du Souffle Désorientation. Vous devez gérer avec votre MJ les effets de ce souffle.
" + item.data.description; - } else if ( item.name.toLowerCase() == 'double résistance du fleuve' ) { + } else if (item.name.toLowerCase() == 'double résistance du fleuve') { content = "RAPPEL ! Vous souffrez du Souffle Double Résistance du Fleuve. Vous devez gérer avec votre MJ les effets de ce souffle.
" + item.data.description; } } if (content) { ChatMessage.create({ - whisper: ChatUtility.getWhisperRecipientsAndGMs( this.name ), + whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), content: content }); - } + } } } - /* -------------------------------------------- */ - async deleteTMRRencontreAtPosition( ) { + /* -------------------------------------------- */ + async deleteTMRRencontreAtPosition() { let rencontres = duplicate(this.data.data.reve.rencontre); let len = rencontres.list.length; let i = 0; //console.log("List", rencontres, len); let newTable = []; - for( i=0; i < len; i++) { - if (rencontres.list[i].coord != this.data.data.reve.tmrpos.coord ) + for (i = 0; i < len; i++) { + if (rencontres.list[i].coord != this.data.data.reve.tmrpos.coord) newTable.push(rencontres.list[i]); } - if ( newTable.length != len ) { + if (newTable.length != len) { rencontres.list = newTable; //console.log("Result: ", rencontres); - await this.update( {"data.reve.rencontre": rencontres } ); + await this.update({ "data.reve.rencontre": rencontres }); } } - - /* -------------------------------------------- */ - async addTMRRencontre( currentRencontre ) { + + /* -------------------------------------------- */ + async addTMRRencontre(currentRencontre) { let rencontres = duplicate(this.data.data.reve.rencontre); let len = rencontres.list.length; let i = 0; let already = false; - for( i=0; i < len; i++) { - if (rencontres.list[i].coord == this.data.data.reve.tmrpos.coord ) + for (i = 0; i < len; i++) { + if (rencontres.list[i].coord == this.data.data.reve.tmrpos.coord) already = true; } - if ( !already ) { - rencontres.list.push( {coord: this.data.data.reve.tmrpos.coord, rencontre: currentRencontre} ); - await this.update( {"data.reve.rencontre": rencontres } ); + if (!already) { + rencontres.list.push({ coord: this.data.data.reve.tmrpos.coord, rencontre: currentRencontre }); + await this.update({ "data.reve.rencontre": rencontres }); } } - /* -------------------------------------------- */ - async updateCoordTMR( coord ) { - let tmrPos = duplicate(this.data.data.reve.tmrpos ); + /* -------------------------------------------- */ + async updateCoordTMR(coord) { + let tmrPos = duplicate(this.data.data.reve.tmrpos); tmrPos.coord = coord; - await this.update( {"data.reve.tmrpos": tmrPos } ); + await this.update({ "data.reve.tmrpos": tmrPos }); } - - /* -------------------------------------------- */ - async reveActuelIncDec( value ) { + + /* -------------------------------------------- */ + async reveActuelIncDec(value) { let reve = duplicate(this.data.data.reve.reve); reve.value = Math.max(reve.value + value, 0); - await this.update( {"data.reve.reve": reve } ); + await this.update({ "data.reve.reve": reve }); } - + /* -------------------------------------------- */ - async updatePointDeSeuil(value=1) { + async updatePointDeSeuil(value = 1) { const seuil = Misc.toInt(this.data.data.reve.seuil.value); const reve = Misc.toInt(this.data.data.carac.reve.value); if (seuil < reve) { - await this.setPointsDeSeuil(Math.min(seuil+value, reve)); + await this.setPointsDeSeuil(Math.min(seuil + value, reve)); } } - + /* -------------------------------------------- */ - async setPointsDeSeuil( value ) { + async setPointsDeSeuil(value) { let seuil = duplicate(this.data.data.reve.seuil); seuil.value = value; - await this.update( {"data.reve.seuil": seuil } ); + await this.update({ "data.reve.seuil": seuil }); } - /* -------------------------------------------- */ + /* -------------------------------------------- */ getSonne() { - if ( !this.isEntiteCauchemar() && this.data.data.sante.sonne ) { - return this.data.data.sante.sonne.value; - } - return false; + return !this.isEntiteCauchemar() && (this.data.data.sante.sonne?.value ?? false); } - /* -------------------------------------------- */ + /* -------------------------------------------- */ getSConst() { - - if ( !this.isEntiteCauchemar() && this.data.data.attributs ) { + + if (!this.isEntiteCauchemar() && this.data.data.attributs) { return this.data.data.attributs.sconst.value; } return 0; } - /* -------------------------------------------- */ - testSiSonne( sante, endurance ) - { - let result = new Roll("1d20").roll().total; - if ( result <= endurance) - sante.sonne.value = false; - if ( result > endurance || result == 20) // 20 is always a failure - sante.sonne.value = true; - if (result == 1) { - sante.sonne.value = false; - let xp = Misc.toInt(this.data.data.carac.constitution.xp) + 1; - this.update( {"data.carac.constitution.xp": xp } ); // +1 XP ! + /* -------------------------------------------- */ + testSiSonne(sante, endurance) { + 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 ! // TODO : Output to chat } + if (result.sonne) { + // 20 is always a failure + sante.sonne.value = true; + } + return result; } - /* -------------------------------------------- */ - countBlessures( blessuresListe ) - { + /* -------------------------------------------- */ + countBlessures(blessuresListe) { return blessuresListe.filter(b => b.active).length } - /* -------------------------------------------- */ - countBlessuresByName( name ) - { - return this.countBlessures( this.data.data.blessures[name].liste ); + /* -------------------------------------------- */ + countBlessuresByName(name) { + return this.countBlessures(this.data.data.blessures[name].liste); } - - /* -------------------------------------------- */ + + /* -------------------------------------------- */ 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 + "
"; - if ( myRoll.total <= this.data.data.sante.vie.value ) { + if (myRoll.total <= this.data.data.sante.vie.value) { msgText += "Jet réussi, pas de perte de point de vie (prochain jet dans 1 round pour 1 critique, SC minutes pour une grave)"; - if ( myRoll.total == 1) { + if (myRoll.total == 1) { 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); - if ( myRoll.total == 20) { + if (myRoll.total == 20) { msgText += "Votre personnage est mort !!!!!"; } } @@ -1096,58 +1077,67 @@ export class RdDActor extends Actor { content: msgText, whisper: ChatMessage.getWhisperRecipients(game.user.name) }; - ChatMessage.create(message); + ChatMessage.create(message); } - /* -------------------------------------------- */ + /* -------------------------------------------- */ async santeIncDec(name, inc, isCritique = false) { + const sante = duplicate(this.data.data.sante); let data = sante[name]; - if (data==undefined) { + if (!data) { return; } + let result = { + sonne: false, + }; + let minValue = 0; 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; } - let newValue = Math.max(minValue, Math.min(data.value + inc, data.max)); - //console.log("New value ", inc, minValue, newValue); + result.newValue = Math.max(minValue, Math.min(data.value + inc, data.max)); + //console.log("New value ", inc, minValue, result.newValue); - if (name == "endurance" && this.data.type != 'entite' ) { - if ( sante.fatigue && inc < 0 ) { // Each endurance lost -> fatigue lost + if (name == "endurance" && this.data.type != 'entite') { + if (sante.fatigue && inc < 0) { // Each endurance lost -> fatigue lost sante.fatigue.value = sante.fatigue.value - inc } - if ( !isCritique && newValue == 0 && inc < 0) { // perte endurance et endurance devient 0 -> -1 vie sauf si coup critique + if (!isCritique && result.newValue == 0 && inc < 0) { // perte endurance et endurance devient 0 -> -1 vie sauf si coup critique sante.vie.value = sante.vie.value - 1; } - newValue = Math.max(0, newValue); - if (inc>0) { // le max d'endurance s'applique seulement à la récupération - newValue = Math.min(newValue, this._computeEnduranceMax()) + result.newValue = Math.max(0, result.newValue); + if (inc > 0) { // le max d'endurance s'applique seulement à la récupération + result.newValue = Math.min(result.newValue, this._computeEnduranceMax()) } - if (data.value - newValue > 1) { - this.testSiSonne(sante, newValue); // Peut-être sonné si 2 points d'endurance perdus d'un coup - } else if (inc>0) { + if (data.value - result.newValue > 1) { + // Peut-être sonné si 2 points d'endurance perdus d'un coup + const testIsSonne = this.testSiSonne(sante, result.newValue); + result.sonne = testIsSonne.sonne; + result.jetEndurance = testIsSonne.roll.total; + } else if (inc > 0 && !this.isEntiteCauchemar()) { sante.sonne.value = false; } } - data.value = newValue; - //console.log(name, inc, data.value, newValue, minValue, data.max); - if ( sante.fatigue) { // If endurance lost, then the same amount of fatigue cannot be recovered + data.value = result.newValue; + //console.log(name, inc, data.value, result.newValue, minValue, data.max); + if (sante.fatigue) { // If endurance lost, then the same amount of fatigue cannot be recovered sante.fatigue.value = Math.max(sante.fatigue.value, this._computeFatigueMin()); - } + } //console.log("SANTE::::", sante); - - await this.update( {"data.sante": sante } ); + + await this.update({ "data.sante": sante }); + return result; } - /* -------------------------------------------- */ + /* -------------------------------------------- */ _computeFatigueMin() { return this.data.data.sante.endurance.max - this.data.data.sante.endurance.value; } - - /* -------------------------------------------- */ + + /* -------------------------------------------- */ _computeEnduranceMax() { let blessures = this.data.data.blessures; let diffVie = this.data.data.sante.vie.max - this.data.data.sante.vie.value; @@ -1159,33 +1149,33 @@ export class RdDActor extends Actor { return Math.max(0, Math.min(maxEndVie, maxEndGraves, maxEndCritiques)); } - /* -------------------------------------------- */ - async manageBlessureFromSheet( bType, index, active ) { - let bList = duplicate(this.data.data.blessures); - let blessure = bList[bType+"s"].liste[index]; + /* -------------------------------------------- */ + async manageBlessureFromSheet(bType, index, active) { + let bList = duplicate(this.data.data.blessures); + let blessure = bList[bType + "s"].liste[index]; blessure.active = !blessure.active; - if ( !blessure.active ) { + if (!blessure.active) { blessure.premiers_soins = 0; blessure.soins_complets = 0; blessure.jours = 0; - blessure.loc = ""; + blessure.loc = ""; } //console.log("Blessure update", bType, index, blessure, bList ); - await this.update( { 'data.blessures': bList } ); + await this.update({ 'data.blessures': bList }); } - /* -------------------------------------------- */ - async setDataBlessureFromSheet( bType, index, psoins, pcomplets, jours, loc) { - let bList = duplicate(this.data.data.blessures); - let blessure = bList[bType+"s"].liste[index]; + /* -------------------------------------------- */ + async setDataBlessureFromSheet(bType, index, psoins, pcomplets, jours, loc) { + let bList = duplicate(this.data.data.blessures); + let blessure = bList[bType + "s"].liste[index]; blessure.premiers_soins = psoins; blessure.soins_complets = pcomplets; blessure.jours = jours; blessure.loc = loc; - await this.update( { 'data.blessures': bList } ); + await this.update({ 'data.blessures': bList }); } - /* -------------------------------------------- */ + /* -------------------------------------------- */ async jetDeMoral(situation) { let jetMoral = new Roll("1d20").roll(); RdDDice.show(jetMoral); @@ -1194,16 +1184,16 @@ export class RdDActor extends Actor { const succes = jetMoral.total <= difficulte; let ajustementMoral = this._calculAjustementMoral(succes, moralActuel, situation); - + await this.moralIncDec(ajustementMoral); ChatMessage.create({ whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), - 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"}` + 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"}` }); return ajustementMoral; } - /* -------------------------------------------- */ + /* -------------------------------------------- */ async moralIncDec(ajustementMoral) { let compteurs = duplicate(this.data.data.compteurs); compteurs.moral.value = Misc.toInt(compteurs.moral.value);; @@ -1224,7 +1214,7 @@ export class RdDActor extends Actor { } } - /* -------------------------------------------- */ + /* -------------------------------------------- */ _calculAjustementMoral(succes, moral, situation) { switch (situation) { case 'heureuse': return succes ? 1 : 0; @@ -1236,7 +1226,7 @@ export class RdDActor extends Actor { return 0; } - /* -------------------------------------------- */ + /* -------------------------------------------- */ async setEthylisme(degre) { let ethylisme = duplicate(this.data.data.compteurs.ethylisme); ethylisme.value = degre; @@ -1244,12 +1234,12 @@ export class RdDActor extends Actor { if (degre == 1) { ethylisme.jet_moral = false; } - await this.update({ "data.compteurs.ethylisme": ethylisme}); + await this.update({ "data.compteurs.ethylisme": ethylisme }); } /* -------------------------------------------- */ async ethylismeTest() { - let rollData = { + let rollData = { vieValue: this.data.data.sante.vie.value, 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) diffNbDoses: -Number(this.data.data.compteurs.ethylisme.nb_doses || 0), @@ -1259,31 +1249,31 @@ export class RdDActor extends Actor { forceAlcool: 0 } let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ethylisme.html', rollData); - new RdDRollDialogEthylisme(html, rollData, this ).render(true); + new RdDRollDialogEthylisme(html, rollData, this).render(true); } - + /* -------------------------------------------- */ - async performEthylisme( rollData ) { + async performEthylisme(rollData) { let ethylisme = duplicate(this.data.data.compteurs.ethylisme); - + // Je d'ethylisme - let rollEthylisme = await RdDResolutionTable.roll( rollData.vieValue, rollData.finalLevel); + let rollEthylisme = await RdDResolutionTable.roll(rollData.vieValue, rollData.finalLevel); let msgText = RdDResolutionTable.explain(rollEthylisme) + "
"; - if (rollEthylisme.isSuccess ) { - ethylisme.nb_doses ++; + if (rollEthylisme.isSuccess) { + ethylisme.nb_doses++; msgText += `Vous avez réussi votre jet d'éthylisme, vous avez consommé ${ethylisme.nb_doses} doses sans effet.`; } else { - ethylisme.value = Math.max(ethylisme.value -1, -7); + ethylisme.value = Math.max(ethylisme.value - 1, -7); ethylisme.nb_doses = 0; let enduranceLost = new Roll("1d6").roll().total; await this.santeIncDec("endurance", -enduranceLost); const ajustementEthylique = ethylisme.value; // Qui a bu boira (p 164) - let rollVolonte = await RdDResolutionTable.roll( this.data.data.carac.volonte.value, Math.min(ajustementEthylique, 0) + this.data.data.compteurs.moral.value); + let rollVolonte = await RdDResolutionTable.roll(this.data.data.carac.volonte.value, Math.min(ajustementEthylique, 0) + this.data.data.compteurs.moral.value); msgText += `Vous avez échoué à votre jet d'éthylisme, vous êtes maintenant ${RdDUtility.getNomEthylisme(ajustementEthylique)} (${ajustementEthylique}).` msgText += "
" + RdDResolutionTable.explain(rollVolonte) + "
"; - msgText += "Qui a bu boira : " +(rollVolonte.isSuccess + msgText += "Qui a bu boira : " + (rollVolonte.isSuccess ? "vous êtes libre de continuer à boire ou pas." : "vous avez une envie irrépréssible de reprendre un verre."); } @@ -1291,14 +1281,14 @@ export class RdDActor extends Actor { ChatMessage.create({ content: msgText, whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name) - }); - + }); + if (rollEthylisme.isEchec) { await this._jetDeMoralEthylique(ethylisme); } - await this.update( { 'data.compteurs.ethylisme': ethylisme} ); + await this.update({ 'data.compteurs.ethylisme': ethylisme }); } - + /* -------------------------------------------- */ async _jetDeMoralEthylique(ethylisme) { if (ethylisme.value >= -1 && !ethylisme.jet_moral) { @@ -1311,7 +1301,7 @@ export class RdDActor extends Actor { ChatMessage.create({ content: "Décidément, vous avez l'alcool triste, vous perdez finalement un point de moral!", whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name) - }); + }); this.moralIncDec(-1); } } @@ -1332,22 +1322,22 @@ export class RdDActor extends Actor { async transformerStress(message) { let compteurs = duplicate(this.data.data.compteurs); const stress = Misc.toInt(compteurs.stress.value); - - if (stress<=0) { + + if (stress <= 0) { return; } - - + + let stressRoll = await this._stressRoll(); let convertis = Math.floor(stress * stressRoll.factor); compteurs.stress.value = Math.max(stress - convertis - 1, 0); - + 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; - if (dissolution>0) { + if (dissolution > 0) { const perdus = Math.min(dissolution, convertis); convertis -= perdus; dissolution -= perdus; @@ -1384,7 +1374,7 @@ export class RdDActor extends Actor { } } - /* -------------------------------------------- */ + /* -------------------------------------------- */ createCallbackExperience() { return { condition: r => r.rolled.isPart && r.finalLevel < 0 && game.settings.get("core", "rollMode") != 'selfroll', @@ -1392,99 +1382,101 @@ export class RdDActor extends Actor { }; } - /* -------------------------------------------- */ - async checkCaracXP( caracName ) { + /* -------------------------------------------- */ + async checkCaracXP(caracName) { let carac = this.data.data.carac[caracName]; console.log("XP chek", carac, caracName); if (carac && carac.xp > 0) { - let xpNeeded = RdDUtility.getCaracNextXp( carac.value ); - if ( carac.xp >= xpNeeded ) { + let xpNeeded = RdDUtility.getCaracNextXp(carac.value); + if (carac.xp >= xpNeeded) { carac = duplicate(carac); carac.value = Number(carac.value) + 1; - await this.updateCarac( caracName, carac.value ); - carac.xp -= xpNeeded; - await this.updateCaracXP( caracName, carac.xp ); + await this.updateCarac(caracName, carac.value); + carac.xp -= xpNeeded; + await this.updateCaracXP(caracName, carac.xp); - let xpData = { - alias: this.name, + let xpData = { + alias: this.name, carac: caracName, value: carac.value, xp: carac.xp } - let content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html`, xpData); - ChatUtility.createChatMessage({ content: content }, "default", this.name); + ChatUtility.createChatMessage(this.name, "default", { + content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html`, xpData) + }); } } } - /* -------------------------------------------- */ - async checkCompetenceXP( compName ) { - let competence = RdDItemCompetence.findCompetence( this.data.items, compName); - if ( competence && competence.data.xp > 0) { - let xpNeeded = RdDItemCompetence.getCompetenceNextXp( competence.data.niveau ); - if ( competence.data.xp >= xpNeeded ) { + /* -------------------------------------------- */ + async checkCompetenceXP(compName) { + let competence = RdDItemCompetence.findCompetence(this.data.items, compName); + if (competence && competence.data.xp > 0) { + let xpNeeded = RdDItemCompetence.getCompetenceNextXp(competence.data.niveau); + if (competence.data.xp >= xpNeeded) { competence.data.xp -= xpNeeded; competence.data.niveau += 1; - let update = {_id: competence._id, "data.xp": competence.data.xp, "data.niveau": competence.data.niveau}; - await this.updateEmbeddedEntity( "OwnedItem", update ); + let update = { _id: competence._id, "data.xp": competence.data.xp, "data.niveau": competence.data.niveau }; + await this.updateEmbeddedEntity("OwnedItem", update); - let xpData = { - alias: this.name, + let xpData = { + alias: this.name, competence: competence.name, niveau: competence.data.niveau, - xp: competence.data.xp, - archetype: competence.data.niveau_archetype, + xp: competence.data.xp, + archetype: competence.data.niveau_archetype, archetypeWarning: competence.data.niveau > competence.data.niveau_archetype } - let content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html`, xpData); - ChatUtility.createChatMessage({ content: content }, "default", this.name); + ChatUtility.createChatMessage(this.name, "default", { + content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html`, xpData) + }); } } } - /* -------------------------------------------- */ - async _appliquerAjoutExperience(rollData, display=true) { + /* -------------------------------------------- */ + async _appliquerAjoutExperience(rollData, display = true) { if (!this.isPersonnage()) return; - let xpResult = this.appliquerExperience( rollData.rolled, rollData.selectedCarac.label, rollData.competence); - if (display && xpResult.result ) { + let xpResult = this.appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence); + if (display && xpResult.result) { let xpmsg = "
Points d'expérience gagnés ! Carac: " + xpResult.xpCarac + ", Comp: " + xpResult.xpCompetence; let message = ChatUtility.prepareChatMessage('gmroll', this.name); message.content = "" + rollData.selectedCarac.label + "" - + xpmsg; + + xpmsg; ChatMessage.create(message); } - if ( xpResult && xpResult.xpComp > 0 && rollData.competence) { - this.checkCompetenceXP( rollData.competence.name ); + if (xpResult && xpResult.xpComp > 0 && rollData.competence) { + this.checkCompetenceXP(rollData.competence.name); } - if ( xpResult && xpResult.xpCarac > 0 && rollData.selectedCarac) { - this.checkCaracXP( rollData.selectedCarac.name ); + if (xpResult && xpResult.xpCarac > 0 && rollData.selectedCarac) { + this.checkCaracXP(rollData.selectedCarac.name); } } /* -------------------------------------------- */ async rollUnSort(coord) { let sortList = duplicate(this.getSortList()); // Duplication car les pts de reve sont modifiés dans le sort - if (!sortList || sortList.length == 0) - { + if (!sortList || sortList.length == 0) { ui.notifications.info("Aucun sort disponible!"); return; } - if ( this.currentTMR) this.currentTMR.minimize(); // Hide - - let rollData = { + if (this.currentTMR) this.currentTMR.minimize(); // Hide + + let rollData = { selectedCarac: this.data.data.carac.reve, draconicList: this.getDraconicList(), sortList: sortList, competence: this.getBestDraconic(), selectedSort: sortList[0], coord: coord, - coordLabel: TMRUtility.getTMRDescription( coord).label, + coordLabel: TMRUtility.getTMRDescription(coord).label, diffLibre: sortList[0].data.difficulte, // Per default at startup coutreve: Array(20).fill().map((item, index) => 1 + index) } const dialog = await RdDRoll.create(this, rollData, - { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html', + { + html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html', close: html => { this.currentTMR.maximize() } // Re-display TMR }, { @@ -1500,7 +1492,7 @@ export class RdDActor extends Actor { label: 'Mettre un sort en réserve', callbacks: [ this.createCallbackExperience(), - { action: r => this._rollUnSortResult(r, true) } + { action: r => this._rollUnSortResult(r, true) } ] } ); @@ -1508,54 +1500,57 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - isRencontreSpeciale( ) { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective' + isRencontreSpeciale() { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective' let addMsg = ""; - let rencSpecial = this.data.items.find( item => (item.type == 'queue' || item.type == 'souffle') && item.name.toLowerCase().includes( 'mauvaise rencontre' ) ); - if ( rencSpecial ) { + let rencSpecial = this.data.items.find(item => (item.type == 'queue' || item.type == 'souffle') && item.name.toLowerCase().includes('mauvaise rencontre')); + if (rencSpecial) { rencSpecial = duplicate(rencSpecial); // To keep it - if ( rencSpecial.type == 'queue') { - this.deleteOwnedItem( rencSpecial._id ); // Suppression dans la liste des queues + if (rencSpecial.type == 'queue') { + this.deleteOwnedItem(rencSpecial._id); // Suppression dans la liste des queues 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."; - } - ChatMessage.create( { + } + ChatMessage.create({ content: "Vous êtes sous le coup d'une Mauvaise Rencontre en Persective." + addMsg, - whisper: ChatMessage.getWhisperRecipients(game.user.name) } ); + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); } return rencSpecial; } /* -------------------------------------------- */ getTMRFatigue() { // Pour l'instant uniquement Inertie Draconique - let inertieDraconique = this.data.items.find( item => item.type == 'queue' && item.name.toLowerCase().includes( 'inertie draconique' ) ); - if ( inertieDraconique ) { - ChatMessage.create( { + let inertieDraconique = this.data.items.find(item => item.type == 'queue' && item.name.toLowerCase().includes('inertie draconique')); + if (inertieDraconique) { + ChatMessage.create({ content: "Vous êtes sous le coup d'une Inertie Draconique : vous perdez 2 cases de Fatigue par déplacement au lieu d'1.", - whisper: ChatMessage.getWhisperRecipients(game.user.name) } ); + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); return 2; } return 1; } /* -------------------------------------------- */ - isConnaissanceFleuve( ) { - return this.data.items.find( item => item.type == 'tete' && item.name.toLowerCase().includes( 'connaissance du fleuve' ) ); + isConnaissanceFleuve() { + return this.data.items.find(item => item.type == 'tete' && item.name.toLowerCase().includes('connaissance du fleuve')); } /* -------------------------------------------- */ isReserveEnSecurite() { - let reserveSecurite = this.data.items.find( item => item.type == 'tete' && item.name.toLowerCase().includes( ' en sécurité' ) ); + let reserveSecurite = this.data.items.find(item => item.type == 'tete' && item.name.toLowerCase().includes(' en sécurité')); return reserveSecurite; } /* -------------------------------------------- */ - isDoubleResistanceFleuve( ) { - let resistFleuve = this.data.items.find( item => item.type == 'souffle' && item.name.toLowerCase().includes( 'résistance du fleuve' ) ); - if ( resistFleuve ) { - ChatMessage.create( { + isDoubleResistanceFleuve() { + let resistFleuve = this.data.items.find(item => item.type == 'souffle' && item.name.toLowerCase().includes('résistance du fleuve')); + if (resistFleuve) { + ChatMessage.create({ 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é.", - whisper: ChatMessage.getWhisperRecipients(game.user.name) } ); + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); return true; } return false; @@ -1563,40 +1558,42 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async checkSoufflePeage(cellDescr) { - 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( { + 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({ 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).", - whisper: ChatMessage.getWhisperRecipients(game.user.name) } ); + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); } } /* -------------------------------------------- */ checkTeteDeplacementAccelere() { - let deplAccelere = this.data.items.find( item => item.type == 'tete' && item.name.toLowerCase().includes( ' déplacement accéléré' ) ); - if ( deplAccelere ) { + let deplAccelere = this.data.items.find(item => item.type == 'tete' && item.name.toLowerCase().includes(' déplacement accéléré')); + if (deplAccelere) { return true; } return false; } /* -------------------------------------------- */ - 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( { + 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({ content: "Vous êtes sous le coup d'une Impraticabilité des Ponts : ils doivent être maîtrisés comme des cases humides.", - whisper: ChatMessage.getWhisperRecipients(game.user.name) } ); + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); return true; } // Débordement ? - let debordementList = this.data.items.filter( item => item.type == 'casetmr' && item.data.specific == 'debordement' ); + let debordementList = this.data.items.filter(item => item.type == 'casetmr' && item.data.specific == 'debordement'); for (let caseTMR of debordementList) { - if ( caseTMR.data.coord == coordTMR ) + if (caseTMR.data.coord == coordTMR) return true; } - + return false; } @@ -1609,7 +1606,7 @@ export class RdDActor extends Actor { ui.notifications.error("Impossible de mettre le rituel '" + selectedSort.name + "' en réserve"); this.currentTMR.close(); // Close TMR ! return; - } + } rollData.isSortReserve = isSortReserve; rollData.show = {} @@ -1627,7 +1624,7 @@ export class RdDActor extends Actor { if (myReve.value > rollData.depenseReve) { // Incrémenter/gére le bonus de case RdDItemSort.incrementBonusCase(this, selectedSort, rollData.coord); - + if (rollData.isSortReserve) { await this.sortMisEnReserve(rollData, selectedSort); closeTMR = false; @@ -1636,7 +1633,7 @@ export class RdDActor extends Actor { else { rollData.depenseReve = 0; rollData.show.reveInsuffisant = true; - mergeObject(rollData.rolled, RdDResolutionTable.getResultat("echec"), {overwrite:true}); + mergeObject(rollData.rolled, RdDResolutionTable.getResultat("echec"), { overwrite: true }); } } else { if (rolled.isETotal) { // Echec total ! @@ -1649,7 +1646,7 @@ export class RdDActor extends Actor { myReve.value = Math.max(myReve.value - rollData.depenseReve, 0); await this.update({ "data.reve.reve": myReve }); - + if (closeTMR) { this.currentTMR.close(); // Close TMR ! } else { @@ -1664,14 +1661,14 @@ export class RdDActor extends Actor { } } - /* -------------------------------------------- */ - async rollCarac( caracName ) { + /* -------------------------------------------- */ + async rollCarac(caracName) { let rollData = { selectedCarac: this.getCaracByName(caracName) }; const dialog = await RdDRoll.create(this, rollData, - {html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html'}, + { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html' }, { - name: 'jet-'+caracName, + name: 'jet-' + caracName, label: 'Jet ' + Grammar.apostrophe('de', rollData.selectedCarac.label), callbacks: [ this.createCallbackExperience(), @@ -1682,16 +1679,16 @@ export class RdDActor extends Actor { dialog.render(true); } - /* -------------------------------------------- */ + /* -------------------------------------------- */ async _onRollCaracResult(rollData) { // Final chat message RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-general.html'); } - /* -------------------------------------------- */ - async rollCompetence( name ) { + /* -------------------------------------------- */ + async rollCompetence(name) { let rollData = { competence: this.getCompetence(name) } - + if (rollData.competence.type == 'competencecreature') { // Fake competence pour créature RdDItemCompetence.setRollDataCreature(rollData); @@ -1701,61 +1698,62 @@ export class RdDActor extends Actor { } console.log("rollCompetence !!!", rollData); - 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); + 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 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 ) ); + async rollTache(id) { + let tache = duplicate(this.getTache(id)); let competence = duplicate(this.getCompetence(tache.data.competence)); competence.data.defaut_carac = tache.data.carac; // Patch ! let rollData = { - competence: competence, + competence: competence, tache: tache, diffConditions: tache.data.difficulte, editLibre: false, editConditions: false, - carac : { } + carac: {} }; rollData.carac[tache.data.carac] = duplicate(this.data.data.carac[tache.data.carac]); // Single carac console.log("rollTache !!!", rollData); - 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) } - ] - } ); + 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) } + ] + }); dialog.render(true); } @@ -1763,8 +1761,8 @@ export class RdDActor extends Actor { async _tacheResult(rollData) { // Mise à jour de la tache rollData.tache.data.points_de_tache_courant += rollData.rolled.ptTache; - this.updateEmbeddedEntity( "OwnedItem", rollData.tache); - this.santeIncDec( "fatigue", rollData.tache.data.fatigue); + this.updateEmbeddedEntity("OwnedItem", rollData.tache); + this.santeIncDec("fatigue", rollData.tache.data.fatigue); RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-tache.html'); } @@ -1772,11 +1770,11 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ _tacheETotal(rollData) { rollData.tache.data.difficulte--; - this.updateEmbeddedEntity( "OwnedItem", rollData.tache); + this.updateEmbeddedEntity("OwnedItem", rollData.tache); } /* -------------------------------------------- */ - async rollMeditation( id ) { + async rollMeditation(id) { let meditation = duplicate(this.getMeditation(id)); let competence = duplicate(this.getCompetence(meditation.data.competence)); competence.data.defaut_carac = "intellect"; // Meditation = tjs avec intellect @@ -1792,55 +1790,54 @@ export class RdDActor extends Actor { diffConditions: 0, editLibre: false, editConditions: true, - carac : { } + carac: {} }; - meditationData.carac["intellect"] = duplicate(this.data.data.carac["intellect"]); + meditationData.carac["intellect"] = duplicate(this.data.data.carac["intellect"]); console.log("rollMeditation !!!", meditationData); - 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) } - ] - } ); + 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) } + ] + }); dialog.render(true); } /* -------------------------------------------- */ async _meditationResult(meditationData) { - this.santeIncDec( "fatigue", 2); - + this.santeIncDec("fatigue", 2); + meditationData.diffLecture = -7; - if (meditationData.rolled.isPart ) + if (meditationData.rolled.isPart) meditationData.diffLecture = 0; - else if (meditationData.rolled.isSign ) + else if (meditationData.rolled.isSign) meditationData.diffLecture = -3; RdDResolutionTable.displayRollData(meditationData, this.name, 'chat-resultat-meditation.html'); } - + /* -------------------------------------------- */ _meditationETotal(meditationData) { meditationData.meditation.data.malus--; - this.updateEmbeddedEntity( "OwnedItem", meditationData.meditation); + this.updateEmbeddedEntity("OwnedItem", meditationData.meditation); } - + /* -------------------------------------------- */ async _competenceResult(rollData) { RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-competence.html') } /* -------------------------------------------- */ - async rollAppelChance(onSuccess = () => {}, onEchec = () => {}) - { + async rollAppelChance(onSuccess = () => { }, onEchec = () => { }) { let rollData = { selectedCarac: this.getCaracByName('chance-actuelle'), surprise: '' }; const dialog = await RdDRoll.create(this, rollData, - { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html'}, + { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html' }, { name: 'appelChance', label: 'Appel à la chance', @@ -1849,36 +1846,36 @@ export class RdDActor extends Actor { { action: r => this._appelChanceResult(r, onSuccess, onEchec) }, ] } - ); - 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(); - } + ); + 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(); + } + } + /* -------------------------------------------- */ async chanceActuelleIncDec(value) { let chance = duplicate(this.data.data.compteurs.chance); chance.value = Math.max(chance.value + value, 0); - await this.update( {"data.compteurs.chance": chance } ); + await this.update({ "data.compteurs.chance": chance }); } - + /* -------------------------------------------- */ - async appelDestinee( onSuccess = () => {}, onEchec= ()=>{}) { - if (this.data.data.compteurs.destinee?.value ?? 0 >0 ) { - ChatMessage.create({content: `${this.name} a fait appel à la Destinée !` }); + async appelDestinee(onSuccess = () => { }, onEchec = () => { }) { + if (this.data.data.compteurs.destinee?.value ?? 0 > 0) { + ChatMessage.create({ content: `${this.name} a fait appel à la Destinée !` }); let destinee = duplicate(this.data.data.compteurs.destinee); destinee.value = destinee.value - 1; - await this.update( {"data.compteurs.destinee": destinee } ); + await this.update({ "data.compteurs.destinee": destinee }); onSuccess(); } else { @@ -1896,82 +1893,87 @@ export class RdDActor extends Actor { return game.system.rdd.calendrier.getAjustementAstrologique(this.data.data.heure, this.data.name); } /* -------------------------------------------- */ - checkDesirLancinant( ) { - let queue = this.data.items.filter( (item) => item.name.toLowerCase().includes('lancinant') ); + checkDesirLancinant() { + let queue = this.data.items.filter((item) => item.name.toLowerCase().includes('lancinant')); return (queue.length > 0); } /* -------------------------------------------- */ - async appliquerExperience( rolled, caracName, competence = undefined ) { + async appliquerExperience(rolled, caracName, competence = undefined) { - if ( rolled.isPart && rolled.finalLevel < 0) { + if (rolled.isPart && rolled.finalLevel < 0) { // Cas de désir lancinant, pas d'expérience sur particulière - 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 }; + 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 }; } if (caracName == 'derobee') caracName = 'agilite'; let xp = Math.abs(rolled.finalLevel); let xpCarac = Math.floor(xp / 2); // impair: arrondi inférieur en carac let xpComp = 0; - if ( competence ) { + if (competence) { xpComp = xp - xpCarac; - competence = duplicate(competence ); + competence = duplicate(competence); competence.data.xp = Misc.toInt(competence.data.xp) + xpComp; - await this.updateEmbeddedEntity( "OwnedItem", competence); + await this.updateEmbeddedEntity("OwnedItem", competence); } else { xpCarac = Math.max(xpCarac, 1); - } + } if (xpCarac > 0) { let carac = duplicate(this.data.data.carac); let selectedCarac = RdDActor._findCaracByName(carac, caracName); - if ( !selectedCarac.derivee) { + if (!selectedCarac.derivee) { selectedCarac.xp = Misc.toInt(selectedCarac.xp) + xpCarac; - await this.update( {"data.carac": carac } ); + await this.update({ "data.carac": carac }); } else { - 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) } ); + 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) + }); } } - return { result:true, xpCarac:xpCarac, xpCompetence: xpComp }; //XP + return { result: true, xpCarac: xpCarac, xpCompetence: xpComp }; //XP } - return { result:false, xpCarac:0, xpCompetence: 0 }; // Pas d'XP + return { result: false, xpCarac: 0, xpCompetence: 0 }; // Pas d'XP } - + /* -------------------------------------------- */ - async ajouteNombreAstral( data ) { + async ajouteNombreAstral(data) { // Gestion expérience (si existante) - data.competence = RdDItemCompetence.findCompetence( this.data.items, "astrologie"); + data.competence = RdDItemCompetence.findCompetence(this.data.items, "astrologie"); data.selectedCarac = this.data.data.carac["vue"]; - this._appliquerAjoutExperience( data ); + this._appliquerAjoutExperience(data); // Ajout du nombre astral - 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) ) } }; + 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)) } + }; await this.createEmbeddedEntity("OwnedItem", item); - + // Suppression des anciens nombres astraux - let toDelete = this.data.items.filter( (item) => item.data.jourindex < game.system.rdd.calendrier.getCurrentDayIndex() ); + let toDelete = this.data.items.filter((item) => item.data.jourindex < game.system.rdd.calendrier.getCurrentDayIndex()); const deletions = toDelete.map(i => i._id); await this.deleteEmbeddedEntity("OwnedItem", deletions); // Affichage Dialog this.astrologieNombresAstraux(); - } + } /* -------------------------------------------- */ - async astrologieNombresAstraux( ) { + async astrologieNombresAstraux() { // Afficher l'interface spéciale - const astrologieDialog = await RdDAstrologieJoueur.create( this, {} ); + const astrologieDialog = await RdDAstrologieJoueur.create(this, {}); astrologieDialog.render(true); } /* -------------------------------------------- */ getCaracByName(caracName) { - switch (caracName) - { + switch (caracName) { case 'reve-actuel': case 'Rêve actuel': return { label: 'Rêve actuel', @@ -1990,8 +1992,7 @@ export class RdDActor extends Actor { static _findCaracByName(carac, name) { name = name.toLowerCase(); - switch (name) - { + switch (name) { case 'reve-actuel': case 'rêve actuel': return carac.reve; case 'chance-actuelle': case 'chance actuelle': @@ -2009,63 +2010,63 @@ export class RdDActor extends Actor { getSortList() { return this.data.items.filter(item => item.type == "sort"); } - + /* -------------------------------------------- */ getDraconicList() { return this.data.items.filter(item => item.data.categorie == 'draconic') } - - /* -------------------------------------------- */ - 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( { + + /* -------------------------------------------- */ + 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({ 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.", - whisper: ChatMessage.getWhisperRecipients(game.user.name) } ); + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); return 1; } return 0; } - /* -------------------------------------------- */ - async displayTMR(mode="normal") - { - let isRapide= mode == "rapide"; - if (mode != "visu") - { + /* -------------------------------------------- */ + async displayTMR(mode = "normal") { + let isRapide = mode == "rapide"; + if (mode != "visu") { let minReveValue = (isRapide) ? 3 : 2; - if (this.getReveActuel() < minReveValue ) { - ChatMessage.create( { + if (this.getReveActuel() < minReveValue) { + ChatMessage.create({ content: "Vous n'avez plus assez de Points de Reve pour monter dans les Terres Médianes", - whisper: ChatMessage.getWhisperRecipients(game.user.name) } ); + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); return; - } + } } - + // Notification au MJ - ChatMessage.create( { content: game.user.name + " est monté dans les TMR en mode : " + mode, whisper: ChatMessage.getWhisperRecipients("GM") } ); + ChatMessage.create({ content: game.user.name + " est monté dans les TMR en mode : " + mode, whisper: ChatMessage.getWhisperRecipients("GM") }); let data = { fatigue: { - malus: RdDUtility.calculMalusFatigue(this.data.data.sante.fatigue.value, this.data.data.sante.endurance.max), - html: "" + RdDUtility.makeHTMLfatigueMatrix( this.data.data.sante.fatigue.value, this.data.data.sante.endurance.max ).html() + "
" + malus: RdDUtility.calculMalusFatigue(this.data.data.sante.fatigue.value, this.data.data.sante.endurance.max), + html: "" + RdDUtility.makeHTMLfatigueMatrix(this.data.data.sante.fatigue.value, this.data.data.sante.endurance.max).html() + "
" }, draconic: this.getDraconicList(), sort: this.getSortList(), caracReve: this.data.data.carac.reve.value, pointsReve: this.getReveActuel(), isRapide: isRapide - } - let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', data ); + } + let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', data); this.currentTMR = new RdDTMRDialog(html, this, data, mode); this.currentTMR.render(true); } - - /* -------------------------------------------- */ - async rollCompetenceCreature( compName ) { + + /* -------------------------------------------- */ + async rollCompetenceCreature(compName) { let competence = this.getCompetence(compName); - if ( competence.type == 'competencecreature' && competence.data.iscombat ) { + if (competence.type == 'competencecreature' && competence.data.iscombat) { let competence = this.getCompetence(compName); RdDCombat.createUsingTarget(this).attaque(competence, armeItem); } @@ -2074,15 +2075,15 @@ export class RdDActor extends Actor { } } - /* -------------------------------------------- */ + /* -------------------------------------------- */ rollArme(compName, armeName = undefined) { - let arme = this.data.items.find( item => item.name == armeName && RdDItemArme.isArme(item)); + let arme = this.data.items.find(item => item.name == armeName && RdDItemArme.isArme(item)); let competence = this.getCompetence(compName); - + if (arme || armeName || (competence.type == 'competencecreature' && competence.data.iscombat)) { RdDCombat.createUsingTarget(this).attaque(competence, arme); } else { - this.rollCompetence( competence.name ); + this.rollCompetence(competence.name); } } @@ -2095,22 +2096,21 @@ export class RdDActor extends Actor { } return undefined; } - - /* -------------------------------------------- */ - async equiperObjet( itemID ) { + + /* -------------------------------------------- */ + async equiperObjet(itemID) { let item = this.getOwnedItem(itemID); - if ( item && item.data.data ) { - let update = {_id: item._id, "data.equipe": !item.data.data.equipe }; - await this.updateEmbeddedEntity("OwnedItem", update); + if (item && item.data.data) { + let update = { _id: item._id, "data.equipe": !item.data.data.equipe }; + await this.updateEmbeddedEntity("OwnedItem", update); this.computeEncombrementTotalEtMalusArmure(); // Mise à jour encombrement } } - - /* -------------------------------------------- */ - computeArmure( attackerRoll ) { - let locData = attackerRoll.loc; + + /* -------------------------------------------- */ + computeArmure(attackerRoll) { let dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor; - let arme = attackerRoll.arme; + let arme = attackerRoll.arme; // TODO: arc ignore armure let protection = 0; for (const item of this.data.items) { @@ -2119,26 +2119,26 @@ export class RdDActor extends Actor { protection += new Roll(update.data.protection.toString()).roll().total; update.data.deterioration = Misc.toInt(update.data.deterioration) + dmg; dmg = 0; // Reset it - if ( update.data.deterioration >= 10) { + 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; + if (res) + update.data.protection = "1d" + update.data.protection; // if ( update.data.protection.toString().length == 1 ) // update.data.protection = "1d"+update.data.protection; - else if (res = /(\d+d\d+)(\-\d+)?/.exec( 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{ + else { ui.notifications.warn(`La valeur d'armure de votre ${item.name} est incorrecte`) } - ChatMessage.create( {content: "Détérioration d'armure: " + update.data.protection } ); + ChatMessage.create({ content: "Détérioration d'armure: " + update.data.protection }); } - this.updateEmbeddedEntity("OwnedItem", update); + this.updateEmbeddedEntity("OwnedItem", update); } } + // TODO: max armure (chutes) const penetration = arme ? Misc.toInt(arme.data.penetration) : 0; protection = Math.max(protection - penetration, 0); protection += this.getProtectionNaturelle(); @@ -2146,87 +2146,85 @@ export class RdDActor extends Actor { return protection; } - /* -------------------------------------------- */ - async encaisser( ) { - let data = { ajustementsEncaissement: RdDUtility.getAjustementsEncaissement() }; - let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html', data ); - new RdDEncaisser(html, this ).render(true); - } - /* -------------------------------------------- */ - async encaisser( ) { + async encaisser() { let data = { ajustementsEncaissement: RdDUtility.getAjustementsEncaissement() }; - let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html', data ); + let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html', data); new RdDEncaisser(html, this).render(true); } /* -------------------------------------------- */ - async encaisserDommages( attackerRoll, attacker = undefined ) { + async encaisserDommages(attackerRoll, attacker = undefined) { if (attacker && !await attacker.accorder(this, 'avant-encaissement')) { return; } - console.log("encaisserDommages", attackerRoll ) + console.log("encaisserDommages", attackerRoll) + let santeOrig = duplicate(this.data.data.sante); let encaissement = this.jetEncaissement(attackerRoll); this.ajouterBlessure(encaissement); // Will upate the result table - - await this.santeIncDec("vie", encaissement.vie); - await this.santeIncDec("endurance", encaissement.endurance, (encaissement.critiques > 0)); - - const blessureLegere = (encaissement.legeres > 0 ? "une blessure légère" : ""); - const blessureGrave = (encaissement.graves > 0 ? "une blessure grave" : ""); - const blessureCritique = (encaissement.critiques > 0 ? "une blessure critique" : ""); - - let commonMsg = { - title: "Blessures !", - roll: encaissement.roll, - content: `${this.data.name} a encaissé ${blessureLegere}${blessureGrave}${blessureCritique} (${encaissement.locName})` - } - let addonMsg = "
Et a perdu :
" + encaissement.endurance + " Endurance et " + encaissement.vie + " Points de Vie"; - if ( this.hasPlayerOwner ) { - commonMsg.content += addonMsg; // Message pour tout le monde - ChatMessage.create( commonMsg ); - } else { // Le defenseur n'est pas un PJ, donc message complet uniquement pour le MJ - ChatMessage.create( commonMsg ); // Message pour tout le monde - let gmMsg = duplicate(commonMsg); - gmMsg.content = addonMsg; // Et message complémentaire uniquement pour le MJ - gmMsg.whisper = ChatMessage.getWhisperRecipients( "GM" ); - ChatMessage.create( gmMsg ); - } - + const perteVie = await this.santeIncDec("vie", - encaissement.vie); + const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, (encaissement.critiques > 0)); + this.computeEtatGeneral(); this.sheet.render(false); + + let santeActuelle = duplicate(this.data.data.sante); + + encaissement.alias = this.data.name; + encaissement.hasPlayerOwner = this.hasPlayerOwner; + encaissement.resteEndurance = santeActuelle.endurance.value + encaissement.sonne = perteEndurance.sonne; + encaissement.jetEndurance = perteEndurance.jetEndurance, + encaissement.endurance = santeOrig.endurance.value - perteEndurance.newValue; + encaissement.vie = santeOrig.vie.value - perteVie.newValue; + + ChatUtility.createChatWithRollMode(this.name, { + roll: encaissement.roll, + content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html', encaissement) + }); + + 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) + }); + } } /* -------------------------------------------- */ jetEncaissement(rollData) { - - rollData.dmg.loc = rollData.dmg.loc?? RdDUtility.getLocalisation(); - - const roll = new Roll("2d10 + @dmg - @armure", { - dmg: rollData.dmg.total, - armure: this.computeArmure( rollData ) - }).roll(); + const roll = new Roll("2d10").roll(); + roll.showDice = true; RdDDice.show(roll, game.settings.get("core", "rollMode")); - let encaissement = RdDUtility.selectEncaissement(roll.total, rollData.dmg.mortalite) - let over20 = Math.max(roll.total - 20, 0); + 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;' encaissement.roll = roll; - encaissement.vie = - RdDUtility._evaluatePerte(encaissement.vie, over20); - encaissement.endurance = - RdDUtility._evaluatePerte(encaissement.endurance, over20); - encaissement.loc = rollData.dmg.loc; - encaissement.locName = rollData.dmg.loc.label ?? "Corps"; + 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; + return encaissement; } - /* -------------------------------------------- */ - ajouterBlessure( encaissement ) - { + /* -------------------------------------------- */ + ajouterBlessure(encaissement) { // Fast exit - if ( this.data.type == 'entite') return; // Une entité n'a pas de blessures - if ( encaissement.legeres + encaissement.graves + encaissement.critiques == 0 ) return; + if (this.data.type == 'entite') return; // Une entité n'a pas de blessures + if (encaissement.legeres + encaissement.graves + encaissement.critiques == 0) return; const endActuelle = Number(this.data.data.sante.endurance.value); let blessures = duplicate(this.data.data.blessures); @@ -2245,7 +2243,7 @@ export class RdDActor extends Actor { break; } } - + count = encaissement.graves; while (count > 0) { let grave = blessures.graves.liste.find(it => !it.active); @@ -2253,7 +2251,7 @@ export class RdDActor extends Actor { this._setBlessure(grave, encaissement); count--; } - else{ + else { encaissement.critiques += count; encaissement.graves -= count; encaissement.endurance = -endActuelle; @@ -2261,71 +2259,68 @@ export class RdDActor extends Actor { break; } } - + count = encaissement.critique; - while( count > 0 ) { + while (count > 0) { let critique = blessures.critiques.liste[0]; - if (!critique.active ) { + if (!critique.active) { this._setBlessure(critique, encaissement); count--; } else { // TODO: status effect dead - ChatMessage.create({ content: `${this.name} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !`}); + ChatMessage.create({ content: `${this.name} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !` }); encaissement.critique -= count; break; } } encaissement.endurance = Math.max(encaissement.endurance, -endActuelle); - this.update( { "data.blessures": blessures } ); + this.update({ "data.blessures": blessures }); } - /* -------------------------------------------- */ + /* -------------------------------------------- */ _setBlessure(blessure, encaissement) { blessure.active = true; blessure.loc = encaissement.locName; } - /* -------------------------------------------- */ + /* -------------------------------------------- */ /** @override */ getRollData() { const data = super.getRollData(); return data; } - - /* -------------------------------------------- */ + + /* -------------------------------------------- */ /* -- entites -- */ /* retourne true si on peut continuer, false si on ne peut pas continuer */ - async targetEntiteNonAccordee(target, when='avant-encaissement') - { - if (target) - { + async targetEntiteNonAccordee(target, when = 'avant-encaissement') { + if (target) { return !await this.accorder(target.actor, when); } return false; } - /* -------------------------------------------- */ - async accorder(entite, when = 'avant-encaissement') - { + /* -------------------------------------------- */ + async accorder(entite, when = 'avant-encaissement') { if (when != game.settings.get("foundryvtt-reve-de-dragon", "accorder-entite-cauchemar") - || !entite.isEntiteCauchemar() - || entite.isEntiteCauchemarAccordee(this)) { + || !entite.isEntiteCauchemar() + || entite.isEntiteCauchemarAccordee(this)) { return true; } - - let rolled = await RdDResolutionTable.roll( this.getReveActuel(), - Number(entite.data.data.carac.niveau.value)); + + let rolled = await RdDResolutionTable.roll(this.getReveActuel(), - Number(entite.data.data.carac.niveau.value)); const rollData = { alias: this.name, rolled: rolled, entite: entite.name, - selectedCarac : this.data.data.carac.reve + selectedCarac: this.data.data.carac.reve }; - + if (rolled.isSuccess) { await entite.setEntiteReveAccordee(this); } - + await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.html'); if (rolled.isPart) { await this._appliquerAjoutExperience(rollData, true); @@ -2333,137 +2328,135 @@ export class RdDActor extends Actor { return rolled.isSuccess; } - /* -------------------------------------------- */ - isEntiteCauchemar() - { + /* -------------------------------------------- */ + isEntiteCauchemar() { return this.data.type == 'entite'; } - /* -------------------------------------------- */ - isEntiteCauchemarAccordee(attaquant) - { + /* -------------------------------------------- */ + isEntiteCauchemarAccordee(attaquant) { if (!this.isEntiteCauchemar()) { return true; } let resonnance = this.data.data.sante.resonnance; return (resonnance.actors.find(it => it == attaquant._id)); } - /* -------------------------------------------- */ - async setEntiteReveAccordee(attaquant) - { + /* -------------------------------------------- */ + async setEntiteReveAccordee(attaquant) { 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); - if (resonnance.actors.find(it => it == attaquant._id)){ + if (resonnance.actors.find(it => it == attaquant._id)) { // déjà accordé return; } resonnance.actors.push(attaquant._id); - await this.update( {"data.sante.resonnance": resonnance}); + await this.update({ "data.sante.resonnance": resonnance }); return; } - /* -------------------------------------------- */ - async optimizeArgent( sumDenier ) { + /* -------------------------------------------- */ + async optimizeArgent(sumDenier) { let sols = Math.floor(sumDenier / 100); - let deniers = sumDenier - (sols*100); + let deniers = sumDenier - (sols * 100); let nbOr = Math.floor(sols / 10); - let nbArgent = sols - (nbOr*10); - let nbBronze = Math.floor(deniers / 10 ); - let nbEtain = deniers - (nbBronze*10); + let nbArgent = sols - (nbOr * 10); + let nbBronze = Math.floor(deniers / 10); + let nbEtain = deniers - (nbBronze * 10); // console.log("ARGENT", nbOr, nbArgent, nbBronze, nbEtain); - 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); + 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); } - 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); + 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); } - 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); + 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); } - 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); + 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); } } - /* -------------------------------------------- */ - async payerDenier( sumDenier, dataObj=undefined ) { + /* -------------------------------------------- */ + async payerDenier(sumDenier, dataObj = undefined) { sumDenier = Number(sumDenier); let denierDisponible = 0; - let monnaie = this.data.items.filter( item => item.type =='monnaie'); - for ( let piece of monnaie ) { - denierDisponible += piece.data.valeur_deniers * Number(piece.data.quantite); + let monnaie = this.data.items.filter(item => item.type == 'monnaie'); + for (let piece of monnaie) { + denierDisponible += piece.data.valeur_deniers * Number(piece.data.quantite); } console.log("DENIER", game.user.character, sumDenier, denierDisponible); let msg = ""; - if ( denierDisponible >= sumDenier) { + if (denierDisponible >= sumDenier) { denierDisponible -= sumDenier; this.optimizeArgent(denierDisponible); msg = `Vous avez payé ${sumDenier} Deniers, qui ont été soustraits de votre argent.`; - RdDAudio.PlayContextAudio( "argent"); // Petit son + RdDAudio.PlayContextAudio("argent"); // Petit son } else { - msg = "Vous n'avez pas assez d'argent pour paye cette somme !"; + msg = "Vous n'avez pas assez d'argent pour paye cette somme !"; } - if ( dataObj ) { + if (dataObj) { dataObj.payload.data.cout = sumDenier / 100; // Mise à jour du prix en sols , avec le prix acheté - await this.createOwnedItem( dataObj.payload ); + await this.createOwnedItem(dataObj.payload); msg += `
Et l'objet ${dataObj.payload.name} a été ajouté à votre inventaire.`; } - let message = { - whisper: ChatUtility.getWhisperRecipientsAndGMs( this.name ), - content : msg + let message = { + whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), + content: msg }; - ChatMessage.create( message ); + ChatMessage.create(message); } - /* -------------------------------------------- */ - async monnaieIncDec( id, value) { - let monnaie = this.data.items.find( item => item.type =='monnaie' && item._id == id ); - if (monnaie ) { + /* -------------------------------------------- */ + async monnaieIncDec(id, value) { + let monnaie = this.data.items.find(item => item.type == 'monnaie' && item._id == id); + if (monnaie) { monnaie.data.quantite += value; - 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); + 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); } } - /* -------------------------------------------- */ - 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" ); + /* -------------------------------------------- */ + 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"); let diffAlchimie = RdDAlchimie.getDifficulte(alchimieData); - let rollData = { + let rollData = { recetteName: recette.name, competence: competence, diffLibre: diffAlchimie // Per default at startup } - if ( alchimieName == "couleur") { + if (alchimieName == "couleur") { rollData.selectedCarac = this.data.data.carac.vue, - rollData.alchimieTexte = `Couleurs ${alchimieData} (${diffAlchimie}) (Malus de -4 si vous ne possédez pas de Cristal Alchimique)`; + rollData.alchimieTexte = `Couleurs ${alchimieData} (${diffAlchimie}) (Malus de -4 si vous ne possédez pas de Cristal Alchimique)`; } else { - rollData.selectedCarac = this.data.data.carac.dexterite, - rollData.alchimieTexte = `Consistances ${alchimieData} (${diffAlchimie})`; + rollData.selectedCarac = this.data.data.carac.dexterite, + rollData.alchimieTexte = `Consistances ${alchimieData} (${diffAlchimie})`; } - + const dialog = await RdDRoll.create(this, rollData, - { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html', + { + html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html', }, { name: 'tache-alchimique', @@ -2479,8 +2472,8 @@ export class RdDActor extends Actor { } - /* -------------------------------------------- */ - _alchimieResult( rollData ) { + /* -------------------------------------------- */ + _alchimieResult(rollData) { RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-alchimie.html'); } } diff --git a/module/chat-utility.js b/module/chat-utility.js index 6535d1f1..4649b4cc 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -3,21 +3,20 @@ * Class providing helper methods to get the list of users, and */ export class ChatUtility { + /* -------------------------------------------- */ static removeMyChatMessageContaining(part) { const toDelete = game.messages.filter(it => it.user._id == game.user._id) .filter(it => it.data.content.includes(part)); toDelete.forEach(it => it.delete()); } - /* -------------------------------------------- */ - static chatWithRollMode(chatOptions, name) { - let rollMode = game.settings.get("core", "rollMode"); - ChatUtility.createChatMessage(chatOptions, rollMode, name); + static createChatWithRollMode(name, chatOptions) { + ChatUtility.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions); } /* -------------------------------------------- */ - static createChatMessage(chatOptions, rollMode, name) { + static createChatMessage(name, rollMode, chatOptions) { switch (rollMode) { case "blindroll": // GM only if (!game.user.isGM) { diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 9616299a..14f3966b 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -136,7 +136,6 @@ export class RdDCombat { } const defenderTokenId = event.currentTarget.attributes['data-defenderTokenId'].value; - let defenderRoll = this._getDefense(attackerRoll.passeArme); const armeParadeId = event.currentTarget.attributes['data-armeid']?.value; switch (button) { @@ -150,13 +149,13 @@ export class RdDCombat { () => this.attaqueChanceuse(attackerRoll), () => this._onEchecTotal(attackerRoll)); case '#appel-chance-defense': return this.defender.rollAppelChance( - () => this.defenseChanceuse(attackerRoll, defenderRoll), + () => this.defenseChanceuse(attackerRoll), () => this.afficherOptionsDefense(attackerRoll, { defenseChance: true })); case '#appel-destinee-attaque': return this.attacker.appelDestinee( - () => this.attaqueSignificative(attackerRoll), + () => this.attaqueSignificative(attackerRoll), () => { }); case '#appel-destinee-defense': return this.defender.appelDestinee( - () => this.defenseDestinee(defenderRoll), + () => this.defenseDestinee(attackerRoll), () => { }); } } @@ -194,7 +193,7 @@ export class RdDCombat { } /* -------------------------------------------- */ - defenseChanceuse(attackerRoll, defenderRoll) { + defenseChanceuse(attackerRoll) { ui.notifications.info("La défense est rejouée grâce à la chance") attackerRoll.essais.defenseChance = true; attackerRoll.essais.defense = false; @@ -203,15 +202,21 @@ export class RdDCombat { } /* -------------------------------------------- */ - defenseDestinee(defenderRoll) { - ui.notifications.info('Défense significative grâce à la destinée') - RdDResolutionTable.forceSignificative(defenderRoll.rolled); - this.removeChatMessageActionsPasseArme(defenderRoll.passeArme); - if (defenderRoll.arme) { - this._onParadeNormale(defenderRoll); + defenseDestinee(attackerRoll) { + let defenderRoll = this._getDefense(attackerRoll.passeArme); + if (defenderRoll) { + ui.notifications.info('Défense significative grâce à la destinée') + RdDResolutionTable.forceSignificative(defenderRoll.rolled); + this.removeChatMessageActionsPasseArme(defenderRoll.passeArme); + if (defenderRoll.arme) { + this._onParadeNormale(defenderRoll); + } + else { + this._onEsquiveNormale(defenderRoll); + } } else { - this._onEsquiveNormale(defenderRoll); + ui.notifications.warn("Appel à la destinée impossible, la passe d'armes est déjà terminée!") } } @@ -223,7 +228,7 @@ export class RdDCombat { /* -------------------------------------------- */ removeChatMessageActionsPasseArme(passeArme) { - if (game.settings.get("foundryvtt-reve-de-dragon", "supprimer-dialogues-combat-chat")){ + if (game.settings.get("foundryvtt-reve-de-dragon", "supprimer-dialogues-combat-chat")) { ChatUtility.removeMyChatMessageContaining(`
`); } } @@ -296,7 +301,7 @@ export class RdDCombat { competence: competence, surprise: this.attacker.getSurprise(), surpriseDefenseur: this.defender.getSurprise(), - essais: { } + essais: {} }; if (this.attacker.isCreature()) { @@ -359,7 +364,7 @@ export class RdDCombat { console.log("RdDCombat._sendMessageDefense", attackerRoll, essais, " / ", this.attacker, this.target, this.attackerId, attackerRoll.competence.data.categorie); this.removeChatMessageActionsPasseArme(attackerRoll.passeArme); - mergeObject(attackerRoll.essais, essais, {overwrite: true}); + mergeObject(attackerRoll.essais, essais, { overwrite: true }); const paramDemandeDefense = { passeArme: attackerRoll.passeArme, essais: attackerRoll.essais, @@ -417,9 +422,9 @@ export class RdDCombat { const arme = rollData.arme; const avecArme = arme?.data.categorie_parade != 'sans-armes'; const action = (rollData.attackerRoll ? (arme ? "la parade" : "l'esquive") : "l'attaque"); - ChatUtility.chatWithRollMode({ + ChatUtility.createChatWithRollMode(this.defender.name, { content: `Echec total à ${action}! ` + await RdDRollTables.getMaladresse({ arme: avecArme }) - }, this.defender.name) + }); } /* -------------------------------------------- */ @@ -489,45 +494,45 @@ export class RdDCombat { } /* -------------------------------------------- */ - _getDiviseurSignificative(rollData) { - let facteurSign = (this.defender.isDemiSurprise() || rollData.needParadeSignificative) ? 2 : 1; - if (RdDBonus.isDefenseAttaqueFinesse(rollData)) { + _getDiviseurSignificative(defenderRoll) { + let facteurSign = (this.defender.isDemiSurprise() || defenderRoll.needParadeSignificative) ? 2 : 1; + if (RdDBonus.isDefenseAttaqueFinesse(defenderRoll)) { facteurSign *= 2; } return facteurSign; } /* -------------------------------------------- */ - _onParadeParticuliere(rollData) { - console.log("RdDCombat._onParadeParticuliere >>>", rollData); - if (!rollData.attackerRoll.isPart) { + _onParadeParticuliere(defenderRoll) { + console.log("RdDCombat._onParadeParticuliere >>>", defenderRoll); + if (!defenderRoll.attackerRoll.isPart) { // TODO: attaquant doit jouer résistance et peut être désarmé p132 - ChatUtility.chatWithRollMode({ + ChatUtility.createChatWithRollMode(this.defender.name, { content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` - }, this.defender.name) + }); } } /* -------------------------------------------- */ - async _onParadeNormale(rollData) { - console.log("RdDCombat._onParadeNormale >>>", rollData); + async _onParadeNormale(defenderRoll) { + console.log("RdDCombat._onParadeNormale >>>", defenderRoll); - this._consumeDefense(rollData.passeArme); - await this.computeRecul(rollData); - await this.computeDeteriorationArme(rollData); + this._consumeDefense(defenderRoll.passeArme); + await this.computeRecul(defenderRoll); + await this.computeDeteriorationArme(defenderRoll); - await RdDResolutionTable.displayRollData(rollData, this.defender, 'chat-resultat-parade.html'); + await RdDResolutionTable.displayRollData(defenderRoll, this.defender, 'chat-resultat-parade.html'); } /* -------------------------------------------- */ - async _onParadeEchec(rollData) { - console.log("RdDCombat._onParadeEchec >>>", rollData); + async _onParadeEchec(defenderRoll) { + console.log("RdDCombat._onParadeEchec >>>", defenderRoll); - await RdDResolutionTable.displayRollData(rollData, this.defender, 'chat-resultat-parade.html'); + await RdDResolutionTable.displayRollData(defenderRoll, this.defender, 'chat-resultat-parade.html'); - this.removeChatMessageActionsPasseArme(rollData.passeArme); - this._sendMessageDefense(rollData.attackerRoll, { defense: true }); - this._storeDefense(rollData); + this.removeChatMessageActionsPasseArme(defenderRoll.passeArme); + this._sendMessageDefense(defenderRoll.attackerRoll, { defense: true }); + this._storeDefense(defenderRoll); } /* -------------------------------------------- */ @@ -579,10 +584,9 @@ export class RdDCombat { /* -------------------------------------------- */ _onEsquiveParticuliere(rollData) { console.log("RdDCombat._onEsquiveParticuliere >>>", rollData); - let chatOptions = { + ChatUtility.createChatWithRollMode(this.defender.name, { content: "Vous pouvez esquiver une deuxième esquive!" - } - ChatUtility.chatWithRollMode(chatOptions, this.defender.name) + }); } /* -------------------------------------------- */ @@ -651,11 +655,11 @@ export class RdDCombat { } } /* -------------------------------------------- */ - async computeRecul(rollData) { // Calcul du recul (p. 132) - const attaque = rollData.attackerRoll; - if (this._isAttaqueCauseRecul(attaque)) { + async computeRecul(defenderRoll) { // Calcul du recul (p. 132) + const attackerRoll = defenderRoll.attackerRoll; + if (this._isAttaqueCauseRecul(attackerRoll)) { - let impactRecul = this._computeImpactRecul(attaque); + let impactRecul = this._computeImpactRecul(attackerRoll); const agilite = this.defender.isEntiteCauchemar() ? this.defender.data.data.carac.reve.value : this.defender.data.data.carac.agilite.value; @@ -663,13 +667,13 @@ export class RdDCombat { let rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impactRecul, showDice: false }); if (rollRecul.isSuccess) { - rollData.show.recul = 'encaisse'; + defenderRoll.show.recul = 'encaisse'; } else if (rollRecul.isETotal) { - rollData.show.recul = 'chute'; + defenderRoll.show.recul = 'chute'; } else { let chute = await RdDResolutionTable.rollData({ caracValue: agilite, finalLevel: impactRecul, showDice: false }); - rollData.show.recul = (chute.isSuccess) + defenderRoll.show.recul = (chute.isSuccess) ? 'recul' : 'chute'; } @@ -696,7 +700,13 @@ export class RdDCombat { console.log("RdDCombat.encaisser >>>", attackerRoll, defenderTokenId); let defenderRoll = this._consumeDefense(attackerRoll.passeArme); - if (defenderRoll && RdDCombat.isEchecTotal(defenderRoll)) { + if (!defenderRoll) { + defenderRoll = { + attackerRoll: attackerRoll, + show: {} + }; + } + else if (RdDCombat.isEchecTotal(defenderRoll)) { // TODO: echec total!!! this._onEchecTotal(defenderRoll); } @@ -746,7 +756,6 @@ export class RdDCombat { /* -------------------------------------------- */ static async displayActorCombatStatus(actor) { - let rollMode = game.settings.get("core", "rollMode"); let rollData = { alias: actor.name, etatGeneral: actor.getEtatGeneral(), @@ -762,8 +771,9 @@ export class RdDCombat { } else if (actor.countBlessuresByName("graves") > 0) { rollData.isGrave = true; } - let content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, rollData); - ChatUtility.createChatMessage({ content: content }, rollMode, actor.name); + ChatUtility.createChatWithRollMode(actor.name, { + content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, rollData) + }); } /* -------------------------------------------- */ diff --git a/module/rdd-commands.js b/module/rdd-commands.js index 6cc330de..53385113 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -69,7 +69,7 @@ export class RdDCommands { return; } const term = path[0]; - fullPath = fullPath+term+' ' + fullPath = fullPath + term + ' ' if (path.length == 1) { command.descr = `${fullPath}: ${command.descr}`; targetTable[term] = command; @@ -192,15 +192,14 @@ export class RdDCommands { }; await RdDResolutionTable.rollData(rollData); msg.content = await RdDResolutionTable.buildRollDataHtml(rollData); - ChatUtility.chatWithRollMode(msg, game.user.name); + ChatUtility.createChatWithRollMode(game.user.name, msg); } async rollDeDraconique(msg) { - let rollMode = game.settings.get("core", "rollMode"); let ddr = new DeDraconique().evaluate(); await RdDDice.show(ddr, rollMode); msg.content = `Lancer d'un Dé draconique: ${ddr.total}`; - ChatUtility.createChatMessage(msg, rollMode, game.user.name); + ChatUtility.createChatWithRollMode(game.user.name, msg); } } diff --git a/module/rdd-dice.js b/module/rdd-dice.js index e98e7241..81d41057 100644 --- a/module/rdd-dice.js +++ b/module/rdd-dice.js @@ -15,7 +15,7 @@ export class RdDDice { if (game.modules.get("dice-so-nice") && game.modules.get("dice-so-nice").active) { let whisper = null; let blind = false; - rollMode = rollMode || game.settings.get("core", "rollMode"); + rollMode = rollMode ?? game.settings.get("core", "rollMode"); switch (rollMode) { case "blindroll": //GM only blind = true; diff --git a/module/rdd-resolution-table.js b/module/rdd-resolution-table.js index 83dff5b7..fd516b21 100644 --- a/module/rdd-resolution-table.js +++ b/module/rdd-resolution-table.js @@ -91,9 +91,9 @@ export class RdDResolutionTable { /* -------------------------------------------- */ static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.html') { - ChatUtility.chatWithRollMode( - { content: await RdDResolutionTable.buildRollDataHtml(rollData, actor, template) }, - actor?.userName ?? game.user.name) + ChatUtility.createChatWithRollMode(actor?.userName ?? game.user.name, { + content: await RdDResolutionTable.buildRollDataHtml(rollData, actor, template) + }); } /* -------------------------------------------- */ @@ -139,7 +139,7 @@ export class RdDResolutionTable { } } static forceSignificative(chances) { - chances.roll = Math.floor(chances.score /2); + chances.roll = Math.floor(chances.score / 2); mergeObject(chances, reussites.find(x => x.code == 'sign'), { overwrite: true }); } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index e10e776e..7b263dff 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -98,25 +98,25 @@ const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "C /* -------------------------------------------- */ const definitionsEncaissement = { "mortel": [ - { minimum: undefined, maximum: 0, endurance: "0", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", legeres: 1, graves: 0, critiques: 0 }, - { minimum: 16, maximum: 19, endurance: "2d6", vie: "2", legeres: 0, graves: 1, critiques: 0 }, - { minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", legeres: 0, graves: 0, critiques: 1 }, + { minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 }, + { minimum: 16, maximum: 19, endurance: "2d6", vie: "2", eraflures: 0, legeres: 0, graves: 1, critiques: 0 }, + { minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", eraflures: 0, legeres: 0, graves: 0, critiques: 1 }, ], "non-mortel": [ - { minimum: undefined, maximum: 0, endurance: "0", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", legeres: 1, graves: 0, critiques: 0 }, - { minimum: 20, maximum: undefined, endurance: "100", vie: "1", legeres: 1, graves: 0, critiques: 0 }, + { minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 }, + { minimum: 20, maximum: undefined, endurance: "100", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 }, ], "cauchemar": [ - { minimum: undefined, maximum: 0, endurance: "0", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", legeres: 0, graves: 0, critiques: 0 }, - { minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", legeres: 0, graves: 0, critiques: 0 }, + { minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, + { minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 }, ] }; @@ -193,6 +193,7 @@ export class RdDUtility { 'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-appelchance.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-attaque.html', + 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-parade.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-esquive.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-competence.html', @@ -260,14 +261,14 @@ export class RdDUtility { } /* -------------------------------------------- */ - static async processItemDropEvent( actorSheet, event) { + static async processItemDropEvent(actorSheet, event) { let dragData = JSON.parse(event.dataTransfer.getData("text/plain")); console.log(dragData, actorSheet.actor._id); let dropID = $(event.target).parents(".item").attr("data-item-id"); // Only relevant if container drop let objetId = dragData.id || dragData.data._id; if ( dropID ) { // Dropped over an item !!! - if ( actorSheet.objetVersConteneur[objetId] != dropID && objetId != dropID) { - if ( actorSheet.actor.validateConteneur(objetId, dropID) && actorSheet.actor.testConteneurCapacite(objetId, dropID) ) { + if (actorSheet.objetVersConteneur[objetId] != dropID && objetId != dropID) { + if (actorSheet.actor.validateConteneur(objetId, dropID) && actorSheet.actor.testConteneurCapacite(objetId, dropID)) { await actorSheet.actor.enleverDeConteneur(objetId, actorSheet.objetVersConteneur[objetId]); await actorSheet.actor.ajouterAConteneur(objetId, dropID); } @@ -281,9 +282,9 @@ export class RdDUtility { actorSheet.actor.computeEncombrementTotalEtMalusArmure(); return true; } - + /* -------------------------------------------- */ - static buildArbreDeConteneur( actorSheet, data ) { + static buildArbreDeConteneur(actorSheet, data) { actorSheet.objetVersConteneur = {}; // Table de hash locale pour recupération rapide du conteneur parent (si existant) // Attribution des objets aux conteneurs for (let conteneur of data.data.conteneurs) { @@ -551,10 +552,10 @@ export class RdDUtility { /* -------------------------------------------- */ static _evaluatePerte(formula, over20) { - console.log("_evaluatePerte", formula, over20) - let perte = new Roll(formula, { over20: over20 }) - perte.evaluate() - return perte.total + console.log("_evaluatePerte", formula, over20); + let perte = new Roll(formula, { over20: over20 }); + perte.evaluate(); + return perte.total; } /* -------------------------------------------- */ diff --git a/templates/chat-demande-defense.html b/templates/chat-demande-defense.html index 2fdfdd8d..b3117441 100644 --- a/templates/chat-demande-defense.html +++ b/templates/chat-demande-defense.html @@ -2,7 +2,7 @@ {{#if (eq surprise 'totale')}} {{defender.name}} est totalement surpris {{else if essais.defense}} - {{defender.name}} doit + {{defender.name}} doit : {{else}} {{defender.name}} doit se défendre {{#if (eq surprise 'demi')}} avec une significative {{/if}} : @@ -12,7 +12,6 @@
{{#unless (eq surprise 'totale')}} {{#if essais.defense}} -
{{#unless essais.defenseChance}} {{#if (eq defender.data.type 'personnage')}}
{{/if}} - {{/unless}} - {{#if (eq defender.data.type 'personnage')}} + {{#if (eq defender.data.type 'personnage')}} {{#if (gt defender.data.data.compteurs.destinee.value 0)}}
Utiliser la destinée
{{/if}} - {{/if}} + {{/if}} + {{/unless}} {{else}} {{#each armes as |arme key|}} diff --git a/templates/chat-resultat-encaissement.html b/templates/chat-resultat-encaissement.html new file mode 100644 index 00000000..8413dd3e --- /dev/null +++ b/templates/chat-resultat-encaissement.html @@ -0,0 +1,42 @@ +{{#if isGM}} + + {{#if (gt endurance 0)}} + De plus, {{alias}} a perdu {{endurance}} points d'endurance + {{#if (ne vie 0)}}et {{vie}} points de vie{{/if}} + {{/if}} + +{{else}} +

{{alias}} encaisse à + + {{numberFormat dmg.total decimals=0 sign=true}} + {{#if (eq dmg.mortalite 'non-mortel')~}}(coups non mortels) + {{~else if (eq dmg.mortalite 'cauchemar')}}(entité de cauchemar) + {{~/if}} + +

+
+ Je d'encaissement de {{roll.total}} + {{#unless (eq armure 0)}}, l'armure a protègé de {{armure}} {{#unless (eq penetration 0)}}(pénétration de {{penetration}}) + {{/unless}} + {{/unless}}, total: {{total}} +
+ {{alias}} subit + {{#if (gt eraflures 0)}}une contusion + {{else if (gt legeres 0)}}une blessure légère + {{else if (gt graves 0)}}une blessure grave + {{else if (gt critique 0)}}une blessure critique + {{else}}Rien du tout + {{/if}} + + ({{dmg.loc.label}}) + {{#if (gt endurance 0)}} + {{#if hasPlayerOwner}}, a perdu {{endurance}} points d'endurance + {{#if (ne vie 0)}}, {{vie}} points de vie{{/if}} + {{/if}} + {{#if (gt endurance 1)}} + et {{#if sonne}}est sonnécharge jusqu'à la fin du prochain round{{else}}n'est pas sonné{{/if}} + ({{jetEndurance}} / {{resteEndurance}})! + {{/if}} + {{/if}} +
+{{/if}} \ No newline at end of file