From acc5ddac089872e67ddf6f61153437cc75348d92 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 23 Nov 2022 00:10:06 +0100 Subject: [PATCH 1/3] =?UTF-8?q?Simplifier=20la=20s=C3=A9lection?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Lorsque plusieurs tokens sont ciblés, laisser le joueur choisir parmi ceux-là --- module/actor.js | 53 +++++++++++++------------ module/dialog-select-target.js | 60 +++++++++++++++++++++++++++++ module/rdd-combat.js | 28 ++++++++------ styles/simple.css | 32 +++++++++++---- templates/dialog-select-target.html | 14 +++++++ 5 files changed, 141 insertions(+), 46 deletions(-) create mode 100644 module/dialog-select-target.js create mode 100644 templates/dialog-select-target.html diff --git a/module/actor.js b/module/actor.js index 8b95cfe0..0a3b5c28 100644 --- a/module/actor.js +++ b/module/actor.js @@ -35,6 +35,7 @@ import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SHOW_DIC import { RdDConfirm } from "./rdd-confirm.js"; import { DialogValidationEncaissement } from "./dialog-validation-encaissement.js"; import { RdDRencontre } from "./item-rencontre.js"; +import { DialogSelectTarget } from "./dialog-select-target.js"; const POSSESSION_SANS_DRACONIC = { img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp', @@ -2551,18 +2552,17 @@ export class RdDActor extends Actor { competence: this.getCompetence(idOrName) } if (rollData.competence.type == 'competencecreature') { - if (rollData.competence.system.iscombat && options.tryTarget) { - const target = RdDCombat.getTarget(); - if (target) { - if (rollData.competence.system.ispossession) { - RdDPossession.onAttaquePossession(target, this, rollData.competence) - } - else { - const arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence) - RdDCombat.rddCombatTarget(this, target).attaque(competence, arme) - } - return; - } + if (rollData.competence.system.iscombat && options.tryTarget && DialogSelectTarget.hasTargets()) { + DialogSelectTarget.selectOneToken(target => { + if (rollData.competence.system.ispossession) { + RdDPossession.onAttaquePossession(target, this, rollData.competence) + } + else { + const arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence) + RdDCombat.rddCombatTarget(target, this).attaque(competence, arme) + } + }); + return; } // Transformer la competence de créature RdDItemCompetenceCreature.setRollDataCreature(rollData) @@ -3222,8 +3222,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ rollArme(arme) { - const target = RdDCombat.getTarget(); - if (!target) { + if (!DialogSelectTarget.hasTargets()) { RdDConfirm.confirmer({ settingConfirmer: "confirmer-combat-sans-cible", content: `

Voulez vous faire un jet de compétence ${arme.system.competence} sans choisir de cible valide? @@ -3237,20 +3236,20 @@ export class RdDActor extends Actor { }); return; } - if (RdDCombat.isTargetEntite(target)){ - ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée avec votre ${arme.name}!!!!`); - return; - } - // if (RdDCombat.isTargetEntite(targets[0])) { - // ui.notifications.warn("Vous ne pouvez pas cibler une entité non incarnée!"); - // return; - // } + DialogSelectTarget.selectOneToken(target => { + if (RdDCombat.isTargetEntite(target)){ + ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée avec votre ${arme.name}!!!!`); + return; + } + + + const competence = this.getCompetence(arme.system.competence) + if (competence.system.ispossession) { + return RdDPossession.onAttaquePossession(target, this, competence); + } + RdDCombat.rddCombatTarget(target, this).attaque(competence, arme); + }) - const competence = this.getCompetence(arme.system.competence) - if (competence.system.ispossession) { - return RdDPossession.onAttaquePossession(target, this, competence); - } - RdDCombat.rddCombatTarget(this, target).attaque(competence, arme); } /* -------------------------------------------- */ diff --git a/module/dialog-select-target.js b/module/dialog-select-target.js new file mode 100644 index 00000000..9b6b128a --- /dev/null +++ b/module/dialog-select-target.js @@ -0,0 +1,60 @@ + +export class DialogSelectTarget extends Dialog { + static hasTargets() { + return (game.user.targets?.size ?? 0) > 0; + } + + static async selectOneToken(onSelectTarget = target => { }) { + if (DialogSelectTarget.hasTargets()) { + const targets = game.user.targets.map(it => it); + switch (targets.size) { + case 0: return; + case 1: + onSelectTarget(targets[0]); + return; + default: + { + const tokens = targets.map(it => { return { id: it.id, name: it.document.name, img: it.document.texture.src ?? it.actor.img ?? 'icons/svg/mystery-man.svg' } }) + const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-select-target.html", { + tokens: tokens + }); + new DialogSelectTarget(html, onSelectTarget, targets).render(true); + } + } + } + } + + constructor(html, onSelectTarget, targets) { + const options = { + classes: ["rdd-dialog-select-target"], + width: 'fit-content', + height: 'fit-content', + 'max-height': 600, + 'z-index': 99999 + }; + const conf = { + title: "Choisir une cible", + content: html, + buttons: {} + }; + super(conf, options); + this.onSelectTarget = onSelectTarget; + this.targets = targets; + } + + activateListeners(html) { + super.activateListeners(html); + html.find("li.select-target").click((event) => { + this.targetSelected($(event.currentTarget)?.data("token-id")); + }); + } + + + targetSelected(tokenId) { + const target = this.targets.find(it => it.id == tokenId); + this.close(); + if (target) { + this.onSelectTarget(target); + } + } +} \ No newline at end of file diff --git a/module/rdd-combat.js b/module/rdd-combat.js index ffdec171..9c77347f 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -1,5 +1,6 @@ import { ChatUtility } from "./chat-utility.js"; import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; +import { DialogSelectTarget } from "./dialog-select-target.js"; import { Grammar } from "./grammar.js"; import { RdDItemArme } from "./item-arme.js"; import { RdDItemCompetence } from "./item-competence.js"; @@ -469,17 +470,6 @@ export class RdDCombat { return true; } - /* -------------------------------------------- */ - static rddCombatTarget(attacker, target) { - const defender = target?.actor; - const defenderTokenId = target?.id; - return new RdDCombat(attacker, defender, defenderTokenId, target) - } - - static isTargetEntite(target) { - return target?.actor.type == 'entite' && target?.actor.system.definition.typeentite == ENTITE_NONINCARNE; - } - /* -------------------------------------------- */ static getTarget() { const targets = game.user.targets; @@ -488,10 +478,25 @@ export class RdDCombat { for (let t of targets) { return t; } + case 0: + ui.notifications.warn("Vous devez choisir une cible à attaquer!"); + break; default: + DialogSelectTarget.selectOneToken(t => console.info(`selecte target ${t}`)); ui.notifications.warn("Vous devez choisir une cible (et une seule) à attaquer!"); return; + } + } + + static isTargetEntite(target) { + return target?.actor.type == 'entite' && target?.actor.system.definition.typeentite == ENTITE_NONINCARNE; } + + /* -------------------------------------------- */ + static rddCombatTarget(target, attacker) { + const defender = target?.actor; + const defenderTokenId = target?.id; + return new RdDCombat(attacker, defender, defenderTokenId, target) } /* -------------------------------------------- */ @@ -500,6 +505,7 @@ export class RdDCombat { let defender = defenderTokenId ? canvas.tokens.get(defenderTokenId)?.actor : undefined; let target = undefined if (!defenderTokenId || !defender) { + console.warn(`RdDCombat.rddCombatForAttackerAndDefender: appel avec defenderTokenId ${defenderTokenId} incorrect, ou pas de defender correspondant`); target = RdDCombat.getTarget() if (!target) { return; diff --git a/styles/simple.css b/styles/simple.css index 5915b626..0fafff30 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -332,6 +332,22 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) { object-fit: cover; object-position: 50% 0; } +.rdd-dialog-select-target img.select-token-img { + -webkit-box-flex: 0; + -ms-flex: 0 0 48px; + flex: 0 0 48px; + height: 48px; + width: 48px; + border: 0; + margin-right: 0.5rem; + object-fit: cover; + vertical-align: baseline; +} + +.rdd-dialog-select-target li.select-target { + vertical-align: baseline; + padding: 0.1rem; +} .dice-img { border-width: 0; @@ -488,40 +504,40 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) { text-shadow: none; } -.foundryvtt-reve-de-dragon .items-list { +.foundryvtt-reve-de-dragon .item-list { list-style: none; margin: 7px 0; padding: 0; overflow-y: auto; } -.foundryvtt-reve-de-dragon .items-list .item-header { +.foundryvtt-reve-de-dragon .item-list .item-header { font-weight: bold; } -.foundryvtt-reve-de-dragon .items-list .item { +.foundryvtt-reve-de-dragon .item-list .item { height: 30px; line-height: 24px; padding: 3px 0; border-bottom: 1px solid #BBB; } -.foundryvtt-reve-de-dragon .items-list .item .item-image { +.foundryvtt-reve-de-dragon .item-list .item .item-image { -webkit-box-flex: 0; -ms-flex: 0 0 24px; flex: 0 0 24px; margin-right: 5px; } -.foundryvtt-reve-de-dragon .items-list .item img { +.foundryvtt-reve-de-dragon .item-list .item img { display: block; } -.foundryvtt-reve-de-dragon .items-list .item-name { +.foundryvtt-reve-de-dragon .item-list .item-name { margin: 0; } -.foundryvtt-reve-de-dragon .items-list .item-controls { +.foundryvtt-reve-de-dragon .item-list .item-controls { -webkit-box-flex: 0; -ms-flex: 0 0 86px; flex: 0 0 86px; @@ -862,7 +878,7 @@ ul, li { box-shadow: inset 0px 0px 1px #00000096; border-radius: 0.25rem; padding: 0.1rem; - flex: 1 1 5rem; + flex: 1 1 1.5rem; display: flex !important; align-items: center !important; } diff --git a/templates/dialog-select-target.html b/templates/dialog-select-target.html new file mode 100644 index 00000000..34426125 --- /dev/null +++ b/templates/dialog-select-target.html @@ -0,0 +1,14 @@ +

+ +
+ +
\ No newline at end of file -- 2.35.3 From eca61fff57734bc3818d9f7e78126772f70fbf60 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 23 Nov 2022 00:12:54 +0100 Subject: [PATCH 2/3] Fix: hauteur des onglets Foundry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le texte des onglets de configuration Foundry (vision des tokens, lumières par exemple) sont sur plusieurs lignes. La réduction de la hauteur des lignes éviter que le titre de l'onglet soit par dessus le contenu. Fixe aussi l'onglêt "haut-rêve" si la fenêtre d'acteur est de largeur réduite. --- styles/simple.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles/simple.css b/styles/simple.css index 0fafff30..660b6156 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -696,7 +696,7 @@ section.sheet-body{padding: 0.25rem 0.5rem;} padding: 0 0 0 0.25rem; text-align: center; text-transform: uppercase; - line-height: 2.5rem; + line-height: 1.2rem; border-top: 0 none; border-bottom: 0 none; color: rgba(52, 52, 52, 0.95); -- 2.35.3 From 8e1b33d96458f97f01a619c350bd3d5c0e702539 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 23 Nov 2022 00:14:55 +0100 Subject: [PATCH 3/3] Version 10.2.8 --- system.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system.json b/system.json index fd8906a1..6710d04f 100644 --- a/system.json +++ b/system.json @@ -1,8 +1,8 @@ { "id": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", - "version": "10.2.7", - "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.2.7.zip", + "version": "10.2.8", + "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.2.8.zip", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json", "compatibility": { "minimum": "10", -- 2.35.3