-
Notifications
You must be signed in to change notification settings - Fork 14
Module Integration
This page covers how to create FoundryVTT modules that integrate with the PbtA system to provide pre-configured character sheets for specific games.
Module integration allows you to:
- Override the default sheet configuration interface
- Provide pre-built character sheets for specific PbtA games
- Customize tag systems for your game
- Distribute complete game implementations
To create a module that provides a pre-configured sheet, use the pbtaSheetConfig hook to override the system's configuration.
Create a module that overrides the sheet configuration:
Hooks.once('pbtaSheetConfig', () => {
// Disable the sheet config form for users
game.settings.set('pbta', 'sheetConfigOverride', true);
// Replace the sheet configuration with your pre-built config
game.pbta.sheetConfig = {
rollFormula: "2d6",
rollResults: {
failure: {
range: "6-",
label: "Miss..."
},
partial: {
range: "7-9",
label: "Partial Success"
},
success: {
range: "10+",
label: "Success!"
}
},
// ... complete configuration object
};
});To get the proper format for your module override:
- Configure manually: Set up your sheet using the TOML interface in a test world
-
Export configuration: In the browser console, run:
console.log(JSON.stringify(game.pbta.sheetConfig, null, 2));
- Copy output: Use the logged object as your module's configuration
- Clean up: Remove any unnecessary properties or defaults
The configuration object uses this structure (converted from TOML):
{
rollFormula: "2d6",
minMod: -3,
maxMod: 4,
rollShifting: true,
statToggle: {
label: "Highlight",
modifier: 1
},
rollResults: {
failure: { range: "6-", label: "Miss..." },
success: { range: "10+", label: "Success!" }
},
actorTypes: {
character: {
stats: {
cool: "Cool",
hard: "Hard"
},
attributes: {
harm: {
type: "Clock",
label: "Harm",
max: 6,
position: "top"
}
},
moveTypes: {
basic: "Basic Moves"
},
equipmentTypes: {
gear: "Gear"
}
},
npc: {
// NPC configuration
}
}
}Modules can also customize the tag system used for equipment and actors.
Hooks.once('pbtaSheetConfig', () => {
game.pbta.tagConfigOverride = {
// General tags available to all items/actors
general: '[{"value":"magic"},{"value":"mundane"},{"value":"rare"}]',
// Actor-specific tags
actor: {
all: '[{"value":"important"},{"value":"recurring"}]',
character: '[{"value":"hero"},{"value":"protagonist"}]',
npc: '[{"value":"villain"},{"value":"ally"}]'
},
// Item-specific tags
item: {
all: '[{"value":"valuable"},{"value":"cursed"}]',
equipment: '[{"value":"weapon"},{"value":"armor"},{"value":"tool"}]',
move: '[{"value":"basic"},{"value":"advanced"}]'
}
};
});Tags are defined as JSON strings containing arrays of tag objects:
// Simple tags
'[{"value":"weapon"},{"value":"armor"}]'
// Tags with tooltips (using | separator)
'[{"value":"magic | Items with supernatural properties"}]'
// Localized tags
'[{"value":"GAME.TagWeapon | GAME.TagWeaponDesc"}]'Here's a complete example module for a fictional PbtA game:
// module.js
Hooks.once('pbtaSheetConfig', () => {
// Disable default configuration interface
game.settings.set('pbta', 'sheetConfigOverride', true);
// Custom tags for this game
game.pbta.tagConfigOverride = {
general: '[{"value":"tech"},{"value":"bio"},{"value":"psi"}]',
actor: {
character: '[{"value":"augmented"},{"value":"natural"}]'
},
item: {
equipment: '[{"value":"cybernetic"},{"value":"weapon"},{"value":"armor"}]'
}
};
// Complete sheet configuration
game.pbta.sheetConfig = {
rollFormula: "2d6",
statToggle: {
label: "Glitched",
modifier: -2
},
rollResults: {
failure: {
range: "6-",
label: "System Failure"
},
partial: {
range: "7-9",
label: "Partial Success"
},
success: {
range: "10-12",
label: "Clean Success"
},
critical: {
range: "13+",
label: "Critical Override"
}
},
actorTypes: {
character: {
stats: {
interface: "Interface",
edge: "Edge",
flesh: "Flesh",
ghost: "Ghost"
},
attributes: {
stress: {
type: "Clock",
label: "Stress",
max: 8,
position: "top"
},
harm: {
type: "Clock",
label: "Harm",
max: 6,
position: "top"
},
credits: {
type: "Number",
label: "Credits",
position: "top",
default: 0
},
background: {
type: "LongText",
label: "Background",
position: "left"
},
augmentations: {
type: "LongText",
label: "Augmentations",
position: "left"
}
},
moveTypes: {
basic: "Basic Moves",
interface: "Interface Moves",
background: "Background Moves"
},
equipmentTypes: {
gear: "Gear",
software: "Software",
augments: "Augmentations"
}
},
npc: {
stats: false,
attributes: {
threat: {
type: "Number",
label: "Threat Level",
position: "top",
default: 1
},
harm: {
type: "Resource",
label: "Harm Capacity",
position: "top"
},
motivation: {
type: "LongText",
label: "Motivation",
position: "left"
}
},
moveTypes: {
gm: "GM Moves",
threat: "Threat Moves"
},
equipmentTypes: {
gear: "Gear"
}
}
}
};
});- Start Simple: Begin with a minimal configuration done in TOML then:
-
Use Console: Check
game.pbta.sheetConfigto get your json version.
Wrap your configuration in error handling:
Hooks.once('pbtaSheetConfig', () => {
try {
game.settings.set('pbta', 'sheetConfigOverride', true);
game.pbta.sheetConfig = yourConfigurationObject;
console.log("Custom PbtA configuration loaded successfully");
} catch (error) {
console.error("Failed to load custom PbtA configuration:", error);
}
});Check for required system versions:
Hooks.once('pbtaSheetConfig', () => {
const requiredVersion = "0.7.0"; // Example version
const currentVersion = game.system.data.version;
if (!isNewerVersion(currentVersion, requiredVersion)) {
ui.notifications.warn(`This module requires PbtA system version ${requiredVersion} or higher`);
return;
}
// Your configuration code here
});Support multiple languages in your module:
// In your configuration
label: game.i18n.localize("MYGAME.StatInterface"),
description: game.i18n.localize("MYGAME.StatInterfaceDesc"),
// In your language files (en.json)
{
"MYGAME": {
"StatInterface": "Interface",
"StatInterfaceDesc": "Your connection to the digital realm"
}
}Ensure you have proper licensing for:
- Game content you're implementing
- Any artwork or assets
- Compliance with FoundryVTT package policies
- Check browser console for errors
- Verify the hook is firing:
Hooks.once('pbtaSheetConfig', () => console.log('Hook fired')) - Ensure your module is active and loading after the PbtA system
- Validate your configuration object structure
- Verify tag JSON is valid
- Check that tags are properly formatted strings
- Ensure the hook runs before sheets are rendered
- Refresh the page after installing your module
- Close and reopen character sheets
- Check that
sheetConfigOverrideis set totrue - Verify no TOML configuration is overriding your module config
For additional support, consult the PbtA system documentation or ask in the FoundryVTT Discord's powered-by-the-apocalypse channel.
List of TOML presets for your games.
List of FoundryVTT modules that implement the rules of some PbtA games.
Covers how to create FoundryVTT modules that integrate with the PbtA system.