import { SYSTEM } from "../../config/system.mjs" import CthulhuEternalRoll from '../../documents/roll.mjs' export let RollHandler = null Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { /** * Extends Token Action HUD Core's RollHandler class and handles action events triggered when an action is clicked */ RollHandler = class RollHandler extends coreModule.api.RollHandler { /** * Handle action click * Called by Token Action HUD Core when an action is left or right-clicked * @override * @param {object} event The event * @param {string} encodedValue The encoded value */ async handleActionClick (event, encodedValue) { const [actionTypeId, actionId] = encodedValue.split('|') const knownCharacters = ['character'] // If single actor is selected if (this.actor) { await this.#handleAction(event, this.actor, this.token, actionTypeId, actionId) return } const controlledTokens = canvas.tokens.controlled .filter((token) => knownCharacters.includes(token.actor?.type)) // If multiple actors are selected for (const token of controlledTokens) { const actor = token.actor await this.#handleAction(event, actor, token, actionTypeId, actionId) } } /** * Handle action hover * Called by Token Action HUD Core when an action is hovered on or off * @override * @param {object} event The event * @param {string} encodedValue The encoded value */ async handleActionHover (event, encodedValue) { } /** * Handle group click * Called by Token Action HUD Core when a group is right-clicked while the HUD is locked * @override * @param {object} event The event * @param {object} group The group */ async handleGroupClick (event, group) { } /** * Handle action * @private * @param {object} event The event * @param {object} actor The actor * @param {object} token The token * @param {string} actionTypeId The action type id * @param {string} actionId The actionId */ async #handleAction (event, actor, token, actionTypeId, actionId) { switch (actionTypeId) { case 'attributes': await this.#handleAttributesAction(event, actor, actionId) break case 'skills': await this.#handleSkillsAction(event, actor, actionId) break case 'weapons': await this.#handleWeaponsAction(event, actor, actionId) break case 'damage': await this.#handleDamageAction(event, actor, actionId) break case 'lethality': await this.#handleLethalityAction(event, actor, actionId) break case 'specialTraining': await this.#handleSpecialTrainingAction(event, actor, actionId) break case 'typedSkills': await this.#handleCustomTypedAction(event, actor, actionId) break /* case 'rituals': await this.#handleRitualsAction(event, actor, actionId) break */ case 'utility': await this.#handleUtilityAction(token, actionId) break } } /** * Handle Attribute action * @private * @param {object} event The event * @param {object} actor The actor * @param {string} actionId The action id */ async #handleAttributesAction (event, actor, actionId) { let rollType if (actionId === 'wp' || actionId === 'health') return if (actionId.includes('_add') || actionId.includes('_subtract')) { const attr = actionId.split('_')[0] const action = actionId.split('_')[1] const update = {} update.system = {} update.system[attr] = {} update.system[attr].value = action === 'add' ? this.actor.system[attr].value + 1 : this.actor.system[attr].value - 1 if (update.system[attr].value > this.actor.system[attr].max || update.system[attr].value < this.actor.system[attr].min) return return await this.actor.update(update) } if (actionId === 'sanity') { rollType = actionId } else if (actionId === 'luck') { rollType = actionId } else { rollType = 'stat' } const options = { actor: this.actor, rollType, key: actionId } const roll = new DGPercentileRoll('1D100', {}, options) return await this.actor.sheet.processRoll(event, roll) } /** * Handle Skill action * @private * @param {object} event The event * @param {object} actor The actor * @param {string} actionId The action id */ async #handleSkillsAction (event, actor, actionId) { const options = { actor: this.actor, rollType: 'skill', key: actionId } const skill = this.actor.system.skills[actionId] if (!skill) return ui.notifications.warn('Bad skill name in HUD.') const roll = new DGPercentileRoll('1D100', {}, options) await this.actor.sheet.processRoll(event, roll) } /** * Handle Typed/Custom skills action * @private * @param {object} event The event * @param {object} actor The actor * @param {string} actionId The action id */ async #handleCustomTypedAction (event, actor, actionId) { const options = { actor: this.actor, rollType: 'skill', key: actionId } const roll = new DGPercentileRoll('1D100', {}, options) await this.actor.sheet.processRoll(event, roll) } /** * Handle SoecialTraining action * @private * @param {object} event The event * @param {object} actor The actor * @param {string} actionId The action id */ async #handleSpecialTrainingAction (event, actor, actionId) { const attr = this.actor.system.specialTraining.find(a => a.name === actionId).attribute let target = 0 if (DG.statistics.includes(attr)) { target = this.actor.system.statistics[attr].x5 } else if (DG.skills.includes(attr)) { target = this.actor.system.skills[attr].proficiency } else { target = this.actor.system.typedSkills[attr].proficiency } const options = { actor: this.actor, rollType: 'special-training', key: attr, specialTrainingName: actionId, target } const roll = new DGPercentileRoll('1D100', {}, options) await this.actor.sheet.processRoll(event, roll) } /** * Handle Weapon action * @private * @param {object} event The event * @param {object} actor The actor * @param {string} actionId The action id */ async #handleWeaponsAction (event, actor, actionId) { const item = this.actor.items.get(actionId) const options = { actor: this.actor, rollType: 'weapon', key: item.system.skill, item } const roll = new DGPercentileRoll('1D100', {}, options) await this.actor.sheet.processRoll(event, roll) } /** * Handle Damage action * @private * @param {object} event The event * @param {object} actor The actor * @param {string} actionId The action id */ async #handleDamageAction (event, actor, actionId) { const item = this.actor.items.get(actionId) if (item.system.lethality > 0 && event.ctrlKey) { // Toggle on/off lethality const isLethal = !item.system.isLethal await item.update({ 'system.isLethal': isLethal }) } else { const options = { actor: this.actor, rollType: 'damage', key: item.system.damage, item } const roll = new DGDamageRoll(item.system.damage, {}, options) await this.actor.sheet.processRoll(event, roll) } } /** * Handle Lethality action * @private * @param {object} event The event * @param {object} actor The actor * @param {string} actionId The action id */ async #handleLethalityAction (event, actor, actionId) { const item = await this.actor.items.get(actionId) if (item.system.damage !== '' && event.ctrlKey) { const isLethal = !item.system.isLethal await item.update({ 'system.isLethal': isLethal }) } else { const options = { actor: this.actor, rollType: 'lethality', key: item.system.lethality, item } const roll = new DGLethalityRoll(item.system.damage, {}, options) await this.actor.sheet.processRoll(event, roll) } } /** * Handle Ritual action * @private * @param {object} event The event * @param {object} actor The actor * @param {string} actionId The action id */ async #handleRitualsAction (event, actor, actionId) { const options = { actor: this.actor, rollType: 'ritual', key: actionId } const roll = new DGPercentileRoll('1D100', {}, options) await this.actor.sheet.processRoll(event, roll) } /** * Handle utility action * @private * @param {object} token The token * @param {string} actionId The action id */ async #handleUtilityAction (token, actionId) { switch (actionId) { case 'endTurn': if (game.combat?.current?.tokenId === token.id) { await game.combat?.nextTurn() } break } } } })