Vincent Vandemeulebrouck
7eb1d9f838
Le malus armure est correctement affiché dans l'onglet caractéristiques. Il n'est plus stocké dans l'acteur mais calculé.
352 lines
15 KiB
JavaScript
352 lines
15 KiB
JavaScript
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
|
import { HtmlUtility } from "./html-utility.js";
|
|
import { RdDItemCompetence } from "./item-competence.js";
|
|
import { RdDItemSort } from "./item-sort.js";
|
|
import { Misc } from "./misc.js";
|
|
import { RdDBonus } from "./rdd-bonus.js";
|
|
import { RdDCarac } from "./rdd-carac.js";
|
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
|
|
|
/**
|
|
* Extend the base Dialog entity to select roll parameters
|
|
* @extends {Dialog}
|
|
*/
|
|
/* -------------------------------------------- */
|
|
export class RdDRoll extends Dialog {
|
|
|
|
/* -------------------------------------------- */
|
|
static async create(actor, rollData, dialogConfig, action) {
|
|
RdDRoll._ensureCorrectAction(action);
|
|
RdDRoll._setDefaultOptions(actor, rollData);
|
|
|
|
const html = await renderTemplate(dialogConfig.html, rollData);
|
|
|
|
let options = { classes: ["rdd-roll-dialog"], width: 600, height: 'fit-content', 'z-index': 99999, close: html => {} };
|
|
if (dialogConfig.close) {
|
|
options.close = dialogConfig.close;
|
|
}
|
|
return new RdDRoll(actor, rollData, html, options, action);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static _setDefaultOptions(actor, rollData) {
|
|
let defaultRollData = {
|
|
alias: actor.name,
|
|
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
|
|
difficultesLibres: CONFIG.RDD.difficultesLibres,
|
|
etat: actor.getEtatGeneral(),
|
|
moral: actor.getMoralTotal(), /* La valeur du moral pour les jets de volonté */
|
|
carac: actor.system.carac,
|
|
finalLevel: 0,
|
|
diffConditions: 0,
|
|
diffLibre: rollData.competence?.system.default_diffLibre ?? 0,
|
|
perteMoralEchec: false, /* Pour l'affichage dans le chat */
|
|
use: {
|
|
moral: false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */
|
|
libre: true,
|
|
conditions: true,
|
|
surenc: actor.isSurenc(),
|
|
encTotal: true
|
|
},
|
|
isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
|
malusArmureValue: actor.getMalusArmure(),
|
|
surencMalusValue: actor.computeMalusSurEncombrement(),
|
|
encTotal: actor.getEncTotal(),
|
|
ajustementAstrologique: actor.ajustementAstrologique(),
|
|
surprise: actor.getSurprise(false),
|
|
canClose: true,
|
|
isGM: game.user.isGM,
|
|
forceDiceResult: -1
|
|
}
|
|
// Mini patch :Ajout du rêve actuel
|
|
if (actor.system.type == "personnage") {
|
|
defaultRollData.carac["reve-actuel"] = actor.system.reve.reve
|
|
}
|
|
|
|
mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });
|
|
if (rollData.forceCarac) {
|
|
rollData.carac = rollData.forceCarac;
|
|
}
|
|
rollData.diviseurSignificative = RdDRoll.getDiviseurSignificative(rollData);
|
|
|
|
RollDataAjustements.calcul(rollData, actor);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static getDiviseurSignificative(rollData) {
|
|
let facteurSign = 1;
|
|
if (rollData.surprise == 'demi') {
|
|
facteurSign *= 2;
|
|
}
|
|
if (rollData.needParadeSignificative) {
|
|
facteurSign *= 2;
|
|
}
|
|
if (RdDBonus.isDefenseAttaqueFinesse(rollData)) {
|
|
facteurSign *= 2;
|
|
}
|
|
if (!ReglesOptionnelles.isUsing('tripleSignificative')) {
|
|
facteurSign = Math.min(facteurSign, 4);
|
|
}
|
|
return facteurSign;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static _ensureCorrectAction(action) {
|
|
if (action.callbacks == undefined) {
|
|
console.warn('No callback defined for ', action.name);
|
|
action.callbacks = [{ action: r => console.warn(action.name, r) }];
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
constructor(actor, rollData, html, options, action) {
|
|
let conf = {
|
|
title: action.label,
|
|
content: html,
|
|
buttons: {
|
|
"onAction": {
|
|
label: action.label, callback: html => {
|
|
this.rollData.canClose = true;
|
|
this.onAction(action)
|
|
}
|
|
}
|
|
},
|
|
default: "onAction",
|
|
close: options.close
|
|
};
|
|
super(conf, options);
|
|
|
|
this.actor = actor;
|
|
this.rollData = rollData;
|
|
}
|
|
|
|
activateListeners(html) {
|
|
super.activateListeners(html);
|
|
this.html = html;
|
|
this.bringToTop();
|
|
|
|
console.log('RdDRoll.activateListeners', this.rollData);
|
|
|
|
// Update html, according to rollData
|
|
if (this.rollData.competence) {
|
|
const defaut_carac = this.rollData.competence.system.defaut_carac
|
|
// Set the default carac from the competence item
|
|
this.rollData.selectedCarac = this.rollData.carac[defaut_carac];
|
|
this.html.find("[name='carac']").val(defaut_carac);
|
|
}
|
|
if (this.rollData.selectedSort) {
|
|
this.setSelectedSort(this.rollData.selectedSort);
|
|
this.html.find(".draconic").val(this.rollData.selectedSort.system.listIndex); // Uniquement a la selection du sort, pour permettre de changer
|
|
}
|
|
RdDItemSort.setCoutReveReel(this.rollData.selectedSort);
|
|
this.html.find("[name='diffLibre']").val(Misc.toInt(this.rollData.diffLibre));
|
|
this.html.find("[name='diffConditions']").val(Misc.toInt(this.rollData.diffConditions));
|
|
this.updateRollResult(html);
|
|
|
|
this.html.find("[name='diffLibre']").change((event) => {
|
|
this.rollData.diffLibre = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find("[name='diffConditions']").change((event) => {
|
|
this.rollData.diffConditions = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find("[name='force-dice-result']").change((event) => {
|
|
this.rollData.forceDiceResult = Misc.toInt(event.currentTarget.value);
|
|
});
|
|
this.html.find("[name='carac']").change((event) => {
|
|
let caracKey = event.currentTarget.value;
|
|
this.rollData.selectedCarac = this.rollData.carac[caracKey]; // Update the selectedCarac
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find('.roll-draconic').change((event) => {
|
|
let draconicKey = Misc.toInt(event.currentTarget.value);
|
|
this.rollData.competence = this.rollData.draconicList[draconicKey]; // Update the selectedCarac
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find('.roll-sort').change((event) => {
|
|
let sortKey = Misc.toInt(event.currentTarget.value);
|
|
this.setSelectedSort(this.rollData.sortList[sortKey]);
|
|
this.updateRollResult(html);
|
|
this.html.find("[name='diffLibre']").val(this.rollData.diffLibre);
|
|
});
|
|
this.html.find('.roll-carac-competence').change((event) => {
|
|
const competence = event.currentTarget.value;
|
|
this.rollData.competence = this.rollData.competences.find(it => it.name == competence);
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find('.roll-signedraconique').change((event) => {
|
|
let sortKey = Misc.toInt(event.currentTarget.value);
|
|
this.setSelectedSigneDraconique(this.rollData.signes[sortKey]);
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find("[name='ptreve-variable']").change((event) => {
|
|
let ptreve = Misc.toInt(event.currentTarget.value);
|
|
this.rollData.selectedSort.system.ptreve_reel = ptreve;
|
|
console.log("RdDRollSelectDialog - Cout reve", ptreve);
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find("[name='mortalite']").change((event) => {
|
|
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find('.cuisine-proportions').change((event) => {
|
|
this.rollData.proportions = Number(event.currentTarget.value);
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find('.select-by-name').change((event) => {
|
|
const attribute = event.currentTarget.attributes['name'].value;
|
|
this.rollData[attribute] = event.currentTarget.value;
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find('.checkbox-by-name').change((event) => {
|
|
const attribute = event.currentTarget.attributes['name'].value;
|
|
this.rollData[attribute] = event.currentTarget.checked;
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find('input.use-encTotal').change((event) => {
|
|
this.rollData.use.encTotal = event.currentTarget.checked;
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find('input.use-surenc').change((event) => {
|
|
this.rollData.use.surenc = event.currentTarget.checked;
|
|
this.updateRollResult(html);
|
|
});
|
|
this.html.find('.appel-moral').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */
|
|
this.rollData.use.moral = !this.rollData.use.moral;
|
|
const appelMoral = this.html.find('.icon-appel-moral')[0];
|
|
const tooltip = this.html.find('.tooltipAppelAuMoralText')[0];
|
|
if (this.rollData.use.moral) {
|
|
if (this.rollData.moral > 0) {
|
|
tooltip.innerHTML = "Appel au moral";
|
|
appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg";
|
|
} else {
|
|
tooltip.innerHTML = "Appel à l'énergie du désespoir";
|
|
appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-malheureux.svg";
|
|
}
|
|
} else {
|
|
tooltip.innerHTML = "Sans appel au moral";
|
|
appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-neutre.svg";
|
|
}
|
|
this.updateRollResult(html);
|
|
});
|
|
// Section Méditation
|
|
this.html.find('.conditionMeditation').change((event) => {
|
|
let condition = event.currentTarget.attributes['name'].value;
|
|
this.rollData.conditionMeditation[condition] = event.currentTarget.checked;
|
|
this.updateRollResult(html);
|
|
});
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
close() {
|
|
if (this.rollData.canClose) {
|
|
return super.close();
|
|
}
|
|
ui.notifications.info("Vous devez faire ce jet de dés!");
|
|
}
|
|
|
|
async onAction(action) {
|
|
this.rollData.forceDiceResult = Number.parseInt(this.html.find("[name='force-dice-result']").val()) ?? -1;
|
|
await RdDResolutionTable.rollData(this.rollData);
|
|
console.log("RdDRoll -=>", this.rollData, this.rollData.rolled);
|
|
if (action.callbacks)
|
|
for (let callback of action.callbacks) {
|
|
if (callback.condition == undefined || callback.condition(this.rollData)) {
|
|
await callback.action(this.rollData);
|
|
}
|
|
}
|
|
}
|
|
|
|
async setSelectedSort(sort) {
|
|
this.rollData.selectedSort = sort; // Update the selectedCarac
|
|
this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.system.draconic);
|
|
this.rollData.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord);
|
|
this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7);
|
|
RdDItemSort.setCoutReveReel(sort);
|
|
const htmlSortDescription = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html", { sort: sort });
|
|
this.html.find(".sort-ou-rituel").text(sort.system.isrituel ? "rituel" : "sort");
|
|
this.html.find(".bonus-case").text(`${this.rollData.bonus}%`);
|
|
this.html.find(".placeholder-description-sort").children().remove();
|
|
this.html.find(".placeholder-description-sort").append(htmlSortDescription);
|
|
this.html.find(".roll-draconic").val(sort.system.listIndex);
|
|
this.html.find(".div-sort-difficulte-fixe").text(Misc.toSignedString(sort.system.difficulte));
|
|
this.html.find(".div-sort-ptreve-fixe").text(sort.system.ptreve);
|
|
const diffVariable = RdDItemSort.isDifficulteVariable(sort);
|
|
const coutVariable = RdDItemSort.isCoutVariable(sort);
|
|
|
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-non-rituel"), !sort.system.isrituel);
|
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-difficulte-var"), diffVariable);
|
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-difficulte-fixe"), !diffVariable);
|
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-ptreve-var"), coutVariable);
|
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-ptreve-fixe"), !coutVariable);
|
|
}
|
|
|
|
async setSelectedSigneDraconique(signe) {
|
|
this.rollData.signe = signe;
|
|
this.rollData.diffLibre = signe.system.difficulte,
|
|
$(".signe-difficulte").text(Misc.toSignedString(this.rollData.diffLibre));
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async updateRollResult(html) {
|
|
let rollData = this.rollData;
|
|
|
|
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat())
|
|
rollData.caracValue = parseInt(rollData.selectedCarac.value)
|
|
rollData.mortalite = rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite ?? rollData.mortalite ?? 'mortel';
|
|
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);
|
|
let dmgText = Misc.toSignedString(rollData.dmg.total);
|
|
|
|
switch (rollData.mortalite) {
|
|
case 'non-mortel': dmgText = `(${dmgText}) non-mortel`; break;
|
|
case 'empoignade': dmgText = `empoignade`; break;
|
|
}
|
|
|
|
RollDataAjustements.calcul(rollData, this.actor);
|
|
|
|
const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel))
|
|
const adjustements = await this.buildAjustements(rollData);
|
|
|
|
HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac));
|
|
HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
|
|
HtmlUtility.showControlWhen(this.html.find(".utilisation-moral"), rollData.use.appelAuMoral);
|
|
HtmlUtility.showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
|
HtmlUtility.showControlWhen(this.html.find(".diffMoral"), rollData.ajustements.moralTotal.used);
|
|
|
|
// Mise à jour valeurs
|
|
this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
|
|
this.html.find("[name='mortalite']").prop('checked', rollData.mortalite == 'non-mortel');
|
|
this.html.find(".dmg-arme-actor").text(dmgText);
|
|
this.html.find("div.placeholder-ajustements").empty().append(adjustements);
|
|
this.html.find("div.placeholder-resolution").empty().append(resolutionTable)
|
|
}
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
async buildAjustements(rollData) {
|
|
return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html`, rollData);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_getTitle(rollData) {
|
|
const carac = rollData.selectedCarac.label;
|
|
if (!rollData.competence) {
|
|
return carac;
|
|
}
|
|
const compName = rollData.competence.name;
|
|
if (rollData.draconicList && rollData.selectedSort) {
|
|
return compName + " - " + rollData.selectedSort.name;
|
|
}
|
|
// If a weapon is there, add it in the title
|
|
const niveau = Misc.toSignedString(rollData.competence.system.niveau)
|
|
if (compName == carac) {
|
|
// cas des créatures
|
|
return carac + " Niveau " + niveau
|
|
}
|
|
const armeTitle = (rollData.arme) ? " (" + rollData.arme.name + ") " : "";
|
|
return carac + "/" + compName + armeTitle + " Niveau " + niveau
|
|
}
|
|
}
|