Clarification des maladresses

This commit is contained in:
2025-09-23 00:21:57 +02:00
parent 74515d28f4
commit 1f330c734e
6 changed files with 97 additions and 26 deletions

View File

@@ -4,6 +4,7 @@
- Fix
- La montée en TMR fonctionne
- ajout d'un status "Force insuffisante"
- clarification des maladresses à l'attaque (en demi surprise, ou à cause d'un échec total)
- Nouvelle fenêtre de jets de dés
- ajout du statut "Force insuffisante" aux acteurs si la
force est insuffisante pour l'arme

View File

@@ -19,6 +19,7 @@ import RollDialog from "./roll/roll-dialog.mjs";
import { PART_DEFENSE } from "./roll/roll-part-defense.mjs";
import { PART_ATTAQUE } from "./roll/roll-part-attaque.mjs";
import { RollDialogAdapter } from "./roll/roll-dialog-adapter.mjs";
import { ROLL_MODE_ATTAQUE, ROLL_MODE_DEFENSE } from "./roll/roll-constants.mjs";
/* -------------------------------------------- */
const premierRoundInit = [
@@ -559,33 +560,42 @@ export class RdDCombat {
/* -------------------------------------------- */
static isEchecTotal(rollData) {
if (!rollData.attackerRoll && rollData.ajustements.surprise.used) {
return rollData.rolled.isEchec && rollData.rolled.code != 'notSign';
if (rollData.ids /* roll V2*/) {
// TODO: en cas de demi-surprise à l'attaque, tout échec est un echec total.
// TODO: en cas de demi-surprise en défense, pas de changement à la règle de base
return rollData.rolled.isETotal
}
return rollData.rolled.isETotal;
if (rollData.mode == ROLL_MODE_ATTAQUE && rollData.surprise == 'demi'){
// échec normal à l'attaque en demi surprise
return rollData.rolled.isEchec && rollData.rolled.code != 'notSign'
}
return rollData.rolled.isETotal
}
/* -------------------------------------------- */
static isParticuliere(rollData) {
if (rollData.ids) {
if (rollData.ids /* roll V2*/) {
return rollData.rolled.isPart
}
if (!rollData.attackerRoll && rollData.ajustements.surprise.used) {
return false;
if (rollData.attackerRoll || !rollData.ajustements.surprise.used) {
return rollData.rolled.isPart
}
return rollData.rolled.isPart;
return false
}
/* -------------------------------------------- */
static isReussite(rollData) {
if (rollData.ids) {
return rollData.rolled.is
if (rollData.ids /* roll V2*/) {
return rollData.rolled.isSuccess
}
if (!rollData.ajustements.surprise.used) {
return rollData.rolled.isSuccess
}
switch (rollData.ajustements.surprise.used) {
case 'totale': return false;
case 'demi': return rollData.rolled.isSign;
case 'totale': return false
case 'demi': return rollData.rolled.isSign
}
return rollData.rolled.isSuccess;
return rollData.rolled.isSuccess
}
/* -------------------------------------------- */
@@ -692,6 +702,7 @@ export class RdDCombat {
/* -------------------------------------------- */
_prepareAttaque(competence, arme) {
let rollData = {
mode: ROLL_MODE_ATTAQUE,
alias: this.attacker?.getAlias(),
passeArme: foundry.utils.randomID(16),
mortalite: arme?.system.mortalite,
@@ -889,6 +900,7 @@ export class RdDCombat {
const choixEchecTotal = await ChatMessage.create({
whisper: ChatUtility.getOwners(this.attacker),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.hbs', {
rolled: attackerRoll.rolled,
attackerId: this.attackerId,
attacker: this.attacker,
attackerToken: this.attackerToken,
@@ -984,8 +996,8 @@ export class RdDCombat {
this.removeChatMessageActionsPasseArme(rd.passeArme)
// defense: esquive / arme de parade / competence de défense
if (!RdDCombat.isParticuliere(rd))
await rd.active.actor.incDecItemUse(rd.current[PART_DEFENSE].defense?.id, )
await this._onDefenseV2(rd)
await rd.active.actor.incDecItemUse(rd.current[PART_DEFENSE].defense?.id,)
await this._onDefense(rd)
}]
})
}
@@ -994,6 +1006,7 @@ export class RdDCombat {
/* -------------------------------------------- */
_prepareParade(attackerRoll, armeParade, competenceParade) {
let defenderRoll = {
mode: ROLL_MODE_DEFENSE,
alias: this.defender?.getAlias(),
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,
@@ -1016,17 +1029,63 @@ export class RdDCombat {
return defenderRoll;
}
async _onParade(defenderRoll) {
if (RdDCombat.isReussite(defenderRoll)) {
await this._onParadeNormale(defenderRoll)
if (RdDCombat.isParticuliere(defenderRoll)) {
await this._onParadeParticuliere(defenderRoll)
async _onDefense(rollData) {
if (RdDCombat.isReussite(rollData)) {
await this._onDefenseNormale(rollData)
if (RdDCombat.isParticuliere(rollData)) {
await this._onDefenseParticuliere(rollData)
}
return
}
await this._onParadeEchec(defenderRoll)
else {
await this._onDefenseEchec(rollData)
}
}
async _onDefenseV2(defenderRoll) {
async _onDefenseParticuliere(rollData) {
console.log("RdDCombat._onDefenseParticuliere >>>", rollData);
if (/*TODO: parade?*/!rollData.attackerRoll?.isPart) {
// TODO: attaquant doit jouer résistance et peut être désarmé p132
ChatUtility.createChatWithRollMode(
{ content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` },
this.defender)
}
ChatUtility.createChatWithRollMode(
{ content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" },
this.defender);
}
async _onDefenseNormale(rollData) {
console.log("RdDCombat._onDefenseNormale >>>", rollData);
// console.log("RdDCombat._onEsquiveNormal >>>", rollData);
// await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-esquive.hbs');
// this.removeChatMessageActionsPasseArme(rollData.passeArme);
//TODO
await this.computeRecul(rollData);
await this.computeDeteriorationArme(rollData);
await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-parade.hbs');
this.removeChatMessageActionsPasseArme(rollData.passeArme);
}
async _onDefenseEchec(rollData) {
console.log("RdDCombat._onDefenseEchec >>>", rollData);
// console.log("RdDCombat._onEsquiveEchec >>>", rollData);
// await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-esquive.hbs');
// this.removeChatMessageActionsPasseArme(rollData.passeArme);
// this._sendMessageDefense(rollData.attackerRoll, rollData, { defense: true })
await RdDRollResult.displayRollData(rollData, this.defender, 'chat-resultat-parade.hbs');
this.removeChatMessageActionsPasseArme(rollData.passeArme);
this._sendMessageDefense(rollData.attackerRoll, rollData, { defense: true });
}
async _onParade(defenderRoll) {
if (RdDCombat.isReussite(defenderRoll)) {
await this._onParadeNormale(defenderRoll)
if (RdDCombat.isParticuliere(defenderRoll)) {
@@ -1096,6 +1155,7 @@ export class RdDCombat {
/* -------------------------------------------- */
_prepareEsquive(attackerRoll, competence) {
let rollData = {
mode: ROLL_MODE_DEFENSE,
alias: this.defender.getAlias(),
passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre,

View File

@@ -4,8 +4,9 @@ import { PART_COMP } from "./roll-part-comp.mjs";
import { RdDResolutionTable } from "../rdd-resolution-table.js";
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
import { PART_OEUVRE } from "./roll-part-oeuvre.mjs";
import { ATTAQUE_TYPE, RdDItemArme } from "../item/arme.js";
import { RdDItemArme } from "../item/arme.js";
import { RdDBonus } from "../rdd-bonus.js";
import { ROLL_MODE_ATTAQUE } from "./roll-constants.mjs";
/* -------------------------------------------- */
export class RollDialogAdapter {
@@ -36,7 +37,9 @@ export class RollDialogAdapter {
}
async rollChances(rollData, chances) {
const rolled = await RdDResolutionTable.rollChances(chances, rollData.current.sign, rollData.current.resultat)
const rolled = await RdDResolutionTable.rollChances(chances,
rollData.current.sign,
rollData.current.resultat)
rolled.caracValue = rollData.current.carac.value
rolled.finalLevel = rollData.current.totaldiff
rolled.bonus = rollData.current.bonus ?? 0

View File

@@ -47,6 +47,7 @@ export class RollPartDefense extends RollPartSelect {
img: esquive.img,
// TODO: carac pour créatures
carac: defenseur.isPersonnage() ? CARACS.DEROBEE : esquive.name,
verb: "esquive",
comp: esquive
}
}
@@ -61,6 +62,7 @@ export class RollPartDefense extends RollPartSelect {
img: armeDefense.img,
// TODO: carac pour créatures
carac: defenseur.isPersonnage() ? CARACS.MELEE : comp.name,
verb: "pare",
comp: comp,
arme: armeDefense,
forceRequise: armeDefense ? RdDItemArme.valeurMain(armeDefense.system.force ?? 0, RdDItemArme.getMainAttaque(comp)) : 0,

View File

@@ -1,5 +1,11 @@
<div data-passearme="{{passeArme}}">
<h4 class="rdd-roll-etotal"><strong>Echec total en attaque</strong></h4>
<h4 class="rdd-roll-etotal">Maladresse à l'attaque
{{#if rolled.isETotal}}
(échec total)
{{else}}
(échec en demi-surprise)
{{/if}}
</h4>
<br>
{{#if (eq attacker.type 'personnage')}}
{{#unless essais.attaqueChance}}

View File

@@ -2,7 +2,6 @@
<span {{#if ajustements}}class="tooltip-overflow tooltip-dotted" {{/if}}>
<span>
<span>{{rolled.caracValue}} à {{plusMoins rolled.finalLevel}}</span>
{{log rolled}}
{{#if (and rolled.factorHtml (gt rolled.factorHtml 1))}}
<span class="rdd-diviseur">&times;{{{rolled.factorHtml}}}</span>
<span>= {{rolled.score}}%</span>