Merge pull request 'Choisir parmi plusieurs cibles' (#579) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10

Reviewed-on: #579
This commit is contained in:
uberwald 2022-11-23 08:24:17 +01:00
commit 81aaf9e8d7
6 changed files with 144 additions and 49 deletions

View File

@ -35,6 +35,7 @@ import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SHOW_DIC
import { RdDConfirm } from "./rdd-confirm.js"; import { RdDConfirm } from "./rdd-confirm.js";
import { DialogValidationEncaissement } from "./dialog-validation-encaissement.js"; import { DialogValidationEncaissement } from "./dialog-validation-encaissement.js";
import { RdDRencontre } from "./item-rencontre.js"; import { RdDRencontre } from "./item-rencontre.js";
import { DialogSelectTarget } from "./dialog-select-target.js";
const POSSESSION_SANS_DRACONIC = { const POSSESSION_SANS_DRACONIC = {
img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp', img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp',
@ -2551,19 +2552,18 @@ export class RdDActor extends Actor {
competence: this.getCompetence(idOrName) competence: this.getCompetence(idOrName)
} }
if (rollData.competence.type == 'competencecreature') { if (rollData.competence.type == 'competencecreature') {
if (rollData.competence.system.iscombat && options.tryTarget) { if (rollData.competence.system.iscombat && options.tryTarget && DialogSelectTarget.hasTargets()) {
const target = RdDCombat.getTarget(); DialogSelectTarget.selectOneToken(target => {
if (target) {
if (rollData.competence.system.ispossession) { if (rollData.competence.system.ispossession) {
RdDPossession.onAttaquePossession(target, this, rollData.competence) RdDPossession.onAttaquePossession(target, this, rollData.competence)
} }
else { else {
const arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence) const arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence)
RdDCombat.rddCombatTarget(this, target).attaque(competence, arme) RdDCombat.rddCombatTarget(target, this).attaque(competence, arme)
} }
});
return; return;
} }
}
// Transformer la competence de créature // Transformer la competence de créature
RdDItemCompetenceCreature.setRollDataCreature(rollData) RdDItemCompetenceCreature.setRollDataCreature(rollData)
} }
@ -3222,8 +3222,7 @@ export class RdDActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
rollArme(arme) { rollArme(arme) {
const target = RdDCombat.getTarget(); if (!DialogSelectTarget.hasTargets()) {
if (!target) {
RdDConfirm.confirmer({ RdDConfirm.confirmer({
settingConfirmer: "confirmer-combat-sans-cible", settingConfirmer: "confirmer-combat-sans-cible",
content: `<p>Voulez vous faire un jet de compétence ${arme.system.competence} sans choisir de cible valide? content: `<p>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; return;
} }
DialogSelectTarget.selectOneToken(target => {
if (RdDCombat.isTargetEntite(target)){ if (RdDCombat.isTargetEntite(target)){
ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée avec votre ${arme.name}!!!!`); ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée avec votre ${arme.name}!!!!`);
return; return;
} }
// if (RdDCombat.isTargetEntite(targets[0])) {
// ui.notifications.warn("Vous ne pouvez pas cibler une entité non incarnée!");
// return;
// }
const competence = this.getCompetence(arme.system.competence) const competence = this.getCompetence(arme.system.competence)
if (competence.system.ispossession) { if (competence.system.ispossession) {
return RdDPossession.onAttaquePossession(target, this, competence); return RdDPossession.onAttaquePossession(target, this, competence);
} }
RdDCombat.rddCombatTarget(this, target).attaque(competence, arme); RdDCombat.rddCombatTarget(target, this).attaque(competence, arme);
})
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -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);
}
}
}

View File

@ -1,5 +1,6 @@
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js";
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.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 { Grammar } from "./grammar.js";
import { RdDItemArme } from "./item-arme.js"; import { RdDItemArme } from "./item-arme.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
@ -469,17 +470,6 @@ export class RdDCombat {
return true; 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() { static getTarget() {
const targets = game.user.targets; const targets = game.user.targets;
@ -488,18 +478,34 @@ export class RdDCombat {
for (let t of targets) { for (let t of targets) {
return t; return t;
} }
case 0:
ui.notifications.warn("Vous devez choisir une cible à attaquer!");
break;
default: default:
DialogSelectTarget.selectOneToken(t => console.info(`selecte target ${t}`));
ui.notifications.warn("Vous devez choisir une cible (et <strong>une seule</strong>) à attaquer!"); ui.notifications.warn("Vous devez choisir une cible (et <strong>une seule</strong>) à attaquer!");
return; 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)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static rddCombatForAttackerAndDefender(attackerId, defenderTokenId) { static rddCombatForAttackerAndDefender(attackerId, defenderTokenId) {
const attacker = game.actors.get(attackerId); const attacker = game.actors.get(attackerId);
let defender = defenderTokenId ? canvas.tokens.get(defenderTokenId)?.actor : undefined; let defender = defenderTokenId ? canvas.tokens.get(defenderTokenId)?.actor : undefined;
let target = undefined let target = undefined
if (!defenderTokenId || !defender) { if (!defenderTokenId || !defender) {
console.warn(`RdDCombat.rddCombatForAttackerAndDefender: appel avec defenderTokenId ${defenderTokenId} incorrect, ou pas de defender correspondant`);
target = RdDCombat.getTarget() target = RdDCombat.getTarget()
if (!target) { if (!target) {
return; return;

View File

@ -332,6 +332,22 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) {
object-fit: cover; object-fit: cover;
object-position: 50% 0; 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 { .dice-img {
border-width: 0; border-width: 0;
@ -488,40 +504,40 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) {
text-shadow: none; text-shadow: none;
} }
.foundryvtt-reve-de-dragon .items-list { .foundryvtt-reve-de-dragon .item-list {
list-style: none; list-style: none;
margin: 7px 0; margin: 7px 0;
padding: 0; padding: 0;
overflow-y: auto; overflow-y: auto;
} }
.foundryvtt-reve-de-dragon .items-list .item-header { .foundryvtt-reve-de-dragon .item-list .item-header {
font-weight: bold; font-weight: bold;
} }
.foundryvtt-reve-de-dragon .items-list .item { .foundryvtt-reve-de-dragon .item-list .item {
height: 30px; height: 30px;
line-height: 24px; line-height: 24px;
padding: 3px 0; padding: 3px 0;
border-bottom: 1px solid #BBB; 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; -webkit-box-flex: 0;
-ms-flex: 0 0 24px; -ms-flex: 0 0 24px;
flex: 0 0 24px; flex: 0 0 24px;
margin-right: 5px; margin-right: 5px;
} }
.foundryvtt-reve-de-dragon .items-list .item img { .foundryvtt-reve-de-dragon .item-list .item img {
display: block; display: block;
} }
.foundryvtt-reve-de-dragon .items-list .item-name { .foundryvtt-reve-de-dragon .item-list .item-name {
margin: 0; margin: 0;
} }
.foundryvtt-reve-de-dragon .items-list .item-controls { .foundryvtt-reve-de-dragon .item-list .item-controls {
-webkit-box-flex: 0; -webkit-box-flex: 0;
-ms-flex: 0 0 86px; -ms-flex: 0 0 86px;
flex: 0 0 86px; flex: 0 0 86px;
@ -680,7 +696,7 @@ section.sheet-body{padding: 0.25rem 0.5rem;}
padding: 0 0 0 0.25rem; padding: 0 0 0 0.25rem;
text-align: center; text-align: center;
text-transform: uppercase; text-transform: uppercase;
line-height: 2.5rem; line-height: 1.2rem;
border-top: 0 none; border-top: 0 none;
border-bottom: 0 none; border-bottom: 0 none;
color: rgba(52, 52, 52, 0.95); color: rgba(52, 52, 52, 0.95);
@ -862,7 +878,7 @@ ul, li {
box-shadow: inset 0px 0px 1px #00000096; box-shadow: inset 0px 0px 1px #00000096;
border-radius: 0.25rem; border-radius: 0.25rem;
padding: 0.1rem; padding: 0.1rem;
flex: 1 1 5rem; flex: 1 1 1.5rem;
display: flex !important; display: flex !important;
align-items: center !important; align-items: center !important;
} }

View File

@ -1,8 +1,8 @@
{ {
"id": "foundryvtt-reve-de-dragon", "id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon", "title": "Rêve de Dragon",
"version": "10.2.7", "version": "10.2.8",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-10.2.7.zip", "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", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v10/system.json",
"compatibility": { "compatibility": {
"minimum": "10", "minimum": "10",

View File

@ -0,0 +1,14 @@
<form class="rdd-dialog-select-target">
<label>Choisir une seule des cibles</label>
<hr>
<ul class="flexcol item-list alterne-list">
{{#each tokens as |token key|}}
<li class="select-target item list-item flexrow" data-token-id="{{token.id}}">
<img class="select-token-img flex-shrink" src="{{token.img}}" title="{{token.name}}" />
<a>
<label>{{token.name}}</label>
</a>
</li>
{{/each}}
</ul>
</form>