Initial commit
This commit is contained in:
commit
03761d2e2f
17 changed files with 5662 additions and 0 deletions
131
scripts/action-handler.js
Normal file
131
scripts/action-handler.js
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
// System Module Imports
|
||||
import { ACTION_TYPE, ITEM_TYPE } from './constants.js'
|
||||
import { Utils } from './utils.js'
|
||||
|
||||
export let ActionHandler = null
|
||||
|
||||
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
/**
|
||||
* Extends Token Action HUD Core's ActionHandler class and builds system-defined actions for the HUD
|
||||
*/
|
||||
ActionHandler = class ActionHandler extends coreModule.api.ActionHandler {
|
||||
/**
|
||||
* Build system actions
|
||||
* Called by Token Action HUD Core
|
||||
* @override
|
||||
* @param {array} groupIds
|
||||
*/a
|
||||
async buildSystemActions (groupIds) {
|
||||
// Set actor and token variables
|
||||
this.actors = (!this.actor) ? this._getActors() : [this.actor]
|
||||
this.actorType = this.actor?.type
|
||||
|
||||
// Settings
|
||||
this.displayUnequipped = Utils.getSetting('displayUnequipped')
|
||||
|
||||
// Set items variable
|
||||
if (this.actor) {
|
||||
let items = this.actor.items
|
||||
items = coreModule.api.Utils.sortItemsByName(items)
|
||||
this.items = items
|
||||
|
||||
}
|
||||
|
||||
if (this.actorType === 'character') {
|
||||
debugger;
|
||||
this.#buildCharacterActions()
|
||||
} else if (!this.actor) {
|
||||
this.#buildMultipleTokenActions()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build character actions
|
||||
* @private
|
||||
*/
|
||||
#buildCharacterActions () {
|
||||
this._get_attributes({id: "attributes", type:"system"})
|
||||
this.#buildInventory()
|
||||
}
|
||||
|
||||
_get_attributes(parent) {
|
||||
const macroType = "attributes";
|
||||
let actions = [];
|
||||
|
||||
let attributes = Object.entries(this.actor.system.attributes)
|
||||
attributes.forEach((a) => {
|
||||
const key = a[0];
|
||||
const value = a[1].value
|
||||
// img
|
||||
|
||||
actions.push({
|
||||
id: key,
|
||||
name: coreModule.api.Utils.i18n(key),
|
||||
description: coreModule.api.Utils.i18n('GURPS.Attributes'),
|
||||
encodedValue: [macroType, key].join(this.delimiter),
|
||||
})
|
||||
|
||||
|
||||
});
|
||||
this.addActions(actions, parent)
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Build multiple token actions
|
||||
* @private
|
||||
* @returns {object}
|
||||
*/
|
||||
#buildMultipleTokenActions () {
|
||||
}
|
||||
|
||||
/**
|
||||
* Build inventory
|
||||
* @private
|
||||
*/
|
||||
async #buildInventory () {
|
||||
if (this.items.size === 0) return
|
||||
|
||||
const actionTypeId = 'item'
|
||||
const inventoryMap = new Map()
|
||||
|
||||
for (const [itemId, itemData] of this.items) {
|
||||
const type = itemData.type
|
||||
const equipped = itemData.equipped
|
||||
|
||||
if (equipped || this.displayUnequipped) {
|
||||
const typeMap = inventoryMap.get(type) ?? new Map()
|
||||
typeMap.set(itemId, itemData)
|
||||
inventoryMap.set(type, typeMap)
|
||||
}
|
||||
}
|
||||
|
||||
for (const [type, typeMap] of inventoryMap) {
|
||||
const groupId = ITEM_TYPE[type]?.groupId
|
||||
|
||||
if (!groupId) continue
|
||||
|
||||
const groupData = { id: groupId, type: 'system' }
|
||||
|
||||
// Get actions
|
||||
const actions = [...typeMap].map(([itemId, itemData]) => {
|
||||
const id = itemId
|
||||
const name = itemData.name
|
||||
const actionTypeName = coreModule.api.Utils.i18n(ACTION_TYPE[actionTypeId])
|
||||
const listName = `${actionTypeName ? `${actionTypeName}: ` : ''}${name}`
|
||||
const encodedValue = [actionTypeId, id].join(this.delimiter)
|
||||
|
||||
return {
|
||||
id,
|
||||
name,
|
||||
listName,
|
||||
encodedValue
|
||||
}
|
||||
})
|
||||
|
||||
// TAH Core method to add actions to the action list
|
||||
this.addActions(actions, groupData)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
55
scripts/constants.js
Normal file
55
scripts/constants.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/**
|
||||
* Module-based constants
|
||||
*/
|
||||
export const MODULE = {
|
||||
ID: 'token-action-hud-gurps'
|
||||
}
|
||||
|
||||
/**
|
||||
* Core module
|
||||
*/
|
||||
export const CORE_MODULE = {
|
||||
ID: 'token-action-hud-core'
|
||||
}
|
||||
|
||||
/**
|
||||
* Core module version required by the system module
|
||||
*/
|
||||
export const REQUIRED_CORE_MODULE_VERSION = '1.5'
|
||||
|
||||
/**
|
||||
* Action types
|
||||
*/
|
||||
export const ACTION_TYPE = {
|
||||
item: 'tokenActionHud.template.item',
|
||||
utility: 'tokenActionHud.utility'
|
||||
}
|
||||
|
||||
/**
|
||||
* Groups
|
||||
*/
|
||||
export const GROUP = {
|
||||
attributes: { id: 'attributes', name: 'tokenActionHud.gurps.attributes', type: 'system' },
|
||||
armor: { id: 'armor', name: 'tokenActionHud.template.armor', type: 'system' },
|
||||
equipment: { id: 'equipment', name: 'tokenActionHud.template.equipment', type: 'system' },
|
||||
consumables: { id: 'consumables', name: 'tokenActionHud.template.consumables', type: 'system' },
|
||||
containers: { id: 'containers', name: 'tokenActionHud.template.containers', type: 'system' },
|
||||
treasure: { id: 'treasure', name: 'tokenActionHud.template.treasure', type: 'system' },
|
||||
weapons: { id: 'weapons', name: 'tokenActionHud.template.weapons', type: 'system' },
|
||||
combat: { id: 'combat', name: 'tokenActionHud.combat', type: 'system' },
|
||||
token: { id: 'token', name: 'tokenActionHud.token', type: 'system' },
|
||||
utility: { id: 'utility', name: 'tokenActionHud.utility', type: 'system' }
|
||||
}
|
||||
|
||||
/**
|
||||
* Item types
|
||||
*/
|
||||
export const ITEM_TYPE = {
|
||||
attributes: { groupId: 'attributes' },
|
||||
armor: { groupId: 'armor' },
|
||||
backpack: { groupId: 'containers' },
|
||||
consumable: { groupId: 'consumables' },
|
||||
equipment: { groupId: 'equipment' },
|
||||
treasure: { groupId: 'treasure' },
|
||||
weapon: { groupId: 'weapons' }
|
||||
}
|
||||
53
scripts/defaults.js
Normal file
53
scripts/defaults.js
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
import { GROUP } from './constants.js'
|
||||
|
||||
/**
|
||||
* Default layout and groups
|
||||
*/
|
||||
export let DEFAULTS = null
|
||||
|
||||
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
const groups = GROUP
|
||||
Object.values(groups).forEach(group => {
|
||||
group.name = coreModule.api.Utils.i18n(group.name)
|
||||
group.listName = `Group: ${coreModule.api.Utils.i18n(group.listName ?? group.name)}`
|
||||
})
|
||||
const groupsArray = Object.values(groups)
|
||||
debugger;
|
||||
DEFAULTS = {
|
||||
layout: [
|
||||
{
|
||||
nestId: 'inventory',
|
||||
id: 'inventory',
|
||||
name: coreModule.api.Utils.i18n('Template.Inventory'),
|
||||
groups: [
|
||||
{ ...groups.weapons, nestId: 'inventory_weapons' },
|
||||
{ ...groups.armor, nestId: 'inventory_armor' },
|
||||
{ ...groups.equipment, nestId: 'inventory_equipment' },
|
||||
{ ...groups.consumables, nestId: 'inventory_consumables' },
|
||||
{ ...groups.containers, nestId: 'inventory_containers' },
|
||||
{ ...groups.treasure, nestId: 'inventory_treasure' }
|
||||
]
|
||||
},
|
||||
{
|
||||
nestId: 'utility',
|
||||
id: 'utility',
|
||||
name: coreModule.api.Utils.i18n('tokenActionHud.utility'),
|
||||
groups: [
|
||||
{ ...groups.combat, nestId: 'utility_combat' },
|
||||
{ ...groups.token, nestId: 'utility_token' },
|
||||
{ ...groups.rests, nestId: 'utility_rests' },
|
||||
{ ...groups.utility, nestId: 'utility_utility' }
|
||||
]
|
||||
},
|
||||
{
|
||||
nestId: 'attributes',
|
||||
id: 'attributes',
|
||||
name: coreModule.api.Utils.i18n('GURPS.attributes'),
|
||||
groups: [
|
||||
{ ...groups.attributes, nestId: 'attributes_attributes' }
|
||||
]
|
||||
}
|
||||
],
|
||||
groups: groupsArray
|
||||
}
|
||||
})
|
||||
14
scripts/init.js
Normal file
14
scripts/init.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { SystemManager } from './system-manager.js'
|
||||
import { MODULE, REQUIRED_CORE_MODULE_VERSION } from './constants.js'
|
||||
|
||||
Hooks.on('tokenActionHudCoreApiReady', async () => {
|
||||
/**
|
||||
* Return the SystemManager and requiredCoreModuleVersion to Token Action HUD Core
|
||||
*/
|
||||
const module = game.modules.get(MODULE.ID)
|
||||
module.api = {
|
||||
requiredCoreModuleVersion: REQUIRED_CORE_MODULE_VERSION,
|
||||
SystemManager
|
||||
}
|
||||
Hooks.call('tokenActionHudSystemReady', module)
|
||||
})
|
||||
108
scripts/roll-handler.js
Normal file
108
scripts/roll-handler.js
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
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 renderable = ['item']
|
||||
|
||||
if (renderable.includes(actionTypeId) && this.isRenderItem()) {
|
||||
return this.doRenderItem(this.actor, actionId)
|
||||
}
|
||||
|
||||
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 'item':
|
||||
this.#handleItemAction(event, actor, actionId)
|
||||
break
|
||||
case 'utility':
|
||||
this.#handleUtilityAction(token, actionId)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle item action
|
||||
* @private
|
||||
* @param {object} event The event
|
||||
* @param {object} actor The actor
|
||||
* @param {string} actionId The action id
|
||||
*/
|
||||
#handleItemAction (event, actor, actionId) {
|
||||
const item = actor.items.get(actionId)
|
||||
item.toChat(event)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
21
scripts/settings.js
Normal file
21
scripts/settings.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { MODULE } from './constants.js'
|
||||
|
||||
/**
|
||||
* Register module settings
|
||||
* Called by Token Action HUD Core to register Token Action HUD system module settings
|
||||
* @param {function} coreUpdate Token Action HUD Core update function
|
||||
*/
|
||||
export function register (coreUpdate) {
|
||||
game.settings.register(MODULE.ID, 'displayUnequipped', {
|
||||
name: game.i18n.localize('tokenActionHud.template.settings.displayUnequipped.name'),
|
||||
hint: game.i18n.localize('tokenActionHud.template.settings.displayUnequipped.hint'
|
||||
),
|
||||
scope: 'client',
|
||||
config: true,
|
||||
type: Boolean,
|
||||
default: true,
|
||||
onChange: (value) => {
|
||||
coreUpdate(value)
|
||||
}
|
||||
})
|
||||
}
|
||||
92
scripts/system-manager.js
Normal file
92
scripts/system-manager.js
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
// System Module Imports
|
||||
import { ActionHandler } from './action-handler.js'
|
||||
import { RollHandler as Core } from './roll-handler.js'
|
||||
import { MODULE } from './constants.js'
|
||||
import { DEFAULTS } from './defaults.js'
|
||||
import * as systemSettings from './settings.js'
|
||||
|
||||
export let SystemManager = null
|
||||
|
||||
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
/**
|
||||
* Extends Token Action HUD Core's SystemManager class
|
||||
*/
|
||||
SystemManager = class SystemManager extends coreModule.api.SystemManager {
|
||||
/**
|
||||
* Returns an instance of the ActionHandler to Token Action HUD Core
|
||||
* Called by Token Action HUD Core
|
||||
* @override
|
||||
* @returns {class} The ActionHandler instance
|
||||
*/
|
||||
getActionHandler () {
|
||||
return new ActionHandler()
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of roll handlers to Token Action HUD Core
|
||||
* Used to populate the Roll Handler module setting choices
|
||||
* Called by Token Action HUD Core
|
||||
* @override
|
||||
* @returns {object} The available roll handlers
|
||||
*/
|
||||
getAvailableRollHandlers () {
|
||||
const coreTitle = 'Core Template'
|
||||
const choices = { core: coreTitle }
|
||||
return choices
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of the RollHandler to Token Action HUD Core
|
||||
* Called by Token Action HUD Core
|
||||
* @override
|
||||
* @param {string} rollHandlerId The roll handler ID
|
||||
* @returns {class} The RollHandler instance
|
||||
*/
|
||||
getRollHandler (rollHandlerId) {
|
||||
let rollHandler
|
||||
switch (rollHandlerId) {
|
||||
case 'core':
|
||||
default:
|
||||
rollHandler = new Core()
|
||||
break
|
||||
}
|
||||
return rollHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default layout and groups to Token Action HUD Core
|
||||
* Called by Token Action HUD Core
|
||||
* @returns {object} The default layout and groups
|
||||
*/
|
||||
async registerDefaults () {
|
||||
return DEFAULTS
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Token Action HUD system module settings
|
||||
* Called by Token Action HUD Core
|
||||
* @override
|
||||
* @param {function} coreUpdate The Token Action HUD Core update function
|
||||
*/
|
||||
registerSettings (coreUpdate) {
|
||||
systemSettings.register(coreUpdate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns styles to Token Action HUD Core
|
||||
* Called by Token Action HUD Core
|
||||
* @override
|
||||
* @returns {object} The TAH system styles
|
||||
*/
|
||||
registerStyles () {
|
||||
return {
|
||||
template: {
|
||||
class: 'tah-style-template-style', // The class to add to first DIV element
|
||||
file: 'tah-template-style', // The file without the css extension
|
||||
moduleId: MODULE.ID, // The module ID
|
||||
name: 'Template Style' // The name to display in the Token Action HUD Core 'Style' module setting
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
40
scripts/utils.js
Normal file
40
scripts/utils.js
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
import { MODULE } from './constants.js'
|
||||
|
||||
export let Utils = null
|
||||
|
||||
Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => {
|
||||
/**
|
||||
* Utility functions
|
||||
*/
|
||||
Utils = class Utils {
|
||||
/**
|
||||
* Get setting
|
||||
* @param {string} key The key
|
||||
* @param {string=null} defaultValue The default value
|
||||
* @returns {string} The setting value
|
||||
*/
|
||||
static getSetting (key, defaultValue = null) {
|
||||
let value = defaultValue ?? null
|
||||
try {
|
||||
value = game.settings.get(MODULE.ID, key)
|
||||
} catch {
|
||||
coreModule.api.Logger.debug(`Setting '${key}' not found`)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
/**
|
||||
* Set setting
|
||||
* @param {string} key The key
|
||||
* @param {string} value The value
|
||||
*/
|
||||
static async setSetting (key, value) {
|
||||
try {
|
||||
value = await game.settings.set(MODULE.ID, key, value)
|
||||
coreModule.api.Logger.debug(`Setting '${key}' set to '${value}'`)
|
||||
} catch {
|
||||
coreModule.api.Logger.debug(`Setting '${key}' not found`)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
Loading…
Add table
Add a link
Reference in a new issue