Gestion des maladresses #68

This commit is contained in:
Vincent Vandemeulebrouck 2020-12-17 12:29:54 +01:00
parent 84b4063789
commit 3627d05599
3 changed files with 94 additions and 60 deletions

View File

@ -71,7 +71,7 @@ export class RdDItemArme extends Item {
static mainsNues() { static mainsNues() {
const mainsNues = { const mainsNues = {
name: "Mains nues", name: "Mains nues",
data: { unemain: true, deuxmains: false, dommages: 0, dommagesReels: 0, mortalite: 'non-mortel', competence: 'Corps à corps' } data: { unemain: true, deuxmains: false, dommages: 0, dommagesReels: 0, mortalite: 'non-mortel', competence: 'Corps à corps', sansArme:true }
}; };
return mainsNues return mainsNues
} }

View File

@ -5,6 +5,7 @@ import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js"; import { RdDBonus } from "./rdd-bonus.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDRoll } from "./rdd-roll.js"; import { RdDRoll } from "./rdd-roll.js";
import { RdDRollTables } from "./rdd-rolltables.js";
export class RdDCombat { export class RdDCombat {
@ -135,8 +136,10 @@ export class RdDCombat {
console.log("RdDCombat.attaque >>>", rollData); console.log("RdDCombat.attaque >>>", rollData);
const dialog = await RdDRoll.create(this.attacker, rollData, const dialog = await RdDRoll.create(this.attacker, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html', {
options: { height: 540 } }, { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html',
options: { height: 540 }
}, {
name: 'jet-attaque', name: 'jet-attaque',
label: 'Attaque: ' + (arme ? arme.name : competence.name), label: 'Attaque: ' + (arme ? arme.name : competence.name),
callbacks: [ callbacks: [
@ -146,7 +149,7 @@ export class RdDCombat {
{ condition: RdDCombat.isEchec, action: r => this._onAttaqueEchec(r) }, { condition: RdDCombat.isEchec, action: r => this._onAttaqueEchec(r) },
{ condition: RdDCombat.isEchecTotal, action: r => this._onAttaqueEchecTotal(r) }, { condition: RdDCombat.isEchecTotal, action: r => this._onAttaqueEchecTotal(r) },
] ]
} ); });
dialog.render(true); dialog.render(true);
} }
@ -230,9 +233,9 @@ export class RdDCombat {
// Final chat message // Final chat message
let chatOptions = { let chatOptions = {
content: "<strong>Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "</strong>" content: "<strong>Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "</strong>"
+ "<br>Difficultés <strong>libre : " + rollData.diffLibre + "</strong> / conditions : " + Misc.toSignedString(rollData.diffConditions) + " / état : " + rollData.etat + "<br>Difficultés <strong>libre : " + rollData.diffLibre + "</strong> / conditions : " + Misc.toSignedString(rollData.diffConditions) + " / état : " + rollData.etat
+ RdDResolutionTable.explain(rollData.rolled) + RdDResolutionTable.explain(rollData.rolled)
+ explications + explications
} }
ChatUtility.chatWithRollMode(chatOptions, this.attacker.name) ChatUtility.chatWithRollMode(chatOptions, this.attacker.name)
@ -309,11 +312,11 @@ export class RdDCombat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_onAttaqueEchecTotal(rollData) { async _onAttaqueEchecTotal(rollData) {
console.log("RdDCombat.onEchecTotal >>>", rollData); console.log("RdDCombat.onEchecTotal >>>", rollData);
// TODO: proposer un résultat d'échec total
let chatOptions = { let chatOptions = {
content: "<strong>Echec total à l'attaque!</strong>" content: "<strong>Echec total à l'attaque!</strong> "
+ await RdDRollTables.getMaladresse({ arme: rollData.arme && !rollData.arme.data.sansArme })
} }
ChatUtility.chatWithRollMode(chatOptions, this.attacker.name) ChatUtility.chatWithRollMode(chatOptions, this.attacker.name)
} }
@ -347,8 +350,10 @@ export class RdDCombat {
let rollData = this._prepareParade(attackerRoll, arme); let rollData = this._prepareParade(attackerRoll, arme);
const dialog = await RdDRoll.create(this.defender, rollData, const dialog = await RdDRoll.create(this.defender, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html', {
options: { height: 540 } }, { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html',
options: { height: 540 }
}, {
name: 'jet-parade', name: 'jet-parade',
label: 'Parade: ' + (arme ? arme.name : rollData.competence.name), label: 'Parade: ' + (arme ? arme.name : rollData.competence.name),
callbacks: [ callbacks: [
@ -358,7 +363,7 @@ export class RdDCombat {
{ condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) }, { condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) },
{ condition: RdDCombat.isEchecTotal, action: r => this._onParadeEchecTotal(r) }, { condition: RdDCombat.isEchecTotal, action: r => this._onParadeEchecTotal(r) },
] ]
} ); });
dialog.render(true); dialog.render(true);
} }
@ -432,9 +437,9 @@ export class RdDCombat {
let chatOptions = { let chatOptions = {
content: "<strong>Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "</strong>" content: "<strong>Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "</strong>"
+ "<br>Difficultés <strong>libre : " + rollData.diffLibre + "</strong> / conditions : " + Misc.toSignedString(rollData.diffConditions) + " / état : " + rollData.etat + "<br>Difficultés <strong>libre : " + rollData.diffLibre + "</strong> / conditions : " + Misc.toSignedString(rollData.diffConditions) + " / état : " + rollData.etat
+ RdDResolutionTable.explain(rollData.rolled) + RdDResolutionTable.explain(rollData.rolled)
+ "<br><strong>Attaque parée!</strong>" + "<br><strong>Attaque parée!</strong>"
} }
ChatUtility.chatWithRollMode(chatOptions, this.defender.name) ChatUtility.chatWithRollMode(chatOptions, this.defender.name)
await this.computeRecul(rollData, false); await this.computeRecul(rollData, false);
@ -442,11 +447,11 @@ export class RdDCombat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_onParadeEchecTotal(rollData) { async _onParadeEchecTotal(rollData) {
console.log("RdDCombat._onParadeEchecTotal >>>", rollData); console.log("RdDCombat._onParadeEchecTotal >>>", rollData);
// TODO: proposer un résultat d'échec total
let chatOptions = { let chatOptions = {
content: "<strong>Echec total à la parade!</strong>" content: "<strong>Echec total à la parade!</strong> "
+ await RdDRollTables.getMaladresse({ arme: rollData.arme && !rollData.arme.data.sansArme })
} }
ChatUtility.chatWithRollMode(chatOptions, this.defender.name) ChatUtility.chatWithRollMode(chatOptions, this.defender.name)
} }
@ -536,15 +541,15 @@ export class RdDCombat {
+ RdDResolutionTable.explain(rollData.rolled) + RdDResolutionTable.explain(rollData.rolled)
+ "<br><strong>Attaque esquivée!</strong>" + "<br><strong>Attaque esquivée!</strong>"
} }
ChatUtility.chatWithRollMode(chatOptions, this.defender.name) ChatUtility.chatWithRollMode(chatOptions, this.defender.name)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_onEsquiveEchecTotal(rollData) { async _onEsquiveEchecTotal(rollData) {
console.log("RdDCombat._onEsquiveEchecTotal >>>", rollData); console.log("RdDCombat._onEsquiveEchecTotal >>>", rollData);
// TODO: proposer un résultat d'échec total
let chatOptions = { let chatOptions = {
content: "<strong>Echec total à l'esquive'!</strong>" content: "<strong>Echec total à l'esquive'!</strong> "
+ await RdDRollTables.getMaladresse({ arme: false })
} }
ChatUtility.chatWithRollMode(chatOptions, this.defender.name) ChatUtility.chatWithRollMode(chatOptions, this.defender.name)
} }
@ -573,12 +578,12 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
async computeDeteriorationArme( rollData ) { async computeDeteriorationArme(rollData) {
const attackerRoll = rollData.attackerRoll; const attackerRoll = rollData.attackerRoll;
if (rollData.arme && attackerRoll) { // C'est une parade if (rollData.arme && attackerRoll) { // C'est une parade
// Est-ce que l'attaque est une particulière, en force ou charge et que l'attaque n'en est pas une ? // Est-ce que l'attaque est une particulière, en force ou charge et que l'attaque n'en est pas une ?
if ( (rollData.needResist || attackerRoll.particuliereAttaque == 'force' || attackerRoll.tactique == 'charge') if ((rollData.needResist || attackerRoll.particuliereAttaque == 'force' || attackerRoll.tactique == 'charge')
&& !rollData.rolled.isPart ) { && !rollData.rolled.isPart) {
const dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor; const dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor;
let resistance = Misc.toInt(rollData.arme.data.resistance); let resistance = Misc.toInt(rollData.arme.data.resistance);
let msg = ""; let msg = "";
@ -586,44 +591,49 @@ export class RdDCombat {
let resistRoll = await RdDResolutionTable.rollData({ let resistRoll = await RdDResolutionTable.rollData({
caracValue: resistance, caracValue: resistance,
finalLevel: - dmg, finalLevel: - dmg,
showDice: false}); showDice: false
});
if (resistRoll.isSuccess) { // Perte de résistance if (resistRoll.isSuccess) { // Perte de résistance
msg = "Votre " + rollData.arme.name + " tient le choc de la parade. " msg = "Votre " + rollData.arme.name + " tient le choc de la parade. "
} else { } else {
resistance -= dmg; resistance -= dmg;
if ( resistance <= 0 ) { if (resistance <= 0) {
this.defender.deleteEmbeddedEntity("OwnedItem", rollData.arme._id); this.defender.deleteEmbeddedEntity("OwnedItem", rollData.arme._id);
msg = "Sous la violence de la parade, votre " + rollData.arme.name + " s'est brisée sous le coup!"; msg = "Sous la violence de la parade, votre " + rollData.arme.name + " s'est brisée sous le coup!";
} else { } else {
this.defender.updateEmbeddedEntity("OwnedItem", {_id: rollData.arme._id, 'data.resistance': resistance }); this.defender.updateEmbeddedEntity("OwnedItem", { _id: rollData.arme._id, 'data.resistance': resistance });
msg = "En parant, vous endommagez votre " + rollData.arme.name + ", qui perd " + dmg + " de résistance. "; msg = "En parant, vous endommagez votre " + rollData.arme.name + ", qui perd " + dmg + " de résistance. ";
} }
} }
// Jet de désarmement // Jet de désarmement
if (resistance > 0 && !rollData.arme.name.toLowerCase().includes('bouclier') ) { // Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132) if (resistance > 0 && !rollData.arme.name.toLowerCase().includes('bouclier')) { // Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
let desarme = await RdDResolutionTable.rollData({ let desarme = await RdDResolutionTable.rollData({
caracValue: this.defender.data.data.carac.force.value, caracValue: this.defender.data.data.carac.force.value,
finalLevel: Misc.toInt(rollData.competence.data.niveau) - dmg, finalLevel: Misc.toInt(rollData.competence.data.niveau) - dmg,
showDice: false}); showDice: false
if ( desarme.isEchec) { });
if (desarme.isEchec) {
msg += "Vous ne parvenez pas à garder votre arme en main, elle tombe au sol à vos pieds"; msg += "Vous ne parvenez pas à garder votre arme en main, elle tombe au sol à vos pieds";
} }
} }
ChatMessage.create( { content: msg, ChatMessage.create({
user: game.user._id, content: msg,
whisper: [game.user._id, ChatMessage.getWhisperRecipients("GM") ] } ); user: game.user._id,
whisper: [game.user._id, ChatMessage.getWhisperRecipients("GM")]
});
} }
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async computeRecul( rollData, encaisser = undefined ) { // Calcul du recul (p. 132) async computeRecul(rollData, encaisser = undefined) { // Calcul du recul (p. 132)
if ( rollData.arme || encaisser ) { if (rollData.arme || encaisser) {
if ( (rollData.attackerRoll.particuliereAttaque && rollData.attackerRoll.particuliereAttaque == 'force') || rollData.attackerRoll.tactique == 'charge') { if ((rollData.attackerRoll.particuliereAttaque && rollData.attackerRoll.particuliereAttaque == 'force') || rollData.attackerRoll.tactique == 'charge') {
let reculNiveau = Misc.toInt(this.defender.data.data.carac.taille.value) - (rollData.attackerRoll.forceValue+rollData.attackerRoll.arme.data.dommagesReels); let reculNiveau = Misc.toInt(this.defender.data.data.carac.taille.value) - (rollData.attackerRoll.forceValue + rollData.attackerRoll.arme.data.dommagesReels);
let recul = await RdDResolutionTable.rollData({ let recul = await RdDResolutionTable.rollData({
caracValue: 10, caracValue: 10,
finalLevel: reculNiveau, finalLevel: reculNiveau,
showDice: false}); showDice: false
});
let msg = ""; let msg = "";
if (recul.isSuccess) { if (recul.isSuccess) {
@ -632,16 +642,19 @@ export class RdDCombat {
let chute = await RdDResolutionTable.rollData({ let chute = await RdDResolutionTable.rollData({
caracValue: this.defender.data.data.carac.agilite.value, caracValue: this.defender.data.data.carac.agilite.value,
finalLevel: reculNiveau, finalLevel: reculNiveau,
showDice: false}); showDice: false
if ( !chute.isSuccess || recul.isETotal ) { });
if (!chute.isSuccess || recul.isETotal) {
msg = "Sous la violence du coup, vous reculez et chutez au sol ! Vous ne pouvez plus attaquer ce round."; msg = "Sous la violence du coup, vous reculez et chutez au sol ! Vous ne pouvez plus attaquer ce round.";
} else { } else {
msg = "La violence du choc vous fait reculer de quelques mètres ! Vous ne pouvez plus attaquer ce round."; msg = "La violence du choc vous fait reculer de quelques mètres ! Vous ne pouvez plus attaquer ce round.";
} }
} }
ChatMessage.create( {content: msg, ChatMessage.create({
user: game.user._id, content: msg,
whisper: [game.user._id, ChatMessage.getWhisperRecipients("GM") ] } ); user: game.user._id,
whisper: [game.user._id, ChatMessage.getWhisperRecipients("GM")]
});
} }
} }
} }

View File

@ -8,7 +8,6 @@ export class RdDRollTables {
const table = await pack.getEntity(entry._id); const table = await pack.getEntity(entry._id);
const draw = await table.draw({ displayChat: toChat }); const draw = await table.draw({ displayChat: toChat });
console.log("RdDRollTables", tableName, toChat, ":", draw); console.log("RdDRollTables", tableName, toChat, ":", draw);
console.log("RdDRollTables", tableName, toChat, ":", draw.roll, draw.results);
return draw; return draw;
} }
@ -16,9 +15,25 @@ export class RdDRollTables {
static async drawItemFromRollTable(tableName, toChat) { static async drawItemFromRollTable(tableName, toChat) {
const draw = await RdDRollTables.genericGetTableResult(tableName, toChat); const draw = await RdDRollTables.genericGetTableResult(tableName, toChat);
const drawnItemRef = draw.results.length > 0 ? draw.results[0] : undefined; const drawnItemRef = draw.results.length > 0 ? draw.results[0] : undefined;
const pack = game.packs.get(drawnItemRef.collection); if (drawnItemRef.collection) {
return await pack.getEntity(drawnItemRef.resultId); const pack = game.packs.get(drawnItemRef.collection);
return await pack.getEntity(drawnItemRef.resultId);
}
ui.notifications.warn("le tirage ne correspond pas à une entrée d'un Compendium")
return drawnItemRef.text;
} }
/* -------------------------------------------- */
static async drawTextFromRollTable(tableName, toChat) {
const draw = await RdDRollTables.genericGetTableResult(tableName, toChat);
const drawnItemRef = draw.results.length > 0 ? draw.results[0] : undefined;
if (drawnItemRef.collection) {
ui.notifications.warn("le tirage correspond à une entrée d'un Compendium, on attendait un texte")
return await pack.getEntity(drawnItemRef.resultId);
}
return drawnItemRef.text;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getSouffle(toChat = true) { static async getSouffle(toChat = true) {
return await RdDRollTables.drawItemFromRollTable("Souffles de Dragon", toChat); return await RdDRollTables.drawItemFromRollTable("Souffles de Dragon", toChat);
@ -48,4 +63,10 @@ export class RdDRollTables {
static async getTarot(toChat = true) { static async getTarot(toChat = true) {
return await RdDRollTables.drawItemFromRollTable("Tarot Draconique", toChat); return await RdDRollTables.drawItemFromRollTable("Tarot Draconique", toChat);
} }
static async getMaladresse(options = {toChat: false, arme: false}) {
return await RdDRollTables.drawTextFromRollTable(
options.arme ? "Maladresse armé" : "Maladresses non armé",
options.toChat);
}
} }