diff --git a/changelog.md b/changelog.md index cd60d45d..9e326136 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,17 @@ # v11.0 +## v11.0.8 - la poigne de Sémolosse +- lien vers le changelog +- organisation des compendiums du système +- correction de l'empoignade + - les items d'empoignade sont ajoutés par le MJ quand nécessaire + - seul le joueur propriétaire du personnage peut effectuer ses choix et actions d'empoignade + - les caractéristiques du défenseur sont utilisées pour la défense + - la difficulté d'attaque est imposée au défenseur + - les attaques particulières sont en finesse (p133) + - on peut entraîner au sol dès 2 points d'empoignade + - les actions liée à l'immobilisation sont proposées en fin de round + # v11.0.7 - les créatures ont maintenant le droit d'avoir des compétences de tir, lancer, mêlée, armes naturelles, parade. diff --git a/module/actor.js b/module/actor.js index 0e2e31f9..8c0f2581 100644 --- a/module/actor.js +++ b/module/actor.js @@ -273,24 +273,24 @@ export class RdDActor extends RdDBaseActor { getDraconicOuPossession() { const possession = this.items.filter(it => it.type == TYPES.competencecreature && it.system.categorie == 'possession') .sort(Misc.descending(it => it.system.niveau)) - .find(it=>true); + .find(it => true); if (possession) { return possession.clone(); } - const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0).map(it =>it.clone()), + const draconics = [...this.getDraconicList().filter(it => it.system.niveau >= 0).map(it => it.clone()), POSSESSION_SANS_DRACONIC] .sort(Misc.descending(it => it.system.niveau)); return draconics[0]; } getPossession(possessionId) { - return this.items.find(it => it.type == 'possession' && it.system.possessionid == possessionId); + return this.items.find(it => it.type == TYPES.possession && it.system.possessionid == possessionId); } getPossessions() { - return this.items.filter(it => it.type == 'possession'); + return this.items.filter(it => it.type == TYPES.possession); } getEmpoignades() { - return this.items.filter(it => it.type == 'empoignade'); + return this.items.filter(it => it.type == TYPES.empoignade); } getDemiReve() { return this.system.reve.tmrpos.coord; @@ -961,7 +961,7 @@ export class RdDActor extends RdDBaseActor { /* -------------------------------------------- */ async updateCompetence(idOrName, compValue) { - const competence = this.getCompetence(idOrName); + const competence = this.getCompetence(idOrName); if (competence) { const toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie, competence.getCategories()); this.notifyCompetencesTronc(competence, toNiveau); @@ -1362,21 +1362,46 @@ export class RdDActor extends RdDBaseActor { /* -------------------------------------------- */ async finDeRound(options = { terminer: false }) { + await this.$finDeRoundSuppressionEffetsTermines(options); + await this.$finDeRoundBlessuresGraves(); + await this.$finDeRoundSupprimerObsoletes(); + await this.$finDeRoundEmpoignade(); + } + + async $finDeRoundSuppressionEffetsTermines(options) { for (let effect of this.getEffects()) { if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) { await effect.delete(); ChatMessage.create({ content: `${this.name} n'est plus ${Misc.lowerFirst(game.i18n.localize(effect.system.label))} !` }); } } + } + + async $finDeRoundBlessuresGraves() { if (this.isPersonnage() || this.isCreature()) { - const nbGraves = this.filterItems(it => it.isGrave(), 'blessure').length + const nbGraves = this.filterItems(it => it.isGrave(), 'blessure').length; if (nbGraves > 0) { // Gestion blessure graves : -1 pt endurance par blessure grave - await this.santeIncDec("endurance", - nbGraves); + await this.santeIncDec("endurance", -nbGraves); } } } + async $finDeRoundSupprimerObsoletes() { + const obsoletes = [] + .concat(this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp <= 0)) + .concat(this.itemTypes[TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2)) + .map(it => it.id); + await this.deleteEmbeddedDocuments('Item', obsoletes); + } + + async $finDeRoundEmpoignade(){ + const immobilisations = this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id); + immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this, + game.actors.get(emp.system.empoigneid), + emp + )) + } /* -------------------------------------------- */ async setSonne(sonne = true) { if (this.isEntite()) { diff --git a/module/actor/base-actor.js b/module/actor/base-actor.js index d5901382..29e82b7e 100644 --- a/module/actor/base-actor.js +++ b/module/actor/base-actor.js @@ -144,6 +144,18 @@ export class RdDBaseActor extends Actor { .forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp)) } + async creerObjetParMJ(object){ + if (!Misc.isUniqueConnectedGM()) { + RdDBaseActor.remoteActorCall({ + actorId: this.id, + method: 'creerObjetParMJ', + args: [object] + }); + return; + } + await this.createEmbeddedDocuments('Item', [object]) + } + /* -------------------------------------------- */ getFortune() { return Monnaie.getFortune(this.itemTypes['monnaie']); diff --git a/module/chat-utility.js b/module/chat-utility.js index cf707dfc..7c244a4f 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -78,11 +78,7 @@ export class ChatUtility { /* -------------------------------------------- */ static async createChatWithRollMode(name, chatOptions) { - return await ChatUtility.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions); - } - - /* -------------------------------------------- */ - static async createChatMessage(name, rollMode, chatOptions) { + let rollMode = game.settings.get("core", "rollMode") switch (rollMode) { case "blindroll": // GM only if (!game.user.isGM) { diff --git a/module/rdd-empoignade.js b/module/rdd-empoignade.js index 3e46fd0e..89f65256 100644 --- a/module/rdd-empoignade.js +++ b/module/rdd-empoignade.js @@ -4,6 +4,8 @@ import { RdDRoll } from "./rdd-roll.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { ChatUtility } from "./chat-utility.js"; import { STATUSES } from "./settings/status-effects.js"; +import { ReglesOptionelles } from "./settings/regles-optionelles.js"; +import { TYPES } from "./item.js"; /* -------------------------------------------- */ @@ -14,6 +16,47 @@ export class RdDEmpoignade { static init() { } + /* -------------------------------------------- */ + static registerChatCallbacks(html) { + html.on("click", '.defense-empoignade-cac', event => { + const chatMessage = ChatUtility.getChatMessage(event); + const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); + let defenseMode = event.currentTarget.attributes['data-defense-mode'].value + RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee") + }); + html.on("click", '.defense-empoignade-esquive', event => { + const chatMessage = ChatUtility.getChatMessage(event); + const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); + let defenseMode = event.currentTarget.attributes['data-defense-mode'].value + RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee") + }); + html.on("click", '.empoignade-poursuivre', event => { + let attackerId = event.currentTarget.attributes['data-attackerId'].value + let defenderId = event.currentTarget.attributes['data-defenderId'].value + RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId)) + }); + html.on("click", '.empoignade-entrainer-sol', event => { + const chatMessage = ChatUtility.getChatMessage(event); + const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); + RdDEmpoignade.entrainerAuSol(rollData) + ChatUtility.removeChatMessageId(chatMessage.id) + }); + html.on("click", '.empoignade-projeter-sol', event => { + const chatMessage = ChatUtility.getChatMessage(event); + const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); + RdDEmpoignade.projeterAuSol(rollData) + ChatUtility.removeChatMessageId(chatMessage.id) + }); + html.on("change", '.empoignade-perte-endurance', event => { + const chatMessage = ChatUtility.getChatMessage(event); + const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); + if (event.currentTarget.value && event.currentTarget.value != "none") { + RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value) + ChatUtility.removeChatMessageId(chatMessage.id) + } + }); + } + /* -------------------------------------------- */ static checkEmpoignadeEnCours(actor) { // TODO: autoriser la perception? la comédie/séduction? @@ -24,74 +67,92 @@ export class RdDEmpoignade { return false; } + /* -------------------------------------------- */ + static $storeRollEmpoignade(msg, rollData) { + RdDEmpoignade.$reduceActorToIds(rollData); + ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData); + } + + static $reduceActorToIds(rollData) { + rollData.attacker = { id: rollData.attacker.id }; + rollData.defender = { id: rollData.defender.id }; + } + + /* -------------------------------------------- */ + static $readRollEmpoignade(msg) { + const rollData = ChatUtility.getMessageData(msg, 'empoignade-roll-data'); + RdDEmpoignade.$replaceIdsWithActors(rollData); + return rollData + } + + static $replaceIdsWithActors(rollData) { + rollData.attacker = game.actors.get(rollData.attacker.id); + rollData.defender = game.actors.get(rollData.defender.id); + } + /* -------------------------------------------- */ static isEmpoignadeEnCours(actor) { - return actor.itemTypes['empoignade'].find(it => it.system.pointsemp > 0) + return actor.itemTypes[TYPES.empoignade].find(it => it.system.pointsemp > 0) } /* -------------------------------------------- */ static getEmpoignadeById(actor, id) { - let emp = actor.itemTypes['empoignade'].find(it => it.system.empoignadeid == id) + let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id) return emp && duplicate(emp) || undefined; } /* -------------------------------------------- */ static getEmpoignade(attacker, defender) { - let emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) - if (!emp) { - emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id) - } + let emp = attacker.itemTypes[TYPES.empoignade].find(it => + (it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) || + (it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id) + ) if (emp) { return duplicate(emp); } return undefined; } + /* -------------------------------------------- */ static getMalusTaille(emp, attacker, defender) { // Si pas empoigné, alors 0 if (emp.system.pointsemp == 0) { return 0 } - // Malus de -1 si différence de taille de 2 ou plus (p 135) - if (attacker.system.carac.taille.value < defender.system.carac.taille.value - 1) { - return attacker.system.carac.taille.value - (defender.system.carac.taille.value - 1) + // p135: Malus de -1 par point de taille de différence de taille au delà de 1 (donc -2 pour une différence de 3, ...) + const diffTaille = attacker.system.carac.taille.value - defender.system.carac.taille.value; + const diffTailleAbs = Math.abs(diffTaille) + const signDiff = diffTaille > 0 ? 1 : -1 + + if (diffTailleAbs > 2) { + return signDiff * (diffTailleAbs - 1) } return 0 } - /* -------------------------------------------- */ - static async onAttaqueEmpoignadeValidee(attacker, defender) { - let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender) - const isNouvelle = empoignade == undefined; - empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender)) + static isActionAutorisee(mode, attacker, defender) { + const acting = RdDEmpoignade.isActionDefenseur(mode) ? defender : attacker; + if (acting.getUserLevel(game.user) < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) { + ui.notifications.warn(`Vous n'êtes pas autorisé à choisir l'action de ${acting.name}`) + return false; + } + return true + } - let mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer" - - let rollData = { - mode: mode, - isEmpoignade: true, - competence: attacker.getCompetence("Corps à corps").clone(), - selectedCarac: attacker.system.carac.melee, - empoignade: empoignade, - attackerId: attacker.id, - attackerName: attacker.name, - defenderName: defender.name, - defenderId: defender.id, - malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender) - } - if (attacker.isCreatureEntite()) { - RdDItemCompetenceCreature.setRollDataCreature(rollData) - } - if (empoignade.system.pointsemp >= 2) { - let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-actions.html'); - ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData) - } else { - await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle); + static isActionDefenseur(mode) { + switch (mode) { + case "liberer": + case "contrer-empoigner": + return true; } + return false; } /* -------------------------------------------- */ static async onAttaqueEmpoignade(attacker, defender) { + if (!RdDEmpoignade.isActionAutorisee("empoigner", attacker, defender)) { + return + } let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender) const isNouvelle = empoignade == undefined; empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender)) @@ -105,6 +166,38 @@ export class RdDEmpoignade { } } + /* -------------------------------------------- */ + static async onAttaqueEmpoignadeValidee(attacker, defender) { + let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender) + const isNouvelle = empoignade == undefined; + empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender)) + + let mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer" + + if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) { + return + } + + let rollData = { + mode, empoignade, attacker, defender, + isEmpoignade: true, + competence: attacker.getCompetence("Corps à corps").clone(), + selectedCarac: attacker.system.carac.melee, + malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender) + } + if (attacker.isCreatureEntite()) { + RdDItemCompetenceCreature.setRollDataCreature(rollData) + } + if (empoignade.system.pointsemp >= 2) { + if (!empoignade.system.ausol) { + let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.html'); + RdDEmpoignade.$storeRollEmpoignade(msg, rollData); + } + } else { + await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle); + } + } + /* -------------------------------------------- */ static async onAttaqueEmpoignadeFromItem(empoignade) { let attacker = game.actors.get(empoignade.system.empoigneurid) @@ -112,6 +205,20 @@ export class RdDEmpoignade { await this.onAttaqueEmpoignadeValidee(attacker, defender) } + static async onImmobilisation(attacker, defender, empoignade) { + const rollData = { + mode: "immobilise", + empoignade, attacker, defender, + isEmpoignade: true, + competence: attacker.getCompetence("Corps à corps").clone() + } + const msg = await ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(attacker.name), + content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.html`, rollData) + }) + RdDEmpoignade.$storeRollEmpoignade(msg, rollData); + } + /* -------------------------------------------- */ static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) { const dialog = await RdDRoll.create(attacker, rollData, @@ -119,35 +226,40 @@ export class RdDEmpoignade { { name: 'jet-empoignade', label: 'Empoigner', - callbacks: [ - { condition: r => (r.rolled.isSuccess), action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, true, isNouvelle) }, - { condition: r => (r.rolled.isEchec), action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, false, isNouvelle) }, - ] + callbacks: [{ action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, isNouvelle) },] }); dialog.render(true); } /* -------------------------------------------- */ - static async $onRollEmpoignade(rollData, isSuccess, isNouvelle = false) { - let attacker = game.actors.get(rollData.attackerId) - let defender = game.actors.get(rollData.defenderId) + static async $onRollEmpoignade(rollData, isNouvelle = false) { + let attacker = game.actors.get(rollData.attacker.id) + let defender = game.actors.get(rollData.defender.id) - let empoignade = rollData.empoignade - empoignade.isSuccess = isSuccess; - if (isSuccess && isNouvelle) { + if (rollData.rolled.isSuccess && isNouvelle) { + const objectEmpoignade = rollData.empoignade.toObject(); // Creer l'empoignade sur attaquant/defenseur - await attacker.createEmbeddedDocuments('Item', [empoignade.toObject()]) - await defender.createEmbeddedDocuments('Item', [empoignade.toObject()]) + attacker.creerObjetParMJ(objectEmpoignade); + defender.creerObjetParMJ(objectEmpoignade); + } + + rollData.empoignade.isSuccess = rollData.rolled.isSuccess; + if (rollData.rolled.isPart) { + rollData.particuliere = "finesse"; } let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html'); - ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData) + RdDEmpoignade.$storeRollEmpoignade(msg, rollData); } /* -------------------------------------------- */ - static async onDefenseEmpoignade(rollData, defenseMode, competenceName = "Corps à corps", carac = "melee") { - let attacker = game.actors.get(rollData.attackerId) - let defender = game.actors.get(rollData.defenderId) + static async onDefenseEmpoignade(attackerRoll, mode, competenceName = "Corps à corps", carac = "melee") { + let attacker = game.actors.get(attackerRoll.attacker.id) + let defender = game.actors.get(attackerRoll.defender.id) + if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) { + return + } + let empoignade = this.getEmpoignade(attacker, defender) if (!empoignade) { @@ -156,18 +268,23 @@ export class RdDEmpoignade { } empoignade = duplicate(empoignade) - rollData.mode = defenseMode - rollData.empoignade = empoignade - rollData.competence = defender.getCompetence(competenceName), - rollData.selectedCarac = defender.system.carac[carac], - rollData.malusTaille = RdDEmpoignade.getMalusTaille(empoignade, defender, attacker) - - await RdDEmpoignade.$rollDefenseEmpoignade(defender, rollData); + let defenderRoll = { + mode, attacker, defender, empoignade, attackerRoll, + diffLibre: attackerRoll.diffLibre, + attaqueParticuliere: attackerRoll.particuliere, + competence: defender.getCompetence(competenceName).clone(), + surprise: defender.getSurprise(true), + carac: defender.system.carac, + selectedCarac: defender.system.carac[carac], + malusTaille: RdDEmpoignade.getMalusTaille(empoignade, defender, attacker), + show: {} + }; + await RdDEmpoignade.$rollDefenseEmpoignade(defender, defenderRoll); } /* -------------------------------------------- */ - static async $rollDefenseEmpoignade(defender, rollData) { - const dialog = await RdDRoll.create(defender, rollData, + static async $rollDefenseEmpoignade(defender, defenderRoll) { + const dialog = await RdDRoll.create(defender, defenderRoll, { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-empoignade.html' }, { name: 'empoignade', @@ -183,7 +300,7 @@ export class RdDEmpoignade { /* -------------------------------------------- */ static async $onRollContrerLiberer(rollData) { let empoignade = rollData.empoignade - + if (rollData.mode == "contrer-empoigner" && !rollData.rolled.isSuccess) { empoignade.system.pointsemp++ RdDEmpoignade.$updateEtatEmpoignade(empoignade) @@ -192,13 +309,12 @@ export class RdDEmpoignade { empoignade.system.pointsemp-- RdDEmpoignade.$updateEtatEmpoignade(empoignade) } - - if (empoignade.system.pointsemp >= 2) { - let attacker = game.actors.get(empoignade.system.empoigneurid) - let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-actions.html'); - ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData) - } + await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-empoignade-resultat.html') + if (empoignade.system.pointsemp >= 2) { + let msg = await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-empoignade-entrainer.html'); + RdDEmpoignade.$storeRollEmpoignade(msg, rollData); + } } /* -------------------------------------------- */ @@ -223,16 +339,15 @@ export class RdDEmpoignade { let defender = game.actors.get(empoignade.system.empoigneid) let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid) await defender.deleteEmbeddedDocuments('Item', [emp._id]) - - //let attacker = game.actors.get(empoignade.system.empoigneurid) - //emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid) - //await attacker.deleteEmbeddedDocuments('Item', [emp._id]) } /* -------------------------------------------- */ static async entrainerAuSol(rollData) { - let attacker = game.actors.get(rollData.attackerId) - let defender = game.actors.get(rollData.defenderId) + let attacker = game.actors.get(rollData.attacker.id) + let defender = game.actors.get(rollData.defender.id) + if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) { + return + } let empoignade = this.getEmpoignade(attacker, defender) empoignade.system.ausol = true @@ -242,25 +357,32 @@ export class RdDEmpoignade { await defender.setEffect(STATUSES.StatusProne, true); let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.html'); - ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData) + RdDEmpoignade.$storeRollEmpoignade(msg, rollData); } /* -------------------------------------------- */ static async projeterAuSol(rollData) { - let attacker = game.actors.get(rollData.attackerId) - let defender = game.actors.get(rollData.defenderId) + let attacker = game.actors.get(rollData.attacker.id) + let defender = game.actors.get(rollData.defender.id) + if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) { + return + } let empoignade = this.getEmpoignade(attacker, defender) await defender.setEffect(STATUSES.StatusProne, true); await this.$deleteEmpoignade(empoignade) let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-projeter-sol.html'); - ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData) + RdDEmpoignade.$storeRollEmpoignade(msg, rollData); } + /* -------------------------------------------- */ static async perteEndurance(rollData, perteMode) { - let attacker = game.actors.get(rollData.attackerId) - let defender = game.actors.get(rollData.defenderId) + let attacker = game.actors.get(rollData.attacker.id) + let defender = game.actors.get(rollData.defender.id) + if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) { + return + } let empoignade = this.getEmpoignade(attacker, defender) //console.log("Perte d'endurance :!!!", perteMode) @@ -278,7 +400,7 @@ export class RdDEmpoignade { await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4))); } let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.html'); - ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData) + RdDEmpoignade.$storeRollEmpoignade(msg, rollData); } /* -------------------------------------------- */ diff --git a/module/rdd-resolution-table.js b/module/rdd-resolution-table.js index 46700826..02a99b07 100644 --- a/module/rdd-resolution-table.js +++ b/module/rdd-resolution-table.js @@ -91,13 +91,17 @@ export class RdDResolutionTable { /* -------------------------------------------- */ static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.html') { - return await ChatUtility.createChatWithRollMode(actor?.userName ?? game.user.name, { - content: await RdDResolutionTable.buildRollDataHtml(rollData, actor, template) + return await ChatUtility.createChatWithRollMode(RdDResolutionTable.actorChatName(actor), { + content: await RdDResolutionTable.buildRollDataHtml(rollData, template) }); } + static actorChatName(actor) { + return actor?.userName ?? game.user.name; + } + /* -------------------------------------------- */ - static async buildRollDataHtml(rollData, actor, template = 'chat-resultat-general.html') { + static async buildRollDataHtml(rollData, template = 'chat-resultat-general.html') { rollData.show = rollData.show || {}; return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData); } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index e69b9790..59a5f8be 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -668,6 +668,7 @@ export class RdDUtility { /* -------------------------------------------- */ static async chatListeners(html) { RdDCombat.registerChatCallbacks(html); + RdDEmpoignade.registerChatCallbacks(html); // Gestion spécifique message passeurs html.on("click", '.tmr-passeur-coord a', event => { @@ -694,44 +695,6 @@ export class RdDUtility { RdDPossession.onDefensePossession(attackerId, defenderId, possessionId) }); - html.on("click", '.defense-empoignade-cac', event => { - const chatMessage = ChatUtility.getChatMessage(event); - const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data'); - let defenseMode = event.currentTarget.attributes['data-defense-mode'].value - RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee") - }); - html.on("click", '.defense-empoignade-esquive', event => { - const chatMessage = ChatUtility.getChatMessage(event); - const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data'); - let defenseMode = event.currentTarget.attributes['data-defense-mode'].value - RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee") - }); - html.on("click", '.empoignade-poursuivre', event => { - let attackerId = event.currentTarget.attributes['data-attackerId'].value - let defenderId = event.currentTarget.attributes['data-defenderId'].value - RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId)) - }); - html.on("click", '.empoignade-entrainer-sol', event => { - const chatMessage = ChatUtility.getChatMessage(event); - const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data'); - RdDEmpoignade.entrainerAuSol(rollData) - ChatUtility.removeChatMessageId(chatMessage.id) - }); - html.on("click", '.empoignade-projeter-sol', event => { - const chatMessage = ChatUtility.getChatMessage(event); - const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data'); - RdDEmpoignade.projeterAuSol(rollData) - ChatUtility.removeChatMessageId(chatMessage.id) - }); - html.on("change", '.empoignade-perte-endurance', event => { - const chatMessage = ChatUtility.getChatMessage(event); - const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data'); - if (event.currentTarget.value && event.currentTarget.value != "none") { - RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value) - ChatUtility.removeChatMessageId(chatMessage.id) - } - }); - // gestion bouton tchat Acheter html.on("click", '.button-acheter', event => { const venteData = DialogItemAchat.preparerAchat(event.currentTarget); diff --git a/system.json b/system.json index a2983103..ebe15644 100644 --- a/system.json +++ b/system.json @@ -1,9 +1,10 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "11.0.7", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.7.zip", + "version": "11.0.8", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.0.8.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": { "minimum": "11", "verified": "11", @@ -82,7 +83,8 @@ "path": "packs/arts-et-divertissements.db", "type": "Item", "ownership": { - "PLAYER": "OBSERVER" + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" }, "flags": {} }, @@ -117,7 +119,8 @@ "path": "packs/sorts-oniros.db", "type": "Item", "ownership": { - "PLAYER": "OBSERVER" + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" }, "flags": {} }, @@ -128,7 +131,8 @@ "path": "packs/sorts-hypnos.db", "type": "Item", "ownership": { - "PLAYER": "OBSERVER" + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" }, "flags": {} }, @@ -139,7 +143,8 @@ "path": "packs/sorts-narcos.db", "type": "Item", "ownership": { - "PLAYER": "OBSERVER" + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" }, "flags": {} }, @@ -150,7 +155,8 @@ "path": "packs/sorts-thanatos.db", "type": "Item", "ownership": { - "PLAYER": "OBSERVER" + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" }, "flags": {} }, @@ -161,7 +167,8 @@ "path": "packs/equipement.db", "type": "Item", "ownership": { - "PLAYER": "OBSERVER" + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" }, "flags": {} }, @@ -184,7 +191,8 @@ "path": "packs/rappel-des-regles.db", "type": "JournalEntry", "ownership": { - "PLAYER": "OBSERVER" + "PLAYER": "OBSERVER", + "ASSISTANT": "OBSERVER" }, "flags": {} }, @@ -195,7 +203,8 @@ "path": "packs/macros.db", "type": "Macro", "ownership": { - "PLAYER": "OBSERVER" + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" }, "flags": {} }, @@ -242,7 +251,8 @@ "path": "packs/tarot-draconique.db", "type": "Item", "ownership": { - "PLAYER": "OBSERVER" + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" }, "flags": {} }, @@ -253,7 +263,8 @@ "path": "packs/extrait-poetique.db", "type": "Item", "ownership": { - "PLAYER": "OBSERVER" + "PLAYER": "OBSERVER", + "ASSISTANT": "OWNER" }, "flags": {} }, @@ -438,6 +449,72 @@ "flags": {} } ], + "packFolders": [ + { + "name": "Rêve de Dragon", + "sorting": "m", + "packs": [ + "rappel-des-regles" + ], + "folders": [ + { + "name": "Personnages", + "sorting": "m", + "packs": [ + "voyageurs", + "archetypes", + "humanoides", + "equipement", + "competences", + "arts-et-divertissements", + "meditations-et-ecrits", + "recettes-alchimiques" + ] + }, + { + "name": "Le Haut-rêve", + "sorting": "m", + "packs": [ + "tetes-de-dragon-pour-tous-personnages", + "sorts-oniros", + "sorts-hypnos", + "sorts-narcos", + "sorts-thanatos", + "invocations", + "rencontres", + "queues-de-dragon", + "ombres-de-thanatos", + "souffles-de-dragon", + "tetes-de-dragon-pour-haut-revants" + ] + }, + { + "name": "Découverte du monde", + "sorting": "m", + "packs": [ + "animaux", + "vehicules", + "entites", + "faune-flore-mineraux", + "competences-creatures", + "competences-entites", + "maladies-et-poisons" + ] + }, + { + "name": "Outils du Gardien", + "sorting": "m", + "packs": [ + "scenes-rdd", + "tables-diverses", + "macros", + "tarot-draconique", + "extrait-poetique" + ] + } + ] + } + ], "socket": true, "gridDistance": 1, "gridUnits": "m", diff --git a/templates/chat-empoignade-actions.html b/templates/chat-empoignade-actions.html deleted file mode 100644 index 85688188..00000000 --- a/templates/chat-empoignade-actions.html +++ /dev/null @@ -1,39 +0,0 @@ - -

- {{attackerName}} a empoigné {{defenderName}} -

-
-
- - - Au round suivant l'acquisition des 2 points d'Emp, {{attackerName}} peut faire perdre autant de points d'Endurance qu'il souhaite à {{defenderName}} -
- - - - - {{#if empoignade.system.ausol}} - - {{else}} -
- Dès l'acquisition des 2 points d'Emp, {{attackerName}} peut entraîner {{defenderName}} au sol. Les deux protagonistes restent empoignés. -
- - Entraîner au sol - -
- A la fin du round ou les 2 points d'Emp sont acquis, {{attackerName}} peut projeter {{defenderName}} au sol. Les deux protagonistes ne sont plus empoignés. -
- - Projeter au sol - - {{/if}} - - -
diff --git a/templates/chat-empoignade-entrainer-sol.html b/templates/chat-empoignade-entrainer-sol.html index 2185877a..47e6988f 100644 --- a/templates/chat-empoignade-entrainer-sol.html +++ b/templates/chat-empoignade-entrainer-sol.html @@ -1,7 +1,8 @@

- {{attackerName}} a entraîné {{defenderName}} au sol. L'empoignade peut continuer. + {{attacker.name}} a entraîné {{defender.name}} au sol


+ L'empoignade peut continuer.
diff --git a/templates/chat-empoignade-entrainer.html b/templates/chat-empoignade-entrainer.html new file mode 100644 index 00000000..86de5d75 --- /dev/null +++ b/templates/chat-empoignade-entrainer.html @@ -0,0 +1,16 @@ + +

+ {{attacker.name}} a empoigné {{defender.name}} +

+
+
+ + {{attacker.name}} vient d'obtenir 2 points d'Emp, et peut + entraîner {{defender.name}} au sol. Les deux protagonistes + restent empoignés. +
+ + Entraîner au sol + +
+
diff --git a/templates/chat-empoignade-immobilise.html b/templates/chat-empoignade-immobilise.html new file mode 100644 index 00000000..19e87d2f --- /dev/null +++ b/templates/chat-empoignade-immobilise.html @@ -0,0 +1,35 @@ + +

+ {{attacker.name}} a empoigné {{defender.name}} +

+
+
+ +

+ {{attacker.name}} a obtenu 2 points d'Emp à la fin du round précédent, et peut: + +

+

+
+
diff --git a/templates/chat-empoignade-perte-endurance.html b/templates/chat-empoignade-perte-endurance.html index c83803e7..6053e1c0 100644 --- a/templates/chat-empoignade-perte-endurance.html +++ b/templates/chat-empoignade-perte-endurance.html @@ -1,7 +1,8 @@

- {{attackerName}} a fait perdre de l'endurance à {{defenderName}}, qui reste immobilisé. L'empoignade peut continuer. + {{attacker.name}} a fait perdre de l'endurance à {{defender.name}}


+ {{defender.name}} reste immobilisé. L'empoignade peut continuer.
diff --git a/templates/chat-empoignade-projeter-sol.html b/templates/chat-empoignade-projeter-sol.html index 7d937191..22e8cb98 100644 --- a/templates/chat-empoignade-projeter-sol.html +++ b/templates/chat-empoignade-projeter-sol.html @@ -1,7 +1,8 @@

- {{attackerName}} a projeté {{defenderName}} au sol. L'empoignade est terminée et a été supprimée. + {{attacker.name}} a projeté {{defender.name}} au sol


+ L'empoignade est terminée et a été supprimée.
diff --git a/templates/chat-empoignade-resultat.html b/templates/chat-empoignade-resultat.html index cacb36c4..111c8db7 100644 --- a/templates/chat-empoignade-resultat.html +++ b/templates/chat-empoignade-resultat.html @@ -1,16 +1,17 @@

+ {{log 'rollData' this}} {{#if (eq mode "empoigner")}} - {{attackerName}} tente d'empoigner {{defenderName}} + {{attacker.name}} tente d'empoigner {{defender.name}} {{/if}} {{#if (eq mode "contrer-empoigner")}} - {{defenderName}} tente de contrer l'empoignade de {{attackerName}} + {{defender.name}} tente de contrer l'empoignade de {{attacker.name}} {{/if}} {{#if (eq mode "liberer")}} - {{attackerName}} tente de se libérer de l'empoignade de {{defenderName}} + {{attacker.name}} tente de se libérer de l'empoignade de {{defender.name}} {{/if}} {{#if (eq mode "contrer-liberer")}} - {{defenderName}} tente de contrer la libération de {{attackerName}} + {{defender.name}} tente de contrer la libération de {{attacker.name}} {{/if}}

{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}} @@ -20,7 +21,7 @@ {{#if (gte empoignade.system.pointsemp 2)}} -
{{defenderName}} est empoigné et immobilisé par {{attackerName}} ! +
{{defender.name}} est empoigné et immobilisé par {{attacker.name}} ! {{else}} @@ -29,16 +30,12 @@ {{#if (eq mode "empoigner")}} {{#if empoignade.isSuccess}} Contrer l'empoignade (Corps à Corps) {{#if (eq empoignade.system.pointsemp 0)}} Contrer l'empoignade (Esquive) @@ -52,8 +49,6 @@ {{#if (eq mode "liberer")}} {{#if empoignade.isSuccess}} Contrer la libération (Corps à Corps) @@ -78,8 +73,7 @@ La tentative de contrer la libération est un échec! {{/if}} {{/if}} - -
Points d'Emp: {{empoignade.system.pointsemp}} - +
+
Points d'Emp: {{empoignade.system.pointsemp}} {{/if}} diff --git a/templates/chat-empoignade-valider.html b/templates/chat-empoignade-valider.html index b597f976..6be1300f 100644 --- a/templates/chat-empoignade-valider.html +++ b/templates/chat-empoignade-valider.html @@ -1,10 +1,9 @@

- {{attackerName}} tente d'empoigner {{defenderName}} + {{attacker.name}} tente d'empoigner {{defender.name}}


-
{{attacker.name}} tente d'empoigner {{defender.name}}, qui est équipé d'une arme de mêlée. {{defender.name}} @@ -16,5 +15,5 @@ data-defenderId='{{defender.id}}'> Poursuivre l'empoignade
- +
\ No newline at end of file diff --git a/templates/dialog-roll-defense-empoignade.html b/templates/dialog-roll-defense-empoignade.html index f810a9ea..3c9337be 100644 --- a/templates/dialog-roll-defense-empoignade.html +++ b/templates/dialog-roll-defense-empoignade.html @@ -1,6 +1,6 @@

- {{defenderName}} tente de contrer l'empoignade de {{attackerName}} + {{defender.name}} tente de contrer l'empoignade de {{attacker.name}}