From 92b60f78f7e00c7fae93ed20a1323fc7b637acd7 Mon Sep 17 00:00:00 2001 From: Vlyan Date: Tue, 12 Jan 2021 16:55:49 +0100 Subject: [PATCH] Added initiative roll (only tactics for the moment) --- system/lang/en-en.json | 3 +- system/lang/es-es.json | 3 +- system/lang/fr-fr.json | 3 +- system/scripts/combat.js | 56 ++++++++++++++++++++++++++++++++++++ system/scripts/main-l5r5e.js | 8 +++++- 5 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 system/scripts/combat.js diff --git a/system/lang/en-en.json b/system/lang/en-en.json index 38c5985..c5f7bc3 100644 --- a/system/lang/en-en.json +++ b/system/lang/en-en.json @@ -82,7 +82,8 @@ "difficulty_hidden": "TN ???", "dicepicker": "Dice Picker", "void_point_used": "Void point used", - "roll_n_keep": "Roll & Keep" + "roll_n_keep": "Roll & Keep", + "initiative_roll": "Initiative roll" }, "dicepicker": { "difficulty_title": "Difficulty", diff --git a/system/lang/es-es.json b/system/lang/es-es.json index 6481d03..ca6c1eb 100644 --- a/system/lang/es-es.json +++ b/system/lang/es-es.json @@ -82,7 +82,8 @@ "difficulty_hidden": "TN ???", "dicepicker": "Recogedor de dados", "void_point_used": "Punto de vacío utilizado", - "roll_n_keep": "Roll & Keep" + "roll_n_keep": "Roll & Keep", + "initiative_roll": "Iniciativa rollo" }, "dicepicker": { "difficulty_title": "Dificultad", diff --git a/system/lang/fr-fr.json b/system/lang/fr-fr.json index ab9d36f..8798c42 100644 --- a/system/lang/fr-fr.json +++ b/system/lang/fr-fr.json @@ -82,7 +82,8 @@ "difficulty_hidden": "ND ???", "dicepicker": "Dice Picker", "void_point_used": "Point de vide utilisé", - "roll_n_keep": "Roll & Keep" + "roll_n_keep": "Roll & Keep", + "initiative_roll": "Jet d'initiative" }, "dicepicker": { "difficulty_title": "Difficulté", diff --git a/system/scripts/combat.js b/system/scripts/combat.js new file mode 100644 index 0000000..41242a7 --- /dev/null +++ b/system/scripts/combat.js @@ -0,0 +1,56 @@ +/** + * Roll initiative for one or multiple Combatants within the Combat entity + * @param {string|string[]} ids A Combatant id or Array of ids for which to roll + * @param {string|null} [formula] A non-default initiative formula to roll. Otherwise the system default is used. + * @param {boolean} [updateTurn] Update the Combat turn after adding new initiative scores to keep the turn on + * the same Combatant. + * @param {object} [messageOptions] Additional options with which to customize created Chat Messages + * @return {Promise} A promise which resolves to the updated Combat entity once updates are complete. + */ +export async function rollInitiative(ids, { formula = null, updateTurn = true, messageOptions = {} } = {}) { + if (!Array.isArray(ids)) { + ids = [ids]; + } + const updatedCombatants = []; + ids.forEach((combatantId) => { + const combatant = game.combat.combatants.find((c) => c._id === combatantId); + if (!combatant || !combatant.actor) { + return; + } + const data = combatant.actor.data.data; + const skillValue = + combatant.actor.data.type === "npc" ? data.skills["martial"] : data.skills["martial"]["tactics"]; + + const roll = new game.l5r5e.RollL5r5e( + `${data.rings[data.stance]}dr[${data.stance}] + ${skillValue}ds[tactics]` + ); + roll.actor = combatant.actor; + roll.l5r5e.summary.difficulty = 1; + + roll.roll(); + roll.toMessage({ flavor: game.i18n.localize("l5r5e.chatdices.initiative_roll") }); + + updatedCombatants.push({ + _id: combatant._id, + initiative: roll.l5r5e.summary.success, + }); + }); + + // Update all combatants at once + await this.updateEmbeddedEntity("Combatant", updatedCombatants); + return this; +} + +/** + * Define how the array of Combatants is sorted in the displayed list of the tracker. + * This method can be overridden by a system or module which needs to display combatants in an alternative order. + * By default sort by initiative, falling back to name + * @private + */ +export function _sortCombatants(a, b) { + // if tie, sort by honor, less honorable first + if (a.initiative === b.initiative) { + return a.actor.data.data.social.honor - b.actor.data.data.social.honor; + } + return b.initiative - a.initiative; +} diff --git a/system/scripts/main-l5r5e.js b/system/scripts/main-l5r5e.js index 44061fa..cbd4ba6 100644 --- a/system/scripts/main-l5r5e.js +++ b/system/scripts/main-l5r5e.js @@ -15,6 +15,7 @@ import { RingDie } from "./dice/dietype/ring-die.js"; import { RollL5r5e } from "./dice/roll.js"; import { DicePickerDialog } from "./dice/dice-picker-dialog.js"; import { RollnKeepDialog } from "./dice/roll-n-keep-dialog.js"; +import { _sortCombatants, rollInitiative } from "./combat.js"; // Items import { ItemL5r5e } from "./item.js"; import { ItemSheetL5r5e } from "./items/item-sheet.js"; @@ -77,6 +78,11 @@ Hooks.once("init", async function () { // Preload Handlebars templates await PreloadTemplates(); + // ***** Combat ***** + Combat.prototype.rollInitiative = rollInitiative; + Combat.prototype._sortCombatants = _sortCombatants; + // game.combat.settings.resource = "fatigue.value"; // nope :/ + // ***** Register custom sheets ***** // Actors Actors.unregisterSheet("core", ActorSheet); @@ -134,7 +140,7 @@ Hooks.once("init", async function () { // Utility conditional, usable in nested expression // {{#ifCond (ifCond advancement.type '==' 'technique') '||' (ifCond item.data.technique_type '==' 'kata')}} - // {#ifCond '["distinction","passion"]' 'includes' item.data.peculiarity_type}} + // {{#ifCond '["distinction","passion"]' 'includes' item.data.peculiarity_type}} Handlebars.registerHelper("ifCond", function (a, operator, b, options) { let result = false; switch (operator) {