#113 règles de combat optionnelles

This commit is contained in:
Vincent Vandemeulebrouck 2021-01-25 08:48:03 +01:00
parent 56bb117a0c
commit 91610894cc
4 changed files with 130 additions and 8 deletions

View File

@ -12,7 +12,7 @@ import { ChatUtility } from "./chat-utility.js";
import { RdDItemSort } from "./item-sort.js"; import { RdDItemSort } from "./item-sort.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { RdDEncaisser } from "./rdd-roll-encaisser.js"; import { RdDEncaisser } from "./rdd-roll-encaisser.js";
import { RdDCombat } from "./rdd-combat.js"; import { RdDCombat, RdDCombatSettings } from "./rdd-combat.js";
import { DeDraconique } from "./de-draconique.js"; import { DeDraconique } from "./de-draconique.js";
import { RdDAudio } from "./rdd-audio.js"; import { RdDAudio } from "./rdd-audio.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
@ -2222,6 +2222,9 @@ export class RdDActor extends Actor {
} }
_deteriorerArmure(item, dmg) { _deteriorerArmure(item, dmg) {
if (!RdDCombatSettings.isUsingDeteriorationArmure()) {
return;
}
let update = duplicate(item); let update = duplicate(item);
update.data.deterioration = (update.data.deterioration ?? 0) + dmg; update.data.deterioration = (update.data.deterioration ?? 0) + dmg;
if (update.data.deterioration >= 10) { if (update.data.deterioration >= 10) {

View File

@ -11,6 +11,7 @@ import { RdDRollTables } from "./rdd-rolltables.js";
export class RdDCombat { export class RdDCombat {
static init() { static init() {
RdDCombatSettings.onInit();
this.initStorePasseArmes(); this.initStorePasseArmes();
Hooks.on("updateCombat", (combat, data) => { RdDCombat.onUpdateCombat(combat, data) }); Hooks.on("updateCombat", (combat, data) => { RdDCombat.onUpdateCombat(combat, data) });
Hooks.on("preDeleteCombat", (combat, options) => { RdDCombat.onPreDeleteCombat(combat, options); }); Hooks.on("preDeleteCombat", (combat, options) => { RdDCombat.onPreDeleteCombat(combat, options); });
@ -594,7 +595,6 @@ export class RdDCombat {
dialog.render(true); dialog.render(true);
} }
_prepareParade(attackerRoll, armeParade) { _prepareParade(attackerRoll, armeParade) {
const compName = armeParade.data.competence; const compName = armeParade.data.competence;
const armeAttaque = attackerRoll.arme; const armeAttaque = attackerRoll.arme;
@ -606,7 +606,7 @@ export class RdDCombat {
competence: this.defender.getCompetence(compName), competence: this.defender.getCompetence(compName),
arme: armeParade, arme: armeParade,
surprise: this.defender.getSurprise(true), surprise: this.defender.getSurprise(true),
needParadeSignificative: RdDItemArme.needParadeSignificative(armeAttaque, armeParade), needParadeSignificative: RdDCombatSettings.isUsingCategorieParade() && RdDItemArme.needParadeSignificative(armeAttaque, armeParade),
needResist: RdDItemArme.needArmeResist(armeAttaque, armeParade), needResist: RdDItemArme.needArmeResist(armeAttaque, armeParade),
carac: this.defender.data.data.carac, carac: this.defender.data.data.carac,
show: {} show: {}
@ -632,6 +632,9 @@ export class RdDCombat {
if (RdDBonus.isDefenseAttaqueFinesse(defenderRoll)) { if (RdDBonus.isDefenseAttaqueFinesse(defenderRoll)) {
facteurSign *= 2; facteurSign *= 2;
} }
if (!RdDCombatSettings.isUsingTripleSignificative()) {
facteurSign = Math.min(facteurSign, 4);
}
return facteurSign; return facteurSign;
} }
@ -741,6 +744,9 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
async computeDeteriorationArme(rollData) { async computeDeteriorationArme(rollData) {
if (!RdDCombatSettings.isUsingResistanceArmeParade()) {
return;
}
const attackerRoll = rollData.attackerRoll; const attackerRoll = rollData.attackerRoll;
// Est-ce une parade normale? // Est-ce une parade normale?
if (rollData.arme && attackerRoll && !rollData.rolled.isPart) { if (rollData.arme && attackerRoll && !rollData.rolled.isPart) {
@ -772,7 +778,7 @@ export class RdDCombat {
} }
} }
// Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132) // Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
if (resistance > 0 && RdDItemArme.getCategorieParade(rollData.arme) != 'boucliers') { if (RdDCombatSettings.isUsingDefenseurDesarme() && resistance > 0 && RdDItemArme.getCategorieParade(rollData.arme) != 'boucliers') {
let desarme = await RdDResolutionTable.rollData({ let desarme = await RdDResolutionTable.rollData({
caracValue: this.defender.getForce(), caracValue: this.defender.getForce(),
finalLevel: Misc.toInt(rollData.competence.data.niveau) - dmg, finalLevel: Misc.toInt(rollData.competence.data.niveau) - dmg,
@ -787,7 +793,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
async computeRecul(defenderRoll) { // Calcul du recul (p. 132) async computeRecul(defenderRoll) { // Calcul du recul (p. 132)
const attackerRoll = defenderRoll.attackerRoll; const attackerRoll = defenderRoll.attackerRoll;
if (this._isAttaqueCauseRecul(attackerRoll)) { if (RdDCombatSettings.isUsingRecul() && this._isAttaqueCauseRecul(attackerRoll)) {
const impact = this._computeImpactRecul(attackerRoll); const impact = this._computeImpactRecul(attackerRoll);
const rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impact }); const rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impact });
if (rollRecul.rolled.isSuccess) { if (rollRecul.rolled.isSuccess) {
@ -909,5 +915,92 @@ export class RdDCombat {
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, data) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, data)
}); });
} }
} }
export class RdDCombatSettings extends FormApplication {
static onInit() {
game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-recul", { name: "rdd-combat-recul", scope: "world", config: false, default: true, type: Boolean });
game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-resistanceArmeParade", { name: "rdd-combat-resistanceArmeParade", scope: "world", config: false, default: true, type: Boolean });
game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-deteriorationArmure", { name: "rdd-combat-deteriorationArmure", scope: "world", config: false, default: true, type: Boolean });
game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-defenseurDesarme", { name: "rdd-combat-defenseurDesarme", scope: "world", config: false, default: true, type: Boolean });
game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-categorieParade", { name: "rdd-combat-categorieParade", scope: "world", config: false, default: true, type: Boolean });
game.settings.register("foundryvtt-reve-de-dragon", "rdd-combat-tripleSignificative", { name: "rdd-combat-tripleSignificative", scope: "world", config: false, default: true, type: Boolean });
game.settings.registerMenu("foundryvtt-reve-de-dragon", "rdd-combat-options", {
name: "Choisir les options de combat",
label: "Choix des options de combat",
hint: "Ouvre la fenêtre de sélection des options de combats pour désactiver certaines règles",
icon: "fas fa-bars",
type: RdDCombatSettings,
restricted: true
});
}
constructor(...args) {
super(...args);
}
static get defaultOptions() {
const options = super.defaultOptions;
mergeObject(options, {
id: "combat-settings",
template: "systems/foundryvtt-reve-de-dragon/templates/combat-settings.html",
height: 600,
width: 350,
minimizable: false,
closeOnSubmit: true,
title: "Options de combat"
});
return options;
}
getData() {
let data = super.getData();
data.recul = RdDCombatSettings.isUsingRecul();
data.resistanceArmeParade = RdDCombatSettings.isUsingResistanceArmeParade();
data.deteriorationArmure = RdDCombatSettings.isUsingDeteriorationArmure();
data.defenseurDesarme = RdDCombatSettings.isUsingDefenseurDesarme();
data.categorieParade = RdDCombatSettings.isUsingCategorieParade();
data.tripleSignificative = RdDCombatSettings.isUsingTripleSignificative();
return data;
}
static isUsingRecul() {
return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-recul");
}
static isUsingResistanceArmeParade() {
return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-resistanceArmeParade");
}
static isUsingDeteriorationArmure() {
return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-deteriorationArmure");
}
static isUsingDefenseurDesarme() {
return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-defenseurDesarme");
}
static isUsingCategorieParade() {
return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-categorieParade");
}
static isUsingTripleSignificative() {
return game.settings.get("foundryvtt-reve-de-dragon", "rdd-combat-tripleSignificative");
}
activateListeners(html) {
html.find(".select-option").click((event) => {
if (event.currentTarget.attributes.name) {
let id = event.currentTarget.attributes.name.value;
let isChecked = event.currentTarget.checked;
game.settings.set("foundryvtt-reve-de-dragon", id, isChecked);
}
});
}
async _updateObject(event, formData) {
this.close();
}
}

View File

@ -42,8 +42,6 @@ export class RdDRoll extends Dialog {
finalLevel: 0, finalLevel: 0,
diffConditions: 0, diffConditions: 0,
diffLibre: rollData.competence?.data.default_diffLibre ?? 0, diffLibre: rollData.competence?.data.default_diffLibre ?? 0,
editLibre: true,
editConditions: true,
malusArmureValue: actor.getMalusArmure(), malusArmureValue: actor.getMalusArmure(),
surencMalusFlag: actor.isPersonnage() ? (actor.data.data.compteurs.surenc.value < 0) : false, surencMalusFlag: actor.isPersonnage() ? (actor.data.data.compteurs.surenc.value < 0) : false,
surencMalusValue: actor.getSurenc(), surencMalusValue: actor.getSurenc(),

View File

@ -0,0 +1,28 @@
<form autocomplete="off" onsubmit="event.preventDefault();">
<ul>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-recul" {{#if recul}}checked{{/if}}/>
<label>Appliquer le recul en cas de particulière en force ou de charge</label>
</li>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-resistanceArmeParade" {{#if resistanceArmeParade}}checked{{/if}}/>
<label>Faire le jet de résistance des armes lors de parades pouvant les endommager</label>
</li>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-deteriorationArmure" {{#if deteriorationArmure}}checked{{/if}}/>
<label>Tenir compte de la détérioration des armures</label>
</li>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-defenseurDesarme" {{#if defenseurDesarme}}checked{{/if}}/>
<label>Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier</label>
</li>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-categorieParade" {{#if categorieParade}}checked{{/if}}/>
<label>Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes</label>
</li>
<li>
<input class="select-option" type="checkbox" name="rdd-combat-tripleSignificative" {{#if tripleSignificative}}checked{{/if}}/>
<label>En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès</label>
</li>
</ul>
</form>