Working on initiative, and now TN is global with GM tool

This commit is contained in:
Vlyan
2021-01-14 18:44:56 +01:00
parent 30950a0d63
commit 58a4e71b32
15 changed files with 561 additions and 186 deletions

View File

@@ -1,61 +1,103 @@
/**
* 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<Combat>} A promise which resolves to the updated Combat entity once updates are complete.
* Extends the actor to process special things from L5R.
*/
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 formula = [`${data.rings[data.stance]}dr`];
const skillValue =
combatant.actor.data.type === "npc" ? data.skills["martial"] : data.skills["martial"]["tactics"];
if (skillValue > 0) {
formula.push(`${skillValue}ds`);
export class CombatL5r5e extends Combat {
// game.combat.settings.resource = "fatigue.value"; // nope :/
// constructor(...args) {
// super(...args);
// console.log(args);
// }
/**
* 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<Combat>} A promise which resolves to the updated Combat entity once updates are complete.
*/
async rollInitiative(ids, { formula = null, updateTurn = true, messageOptions = {} } = {}) {
if (!Array.isArray(ids)) {
ids = [ids];
}
const roll = new game.l5r5e.RollL5r5e(formula.join("+"));
roll.actor = combatant.actor;
roll.l5r5e.stance = data.stance;
roll.l5r5e.skillId = "tactics";
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,
// Make combatants array
const combatants = [];
ids.forEach((combatantId) => {
const combatant = game.combat.combatants.find((c) => c._id === combatantId);
if (combatant && combatant.actor) {
combatants.push(combatant);
}
});
});
// Update all combatants at once
await this.updateEmbeddedEntity("Combatant", updatedCombatants);
return this;
}
// Get modifiers
const difficulty = game.settings.get("l5r5e", "initiative.difficulty.value");
const difficultyHidden = game.settings.get("l5r5e", "initiative.difficulty.hidden");
const skillId = CONFIG.l5r5e.initiativeSkills[game.settings.get("l5r5e", "initiative.encounter")];
const skillCat = CONFIG.l5r5e.skills.get(skillId);
/**
* 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;
// Get score for each combatant
const updatedCombatants = [];
combatants.forEach((combatant) => {
const data = combatant.actor.data.data;
// A characters initiative value is based on their state of preparedness when the conflict began.
// If the character was ready for the conflict, their base initiative value is their focus attribute.
// If the character was unprepared (such as when surprised), their base initiative value is their vigilance attribute.
const isPrepared = true; // TODO in actor ? (pc and npc)
let initiative = isPrepared ? data.focus : data.vigilance;
// PC and Adversary
// (minion NPCs can generate initiative value without a check, using their focus or vigilance attribute)
if (combatant.actor.data.type !== "npc" || combatant.actor.data.data.type === "minion") {
const formula = [`${data.rings[data.stance]}dr`];
const skillValue =
combatant.actor.data.type === "npc" ? data.skills[skillCat] : data.skills[skillCat][skillId];
if (skillValue > 0) {
formula.push(`${skillValue}ds`);
}
const roll = new game.l5r5e.RollL5r5e(formula.join("+"));
roll.actor = combatant.actor;
roll.l5r5e.stance = data.stance;
roll.l5r5e.skillId = skillId;
roll.l5r5e.summary.difficulty = difficulty;
roll.l5r5e.summary.difficultyHidden = difficultyHidden;
roll.roll();
roll.toMessage({ flavor: game.i18n.localize("l5r5e.chatdices.initiative_roll") });
// if the character succeeded on their Initiative check, they add 1 to their base initiative value,
// plus an additional amount equal to their bonus successes.
if (roll.l5r5e.summary.success >= difficulty) {
initiative = initiative + 1 + Math.max(roll.l5r5e.summary.success - difficulty, 0);
}
}
updatedCombatants.push({
_id: combatant._id,
initiative: initiative,
});
});
// 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
*/
_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;
}
return b.initiative - a.initiative;
}