diff --git a/changelog.md b/changelog.md index 4f2024f6..b358b54c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,17 @@ # 12.0 +## 12.0.7 - La propriété d'Astrobazzarh +- correction des opérations faites à la création d'un Item: + - la durée des queues/rencontres/souffles + - les effets draconiques d'un souffle/queue + - mise à jour des points de tâche des blessures lors des soins +- pas d'expérience sur les particulières quand aucun MJ n'est connecté +- Le drag&drop d'un acteur depuis la liste des acteurs sur la fiche + d'une entité incarnée permet d'accorder le personnage +- Les messages pour résister aux possessions/conjuration sont envoyées + au défenseur +- Les messages pour résister aux empoignades sont envoyées au défenseur +- la commande /voyage affiche maintenant le total de fatigue pour chaque voyageur +- la commande /voyage affiche maintenant les compétences liées au terrain ## 12.0.6 - Le bazar d'Astrobazzarh - Corrections de l'inventaire en bazar: diff --git a/module/actor.js b/module/actor.js index cc07498b..e8c87a07 100644 --- a/module/actor.js +++ b/module/actor.js @@ -1548,6 +1548,9 @@ export class RdDActor extends RdDBaseActorSang { /* -------------------------------------------- */ async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { + if (!Misc.firstConnectedGM()){ + return + } hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence, rollData.jetResistance); if (xpData.length) { diff --git a/module/actor/base-actor-reve.js b/module/actor/base-actor-reve.js index 840e6adf..f2a9205c 100644 --- a/module/actor/base-actor-reve.js +++ b/module/actor/base-actor-reve.js @@ -508,8 +508,8 @@ export class RdDBaseActorReve extends RdDBaseActor { isEntiteAccordee(attacker) { return true } - async setEntiteReveAccordee(attacker) { - ui.notifications.error("Impossible de s'accorder à " + this.name + ": ce n'est pas une entite de cauchemer/rêve"); + async setEntiteReveAccordee(actor) { + ui.notifications.error("Impossible de s'accorder à " + this.name + ": ce n'est pas une entité incarnée"); } } diff --git a/module/actor/creature.js b/module/actor/creature.js index b50c1e43..67b36168 100644 --- a/module/actor/creature.js +++ b/module/actor/creature.js @@ -33,27 +33,4 @@ export class RdDCreature extends RdDBaseActorSang { } } - isEntiteAccordee(attacker) { - if (this.isEntite([ENTITE_INCARNE])) { - let resonnance = this.system.sante.resonnance - return (resonnance.actors.find(it => it == attacker.id)) - } - return true - } - - /* -------------------------------------------- */ - async setEntiteReveAccordee(attacker) { - if (this.isEntite([ENTITE_INCARNE])) { - let resonnance = foundry.utils.duplicate(this.system.sante.resonnance); - if (resonnance.actors.find(it => it == attacker.id)) { - // déjà accordé - return; - } - await this.update({ "system.sante.resonnance": [...resonnance, attacker.id] }); - } - else { - super.setEntiteReveAccordee(attacker) - } - } - } diff --git a/module/actor/entite-sheet.js b/module/actor/entite-sheet.js index 354f4429..d0c485f4 100644 --- a/module/actor/entite-sheet.js +++ b/module/actor/entite-sheet.js @@ -54,6 +54,12 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet { }); } + async _onDropActor(event, dragData) { + const dropActor = fromUuidSync(dragData.uuid) + await this.actor.setEntiteReveAccordee(dropActor) + super._onDropActor(event, dragData) + } + async deleteSubActeur(actorId) { let newResonances = this.actor.system.sante.resonnance.actors.filter(id => id != actorId); await this.actor.update({ 'system.sante.resonnance.actors': newResonances }, { renderSheet: false }); diff --git a/module/actor/entite.js b/module/actor/entite.js index d8052088..ca63f334 100644 --- a/module/actor/entite.js +++ b/module/actor/entite.js @@ -67,7 +67,7 @@ export class RdDEntite extends RdDBaseActorReve { if (this.isNonIncarnee()) { return } - await RdDEncaisser.encaisser(this) + await RdDEncaisser.encaisser(this) } isEffectAllowed(effectId) { @@ -91,20 +91,16 @@ export class RdDEntite extends RdDBaseActorReve { } /* -------------------------------------------- */ - async setEntiteReveAccordee(attacker) { + async setEntiteReveAccordee(actor) { if (this.isEntite([ENTITE_INCARNE])) { - let resonnance = foundry.utils.duplicate(this.system.sante.resonnance); - if (resonnance.actors.find(it => it == attacker.id)) { + if (this.system.sante.resonnance.actors.find(it => it == actor.id)) { // déjà accordé - return; + return } - resonnance.actors.push(attacker.id); - await this.update({ "system.sante.resonnance": resonnance }); + await this.update({ "system.sante.resonnance.actors": [...this.system.sante.resonnance.actors, actor.id] }) } else { - super.setEntiteReveAccordee(attacker) + super.setEntiteReveAccordee(actor) } } - - } diff --git a/module/misc.js b/module/misc.js index bf080cf7..c22fe21e 100644 --- a/module/misc.js +++ b/module/misc.js @@ -166,11 +166,12 @@ export class Misc { } static firstConnectedGM() { - if (game.users?.activeGM) { - return game.users.activeGM + if (foundry.utils.isNewerVersion(game.release.version, '12.0')) { + return game.users.activeGM } - return game.users.sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active); + return game.users.find(u => u.isGM && u.active); } + static connectedGMs() { return game.users.filter(u => u.isGM && u.active); } @@ -188,16 +189,20 @@ export class Misc { * and there is no connected GM */ static documentIfResponsible(document) { - if (document instanceof Document) { - if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) { + if (foundry.utils.isNewerVersion(game.release.version, '12.0')) { + if (game.users.activeGM || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) + { return document } } + else if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) { + return document + } return undefined } - static isOwnerPlayer(actor) { - return actor.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) + static isOwnerPlayer(document) { + return document.testUserPermission && document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) } static isOwnerPlayerOrUniqueConnectedGM(actor) { diff --git a/module/rdd-empoignade.js b/module/rdd-empoignade.js index 38328b86..e8a9f1ce 100644 --- a/module/rdd-empoignade.js +++ b/module/rdd-empoignade.js @@ -248,7 +248,7 @@ export class RdDEmpoignade { if (rollData.rolled.isPart) { rollData.particuliere = "finesse"; } - let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html'); + let msg = await RdDResolutionTable.displayRollData(rollData, defender, 'chat-empoignade-resultat.html'); RdDEmpoignade.$storeRollEmpoignade(msg, rollData); } diff --git a/module/rdd-possession.js b/module/rdd-possession.js index 01421ff4..eb67f7d1 100644 --- a/module/rdd-possession.js +++ b/module/rdd-possession.js @@ -131,7 +131,7 @@ export class RdDPossession { } const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid) RdDPossession.storePossessionAttaque(possession, rollData) - await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html'); + await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html'); } /* -------------------------------------------- */ @@ -171,7 +171,7 @@ export class RdDPossession { rollData.possession = possession RdDPossession.$updateEtatPossession(rollData.possession) - await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html') + await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html') if (rollData.possession.isPosseder || rollData.possession.isConjurer) { // conjuration victime.deleteEmbeddedDocuments("Item", [rollData.possession._id]) diff --git a/module/rdd-resolution-table.js b/module/rdd-resolution-table.js index e2d78331..f8b341e2 100644 --- a/module/rdd-resolution-table.js +++ b/module/rdd-resolution-table.js @@ -97,7 +97,7 @@ export class RdDResolutionTable { } static actorChatName(actor) { - return actor?.userName ?? game.user.name; + return actor?.name ?? game.user.name; } /* -------------------------------------------- */ diff --git a/module/voyage/dialog-fatigue-voyage.js b/module/voyage/dialog-fatigue-voyage.js index 74a4b179..1ae7bef6 100644 --- a/module/voyage/dialog-fatigue-voyage.js +++ b/module/voyage/dialog-fatigue-voyage.js @@ -1,6 +1,7 @@ import { TYPES } from "../item.js" import { RdDItemCompetence } from "../item-competence.js" import { ChatUtility } from "../chat-utility.js" +import { Misc } from "../misc.js" const CODES_COMPETENCES_VOYAGE = ['Extérieur', 'Forêt', 'Montagne', 'Marais', 'Glace', 'Equitation'] const TABLEAU_FATIGUE_MARCHE = [ @@ -36,7 +37,7 @@ export class DialogFatigueVoyage extends Dialog { const parameters = { tableauFatigueMarche: TABLEAU_FATIGUE_MARCHE, playerActors: game.actors.filter(actor => actor.isPersonnageJoueur()) - .map(actor => DialogFatigueVoyage.prepareActor(actor)), + .map(actor => DialogFatigueVoyage.prepareActorParameters(actor)), nombreHeures: 1, } DialogFatigueVoyage.setModeDeplacement(parameters, undefined, undefined) @@ -53,21 +54,37 @@ export class DialogFatigueVoyage extends Dialog { parameters.typeTerrain = ligneFatigueMarche parameters.vitesseDeplacement = rythme.vitesse parameters.fatigueHoraire = rythme.fatigue + parameters.playerActors.forEach(voyageur => + DialogFatigueVoyage.selectSurvie(voyageur, parameters.typeTerrain.code) + ) } - static prepareActor(actor) { - const competencesVoyage = {} - CODES_COMPETENCES_VOYAGE.forEach(codeSurvie => - competencesVoyage[codeSurvie] = RdDItemCompetence.findCompetence(actor.itemTypes[TYPES.competence], codeSurvie, { onMessage: () => { } }) - ) - return { + static prepareActorParameters(actor) { + const actorParameters = { + id: actor.id, actor: actor, selected: true, ajustementFatigue: 0, - competencesVoyage: competencesVoyage + survies: {} } + const competencesVoyage = {} + CODES_COMPETENCES_VOYAGE.forEach(codeSurvie => { + competencesVoyage[codeSurvie] = RdDItemCompetence.findCompetence(actor.itemTypes[TYPES.competence], codeSurvie, { onMessage: () => { } }) + }) + TABLEAU_FATIGUE_MARCHE.forEach(terrain => { + actorParameters.survies[terrain.code] = Misc.join( + terrain.survies.map(survie => { + const niveau = competencesVoyage[survie]?.system.niveau + return `${survie}: ${niveau}` + }), + ', ') + }) + return actorParameters } + static selectSurvie(actorParameters, code) { + actorParameters.survieCourante = actorParameters.survies[code] + } constructor(html, parameters) { const options = { @@ -97,6 +114,7 @@ export class DialogFatigueVoyage extends Dialog { this.html.find('select[name="code-terrain"]').change(event => this.changeParameters()) this.html.find('select[name="vitesse-deplacement"]').change(event => this.changeParameters()) this.html.find('input[name="nombre-heures"]').change(event => this.changeParameters()) + this.html.find('.list-item input[name="ajustement-fatigue"]').change(event => this.changeParameters()) this.html.find('button[name="appliquer-fatigue"]').click(event => this.appliquerFatigue()) } @@ -118,6 +136,10 @@ export class DialogFatigueVoyage extends Dialog { selectVitesseDeplacement.append(await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs', rythme)) }) selectVitesseDeplacement.val(this.parameters.vitesseDeplacement).change() + + Promise.all(this.getActorRows() + .map(async row => row.find('label.voyage-liste-survies').text(this.$extractActorParameters(row).survieCourante) + )) } } @@ -132,16 +154,24 @@ export class DialogFatigueVoyage extends Dialog { } async setFatigue() { - this.html.find('input[name="base-fatigue"]').val(this.parameters.nombreHeures * this.parameters.fatigueHoraire) + const baseFatigue = this.parameters.nombreHeures * this.parameters.fatigueHoraire + this.html.find('input[name="base-fatigue"]').val(baseFatigue) + this.updateActorTotalFatigue(baseFatigue) + } + + async updateActorTotalFatigue(baseFatigue) { + Promise.all(this.getActorRows() + .map(async row => { + const actor = this.$extractActorParameters(row) + row.find('input[name="total-fatigue"]').val(actor.ajustement + baseFatigue) + })) } async appliquerFatigue() { const fatigueBase = parseInt(this.html.find('input[name="base-fatigue"]').val() ?? 0) - const actors = jQuery.map( - this.html.find('div.fatigue-actors-list li.list-item'), - it => this.$extractActor(this.html.find(it)) - ) - actors.filter(it => it.selected) + this.getActorRows() + .map(row => this.$extractActorParameters(row)) + .filter(it => it.selected) .forEach(async it => { const perteFatigue = fatigueBase + it.ajustement ChatMessage.create({ @@ -161,16 +191,24 @@ export class DialogFatigueVoyage extends Dialog { }) } - $extractActor(actorRow) { - const actor = game.actors.get(actorRow.data('actor-id')) + getActorRows() { + return jQuery.map( + this.html.find('div.fatigue-actors-list li.list-item'), + it => this.html.find(it)) + } + + + $extractActorParameters(actorRow) { + const actorId = actorRow.data('actor-id') + const actorParameters = this.parameters.playerActors.find(it => it.id == actorId) + const actor = game.actors.get(actorId) if (!actor) { ui.notifications.warn(`Acteur ${it.actorId} introuvable`) + return {} } - return { - actor: actor, - ajustement: parseInt(actorRow.find('input[name="ajustement-fatigue"]').val() ?? 0), - selected: actor && actorRow.find('input[name="selectionner-acteur"]').is(':checked') - } + actorParameters.ajustement = parseInt(actorRow.find('input[name="ajustement-fatigue"]').val() ?? 0) + actorParameters.selected = actor && actorRow.find('input[name="selectionner-acteur"]').is(':checked') + return actorParameters } async close() { diff --git a/system.json b/system.json index c4a9d00a..d35e1070 100644 --- a/system.json +++ b/system.json @@ -1,8 +1,8 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "12.0.6", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.6.zip", + "version": "12.0.7", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.7.zip", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", "compatibility": { diff --git a/templates/voyage/dialog-fatigue-voyage.hbs b/templates/voyage/dialog-fatigue-voyage.hbs index 4dbd1f9a..8d98c9d5 100644 --- a/templates/voyage/dialog-fatigue-voyage.hbs +++ b/templates/voyage/dialog-fatigue-voyage.hbs @@ -42,7 +42,8 @@