diff --git a/.github/readme/token-action-hud.gif b/.github/readme/token-action-hud.gif new file mode 100644 index 0000000..e613098 Binary files /dev/null and b/.github/readme/token-action-hud.gif differ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..fa3feaa --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,102 @@ +name: Create Module Files For GitHub Release + +env: + # The URL used for the module's "Project URL" link on FoundryVTT's website. + project_url: "https://github.com/${{github.repository}}" + + # A URL that will always point to the latest manifest. + # FoundryVTT uses this URL to check whether the current module version that + # is installed is the latest version. This URL should NOT change, + # otherwise FoundryVTT won't be able to perform this check. + latest_manifest_url: "https://github.com/${{github.repository}}/releases/latest/download/module.json" + + # The URL to the module archive associated with the module release being + # processed by this workflow. + release_module_url: "https://github.com/${{github.repository}}/releases/download/${{github.event.release.tag_name}}/module.zip" + +on: + # Only run this workflow when a release is published. + # To modify this workflow when other events occur, see: + # - https://docs.github.com/en/actions/using-workflows/triggering-a-workflow + # - https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows + # - https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#on + # + # Note that some steps may depend on context variables that are only + # available for release events, so if you add other events, you may need to + # alter other parts of this workflow. + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + permissions: + contents: write + + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + # Extract version embedded in the tag. + # This step expects the tag to be one of the following formats: + # - "v.." (e.g., "v1.2.3") + # - ".." (e.g., "1.2.3") + # + # The version will be used by later steps to fill in the value for the + # "version" key required for a valid module manifest. + - name: Extract Version From Tag + id: get_version + uses: battila7/get-version-action@v2 + + # Modify "module.json" with values specific to the release. + # Since the values for the "version" and "url" keys aren't known ahead of + # time, the manifest file in the repository is updated with these values. + # + # While this does modify the manifest file in-place, the changes are not + # commited to the repository, and only exist in the action's filesystem. + - name: Modify Module Manifest With Release-Specific Values + id: sub_manifest_link_version + uses: cschleiden/replace-tokens@v1 + with: + files: 'module.json' + env: + VERSION: ${{steps.get_version.outputs.version-without-v}} + URL: ${{ env.project_url }} + MANIFEST: ${{ env.latest_manifest_url }} + DOWNLOAD: ${{ env.release_module_url }} + + # Create a "module.zip" archive containing all the module's required files. + # If you have other directories or files that will need to be added to + # your packaged module, add them here. + - name: Create Module Archive + run: | + # Note that `zip` will only emit warnings when a file or directory + # doesn't exist, it will not fail. + zip \ + `# Options` \ + --recurse-paths \ + `# The name of the output file` \ + ./module.zip \ + `# The files that will be included.` \ + module.json \ + readme.md \ + LICENSE \ + languages/ \ + scripts/ \ + styles/ \ + # Don't forget to add a backslash at the end of the line for any + # additional files or directories! + + # Update the GitHub release with the manifest and module archive files. + - name: Update Release with Files + id: create_version_release + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + name: ${{ github.event.release.name }} + draft: ${{ github.event.release.unpublished }} + prerelease: ${{ github.event.release.prerelease }} + token: ${{ secrets.GITHUB_TOKEN }} + artifacts: './module.json, ./module.zip' + tag: ${{ github.event.release.tag_name }} + body: ${{ github.event.release.body }} diff --git a/.gitignore b/.gitignore index bda14b0..ba5b1bc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ node_modules/* .vscode/ mkzip.sh -*.zip \ No newline at end of file +*.zip diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6c2ff60 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "githubPullRequests.ignoredPullRequestBranches": [ + "master" + ] +} \ No newline at end of file diff --git a/module.json b/module.json index 166f80b..3ab37c3 100644 --- a/module.json +++ b/module.json @@ -4,13 +4,13 @@ "description": "Token Action HUD is a repositionable HUD of actions for a selected token", "authors": [ { - "name": "Neill Cox", - "url": "https://github.com/neillc" + "name": "neillc", + "url": "https://git.evatt.ingenious.com.au/neillc" } ], - "url": "This is auto replaced", + "url": "https://git.evatt.ingenious.com.au/neillc/token-action-hud-gurps", "flags": {}, - "version": "0.0.97", + "version": "0.0.100", "compatibility": { "minimum": "11", "verified": "11.351" @@ -63,9 +63,9 @@ } }, "socket": false, - "readme": "http://172.23.0.17:8000/module.json", - "manifest": "http://172.23.0.17:8000/module.json", - "download": "http://172.23.0.17:8000/fvtt-token-action-hud-gurps.zip", + "readme": "https://git.evatt.ingenious.com.au/neillc/token-action-hud-gurps/releases/download/0.0.100/readme.md", + "manifest": "https://git.evatt.ingenious.com.au/neillc/token-action-hud-gurps/releases/download/0.0.100/module.json", + "download": "https://git.evatt.ingenious.com.au/neillc/token-action-hud-gurps/releases/download/0.0.100/fvtt-token-action-hud-gurps.zip", "protected": false, "coreTranslation": false, "library": false diff --git a/readme.md b/readme.md index 2995a9c..b62f0ef 100644 --- a/readme.md +++ b/readme.md @@ -1,14 +1,11 @@ -![Downloads](https://img.shields.io/github/downloads/Larkinabout/fvtt-token-action-hud-template/latest/module.zip?color=2b82fc&label=DOWNLOADS&style=for-the-badge) [![Forge Installs](https://img.shields.io/badge/dynamic/json?label=Forge%20Installs&query=package.installs&suffix=%25&url=https%3A%2F%2Fforge-vtt.com%2Fapi%2Fbazaar%2Fpackage%2Ftoken-action-hud-template&colorB=448d34&style=for-the-badge)](https://forge-vtt.com/bazaar#package=token-action-hud-template) +# Token Action HUD for GURPS -# Token Action HUD Template +Token Action HUD is a repositionable HUD of actions for a selected token for the GURPS game system. -Token Action HUD is a repositionable HUD of actions for a selected token. - -![Token Action HUD](.github/readme/token-action-hud.gif) +This should be considered beta software at the moment. I think it's safe to use, but be careful! # Features - Make rolls directly from the HUD instead of opening your character sheet. -- Use items from the HUD or right-click an item to open its sheet. - Move the HUD and choose to expand the menus up or down. - Unlock the HUD to customise layout and groups per user, and actions per actor. - Add your own macros, journal entries and roll table compendiums. @@ -18,18 +15,18 @@ Token Action HUD is a repositionable HUD of actions for a selected token. ## Method 1 1. On Foundry VTT's **Configuration and Setup** screen, go to **Add-on Modules** 2. Click **Install Module** -3. Search for **Token Action HUD Pathfinder 2** +3. Search for **Token Action HUD for GURPS** 4. Click **Install** next to the module listing ## Method 2 1. On Foundry VTT's **Configuration and Setup** screen, go to **Add-on Modules** 2. Click **Install Module** -3. In the Manifest URL field, paste: `https://github.com/Larkinabout/fvtt-token-action-hud-template/releases/latest/download/module.json` +3. In the Manifest URL field, paste: `https://git.evatt.ingenious.com.au/neillc/token-action-hud-gurps/releases/download/latest/module.json` 4. Click **Install** next to the pasted Manifest URL ## Required Modules -**IMPORTANT** - Token Action HUD Template requires the [Token Action HUD Core](https://foundryvtt.com/packages/token-action-hud-core) module to be installed. +**IMPORTANT** - Token Action HUD for GURPS requires the [Token Action HUD Core](https://foundryvtt.com/packages/token-action-hud-core) module to be installed. ## Recommended Modules Token Action HUD uses the [Color Picker](https://foundryvtt.com/packages/color-picker) library module for its color picker settings. @@ -38,7 +35,7 @@ Token Action HUD uses the [Color Picker](https://foundryvtt.com/packages/color-p For a guide on using Token Action HUD, go to: [How to Use Token Action HUD](https://github.com/Larkinabout/fvtt-token-action-hud-core/wiki/How-to-Use-Token-Action-HUD) -For questions, feature requests or bug reports, please open an issue [here](https://github.com/Larkinabout/fvtt-token-action-hud-core/issues). +For questions, feature requests or bug reports, please open an issue [here](https://git.evatt.ingenious.com.au/neillc/token-action-hud-gurps/issues). Pull requests are welcome. Please include a reason for the request or create an issue before starting one. @@ -48,4 +45,4 @@ Thank you to the Community Helpers on Foundry's Discord who provide tireless sup # License -This Foundry VTT module is licensed under a [Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/) and this work is licensed under [Foundry Virtual Tabletop EULA - Limited License Agreement for module development](https://foundryvtt.com/article/license/). \ No newline at end of file +This Foundry VTT module is licensed under a [Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/) and this work is licensed under [Foundry Virtual Tabletop EULA - Limited License Agreement for module development](https://foundryvtt.com/article/license/). diff --git a/rollup.config.js b/rollup.config.js index 533af63..9bf63c9 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -9,11 +9,11 @@ export default [ 'scripts/*/*.js' ], exclude: [ - 'scripts/token-action-hud-gurps.min.js'] + 'scripts/token-action-hud-template.min.js'] }, output: { format: 'esm', - file: 'scripts/token-action-hud-gurps.min.js' + file: 'scripts/token-action-hud-template.min.js' }, plugins: [ terser({ keep_classnames: true, keep_fnames: true }), diff --git a/scripts/action-handler.js b/scripts/action-handler.js index afc5d70..5bf7861 100644 --- a/scripts/action-handler.js +++ b/scripts/action-handler.js @@ -32,7 +32,6 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } if (this.actorType === 'character') { - //debugger; this.#buildCharacterActions() } else if (!this.actor) { this.#buildMultipleTokenActions() @@ -44,7 +43,6 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { * @private */ #buildCharacterActions () { - // debugger; this._get_attributes({id: "attributes", type:"system"}) this._get_skills({id: "skills", type:"system"}) this._get_spells({id: "spells", type:"system"}) @@ -81,7 +79,6 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } _get_melee_attacks(parent) { - // debugger; const macroType = "melee"; let actions = []; @@ -112,7 +109,6 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } _get_ranged_attacks(parent) { - // debugger; const macroType = "ranged"; let actions = []; @@ -143,57 +139,146 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } _get_skills(parent) { - // debugger; const macroType = "skills"; let actions = []; + // let skills = Object.entries(this.actor.system.skills) + // skills.forEach((a) => { + // const key = a[1].name; + // const value = a[1].level + // // img + + // let actionId = key; + // let otf = 'Sk:"' + key + '"'; // This is going to end badly if the delimiter is set to ":" + + + // actions.push({ + // id: actionId, + // name: coreModule.api.Utils.i18n(key) + " - test", + // description: coreModule.api.Utils.i18n('GURPS.Skills'), + // encodedValue: [macroType, otf].join(this.delimiter), + // }) + + + // }); let skills = Object.entries(this.actor.system.skills) - skills.forEach((a) => { - const key = a[1].name; - const value = a[1].level - // img - - let actionId = key; - let otf = 'Sk:"' + key + '"'; // This is going to end badly if the delimiter is set to ":" - - + // let map = this._get_contents(skills) + let map = this._get_contents(skills, macroType) + let names = Array.from(map.keys()).sort() + names.forEach((a)=> { actions.push({ - id: actionId, - name: coreModule.api.Utils.i18n(key), - description: coreModule.api.Utils.i18n('GURPS.Skills'), - encodedValue: [macroType, otf].join(this.delimiter), + id: a, + name: map.get(a).name, + description: map.get(a).description, + encodedValue: map.get(a).encodedValue }) + }) - - }); this.addActions(actions, parent) } + _get_contents(spells, macroType, result= new Map()) { + console.debug(spells); + console.debug(macroType); + console.debug(result) + + if (spells instanceof Array) { + for (const spell in spells) { + let _contains = spells[spell][1].contains; + + if (Reflect.has(_contains,"00000")) { + for( const i in _contains) { + result = this._get_contents(_contains[i], macroType, result) + } + } + else { + let name = spells[spell][1].name; + let level = spells[spell][1].level; + let otf_type = null; + + if (macroType === "skills") { + otf_type = 'Sk' + } + else { + otf_type = 'Sp' + } + + let otf = otf_type + ':"' + name + '"'; + + if (level) { + result.set( + name, + { + id: name, + name: coreModule.api.Utils.i18n(name), + description: coreModule.api.Utils.i18n('GURPS.Spells'), + encodedValue: [macroType, otf].join(this.delimiter), + } + ) + } + } + } + } + else { + if (spells.uuid) { + let _contains = spells.contains; + if (Reflect.has(_contains,"00000")) { + for( const i in _contains) { + result = this._get_contents(_contains[i], macroType, result) + } + } + else { + let spell = spells; + + let name = spell.name; + let level = spell.level; + let otf_type = null; + + if (macroType === "skills") { + otf_type = 'Sk' + } + else { + otf_type = 'Sp' + } + + let otf = otf_type + ':"' + name + '"'; + + + if (level) { + result.set( + name, + { + id: name, + name: coreModule.api.Utils.i18n(name), + description: coreModule.api.Utils.i18n('GURPS.Spells'), + encodedValue: [macroType, otf].join(this.delimiter), + } + ) + } + + } + } + } + return result; + } + + _get_spells(parent) { - // debugger; const macroType = "spells"; let actions = []; - let spells = Object.entries(this.actor.system.spells) - spells.forEach((a) => { - const key = a[1].name; - const value = a[1].level - // img - - let actionId = key; - let otf = 'Sp:"' + key + '"'; // This is going to end badly if the delimiter is set to ":" - - + let spell_map = this._get_contents(spells, macroType) + let spell_names = Array.from(spell_map.keys()).sort() + spell_names.forEach((a)=> { actions.push({ - id: actionId, - name: coreModule.api.Utils.i18n(key), - description: coreModule.api.Utils.i18n('GURPS.Spells'), - encodedValue: [macroType, otf].join(this.delimiter), + id: a, + name: spell_map.get(a).name, + description: spell_map.get(a).description, + encodedValue: spell_map.get(a).encodedValue }) + }) - - }); this.addActions(actions, parent) } @@ -256,3 +341,4 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { } } }) + diff --git a/scripts/constants.js b/scripts/constants.js index 6e5307e..5dfc46e 100644 --- a/scripts/constants.js +++ b/scripts/constants.js @@ -29,7 +29,7 @@ export const ACTION_TYPE = { * Groups */ -// Note: names are automatically localized. I could have avided some effort if I had realised that sooner. +// Note: names are automatically localized. I could have avoided some effort if I had realised that sooner. export const GROUP = { attributes: { id: 'attributes', name: 'GURPS.attributes', type: 'system' }, diff --git a/scripts/defaults.js b/scripts/defaults.js index c8a92bd..bf3afa4 100644 --- a/scripts/defaults.js +++ b/scripts/defaults.js @@ -12,7 +12,6 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { group.listName = `Group: ${coreModule.api.Utils.i18n(group.listName ?? group.name)}` }) const groupsArray = Object.values(groups) - // debugger; DEFAULTS = { layout: [ { diff --git a/scripts/roll-handler.js b/scripts/roll-handler.js index fac2578..2bf0689 100644 --- a/scripts/roll-handler.js +++ b/scripts/roll-handler.js @@ -120,7 +120,7 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { case 'endTurn': if (game.combat?.current?.tokenId === token.id) { await game.combat?.nextTurn() - }executeOTF + } break } } @@ -130,7 +130,6 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { if ( actionId == "WILL" ) actionId = "Will"; if ( actionId == "PER" ) actionId = "Per"; - // debugger; let formula = '3d6'; let targetmods = null; let prefix = "Rolls vs" // should be i18n of 'GURPS.rollVs' @@ -148,8 +147,6 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { async #handleMeleeAction(actor, actionId) { /* Melee attacks are done using the otf method. Grab the otf and pass it to the function. */ let GURPS = globalThis.GURPS; - - // debugger; let otf = actionId; GURPS.executeOTF(otf, actor=actor); } @@ -157,39 +154,22 @@ Hooks.once('tokenActionHudCoreApiReady', async (coreModule) => { async #handleRangedAction(actor, actionId) { /* Melee attacks are done using the otf method. Grab the otf and pass it to the function. */ let GURPS = globalThis.GURPS; - - // debugger; let otf = actionId; GURPS.executeOTF(otf, actor=actor); - - - // doRoll({ actor, formula, targetmods, prefix, thing, chatthing, origtarget: target, optionalArgs: opt }) } async #handleSkillAction(actor, actionId) { /* Skills are done using the otf method. Grab the otf and pass it to the function. */ let GURPS = globalThis.GURPS; - // actor, formula, targetmods, prefix = '', thing = '', chatthing = '', origtarget = -1, optionalArgs = {}, - - // executeOTF(inputstring, priv = false, event = null, actor = null) { - - // debugger; let otf = actionId; GURPS.executeOTF(otf, actor=actor); - - - // doRoll({ actor, formula, targetmods, prefix, thing, chatthing, origtarget: target, optionalArgs: opt }) } async #handleSpellAction(actor, actionId) { /* Spells are done using the otf method. Grab the otf and pass it to the function. */ let GURPS = globalThis.GURPS; - - // debugger; let otf = actionId; GURPS.executeOTF(otf, actor=actor); - - } } })