270 lines
8.5 KiB
JavaScript
270 lines
8.5 KiB
JavaScript
import { L5rBaseDie } from "./dietype/l5r-base-die.js";
|
|
|
|
/**
|
|
* Roll for L5R5e
|
|
*/
|
|
export class RollL5r5e extends Roll {
|
|
static CHAT_TEMPLATE = "systems/l5r5e/templates/dice/chat-roll.html";
|
|
static TOOLTIP_TEMPLATE = "systems/l5r5e/templates/dice/tooltip.html";
|
|
|
|
// static CHAT_TEMPLATE = `${CONFIG.L5r5e.pathTemplates}dice/chat-roll.html`;
|
|
// static TOOLTIP_TEMPLATE = `${CONFIG.L5r5e.pathTemplates}dice/tooltip.html`;
|
|
|
|
constructor(...args) {
|
|
console.log("RollL5r5e.in.args", args); // TODO tmp
|
|
|
|
super(...args);
|
|
|
|
this.l5r5e = {
|
|
stance: "",
|
|
skillId: "",
|
|
actor: null,
|
|
dicesTypes: {
|
|
std: false,
|
|
l5r: false,
|
|
},
|
|
summary: {
|
|
difficulty: 0,
|
|
success_total: 0,
|
|
success: 0,
|
|
explosive: 0,
|
|
opportunity: 0,
|
|
strife: 0,
|
|
},
|
|
};
|
|
|
|
// TODO parse difficulty stance skillId from cmd line ?
|
|
|
|
console.log("RollL5r5e.out.args", args, this); // TODO tmp
|
|
}
|
|
|
|
/**
|
|
* Execute the Roll, replacing dice and evaluating the total result
|
|
* @override
|
|
**/
|
|
evaluate({ minimize = false, maximize = false } = {}) {
|
|
if (this._rolled) {
|
|
throw new Error("This Roll object has already been rolled.");
|
|
}
|
|
|
|
// console.log('RollL5r5e.evaluate.in', this); return; // TODO tmp
|
|
|
|
// Split L5R dices / regulars
|
|
let l5rDices = this.terms.filter((term) => term instanceof L5rBaseDie);
|
|
this.terms = this.terms.filter((t) => !(t instanceof L5rBaseDie));
|
|
this.terms = this._identifyTerms(this.constructor.cleanFormula(this.terms));
|
|
|
|
// Roll regular dices
|
|
this._total = 0;
|
|
if (this.terms.length > 0) {
|
|
this.l5r5e.dicesTypes.std = true;
|
|
|
|
console.log("this.terms", this.terms);
|
|
|
|
// clean terms (trim symbols)
|
|
this.terms = this._identifyTerms(this.constructor.cleanFormula(this.terms));
|
|
|
|
// Roll
|
|
super.evaluate({ minimize, maximize });
|
|
}
|
|
|
|
// Roll L5R dices
|
|
if (l5rDices.length > 0) {
|
|
this.l5r5e.dicesTypes.l5r = true;
|
|
|
|
l5rDices.forEach((term) => {
|
|
// Roll
|
|
term.evaluate({ minimize, maximize });
|
|
|
|
// Total
|
|
["success", "explosive", "opportunity", "strife"].forEach((props) => {
|
|
this.l5r5e.summary[props] += parseInt(term.l5r5e[props]);
|
|
});
|
|
this.l5r5e.summary.success_total += parseInt(term.l5r5e.success) + parseInt(term.l5r5e.explosive);
|
|
|
|
this.terms.push("+");
|
|
this.terms.push(term);
|
|
});
|
|
|
|
// Clean
|
|
if (this.terms[0] === "+") {
|
|
this.terms.shift();
|
|
}
|
|
|
|
// TODO Others advantage/disadvantage
|
|
|
|
// re-inject L5R dices
|
|
// this.terms = this.terms.concat(l5rTerms);
|
|
}
|
|
|
|
// Store final outputs
|
|
//this._total = total;
|
|
this._rolled = true;
|
|
|
|
console.log("RollL5r5e.evaluate.out", this); // TODO tmp
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Render the tooltip HTML for a Roll instance
|
|
* @override
|
|
*/
|
|
getTooltip() {
|
|
console.log("RollL5r5e.getTooltip", this); // TODO tmp
|
|
|
|
const parts = this.dice
|
|
.filter((t) => !(t instanceof L5rBaseDie))
|
|
.map((d) => {
|
|
const cls = d.constructor;
|
|
return {
|
|
formula: d.formula,
|
|
total: d.total,
|
|
faces: d.faces,
|
|
flavor: d.options.flavor,
|
|
isL5rDices: d.constructor instanceof L5rBaseDie,
|
|
rolls: d.results.map((r) => {
|
|
return {
|
|
result: cls.getResultLabel(r.result),
|
|
classes: [
|
|
cls.name.toLowerCase(),
|
|
"d" + d.faces,
|
|
r.rerolled ? "rerolled" : null,
|
|
r.exploded ? "exploded" : null,
|
|
r.discarded ? "discarded" : null,
|
|
r.result === 1 ? "min" : null,
|
|
r.result === d.faces ? "max" : null,
|
|
]
|
|
.filter((c) => !!c)
|
|
.join(" "),
|
|
};
|
|
}),
|
|
};
|
|
});
|
|
parts.addedResults = this.addedResults;
|
|
return renderTemplate(this.constructor.TOOLTIP_TEMPLATE, { parts });
|
|
}
|
|
|
|
/**
|
|
* Render a Roll instance to HTML
|
|
* @override
|
|
*/
|
|
async render(chatOptions = {}) {
|
|
console.log("RollL5r5e.render", chatOptions, this); // TODO tmp
|
|
|
|
chatOptions = mergeObject(
|
|
{
|
|
user: game.user._id,
|
|
flavor: null,
|
|
template: this.constructor.CHAT_TEMPLATE,
|
|
blind: false,
|
|
},
|
|
chatOptions
|
|
);
|
|
const isPrivate = chatOptions.isPrivate;
|
|
|
|
// Execute the roll, if needed
|
|
if (!this._rolled) {
|
|
this.roll();
|
|
}
|
|
|
|
// Define chat data
|
|
const chatData = {
|
|
formula: isPrivate ? "???" : this._formula,
|
|
flavor: isPrivate ? null : chatOptions.flavor,
|
|
user: chatOptions.user,
|
|
isPublicRoll: !chatOptions.isPrivate,
|
|
tooltip: isPrivate ? "" : await this.getTooltip(),
|
|
total: isPrivate ? "?" : Math.round(this.total * 100) / 100,
|
|
data: this.data,
|
|
l5r5e: isPrivate
|
|
? {}
|
|
: {
|
|
dicesTypes: this.l5r5e.dicesTypes,
|
|
summary: this.l5r5e.summary,
|
|
dices: this.dice.map((d) => {
|
|
return {
|
|
diceTypeL5r: d instanceof L5rBaseDie,
|
|
rolls: d.results.map((r) => {
|
|
return {
|
|
result: d.constructor.getResultLabel(r.result),
|
|
};
|
|
}),
|
|
};
|
|
}),
|
|
},
|
|
};
|
|
|
|
console.log("RollL5r5e.render", chatOptions, chatData, this); // TODO tmp
|
|
|
|
// Render the roll display template
|
|
return renderTemplate(chatOptions.template, chatData);
|
|
}
|
|
|
|
/**
|
|
* Transform a Roll instance into a ChatMessage, displaying the roll result.
|
|
* This function can either create the ChatMessage directly, or return the data object that will be used to create.
|
|
* @override
|
|
*/
|
|
toMessage(messageData = {}, { rollMode = null, create = true } = {}) {
|
|
console.log("RollL5r5e.toMessage", this); // TODO tmp
|
|
|
|
// Perform the roll, if it has not yet been rolled
|
|
if (!this._rolled) {
|
|
this.evaluate();
|
|
}
|
|
|
|
const rMode = rollMode || messageData.rollMode || game.settings.get("core", "rollMode");
|
|
|
|
let template = CONST.CHAT_MESSAGE_TYPES.ROLL;
|
|
if (["gmroll", "blindroll"].includes(rMode)) {
|
|
messageData.whisper = ChatMessage.getWhisperRecipients("GM");
|
|
}
|
|
if (rMode === "blindroll") messageData.blind = true;
|
|
if (rMode === "selfroll") messageData.whisper = [game.user.id];
|
|
|
|
// Prepare chat data
|
|
messageData = mergeObject(
|
|
{
|
|
user: game.user._id,
|
|
type: template,
|
|
content: this.total,
|
|
sound: CONFIG.sounds.dice,
|
|
},
|
|
messageData
|
|
);
|
|
messageData.roll = this;
|
|
|
|
// Prepare message options
|
|
const messageOptions = { rollMode: rMode };
|
|
|
|
// Either create the message or just return the chat data
|
|
return create ? CONFIG.ChatMessage.entityClass.create(messageData, messageOptions) : messageData;
|
|
}
|
|
|
|
/** @override */
|
|
static fromData(data) {
|
|
const roll = super.fromData(data);
|
|
|
|
roll.data = data.data;
|
|
roll.l5r5e = data.l5r5e;
|
|
|
|
console.log("RollL5r5e.fromData", roll); // TODO tmp
|
|
|
|
return roll;
|
|
}
|
|
|
|
/**
|
|
* Represent the data of the Roll as an object suitable for JSON serialization
|
|
* @override
|
|
*/
|
|
toJSON() {
|
|
const json = super.toJSON();
|
|
|
|
json.data = this.data;
|
|
json.l5r5e = this.l5r5e;
|
|
|
|
return json;
|
|
}
|
|
}
|