Améliorations combat #532
@ -1,5 +1,7 @@
|
|||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { SYSTEM_SOCKET_ID } from "./constants.js";
|
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
|
|
||||||
|
export const MESSAGE_DATA = 'message-data';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class providing helper methods to get the list of users, and
|
* Class providing helper methods to get the list of users, and
|
||||||
@ -160,4 +162,20 @@ export class ChatUtility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async setMessageData(chatMessage, key, data) {
|
||||||
|
if (data) {
|
||||||
|
await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(data));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static getMessageData(chatMessage, key) {
|
||||||
|
const json = chatMessage.getFlag(SYSTEM_RDD, key);
|
||||||
|
return json ? JSON.parse(json) : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getChatMessage(event) {
|
||||||
|
const chatMessageId = $(event.currentTarget).closest('.chat-message').attr('data-message-id');
|
||||||
|
return game.messages.get(chatMessageId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -371,19 +371,10 @@ export class RdDCombatManager extends Combat {
|
|||||||
export class RdDCombat {
|
export class RdDCombat {
|
||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
this.initStorePasseArmes();
|
|
||||||
Hooks.on("updateCombat", (combat, change, options, userId) => { RdDCombat.onUpdateCombat(combat, change, options, userId) });
|
Hooks.on("updateCombat", (combat, change, options, userId) => { RdDCombat.onUpdateCombat(combat, change, options, userId) });
|
||||||
Hooks.on("preDeleteCombat", (combat, options, userId) => { RdDCombat.onPreDeleteCombat(combat, options, userId); });
|
Hooks.on("preDeleteCombat", (combat, options, userId) => { RdDCombat.onPreDeleteCombat(combat, options, userId); });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static initStorePasseArmes() {
|
|
||||||
game.system.rdd.combatStore = {
|
|
||||||
attaques: {},
|
|
||||||
defenses: {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static onSocketMessage(sockmsg) {
|
static onSocketMessage(sockmsg) {
|
||||||
switch (sockmsg.msg) {
|
switch (sockmsg.msg) {
|
||||||
@ -391,8 +382,6 @@ export class RdDCombat {
|
|||||||
return RdDCombat.onMsgEncaisser(sockmsg.data);
|
return RdDCombat.onMsgEncaisser(sockmsg.data);
|
||||||
case "msg_defense":
|
case "msg_defense":
|
||||||
return RdDCombat.onMsgDefense(sockmsg.data);
|
return RdDCombat.onMsgDefense(sockmsg.data);
|
||||||
case "msg_combat_passearme":
|
|
||||||
return RdDCombat.onMsgPasseArme(sockmsg.data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,22 +394,11 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static onPreDeleteCombat(combat, options, userId) {
|
static onPreDeleteCombat(combat, options, userId) {
|
||||||
if (game.user.isGM) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
combat.cleanItemUse();
|
combat.cleanItemUse();
|
||||||
ChatUtility.removeChatMessageContaining(`<div data-combatid="${combat.id}" data-combatmessage="actor-turn-summary">`)
|
ChatUtility.removeChatMessageContaining(`<div data-combatid="${combat.id}" data-combatmessage="actor-turn-summary">`)
|
||||||
/*
|
game.messages.filter(m => ChatUtility.getMessageData(m, 'attacker-roll') != undefined && ChatUtility.getMessageData(m, 'defender-roll') != undefined)
|
||||||
* TODO: support de plusieurs combats parallèles
|
.forEach(it => it.delete());
|
||||||
* il faudrait avoir un id de combat en plus de celui de passe d'armes
|
|
||||||
*/
|
|
||||||
for (const key in game.system.rdd.combatStore.attaques) {
|
|
||||||
const attackerRoll = game.system.rdd.combatStore.attaques[key];
|
|
||||||
ChatUtility.removeChatMessageContaining(`<div data-passearme="${attackerRoll.passeArme}">`);
|
|
||||||
}
|
|
||||||
for (const key in game.system.rdd.combatStore.defenses) {
|
|
||||||
const defenderRoll = game.system.rdd.combatStore.defenses[key];
|
|
||||||
ChatUtility.removeChatMessageContaining(`<div data-passearme="${defenderRoll.passeArme}">`);
|
|
||||||
}
|
|
||||||
RdDCombat.initStorePasseArmes();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,61 +449,6 @@ export class RdDCombat {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static messagePasseArme(data) {
|
|
||||||
// TODO: store required info for combat in the chat message presenting choices?
|
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_combat_passearme", data: data });
|
|
||||||
RdDCombat.onMsgPasseArme(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static onMsgPasseArme(data) {
|
|
||||||
switch (data.actionPasseArme) {
|
|
||||||
case "store-attaque":
|
|
||||||
game.system.rdd.combatStore.attaques[data.id] = data.rollData;
|
|
||||||
break;
|
|
||||||
case "store-defense":
|
|
||||||
game.system.rdd.combatStore.defenses[data.id] = data.rollData;
|
|
||||||
break;
|
|
||||||
case "delete-attaque":
|
|
||||||
delete game.system.rdd.combatStore.attaques[data.id];
|
|
||||||
break;
|
|
||||||
case "delete-defense":
|
|
||||||
delete game.system.rdd.combatStore.defenses[data.id];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static _storeAttaque(attackerId, attackerRoll) {
|
|
||||||
RdDCombat.messagePasseArme({ actionPasseArme: "store-attaque", id: attackerId, rollData: attackerRoll });
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static _getAttaque(attackerId) {
|
|
||||||
return game.system.rdd.combatStore.attaques[attackerId];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static _deleteAttaque(attackerId) {
|
|
||||||
RdDCombat.messagePasseArme({ actionPasseArme: "delete-attaque", id: attackerId });
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static _storeDefense(passeArme, defenderRoll) {
|
|
||||||
RdDCombat.messagePasseArme({ actionPasseArme: "store-defense", id: passeArme, rollData: defenderRoll });
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static _getDefense(passeArme) {
|
|
||||||
return game.system.rdd.combatStore.defenses[passeArme];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static _deleteDefense(passeArme) {
|
|
||||||
RdDCombat.messagePasseArme({ actionPasseArme: "delete-defense", id: passeArme });
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static create(attacker, defender, defenderTokenId, target = undefined) {
|
static create(attacker, defender, defenderTokenId, target = undefined) {
|
||||||
return new RdDCombat(attacker, defender, defenderTokenId, target)
|
return new RdDCombat(attacker, defender, defenderTokenId, target)
|
||||||
@ -547,7 +470,7 @@ export class RdDCombat {
|
|||||||
static onMsgEncaisser(data) {
|
static onMsgEncaisser(data) {
|
||||||
let defender = canvas.tokens.get(data.defenderTokenId).actor;
|
let defender = canvas.tokens.get(data.defenderTokenId).actor;
|
||||||
if (Misc.isOwnerPlayerOrUniqueConnectedGM()) {
|
if (Misc.isOwnerPlayerOrUniqueConnectedGM()) {
|
||||||
let attackerRoll = RdDCombat._getAttaque(data.attackerId); // Retrieve the rolldata from the store
|
let attackerRoll = data.attackerRoll;
|
||||||
let attacker = data.attackerId ? game.actors.get(data.attackerId) : null;
|
let attacker = data.attackerId ? game.actors.get(data.attackerId) : null;
|
||||||
|
|
||||||
defender.encaisserDommages(attackerRoll, attacker);
|
defender.encaisserDommages(attackerRoll, attacker);
|
||||||
@ -563,10 +486,8 @@ export class RdDCombat {
|
|||||||
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
|
||||||
if (rddCombat) {
|
if (rddCombat) {
|
||||||
const defenderRoll = msg.defenderRoll;
|
const defenderRoll = msg.defenderRoll;
|
||||||
RdDCombat._storeAttaque(msg.attackerId, defenderRoll.attackerRoll);
|
|
||||||
RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll);
|
|
||||||
rddCombat.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
rddCombat.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
||||||
rddCombat._chatMessageDefense(msg.paramChatDefense);
|
rddCombat._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -621,12 +542,10 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onEvent(button, event) {
|
async onEvent(button, event) {
|
||||||
const attackerRoll = RdDCombat._getAttaque(this.attackerId);
|
const chatMessage = ChatUtility.getChatMessage(event);
|
||||||
if (!attackerRoll) {
|
const defenderRoll = ChatUtility.getMessageData(chatMessage, 'defender-roll');
|
||||||
ui.notifications.warn("Action automatisée impossible, le jet de l'attaquant a été perdu (suite à un raffraichissement?)")
|
const attackerRoll = defenderRoll?.attackerRoll ?? ChatUtility.getMessageData(chatMessage, 'attacker-roll') ;
|
||||||
return;
|
console.log('RdDCombat', attackerRoll, defenderRoll);
|
||||||
}
|
|
||||||
const defenderRoll = game.system.rdd.combatStore.defenses[attackerRoll.passeArme];
|
|
||||||
const defenderTokenId = event.currentTarget.attributes['data-defenderTokenId']?.value;
|
const defenderTokenId = event.currentTarget.attributes['data-defenderTokenId']?.value;
|
||||||
|
|
||||||
const armeParadeId = event.currentTarget.attributes['data-armeid']?.value;
|
const armeParadeId = event.currentTarget.attributes['data-armeid']?.value;
|
||||||
@ -637,7 +556,7 @@ export class RdDCombat {
|
|||||||
case '#particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value);
|
case '#particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value);
|
||||||
case '#parer-button': return this.parade(attackerRoll, armeParadeId);
|
case '#parer-button': return this.parade(attackerRoll, armeParadeId);
|
||||||
case '#esquiver-button': return this.esquive(attackerRoll, compId, competence);
|
case '#esquiver-button': return this.esquive(attackerRoll, compId, competence);
|
||||||
case '#encaisser-button': return this.encaisser(attackerRoll, defenderTokenId);
|
case '#encaisser-button': return this.encaisser(attackerRoll, defenderRoll, defenderTokenId);
|
||||||
case '#echec-total-attaque': return this._onEchecTotal(attackerRoll);
|
case '#echec-total-attaque': return this._onEchecTotal(attackerRoll);
|
||||||
|
|
||||||
case '#appel-chance-attaque': return this.attacker.rollAppelChance(
|
case '#appel-chance-attaque': return this.attacker.rollAppelChance(
|
||||||
@ -650,7 +569,7 @@ export class RdDCombat {
|
|||||||
() => this.attaqueSignificative(attackerRoll),
|
() => this.attaqueSignificative(attackerRoll),
|
||||||
() => { });
|
() => { });
|
||||||
case '#appel-destinee-defense': return this.defender.appelDestinee(
|
case '#appel-destinee-defense': return this.defender.appelDestinee(
|
||||||
() => this.defenseDestinee(attackerRoll),
|
() => this.defenseDestinee(defenderRoll),
|
||||||
() => { });
|
() => { });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -680,8 +599,7 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
defenseDestinee(attackerRoll) {
|
defenseDestinee(defenderRoll) {
|
||||||
let defenderRoll = RdDCombat._getDefense(attackerRoll.passeArme);
|
|
||||||
if (defenderRoll) {
|
if (defenderRoll) {
|
||||||
ui.notifications.info('Défense significative grâce à la destinée')
|
ui.notifications.info('Défense significative grâce à la destinée')
|
||||||
RdDResolutionTable.significativeRequise(defenderRoll.rolled);
|
RdDResolutionTable.significativeRequise(defenderRoll.rolled);
|
||||||
@ -819,7 +737,6 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _onAttaqueParticuliere(rollData) {
|
async _onAttaqueParticuliere(rollData) {
|
||||||
RdDCombat._storeAttaque(this.attackerId, rollData);
|
|
||||||
|
|
||||||
const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0;
|
const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0;
|
||||||
// force toujours, sauf empoignade
|
// force toujours, sauf empoignade
|
||||||
@ -839,7 +756,7 @@ export class RdDCombat {
|
|||||||
return await this.choixParticuliere(rollData, "rapidite");
|
return await this.choixParticuliere(rollData, "rapidite");
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatMessage.create({
|
const choixParticuliere = await ChatMessage.create({
|
||||||
alias: this.attacker.name,
|
alias: this.attacker.name,
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
||||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html', {
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html', {
|
||||||
@ -852,6 +769,7 @@ export class RdDCombat {
|
|||||||
passeArme: rollData.passeArme
|
passeArme: rollData.passeArme
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
ChatUtility.setMessageData(choixParticuliere, 'attacker-roll', rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -860,10 +778,6 @@ export class RdDCombat {
|
|||||||
|
|
||||||
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntiteCauchemar());
|
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntiteCauchemar());
|
||||||
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
|
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
|
||||||
// Save rollData for defender
|
|
||||||
RdDCombat._storeAttaque(this.attackerId, attackerRoll);
|
|
||||||
RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll);
|
|
||||||
|
|
||||||
attackerRoll.show = {
|
attackerRoll.show = {
|
||||||
cible: this.target ? this.defender.data.name : 'la cible',
|
cible: this.target ? this.defender.data.name : 'la cible',
|
||||||
isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge')
|
isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge')
|
||||||
@ -918,7 +832,7 @@ export class RdDCombat {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
await this._chatMessageDefense(paramChatDefense);
|
await this._chatMessageDefense(paramChatDefense, defenderRoll);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._socketSendMessageDefense(paramChatDefense, defenderRoll);
|
this._socketSendMessageDefense(paramChatDefense, defenderRoll);
|
||||||
@ -926,14 +840,16 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _chatMessageDefense(paramDemandeDefense) {
|
async _chatMessageDefense(paramDemandeDefense, defenderRoll) {
|
||||||
ChatMessage.create({
|
const choixDefense = await ChatMessage.create({
|
||||||
// message privé: du défenseur à lui même (et aux GMs)
|
// message privé: du défenseur à lui même (et aux GMs)
|
||||||
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
|
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
|
||||||
alias: this.attacker.name,
|
alias: this.attacker.name,
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.defender.name),
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.defender.name),
|
||||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html', paramDemandeDefense),
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html', paramDemandeDefense),
|
||||||
});
|
});
|
||||||
|
// flag pour garder les jets d'attaque/defense
|
||||||
|
ChatUtility.setMessageData(choixDefense, 'defender-roll', defenderRoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -974,10 +890,7 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _onAttaqueEchecTotal(attackerRoll) {
|
async _onAttaqueEchecTotal(attackerRoll) {
|
||||||
|
const choixEchecTotal = await ChatMessage.create({
|
||||||
RdDCombat._storeAttaque(this.attackerId, attackerRoll);
|
|
||||||
|
|
||||||
ChatMessage.create({
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
||||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', {
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', {
|
||||||
attackerId: this.attackerId,
|
attackerId: this.attackerId,
|
||||||
@ -986,6 +899,7 @@ export class RdDCombat {
|
|||||||
essais: attackerRoll.essais
|
essais: attackerRoll.essais
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
ChatUtility.setMessageData(choixEchecTotal, 'attacker-roll', attackerRoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -1105,7 +1019,6 @@ export class RdDCombat {
|
|||||||
|
|
||||||
this.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
this.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
||||||
this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true });
|
this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true });
|
||||||
RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -1177,7 +1090,6 @@ export class RdDCombat {
|
|||||||
|
|
||||||
this.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
this.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
|
||||||
this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true })
|
this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true })
|
||||||
RdDCombat._storeDefense(defenderRoll.passeArme, defenderRoll);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -1282,15 +1194,10 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async encaisser(attackerRoll, defenderTokenId) {
|
async encaisser(attackerRoll, defenderRoll, defenderTokenId) {
|
||||||
defenderTokenId = defenderTokenId || this.defenderTokenId;
|
defenderTokenId = defenderTokenId || this.defenderTokenId;
|
||||||
console.log("RdDCombat.encaisser >>>", attackerRoll, defenderTokenId);
|
console.log("RdDCombat.encaisser >>>", attackerRoll, defenderTokenId);
|
||||||
|
|
||||||
let defenderRoll = RdDCombat._getDefense(attackerRoll.passeArme);
|
|
||||||
if (!defenderRoll) {
|
|
||||||
ui.notifications.warn("Cette passe d'arme est déjà terminée!")
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (defenderRoll?.rolled && RdDCombat.isEchecTotal(defenderRoll)) {
|
if (defenderRoll?.rolled && RdDCombat.isEchecTotal(defenderRoll)) {
|
||||||
this._onEchecTotal(defenderRoll);
|
this._onEchecTotal(defenderRoll);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user