25d7a447a8
Ajout de méthode Misc.data pour accéder aux data des Actor/Item Dans le cas où on est sur un Actor/Item, retourne le document (noeud data) Dans les autres cas, retourne l'objet lkui même (donc, le document) Du coup, on devrait pouvoir facilement changer en 0.8.0
337 lines
13 KiB
JavaScript
337 lines
13 KiB
JavaScript
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
|
import { HtmlUtility } from "./html-utility.js";
|
|
import { RdDItemCompetence } from "./item-competence.js";
|
|
import { RdDItemMeditation } from "./item-meditation.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";
|
|
|
|
/**
|
|
* Extend the base Dialog entity to select roll parameters
|
|
* @extends {Dialog}
|
|
*/
|
|
/* -------------------------------------------- */
|
|
export class RdDRoll extends Dialog {
|
|
|
|
/* -------------------------------------------- */
|
|
static async create(actor, rollData, dialogConfig, ...actions) {
|
|
|
|
if (actor.isRollWindowsOpened()) {
|
|
ui.notifications.warn("Vous avez déja une fenêtre de Test ouverte, il faut la fermer avant d'en ouvrir une autre.")
|
|
return;
|
|
}
|
|
actor.setRollWindowsOpened(true);
|
|
|
|
RdDRoll._ensureCorrectActions(actions);
|
|
RdDRoll._setDefaultOptions(actor, rollData);
|
|
|
|
const html = await renderTemplate(dialogConfig.html, rollData);
|
|
|
|
let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 };
|
|
if (dialogConfig.options) {
|
|
mergeObject(options, dialogConfig.options, { overwrite: true })
|
|
}
|
|
return new RdDRoll(actor, rollData, html, options, actions, dialogConfig.close);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static _setDefaultOptions(actor, rollData) {
|
|
const actorData = Misc.data(actor);
|
|
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: actorData.data.carac,
|
|
finalLevel: 0,
|
|
diffConditions: 0,
|
|
diffLibre: rollData.competence?.data.default_diffLibre ?? 0,
|
|
malusArmureValue: actor.getMalusArmure(),
|
|
surencMalusFlag: actor.isPersonnage() ? (actorData.data.compteurs.surenc.value < 0) : false,
|
|
surencMalusValue: actor.getSurenc(),
|
|
useMalusSurenc: false,
|
|
useMoral: false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */
|
|
perteMoralEchec: false, /* Pour l'affichage dans le chat */
|
|
use: { libre: true, conditions: true, surenc: false, encTotal: false },
|
|
isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
|
useMalusEncTotal: false,
|
|
encTotal: actor.getEncTotal(),
|
|
ajustementAstrologique: actor.ajustementAstrologique(),
|
|
surprise: actor.getSurprise(false),
|
|
canClose: true
|
|
};
|
|
|
|
|
|
mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });
|
|
if (rollData.forceCarac) {
|
|
rollData.carac = rollData.forceCarac;
|
|
}
|
|
RollDataAjustements.calcul(rollData, actor);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static _ensureCorrectActions(actions) {
|
|
if (actions.length == 0) {
|
|
throw 'No action defined';
|
|
}
|
|
actions.forEach(action => {
|
|
if (action.callbacks == undefined) {
|
|
action.callbacks = [{ action: r => console.log(action.name, r) }];
|
|
}
|
|
});
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
constructor(actor, rollData, html, options, actions, close = undefined) {
|
|
let conf = {
|
|
title: actions[0].label,
|
|
content: html,
|
|
buttons: {},
|
|
default: actions[0].name,
|
|
close: close
|
|
};
|
|
for (let action of actions) {
|
|
conf.buttons[action.name] = {
|
|
label: action.label, callback: html => {
|
|
this.rollData.canClose = true;
|
|
this.onAction(action, html)
|
|
}
|
|
};
|
|
}
|
|
|
|
super(conf, options);
|
|
|
|
this.actor = actor;
|
|
this.rollData = rollData;
|
|
}
|
|
|
|
close() {
|
|
if (this.rollData.canClose) {
|
|
this.actor.setRollWindowsOpened(false);
|
|
return super.close();
|
|
}
|
|
ui.notifications.info("Vous devez faire ce jet de dés!");
|
|
}
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
async onAction(action, html) {
|
|
await RdDResolutionTable.rollData(this.rollData);
|
|
console.log("RdDRoll -=>", this.rollData, this.rollData.rolled);
|
|
this.actor.setRollWindowsOpened(false);
|
|
|
|
if (action.callbacks)
|
|
for (let callback of action.callbacks) {
|
|
if (callback.condition == undefined || callback.condition(this.rollData)) {
|
|
await callback.action(this.rollData);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
activateListeners(html) {
|
|
super.activateListeners(html);
|
|
|
|
this.bringToTop();
|
|
|
|
var dialog = this;
|
|
|
|
function onLoad() {
|
|
let rollData = dialog.rollData;
|
|
// Update html, according to data
|
|
if (rollData.competence) {
|
|
// Set the default carac from the competence item
|
|
rollData.selectedCarac = rollData.carac[rollData.competence.data.defaut_carac];
|
|
$("#carac").val(rollData.competence.data.defaut_carac);
|
|
}
|
|
if (rollData.selectedSort) {
|
|
$("#draconic").val(rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
|
|
}
|
|
RdDItemSort.setCoutReveReel(rollData.selectedSort);
|
|
$("#diffLibre").val(Misc.toInt(rollData.diffLibre));
|
|
$("#diffConditions").val(Misc.toInt(rollData.diffConditions));
|
|
dialog.updateRollResult();
|
|
}
|
|
|
|
// Setup everything onload
|
|
$(function () { onLoad(); });
|
|
|
|
// Update !
|
|
html.find('#diffLibre').change((event) => {
|
|
this.rollData.diffLibre = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus
|
|
this.updateRollResult();
|
|
});
|
|
html.find('#diffConditions').change((event) => {
|
|
this.rollData.diffConditions = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus
|
|
this.updateRollResult();
|
|
});
|
|
html.find('#carac').change((event) => {
|
|
let caracKey = event.currentTarget.value;
|
|
this.rollData.selectedCarac = this.rollData.carac[caracKey]; // Update the selectedCarac
|
|
this.updateRollResult();
|
|
});
|
|
html.find('#draconic').change((event) => {
|
|
let draconicKey = Misc.toInt(event.currentTarget.value);
|
|
this.rollData.competence = this.rollData.draconicList[draconicKey]; // Update the selectedCarac
|
|
this.updateRollResult();
|
|
});
|
|
html.find('#sort').change((event) => {
|
|
let sortKey = Misc.toInt(event.currentTarget.value);
|
|
this.rollData.selectedSort = this.rollData.sortList[sortKey]; // Update the selectedCarac
|
|
this.rollData.bonus = RdDItemSort.getCaseBonus(this.rollData.selectedSort, this.rollData.tmr.coord);
|
|
RdDItemSort.setCoutReveReel(this.rollData.selectedSort);
|
|
$("#draconic").val(this.rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
|
|
this.updateRollResult();
|
|
});
|
|
html.find('#ptreve-variable').change((event) => {
|
|
let ptreve = Misc.toInt(event.currentTarget.value);
|
|
this.rollData.selectedSort.data.ptreve_reel = ptreve;
|
|
console.log("RdDRollSelectDialog - Cout reve", ptreve);
|
|
this.updateRollResult();
|
|
});
|
|
html.find('#coupsNonMortels').change((event) => {
|
|
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
|
|
this.updateRollResult();
|
|
});
|
|
html.find('#tactique-combat').change((event) => {
|
|
this.rollData.tactique = event.currentTarget.value;
|
|
this.updateRollResult();
|
|
});
|
|
html.find('#useMalusSurenc').change((event) => {
|
|
this.rollData.useMalusSurenc = event.currentTarget.checked;
|
|
this.updateRollResult();
|
|
});
|
|
html.find('#useMalusEncTotal').change((event) => {
|
|
this.rollData.useMalusEncTotal = event.currentTarget.checked;
|
|
this.updateRollResult();
|
|
});
|
|
html.find('.imgAppelAuMoral').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */
|
|
this.rollData.useMoral = !this.rollData.useMoral;
|
|
if (this.rollData.useMoral) {
|
|
if (this.rollData.moral > 0) {
|
|
html.find('.imgAppelAuMoral')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg";
|
|
html.find('.tooltipAppelAuMoralText')[0].innerHTML = "Appel au moral";
|
|
} else {
|
|
html.find('.imgAppelAuMoral')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-malheureux.svg";
|
|
html.find('.tooltipAppelAuMoralText')[0].innerHTML = "Appel à l'énergie du désespoir";
|
|
}
|
|
} else {
|
|
html.find('.imgAppelAuMoral')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-neutre.svg";
|
|
html.find('.tooltipAppelAuMoralText')[0].innerHTML = "Sans appel au moral";
|
|
}
|
|
this.updateRollResult();
|
|
});
|
|
// Section Méditation
|
|
html.find('.conditionMeditation').change((event) => {
|
|
let condition = event.currentTarget.attributes['id'].value;
|
|
this.rollData.conditionMeditation[condition] = event.currentTarget.checked;
|
|
this.updateRollResult();
|
|
});
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
async updateRollResult() {
|
|
let rollData = this.rollData;
|
|
|
|
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat());
|
|
rollData.caracValue = parseInt(rollData.selectedCarac.value);
|
|
rollData.coupsNonMortels = (rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite) == 'non-mortel';
|
|
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);
|
|
let dmgText = Misc.toSignedString(rollData.dmg.total);
|
|
|
|
if (rollData.coupsNonMortels) {
|
|
dmgText = '(' + dmgText + ')';
|
|
}
|
|
if (rollData.selectedSort) {
|
|
rollData.bonus = RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.tmr.coord);
|
|
HtmlUtility._showControlWhen($("#div-sort-difficulte"), RdDItemSort.isDifficulteVariable(rollData.selectedSort))
|
|
HtmlUtility._showControlWhen($("#div-sort-ptreve"), RdDItemSort.isCoutVariable(rollData.selectedSort))
|
|
}
|
|
|
|
RollDataAjustements.calcul(rollData, this.actor);
|
|
rollData.finalLevel = this._computeFinalLevel(rollData);
|
|
|
|
HtmlUtility._showControlWhen($(".diffMoral"), rollData.ajustements.moralTotal.used);
|
|
HtmlUtility._showControlWhen($(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
|
HtmlUtility._showControlWhen($("#etat-general"), !RdDCarac.isIgnoreEtatGeneral(rollData.selectedCarac, rollData.competence));
|
|
HtmlUtility._showControlWhen($("#ajust-astrologique"), RdDResolutionTable.isAjustementAstrologique(rollData));
|
|
|
|
// Mise à jour valeurs
|
|
$("#compdialogTitle").text(this._getTitle(rollData));
|
|
$('#coupsNonMortels').prop('checked', rollData.coupsNonMortels);
|
|
$("#dmg-arme-actor").text(dmgText);
|
|
$('.table-ajustement').remove();
|
|
$(".table-resolution").remove();
|
|
$(".table-proba-reussite").remove();
|
|
$("#tableAjustements").append(await this.buildAjustements(rollData));
|
|
$("#tableResolution").append(RdDResolutionTable.buildHTMLTableExtract(rollData.caracValue, rollData.finalLevel));
|
|
$("#tableProbaReussite").append(RdDResolutionTable.buildHTMLResults(rollData.caracValue, rollData.finalLevel));
|
|
}
|
|
|
|
|
|
/* -------------------------------------------- */
|
|
async buildAjustements(rollData) {
|
|
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ajustements.html`, rollData);
|
|
return html;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_computeFinalLevel(rollData) {
|
|
return RollDataAjustements.sum(rollData.ajustements);
|
|
}
|
|
/* -------------------------------------------- */
|
|
_computeDiffCompetence(rollData) {
|
|
if (rollData.competence) {
|
|
return Misc.toInt(rollData.competence.data.niveau);
|
|
}
|
|
if (rollData.draconicList) {
|
|
return Misc.toInt(rollData.competence.data.niveau);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_computeDiffLibre(rollData) {
|
|
let diffLibre = Misc.toInt(rollData.diffLibre);
|
|
if (rollData.draconicList && rollData.selectedSort) {
|
|
return RdDItemSort.getDifficulte(rollData.selectedSort, diffLibre);
|
|
}
|
|
return diffLibre;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_computeMalusArmure(rollData) {
|
|
let malusArmureValue = 0;
|
|
if (rollData.malusArmureValue && (rollData.selectedCarac.label == "Agilité" || rollData.selectedCarac.label == "Dérobée")) {
|
|
$("#addon-message").text("Malus armure appliqué : " + rollData.malusArmureValue);
|
|
malusArmureValue = rollData.malusArmureValue;
|
|
} else {
|
|
$("#addon-message").text("");
|
|
}
|
|
return malusArmureValue;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
_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.data.niveau);
|
|
if (compName == carac) {
|
|
// cas des créatures
|
|
return carac + " " + niveau
|
|
}
|
|
const armeTitle = (rollData.arme) ? " (" + rollData.arme.name + ") " : "";
|
|
return carac + "/" + compName + armeTitle + " " + niveau
|
|
}
|
|
}
|