diff --git a/module/actor.js b/module/actor.js index 0defc7d9..8709a331 100644 --- a/module/actor.js +++ b/module/actor.js @@ -57,10 +57,10 @@ export class RdDActor extends Actor { } static remoteActorCall(data) { - if (Misc.isElectedUser()){ + if (Misc.isElectedUser()) { RdDActor.onRemoteActorCall(data); } - else{ + else { game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_remote_actor_call", data: data }); } } @@ -833,14 +833,14 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async updateCompetenceXP(compName, compValue) { + async updateCompetenceXP(compName, newXp) { let comp = this.getCompetence(compName); if (comp) { - compValue = compValue ?? 0; - this.checkCompetenceXP(compName, compValue); - const update = { _id: comp.id, 'data.xp': compValue }; + newXp = newXp ?? 0; + this.checkCompetenceXP(compName, newXp); + const update = { _id: comp.id, 'data.xp': newXp }; await this.updateEmbeddedDocuments('Item', [update]); // Updates one EmbeddedEntity - this.updateExperienceLog("XP Compétence", compValue, "XP attribués en " + compName); + this.updateExperienceLog("XP Compétence", newXp, "XP attribués en " + compName); } else { console.log("Competence not found", compName); } @@ -873,20 +873,22 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async updateExperienceLog( modeXP, valeurXP, raisonXP = 'Inconnue') { + async updateExperienceLog(modeXP, valeurXP, raisonXP = 'Inconnue') { let d = new Date(); - console.log( modeXP, valeurXP, raisonXP); - let expLog = duplicate( (Misc.templateData(this)).experiencelog ); - expLog.push( { mode: Misc.upperFirst(modeXP), valeur: valeurXP, raison: Misc.upperFirst(raisonXP), - daterdd : game.system.rdd.calendrier.getDateFromIndex(), datereel: `${d.getDate()}/${d.getMonth()+1}/${d.getFullYear()}` } ); - await this.update({ [`data.experiencelog`]: expLog } ); + console.log(modeXP, valeurXP, raisonXP); + let expLog = duplicate((Misc.templateData(this)).experiencelog); + expLog.push({ + mode: Misc.upperFirst(modeXP), valeur: valeurXP, raison: Misc.upperFirst(raisonXP), + daterdd: game.system.rdd.calendrier.getDateFromIndex(), datereel: `${d.getDate()}/${d.getMonth() + 1}/${d.getFullYear()}` + }); + await this.update({ [`data.experiencelog`]: expLog }); console.log("Add XP log", expLog); } /* -------------------------------------------- */ async updateCompteurValue(fieldName, fieldValue, raison = 'Inconnue') { await this.update({ [`data.compteurs.${fieldName}.value`]: fieldValue }); - if ( fieldName == 'stress') { + if (fieldName == 'stress') { await this.updateExperienceLog('stress', fieldValue, raison); } } @@ -894,12 +896,12 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async addCompteurValue(fieldName, fieldValue, raison = 'Inconnue') { let oldValue = (Misc.templateData(this)).compteurs[fieldName].value; - await this.update({ [`data.compteurs.${fieldName}.value`]: Number(oldValue) + Number(fieldValue) } ); - if ( fieldName == 'stress') { - await this.updateExperienceLog('stress', fieldValue, raison ); + await this.update({ [`data.compteurs.${fieldName}.value`]: Number(oldValue) + Number(fieldValue) }); + if (fieldName == 'stress') { + await this.updateExperienceLog('stress', fieldValue, raison); } } - + /* -------------------------------------------- */ async updateAttributeValue(fieldName, fieldValue) { await this.update({ [`data.attributs.${fieldName}.value`]: fieldValue }); @@ -1938,8 +1940,8 @@ export class RdDActor extends Actor { compteurs.dissolution.value = dissolution - perteDissolution; compteurs.exaltation.value = 0; await this.update({ "data.compteurs": compteurs }); - - this.updateExperienceLog( 'XP', stressRollData.xp, "Transformation du stress"); + + this.updateExperienceLog('XP', stressRollData.xp, "Transformation du stress"); } /* -------------------------------------------- */ @@ -1974,7 +1976,7 @@ export class RdDActor extends Actor { createCallbackExperience() { return { condition: r => r.rolled.isPart && r.finalLevel < 0 && game.settings.get("core", "rollMode") != 'selfroll', - action: r => this._appliquerAjoutExperience(r, game.settings.get("core", "rollMode") != 'blindroll') + action: r => this.appliquerAjoutExperience(r, game.settings.get("core", "rollMode") != 'blindroll') }; } @@ -1987,29 +1989,33 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async checkCaracXP(caracName) { - let carac = Misc.templateData(this).carac[caracName]; + async checkCaracXP(caracName, display = true) { + let carac = RdDActor._findCaracByName(Misc.templateData(this).carac, caracName); if (carac && carac.xp > 0) { - let xpNeeded = RdDCarac.getCaracNextXp(carac.value + 1); + const niveauSuivant = Number(carac.value) + 1; + let xpNeeded = RdDCarac.getCaracNextXp(niveauSuivant); if (carac.xp >= xpNeeded) { carac = duplicate(carac); - carac.value = Number(carac.value) + 1; + carac.value = niveauSuivant; - let xpData = { + let checkXp = { alias: this.name, carac: caracName, - value: carac.value, + value: niveauSuivant, xp: carac.xp } - ChatUtility.createChatMessage(this.name, "default", { - content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html`, xpData) - }); + if (display){ + ChatUtility.createChatMessage(this.name, "default", { + content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html`, checkXp) + }); + } + return checkXp; } } } /* -------------------------------------------- */ - async checkCompetenceXP(compName, newXP = undefined) { + async checkCompetenceXP(compName, newXP, display = true) { let compData = Misc.data(this.getCompetence(compName)); if (compData && newXP && newXP == compData.data.xp) { // Si édition, mais sans changement XP return; @@ -2021,8 +2027,7 @@ export class RdDActor extends Actor { let newCompData = duplicate(compData); newCompData.data.niveau += 1; newCompData.data.xp = newXP; - - let xpData = { + let checkXp = { alias: this.name, competence: newCompData.name, niveau: newCompData.data.niveau, @@ -2030,33 +2035,30 @@ export class RdDActor extends Actor { archetype: newCompData.data.niveau_archetype, archetypeWarning: newCompData.data.niveau > compData.data.niveau_archetype } - ChatUtility.createChatMessage(this.name, "default", { - content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html`, xpData) - }); + if (display) { + ChatUtility.createChatMessage(this.name, "default", { + content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html`, checkXp) + }); + } + return checkXp; } } } /* -------------------------------------------- */ - async _appliquerAjoutExperience(rollData, display = true) { + async appliquerAjoutExperience(rollData, display) { if (!this.isPersonnage()) return; - 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 xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence); + if (!xpData) { + return; + } + if (display) { let message = { - whisher: ChatMessage.getWhisperRecipients(["GM", this.name]), - content: "" + rollData.selectedCarac.label + "" + xpmsg, + whisher: ChatUtility.getWhisperRecipientsAndGMs(this.name), + content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.html`, xpData) } ChatMessage.create(message); } - if (xpResult && xpResult.xpComp > 0 && rollData.competence) { - this.checkCompetenceXP(rollData.competence.name); - this.updateExperienceLog("XP", xpResult.xpComp,"XP en compétence "+rollData.competence.name); - } - if (xpResult && xpResult.xpCarac > 0 && rollData.selectedCarac) { - this.checkCaracXP(rollData.selectedCarac.name); - this.updateExperienceLog("XP", xpResult.xpCarac,"XP en carac "+rollData.selectedCarac.name); - } } /* -------------------------------------------- */ @@ -2780,47 +2782,64 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async appliquerExperience(rolled, caracName, competence = undefined) { + async _appliquerExperience(rolled, caracName, competence) { if (!this.isPersonnage()) return; - 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 (caracName == 'Vie') caracName = 'constitution'; - if (caracName == 'derobee') caracName = 'agilite'; - if (caracName == 'reve-actuel') caracName = 'reve'; - let xp = Math.abs(rolled.finalLevel); - let xpCarac = Math.floor(xp / 2); // impair: arrondi inférieur en carac - let xpComp = 0; - if (competence) { - xpComp = xp - xpCarac; - let update = { _id: competence.id, 'data.xp': Misc.toInt(competence.data.xp) + xpComp }; - await this.updateEmbeddedDocuments('Item', [update]); - } else { - xpCarac = Math.max(xpCarac, 1); - } - if (xpCarac > 0) { - let carac = duplicate(Misc.templateData(this).carac); - let selectedCarac = RdDActor._findCaracByName(carac, caracName); - if (!selectedCarac.derivee) { - selectedCarac.xp = Misc.toInt(selectedCarac.xp) + xpCarac; - await this.update({ "data.carac": carac }); - } else { - ChatMessage.create({ - content: `Vous avez ${xpCarac} à répartir pour la caractéristique dérivée ${caracName}. Vous devez le faire manuellement.`, - whisper: ChatMessage.getWhisperRecipients(game.user.name) - }); - } - } - return { result: true, xpCarac: xpCarac, xpCompetence: xpComp }; //XP + // Pas d'XP + if (!rolled.isPart || rolled.finalLevel >= 0) { + return undefined; + } + if (this.checkDesirLancinant()) { + // Cas de désir lancinant, pas d'expérience sur particulière + 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 undefined; + } + if (caracName == 'Vie') caracName = 'constitution'; + if (caracName == 'derobee') caracName = 'agilite'; + if (caracName == 'reve-actuel') caracName = 'reve'; + + let xp = Math.abs(rolled.finalLevel); + // impair: arrondi inférieur en carac + let xpCarac = competence ? Math.floor(xp / 2) : Math.max(Math.floor(xp / 2), 1); + + let xpData = { + alias: this.name, + caracName: caracName, xpCarac: xpCarac, + competence: competence, xpCompetence: competence ? xp - xpCarac : 0 + }; + + await this._xpCompetence(xpData); + await this._xpCarac(xpData); + return xpData; + } + + /* -------------------------------------------- */ + async _xpCompetence(xpData) { + if (xpData.competence) { + const newXp = Misc.toInt(xpData.competence.data.xp) + xpData.xpCompetence; + let update = { _id: xpData.competence._id, 'data.xp': newXp }; + await this.updateEmbeddedDocuments('Item', [update]); + xpData.checkComp = await this.checkCompetenceXP(xpData.competence.name, undefined, false); + this.updateExperienceLog("XP", xpData.xp, "XP en compétence " + xpData.competence.name); + } + } + + /* -------------------------------------------- */ + async _xpCarac(xpData) { + if (xpData.xpCarac > 0) { + let carac = duplicate(Misc.templateData(this).carac); + let selectedCarac = RdDActor._findCaracByName(carac, xpData.caracName); + if (!selectedCarac.derivee) { + selectedCarac.xp = Misc.toInt(selectedCarac.xp) + xpData.xpCarac; + await this.update({ "data.carac": carac }); + xpData.checkCarac = await this.checkCaracXP(selectedCarac.label, false); + this.updateExperienceLog("XP", xpData.xpCarac, "XP en carac " + xpData.caracName); + } else { + xpData.caracRepartitionManuelle = true; + } } - return { result: false, xpCarac: 0, xpCompetence: 0 }; // Pas d'XP } /* -------------------------------------------- */ @@ -2828,7 +2847,7 @@ export class RdDActor extends Actor { // Gestion expérience (si existante) data.competence = Misc.data(this.getCompetence("astrologie")); data.selectedCarac = Misc.templateData(this).carac["vue"]; - this._appliquerAjoutExperience(data); + this.appliquerAjoutExperience(data, false); // Ajout du nombre astral const item = { @@ -2855,14 +2874,14 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ getCaracByName(caracName) { - switch (caracName) { - case 'reve-actuel': case 'Rêve actuel': + switch (Grammar.toLowerCaseNoAccent(caracName)) { + case 'reve-actuel': case 'reve actuel': return { label: 'Rêve actuel', value: this.getReveActuel(), type: "number" }; - case 'chance-actuelle': case 'Chance actuelle': + case 'chance-actuelle': case 'chance-actuelle': return { label: 'Chance actuelle', value: this.getChanceActuel(), @@ -2891,11 +2910,6 @@ export class RdDActor extends Actor { if (keys.length > 0) { return carac[keys[0]]; } - // for (const [key, value] of Object.entries(carac)) { - // if (key.includes(name) || Grammar.toLowerCaseNoAccent(value.label).includes('name')) { - // return carac[key]; - // } - // } return undefined; // Per default } @@ -2925,12 +2939,12 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async displayTMR(mode = "normal") { - let demiReve = this.listeEffets( it => it.label == "Demi-rêve"); - if ( mode != 'visu' && demiReve.length > 0 ) { + let demiReve = this.listeEffets(it => it.label == "Demi-rêve"); + if (mode != 'visu' && demiReve.length > 0) { ui.notifications.warn("Le joueur ou le MJ est déja dans les Terres Médianes avec ce personnage ! Visualisation uniquement"); mode = "visu"; // bascule le mode en visu automatiquement } - + let isRapide = mode == "rapide"; if (mode != "visu") { let minReveValue = (isRapide && !EffetsDraconiques.isDeplacementAccelere(this) ? 3 : 2) + this.countMonteeLaborieuse(); @@ -3280,7 +3294,7 @@ export class RdDActor extends Actor { await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.html'); if (rolled.isPart) { - await this._appliquerAjoutExperience(rollData, true); + await this.appliquerAjoutExperience(rollData, true); } return rolled.isSuccess; } @@ -3908,10 +3922,10 @@ export class RdDActor extends Actor { const ids = Array.from(this.effects?.values()) .filter(it => StatusEffects.statusId(it.data) == StatusEffects.statusId(effect)) .map(it => it.id); - //console.log("Delete effect 1: ", this.effects, ids); - if (ids.length > 0) { - await this.deleteEmbeddedDocuments('ActiveEffect', ids); - } + //console.log("Delete effect 1: ", this.effects, ids); + if (ids.length > 0) { + await this.deleteEmbeddedDocuments('ActiveEffect', ids); + } } /* -------------------------------------------- */ @@ -3928,7 +3942,7 @@ export class RdDActor extends Actor { //effet.flags.core.statusId = effet.id; let effectArray = await this.createEmbeddedDocuments('ActiveEffect', [effet]); if (effectArray[0]) { - await effectArray[0].setFlag( 'core', 'statusId', effet.id); + await effectArray[0].setFlag('core', 'statusId', effet.id); } } diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index 34d20e6e..deb5c9dd 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -386,6 +386,7 @@ export class RdDTMRDialog extends Dialog { rencontre: this.currentRencontre, nbRounds: 1, canClose: false, + selectedCarac: {label: "reve-actuel"}, tmr: TMRUtility.getTMR(this._getActorCoord()) } @@ -393,7 +394,7 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async _tentativeMaitrise(rencData, presentCite) { + async _tentativeMaitrise(rencData) { console.log("-> matriser", rencData); rencData.reve = this.actor.getReveActuel(); diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js index eea11c27..85c12887 100644 --- a/module/tmr-rencontres.js +++ b/module/tmr-rencontres.js @@ -473,7 +473,7 @@ export class TMRRencontres { /* -------------------------------------------- */ static async onPostSuccessReveDeDragon(tmrDialog, tmrData) { if (tmrData.rolled.isPart) { - await tmrData.actor.appliquerExperience(tmrData.rolled, 'reve', tmrData.competence); + await tmrData.actor.appliquerAjoutExperience(tmrData, true); } await tmrData.actor.resultCombatReveDeDragon(tmrData); } diff --git a/templates/chat-actor-gain-xp.html b/templates/chat-actor-gain-xp.html new file mode 100644 index 00000000..ec447eba --- /dev/null +++ b/templates/chat-actor-gain-xp.html @@ -0,0 +1,26 @@ +

{{alias}} a gagné de l'expérience en {{caracName}}{{#if competence}} / {{competence.name}}{{/if}}!

+{{#if (gt xpCarac 0)}} +
+ {{xpCarac}} point{{#if (gt xpCarac 1)}}s{{/if}} + {{#if caracRepartitionManuelle}}à répartir manuellement dans la caractéristique dérivée{{else}}en{{/if}} + {{caracName}}. + {{#if checkCarac}} + L'expérience dans cette caractéristique est de {{checkCarac.xp}}, elle peut progresser! +
Vous devez ouvrir votre fiche de personnage et appliquer (ou pas) l'augmentation manuellement. + {{/if}} +{{/if}} + +{{#if (gt xpCompetence 0)}} +
+ {{xpCompetence}} point{{#if (gt xpCompetence 1)}}s{{/if}} en {{competence.name}}. + {{#if checkComp}} + L'expérience dans cette compétence est de {{checkComp.xp}}, elle peut progresser jusqu'à {{checkComp.niveau}}! + Vous devez ouvrir votre fiche de personnage et appliquer l'augmentation manuellement. + {{#if (gt checkComp.niveau checkComp.archetype)}}
Le niveau d'archétype est de {{checkComp.archetype}}. + {{#if checkComp.archetypeWarning}} +
ATTENTION !! Si vous appliquez cette augmentation, votre compétence dépassera l'archétype. + Veuillez contrôler que votre archétype est à jour, ou bien ne pas augmenter le niveau de cette compétence. + {{/if}} + {{/if}} + {{/if}} +{{/if}}