From a3df0499a7b1e5f4a567a6e7641577dd9bb82fd1 Mon Sep 17 00:00:00 2001 From: LeRatierBretonnien Date: Wed, 28 Jun 2023 11:12:51 +0200 Subject: [PATCH] Update confrontation --- lang/en.json | 13 +- lang/fr.json | 15 ++- modules/actors/ecryme-actor-sheet.js | 5 + modules/actors/ecryme-actor.js | 40 +++++- modules/common/ecryme-config.js | 5 +- modules/common/ecryme-utility.js | 124 ++++++++++++++++-- modules/dialogs/ecryme-confront-dialog.js | 84 ++++++++---- postcss/ecryme.css | 32 ++++- styles/ecryme.css | 34 ++++- system.json | 2 +- template.json | 4 + templates/actors/actor-sheet.hbs | 32 +++-- templates/chat/chat-confrontation-result.hbs | 54 ++++++++ templates/dialogs/confront-dialog.hbs | 17 ++- .../dialogs/partial-confront-bonus-area.hbs | 10 ++ .../dialogs/partial-confront-dice-area.hbs | 8 +- templates/items/item-weapon-sheet.hbs | 11 ++ 17 files changed, 424 insertions(+), 66 deletions(-) create mode 100644 templates/chat/chat-confrontation-result.hbs create mode 100644 templates/dialogs/partial-confront-bonus-area.hbs diff --git a/lang/en.json b/lang/en.json index c3cf6ef..17e1535 100644 --- a/lang/en.json +++ b/lang/en.json @@ -106,7 +106,18 @@ "preservation": "Preservation", "dicepool": "Available dices", "selectconfront": "Select for confrontation", - "transcendapply": "Apply la Transcend to " + "transcendapply": "Apply la Transcend to ", + "healthcombat": "Health&Fight", + "name": "Name", + "weapons": "Weapons", + "weapon": "Weapon", + "melee": "Melee", + "ranged": "Ranged", + "weapontype": "Weapon type", + "type": "Type", + "applyimpact": "Apply impact", + "applybonus": "Apply bonus", + "bonuspool": "Available bonuses" } } } \ No newline at end of file diff --git a/lang/fr.json b/lang/fr.json index 61d6176..7a4a830 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -30,7 +30,7 @@ "ui": { "traitType": "Type de trait", "niveauTrait": "Niveau du trait", - "effect": "Effect", + "effect": "Incidence", "weight": "Poids", "cost": "Prix", "costUnit": "Unité", @@ -106,7 +106,18 @@ "preservation": "Préservation", "dicepool": "Dés disponibles", "selectconfront": "Sélectionner pour la Confrontation", - "transcendapply": "Appliquer la Transcendence à " + "transcendapply": "Appliquer la Transcendence à ", + "healthcombat": "Santé&Combat", + "name": "Nom", + "weapons": "Armes", + "weapon": "Arme", + "melee": "Mêlée", + "ranged": "A Distance", + "weapontype": "Type d'arme", + "type": "Type", + "applyimpact": "Appliquer l'impact", + "applybonus": "Appliquer le bonus", + "bonuspool": "Bonus disponibles" } } } \ No newline at end of file diff --git a/modules/actors/ecryme-actor-sheet.js b/modules/actors/ecryme-actor-sheet.js index 500c5ce..9fd2ef8 100644 --- a/modules/actors/ecryme-actor-sheet.js +++ b/modules/actors/ecryme-actor-sheet.js @@ -122,6 +122,11 @@ export class EcrymeActorSheet extends ActorSheet { let skillKey = $(event.currentTarget).data("skill-key") this.actor.rollSkillConfront(categKey, skillKey) }); + html.find('.roll-weapon-confront').click((event) => { + const li = $(event.currentTarget).parents(".item") + let weaponId = li.data("item-id"); + this.actor.rollWeaponConfront(weaponId) + }); html.find('.impact-modify').click((event) => { let impactType = $(event.currentTarget).data("impact-type") diff --git a/modules/actors/ecryme-actor.js b/modules/actors/ecryme-actor.js index d5d8a61..ce3370f 100644 --- a/modules/actors/ecryme-actor.js +++ b/modules/actors/ecryme-actor.js @@ -298,6 +298,12 @@ export class EcrymeActor extends Actor { } } } + + /* -------------------------------------------- */ + modifyConfrontBonus( modifier ) { + let newBonus = this.system.internals.confrontbonus + bonus + this.update({'system.internals.confrontbonus': newBonus}) + } /* -------------------------------------------- */ spentSkillTranscendence(skill, value) { @@ -306,8 +312,18 @@ export class EcrymeActor extends Actor { this.update({ [`system.skills.${skill.categKey}.skilllist.${skill.skillKey}.value`]: newValue }) } + /* -------------------------------------------- */ + getBonusList() { + let bonusList = [] + for(let i=0; i= __effect2Impact.length) { + return "major" + } + return __effect2Impact[effectValue] + } + /* -------------------------------------------- */ + static async processConfrontation() { + let confront = { + type: "confront-data", + rollData1: this.confrontData1, + rollData2: this.confrontData2, + } + // Compute margin + confront.marginExecution = this.confrontData1.executionTotal - this.confrontData2.preservationTotal + confront.marginPreservation = this.confrontData1.preservationTotal - this.confrontData2.executionTotal + console.log(confront.marginExecution, confront.marginPreservation) + // Filter margin + let maxMargin // Dummy max + if ( confront.marginExecution > 0) { // Successful hit + // Limit with skill+spec + maxMargin = confront.rollData1.skill.value + ((confront.rollData1.spec) ? 2 : 0) + confront.marginExecution = Math.min(confront.marginExecution, maxMargin) + } else { // Failed hit + maxMargin = confront.rollData2.skill.value + ((confront.rollData2.spec) ? 2 : 0) + confront.marginExecution = -Math.min(Math.abs(confront.marginExecution), maxMargin) + } + + if ( confront.marginPreservation > 0) { // Successful defense + // Limit with skill+spec + maxMargin = confront.rollData1.skill.value + ((confront.rollData1.spec) ? 2 : 0) + confront.marginPreservation = Math.min(confront.marginPreservation, maxMargin) + } else { // Failed defense + maxMargin = confront.rollData2.skill.value + ((confront.rollData2.spec) ? 2 : 0) + confront.marginPreservation = - Math.min(Math.abs(confront.marginPreservation), maxMargin) + } + + // Compute effects + confront.effectExecution = confront.marginExecution + if (confront.rollData1.weapon && confront.marginExecution > 0) { + confront.effectExecution += confront.rollData1.weapon.system.effect + confront.impactExecution = this.getImpactFromEffect(confront.effectExecution) + } + if ( confront.marginExecution < 0) { + confront.bonus2 = -confront.marginExecution + } + confront.effectPreservation = confront.marginPreservation + if (confront.rollData2.weapon && confront.marginPreservation < 0) { + confront.effectPreservation = - (Math.abs(confront.marginPreservation) + confront.rollData2.weapon.system.effect) + confront.impactPreservation = this.getImpactFromEffect(Math.abs(confront.effectPreservation)) + } + if ( confront.marginPreservation > 0) { + confront.bonus1 = -confront.marginPreservation + } + + let msg = await this.createChatWithRollMode(this.confrontData1.alias, { + content: await renderTemplate(`systems/fvtt-ecryme/templates/chat/chat-confrontation-result.hbs`, confront) + }) + msg.setFlag("world", "ecryme-rolldata", confront) + console.log("Confront result", confront) + + this.lastConfront = confront + } + + /* -------------------------------------------- */ + static manageConfrontation(rollData) { + console.log("Confront", rollData) + // Auto - Reset + if (this.confrontData1 && this.confrontData2) { + this.confrontData1 = undefined + this.confrontData2 = undefined + } + // Then attribute + if (!this.confrontData1) { + this.confrontData1 = rollData + } else if (this.confrontData1 && this.confrontData1.rollId != rollData.rollId) { + this.confrontData2 = rollData + this.processConfrontation().catch("Error during confrontation processing") + } else { + ui.notifications.warn(game.i18n.localize("ECRY.warn.confrontalready")) + } + } /* -------------------------------------------- */ static chatMenuManager(html, options) { @@ -132,15 +215,24 @@ export class EcrymeUtility { /* -------------------------------------------- */ static async chatListeners(html) { - html.on("click", '.roll-destin', event => { + html.on("click", '.button-select-confront', event => { let messageId = EcrymeUtility.findChatMessageId(event.currentTarget) let message = game.messages.get(messageId) - let rollData = message.getFlag("world", "rolldata") - let actor = this.getActorFromRollData(rollData) - actor.incDecDestin(-1) - rollData.isReroll = true - this.rollEcryme(rollData).catch("Error on rollEcryme") + let rollData = message.getFlag("world", "ecryme-rolldata") + EcrymeUtility.manageConfrontation(rollData) }) + html.on("click", '.button-apply-impact', event => { + let messageId = EcrymeUtility.findChatMessageId(event.currentTarget) + let message = game.messages.get(messageId) + let actor = game.actors.get($(event.currentTarget).data("actor-id")) + actor.modifyImpact($(event.currentTarget).data("impact-type"), $(event.currentTarget).data("impact"), 1) + }) + html.on("click", '.button-apply-bonus', event => { + let messageId = EcrymeUtility.findChatMessageId(event.currentTarget) + let message = game.messages.get(messageId) + let actor = game.actors.get($(event.currentTarget).data("actor-id")) + actor.modifyConfrontBonus( $(event.currentTarget).data("bonus") ) + }) html.on("click", '.draw-tarot-card', event => { let messageId = EcrymeUtility.findChatMessageId(event.currentTarget) this.drawDeckCard(messageId) @@ -158,6 +250,7 @@ export class EcrymeUtility { 'systems/fvtt-ecryme/templates/items/partial-item-description.hbs', 'systems/fvtt-ecryme/templates/dialogs/partial-common-roll-dialog.hbs', 'systems/fvtt-ecryme/templates/dialogs/partial-confront-dice-area.hbs', + 'systems/fvtt-ecryme/templates/dialogs/partial-confront-bonus-area.hbs', 'systems/fvtt-ecryme/templates/actors/partial-impacts.hbs', ] return loadTemplates(templatePaths); @@ -254,7 +347,7 @@ export class EcrymeUtility { } /* -------------------------------------------- */ - static chatDataSetup(content, modeOverride, isRoll = false, forceWhisper) { + static chatDataSetup(content, modeOverride, forceWhisper, isRoll = false) { let chatData = { user: game.user.id, rollMode: modeOverride || game.settings.get("core", "rollMode"), @@ -276,7 +369,7 @@ export class EcrymeUtility { static getImpactMax(impactLevel) { return __maxImpacts[impactLevel] } - static getNextImpactLevel(impactLevel) { + static getNextImpactLevel(impactLevel) { return __nextImpacts[impactLevel] } /* -------------------------------------------- */ @@ -288,7 +381,9 @@ export class EcrymeUtility { rollMode = rollMode ?? game.settings.get("core", "rollMode"); switch (rollMode) { case "blindroll": //GM only + whisper = this.getUsers(user => user.isGM); blind = true; + break case "gmroll": //GM + rolling player whisper = this.getUsers(user => user.isGM); break; @@ -313,7 +408,8 @@ export class EcrymeUtility { rollData.margin = rollData.total - rollData.difficulty if (rollData.total > rollData.difficulty) { rollData.isSuccess = true - rollData.margin = Math.min(rollData.margin, rollData.skill.value) + let maxMargin = rollData.skill.value + (rollData.spec) ? 2 : 0 + rollData.margin = Math.min(rollData.margin, maxMargin) } } @@ -388,7 +484,6 @@ export class EcrymeUtility { content: await renderTemplate(`systems/fvtt-ecryme/templates/chat/chat-generic-result.hbs`, rollData) }) msg.setFlag("world", "ecryme-rolldata", rollData) - console.log("Rolldata result", rollData) } @@ -501,6 +596,7 @@ export class EcrymeUtility { static getBasicRollData() { let rollData = { rollId: randomID(16), + type: "roll-data", bonusMalusPerso: 0, bonusMalusSituation: 0, bonusMalusDef: 0, diff --git a/modules/dialogs/ecryme-confront-dialog.js b/modules/dialogs/ecryme-confront-dialog.js index 379bc5e..284d7cd 100644 --- a/modules/dialogs/ecryme-confront-dialog.js +++ b/modules/dialogs/ecryme-confront-dialog.js @@ -9,7 +9,7 @@ export class EcrymeConfrontDialog extends Dialog { let options = mergeObject(super.defaultOptions, { classes: ["fvtt-ecryme ecryme-confrontation-dialog"], dragDrop: [{ dragSelector: ".confront-dice-container", dropSelector: null }], - width: 540, height: 'fit-content', 'z-index': 99999 + width: 620, height: 'fit-content', 'z-index': 99999 }); let html = await renderTemplate('systems/fvtt-ecryme/templates/dialogs/confront-dialog.hbs', rollData); @@ -50,6 +50,7 @@ export class EcrymeConfrontDialog extends Dialog { let msg = await EcrymeUtility.createChatMessage(this.rollData.alias, "blindroll", { content: await renderTemplate(`systems/fvtt-ecryme/templates/chat/chat-confrontation-pending.hbs`, this.rollData) }) + console.log("MSG", this.rollData) msg.setFlag("world", "ecryme-rolldata", this.rollData) } @@ -61,16 +62,26 @@ export class EcrymeConfrontDialog extends Dialog { let button = this.buttonDisabled setTimeout(function () { $(".launchConfront").attr("disabled", button) }, 180) - } /* ------------------ -------------------------- */ _onDragStart(event) { super._onDragStart(event) - console.log("DRAG", event) - const diceData = { - diceIndex: $(event.srcElement).data("dice-idx"), - diceValue: $(event.srcElement).data("dice-value"), + let dragType = $(event.srcElement).data("drag-type") + let diceData = {} + console.log("DRAGTYPE", dragType) + if (dragType == "dice") { + diceData = { + dragType: "dice", + diceIndex: $(event.srcElement).data("dice-idx"), + diceValue: $(event.srcElement).data("dice-value"), + } + } else { + diceData = { + dragType: "bonus", + bonusIndex: $(event.srcElement).data("bonus-idx"), + bonusValue: 1 + } } event.dataTransfer.setData("text/plain", JSON.stringify(diceData)); } @@ -78,28 +89,42 @@ export class EcrymeConfrontDialog extends Dialog { /* -------------------------------------------- */ _onDrop(event) { let dataJSON = event.dataTransfer.getData('text/plain') - console.log("DICEDATA", dataJSON) let data = JSON.parse(dataJSON) - let idx = Number(data.diceIndex) - //console.log("DATA", data, event, event.srcElement.className) - if (event.srcElement.className.includes("execution")) { - this.rollData.availableDices[idx].location = "execution" - } - if (event.srcElement.className.includes("preservation")) { - this.rollData.availableDices[idx].location = "preservation" - } - if (event.srcElement.className.includes("dice-list")) { - this.rollData.availableDices[idx].location = "mainpool" - } - - if (this.rollData.availableDices.filter(d => d.location == "execution").length == 2 && this.rollData.availableDices.filter(d => d.location == "preservation").length == 2) { - this.buttonDisabled = false + if ( data.dragType == "dice") { + let idx = Number(data.diceIndex) + //console.log("DATA", data, event, event.srcElement.className) + if (event.srcElement.className.includes("execution") && + this.rollData.availableDices.filter(d => d.location == "execution").length < 2) { + this.rollData.availableDices[idx].location = "execution" + } + if (event.srcElement.className.includes("preservation") && + this.rollData.availableDices.filter(d => d.location == "preservation").length < 2) { + this.rollData.availableDices[idx].location = "preservation" + } + if (event.srcElement.className.includes("dice-list")) { + this.rollData.availableDices[idx].location = "mainpool" + } + + if (this.rollData.availableDices.filter(d => d.location == "execution").length == 2 && this.rollData.availableDices.filter(d => d.location == "preservation").length == 2) { + this.buttonDisabled = false + } else { + this.buttonDisabled = true + } } else { - this.buttonDisabled = true + let idx = Number(data.bonusIndex) + if (event.srcElement.className.includes("execution")) { + this.rollData.confrontBonus[idx].location = "execution" + } + if (event.srcElement.className.includes("preservation")) { + this.rollData.confrontBonus[idx].location = "preservation" + } + if (event.srcElement.className.includes("bonus-list")) { + this.rollData.confrontBonus[idx].location = "mainpool" + } } // Manage total values - this.computeTotals().catch("Error on dice pools") + this.computeTotals() } /* -------------------------------------------- */ @@ -115,20 +140,27 @@ export class EcrymeConfrontDialog extends Dialog { } /* -------------------------------------------- */ - async computeTotals() { + computeTotals() { let rollData = this.rollData let actor = game.actors.get(rollData.actorId) rollData.executionTotal = rollData.availableDices.filter(d => d.location == "execution").reduce((previous, current) => { return previous + current.result }, rollData.skill.value) + rollData.executionTotal = rollData.confrontBonus.filter(d => d.location == "execution").reduce((previous, current) => { + return previous + 1 + }, rollData.executionTotal) + rollData.preservationTotal = rollData.availableDices.filter(d => d.location == "preservation").reduce((previous, current) => { return previous + current.result }, rollData.skill.value) + rollData.preservationTotal = rollData.confrontBonus.filter(d => d.location == "preservation").reduce((previous, current) => { + return previous + 1 + }, rollData.preservationTotal) this.processTranscendence() if (rollData.selectedSpecs && rollData.selectedSpecs.length > 0) { - rollData.spec = actor.getSpecialization(rollData.selectedSpecs[0]) + rollData.spec = duplicate(actor.getSpecialization(rollData.selectedSpecs[0])) this.rollData.executionTotal += "+2" this.rollData.preservationTotal += "+2" } @@ -161,7 +193,7 @@ export class EcrymeConfrontDialog extends Dialog { rollData.preservationTotal += rollData.bonusMalusTraits rollData.preservationTotal += rollData.bonusMalusPerso - this.refreshDialog() + this.refreshDialog().catch("Error on refresh confrontation dialog") } /* -------------------------------------------- */ diff --git a/postcss/ecryme.css b/postcss/ecryme.css index aba04ce..602b42e 100644 --- a/postcss/ecryme.css +++ b/postcss/ecryme.css @@ -1350,9 +1350,35 @@ ul, li { .confront-dice { border-width: 0px; } + +.bonus-spec { + max-width: 48px; +} +.confront-bonus-container { + position: relative; + flex-grow: 1; + text-align: center; + color: black; +} +.pool-list { + align-items: center; + justify-content: center; +} +.confront-bonus-centered { + position: absolute; + top: 50%; + left: 50%; + font-size: 1.6rem; + color: darkgreen; + font-family: MailartRubberstamp; + transform: translate(-50%, -55%); +} + +.dice-spec { + max-width: 64px; +} .confront-dice-container { position: relative; - max-width: 128px; flex-grow: 1; text-align: center; color: black; @@ -1364,7 +1390,7 @@ ul, li { font-size: 2rem; color: darkgreen; font-family: MailartRubberstamp; - transform: translate(-50%, -80%); + transform: translate(-50%, -55%); } .confront-area { margin: 2px; @@ -1374,4 +1400,6 @@ ul, li { border-color: #000000; border-radius: 6px; border: 2px ridge #443307; + align-items: center; + justify-content: center; } diff --git a/styles/ecryme.css b/styles/ecryme.css index db96910..c176cf0 100644 --- a/styles/ecryme.css +++ b/styles/ecryme.css @@ -1330,9 +1330,35 @@ ul, li { .confront-dice { border-width: 0px; } + +.bonus-spec { + max-width: 48px; +} +.confront-bonus-container { + position: relative; + flex-grow: 1; + text-align: center; + color: black; +} +.pool-list { + align-items: center; + justify-content: center; +} +.confront-bonus-centered { + position: absolute; + top: 50%; + left: 50%; + font-size: 1.6rem; + color: darkgreen; + font-family: MailartRubberstamp; + transform: translate(-50%, -55%); +} + +.dice-spec { + max-width: 64px; +} .confront-dice-container { position: relative; - max-width: 128px; flex-grow: 1; text-align: center; color: black; @@ -1344,14 +1370,16 @@ ul, li { font-size: 2rem; color: darkgreen; font-family: MailartRubberstamp; - transform: translate(-50%, -80%); + transform: translate(-50%, -55%); } .confront-area { margin: 2px; padding: 4px; - min-height: 96px; + min-height: 64px; border-width: 2px; border-color: #000000; border-radius: 6px; border: 2px ridge #443307; + align-items: center; + justify-content: center; } diff --git a/system.json b/system.json index bbac8dd..561408f 100644 --- a/system.json +++ b/system.json @@ -43,7 +43,7 @@ ], "title": "Ecryme, le Jeu de Rôles", "url": "https://www.uberwald.me/gitea/uberwald/fvtt-ecryme", - "version": "11.0.1", + "version": "11.0.3", "download": "https://www.uberwald.me/gitea/uberwald/fvtt-ecryme/archive/fvtt-ecryme-v10.0.0.zip", "background": "systems/fvtt-ecryme/images/assets/ecryme_extract_panel_01.webp" } \ No newline at end of file diff --git a/template.json b/template.json index 7026fdd..361e527 100644 --- a/template.json +++ b/template.json @@ -135,6 +135,9 @@ "serious": 0, "major": 0 } + }, + "internals": { + "confrontbonus": 0 } }, "npccore": { @@ -200,6 +203,7 @@ "common", "equipement" ], + "weapontype": "melee", "effect": 0 }, "specialization": { diff --git a/templates/actors/actor-sheet.hbs b/templates/actors/actor-sheet.hbs index 344434b..2bb98f4 100644 --- a/templates/actors/actor-sheet.hbs +++ b/templates/actors/actor-sheet.hbs @@ -50,7 +50,7 @@ @@ -69,7 +69,8 @@