-
Notifications
You must be signed in to change notification settings - Fork 43
Extensibility
Moves have two ways to customize them, and oracles provide three. Assets only provide one.
The system will look for folders using localized names; check the lang
folder for your language, and search the file for "Custom Oracles".
In English, these names are:
- "Custom Oracles" in the Roll Tables tab
- "Custom Moves" and "Custom Assets" in the Items tab
If any of these folders are found, the system will include its contents in the moves/oracles/assets area of the sheet:
Only top-level items will be shown for moves and assets, but oracles will import the entire tree.
Note This method is a bit brittle. Prefer the registration method below if at all possible.
This method is more useful for modules, and involves handling the ironswornOracles
hook.
The type of object in the tree is shown in customoracles.ts
.
Here's a simple hook that adds more rows to the "Background Assets" oracle (when using the Starforged oracle set):
const extraAssetsTableUuid = await game.tables.get('MSjHr7AahxxJXAqe').uuid
Hooks.on('ironswornOracles', (root) => {
root.children[0].children[0].tables.push(extraAssetsTableUuid)
})
Another example, which renames "Oracle 14: Elf Names" to "XYZ" (when using the Ironsworn oracle set):
Hooks.on('ironswornOracles', x => x.children[4].children[1].displayName = 'XYZ')
Here is a helper you can use to search the tree for an oracle by name, instead of navigating by array indexes.
function findOracleByName(node, searchName) {
if (node.displayName === searchName) return node
for (const child of node.children) {
const childResult = findOracleByName(child, searchName)
if (childResult) return childResult
}
}
There is also an ironswornMoves
hook, which passes the final tree before display.
See custommoves.ts
for the structure of those objects.
In order to install these hooks as a GM or player, do this:
- Write a macro called "Ironsworn Startup", change its type to "script", and add a
Hooks.on(...)
invocation like above - Change that macro's permissions so that all players have at least "Limited" rights
- Reload your browser window to make sure the macro is invoked.
Another way of customizing oracles, starting with 1.21.0, is custom registration.
The oracle tree is computed on startup, and can be fetched using CONFIG.IRONSWORN.getOracleTree('classic')
(other options are 'delve'
, 'starforged'
, and 'sundered_isles'
).
The ironswornOracleTreesReady
hook will fire when the default tree is ready, and you can fetch that tree, modify it, and send it to CONFIG.IRONSWORN.registerOracleTree
to update the base tree of oracles that's used in every oracle tool in the game.
Here's a sample hook body:
Hooks.on('ironswornOracleTreesReady', () => {
const ironswornOracles = CONFIG.IRONSWORN.getOracleTree('classic')
ironswornOracles.children[0].children.push({
displayName: 'Philosophy',
tables: ['uuid-of-philosophy-table'],
children: []
})
CONFIG.IRONSWORN.registerOracleTree('classic', ironswornOracles)
})
One thing to note is that Foundry's hooks are synchronous – they won't await
your callback function.
That means that if your callback is using promises, Foundry might fire off another one while you're await
ing or then
ing, and the results could be unexpected.
Your best bet right now is to do all your asynchronous processing before the hook is called, perhaps on an init
or ready
hook, and only do synchronous code inside the callback body.
(If this ends up being a problem for you, leave us an issue, and we can see about doing an async hooks method.)