From acc5ddac089872e67ddf6f61153437cc75348d92 Mon Sep 17 00:00:00 2001 From: Vincent Vandemeulebrouck Date: Wed, 23 Nov 2022 00:10:06 +0100 Subject: [PATCH] =?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