SC - More Activities
SC - More Activities
Overview
SC - More Activities extends the native D&D 5e activity system in
Foundry VTT. It does not replace the standard dnd5e activity workflow. It
adds new activity types, a Shattered Codex-owned registration layer, a grouped
activity creation dialog, GM-facing diagnostics, and explicit migration tools
for worlds moving away from the legacy more-activities module.
The module is built for two different jobs:
- GMs who want more activity types without maintaining custom patches
- module authors who want to register custom
dnd5eactivity types through a stable public API
The module ships with built-in SC activity types and a registry flow that can also expose third-party activity types in the same creation UI.
Installation
- In Foundry VTT, open Add-on Modules.
- Choose Install Module.
- Paste this manifest URL:
https://github.com/Shattered-Codex/sc-more-activities/releases/latest/download/module.json- Install the module.
- Enable SC - More Activities in your world.
- Install and enable
libWrapperif you want the recommended compatibility layer.
Compatibility:
- Foundry VTT
v13tov14 - system:
dnd5e dnd5ecompatibility declared inmodule.json: minimum5.0.0, verified5.3.0- localization: English and Brazilian Portuguese
Important behavior:
- the module exits early outside
dnd5eworlds - native
dnd5eactivities remain available - the module relies on items and sheets that already support the
dnd5eactivity workflow
What It Adds
- built-in Shattered Codex activity types for automation, support, progression, inventory, and canvas workflows
- a public registration hook and API for Shattered Codex modules and third-party modules
- a grouped activity creation dialog that separates D&D 5e, Shattered Codex, and External activity groups
- a GM Activity Catalog with diagnostics, filters, and enable or disable controls
- explicit migration tools for legacy
more-activitiesactivity data - per-user preview color settings for teleport, movement, wall, and portal overlays
- module settings shortcuts for the wiki, support links, catalog, migration tools, and preview colors
Built-In Activity Types
| Activity | Use it for | Main configuration | Important notes |
|---|---|---|---|
| SC Sound | Play an audio file after the activity is used. | Audio file, Playback, and Volume. | Broadcasting to Everyone requires a GM. Non-GM use falls back to local playback. |
| SC Macro | Run a selected world macro or inline code stored on the activity. | Macro source, World macro, and Inline code. | Inline code runs only for GMs. World macros still respect the user's macro permissions. |
| SC Hook | Emit a hook or call a whitelisted callback exposed by another module. | Dispatch mode, Hook name, Callback module, and Callback id. | This is primarily an integration and developer workflow, not a player-facing automation shortcut. |
| SC Chain | Execute other activities from the same item in order. | Activity ids, Depth limit, Continue after failure, and Stop when canceled. | Includes loop detection and nested-depth protection. |
| SC Conditional Chain | Branch between activities on the same item based on results, actor data, rolls, or manual choices. | First step, per-step activity, condition type, routes, and flow policies. | Steps can also be decision-only. The flow keeps using the most recent child activity result until another activity runs. |
| SC Contest | Resolve a contested roll between the activity user and a defender. | Defender, Tie rule, and roll configuration for both sides. | The defender can be the selected target or the same actor. Custom formulas are supported. |
| SC Grant | Grant configured items to the activity actor or to a targeted actor. | Recipient, granted item UUIDs, and Quantity. | Using the target flow requires exactly one target token with a valid actor. |
| SC Advancement | Trigger selected dnd5e advancement entries from a source item. | Source item and selected Advancement Entries. | The actor must own the source item at use time. |
| SC Teleport | Choose teleport targets and place their destination on the canvas. | Targets, Maximum targets, Allow self, Target range, Teleport range, destination source, offsets, and arrangement controls. | Scene movement is GM-mediated. Destination placement can be limited by range. |
| SC Movement | Push or pull tokens from the activity actor with a preview workflow. | Targets, Maximum targets, Snap to grid, Movement type, Distance, and Range limit. | Scene movement is GM-mediated and respects the configured range limit. |
| SC Wall | Create walls by placing points directly on the canvas. | Wall type, Placement range, wall limits, panel settings, facing, and block properties. | Can be restricted to GM-only creation or allow player requests through an active GM. |
| SC Portal | Open a linked entry and exit on the active Scene and ask tokens whether they want to cross. | Placement and link ranges, shape, area, crossing triggers, duration, uses, visibility, and optional art. | Scene changes are GM-mediated. Restart Foundry after installing or updating so the SC Portal Region behavior is registered. |
The built-in activities are registered under the Shattered Codex group in the activity creation dialog, but the catalog still tracks their category and source metadata separately.
SC Sound
SC Sound plays one audio file after the activity is used. It is useful for item activation sounds, spoken cues, alarms, and short ambient effects that should stay attached to the item workflow.
Configure it from the activity's Effect tab:
- Choose the Audio file.
- Set Playback to the current user or everyone.
- Adjust Volume from
0to1. - Save and use the activity normally.
Only a GM can broadcast the sound to everyone. If a non-GM uses an activity configured for everyone, the module warns that user and plays the sound only on their client. Playback does not loop.
SC Macro
SC Macro runs either a world Macro or JavaScript stored directly on the activity.
- World macro lets you choose an existing Macro from the world. Foundry still checks whether the current user can execute it.
- Inline code stores the script on the activity. Only a GM can edit or run this code.
Inline code receives the activity, item, actor, usage data, dialog data, chat message options, previous results, speaker, and current targets. Use this mode only for trusted code. For reusable automation, prefer a world Macro or a module-owned integration.
SC Hook
SC Hook is an integration activity for module authors and advanced world automation. Its Dispatch mode determines what happens when the activity is used:
- Hook calls the configured Foundry hook name and passes one payload object.
- Callback calls a function that another active module explicitly exposed through the SC - More Activities callback whitelist.
The payload contains the activity, item, actor, usage data, dialog data, message options, results, speaker, and current targets. A callback also needs the providing Module id and Callback id. SC Hook does not execute an arbitrary function path from another module.
SC Chain
SC Chain executes activities from the same item in a fixed order. Create the child activities first, then add them to the chain from its Effect tab.
The chain provides these flow controls:
- Depth limit stops excessively deep nested chains. The accepted range is
1to20, with5as the default. - Continue after child errors moves to the next entry when a child is missing or throws an error.
- Stop when a child activity is canceled ends the chain when a child does not complete.
- Suppress child chat messages runs child activities without creating their individual chat messages.
Loop detection prevents a chain from calling an activity that is already in the current execution path. Use SC Conditional Chain instead when the next activity must depend on a result or a user choice.
SC Conditional Chain
SC Conditional Chain is the branching version of SC Chain.
Use it when one activity should lead to different outcomes depending on what just happened. A simple example is:
- roll an attack
- deal damage only if the attack hits
- trigger a bonus effect only if the damage total is high enough
Important scope:
- a conditional chain can call only activities that already exist on the same item
- every step can either run one activity or be Decision only (no activity)
- decision-only steps keep using the most recent child activity result until a later step runs another activity
Before You Build The Flow
Build the child activities first. Then add SC Conditional Chain to the same item and use it as the controller.
This is the easiest order for non-technical setup:
- Create the attack, damage, healing, grant, macro, or other activities you want the item to use.
- Add SC Conditional Chain.
- Open the chain's Effect tab.
- Add your steps in the order you want to think about them.
- Pick the First step.
- Configure how each step decides where the flow goes next.
Restrict A Child Activity To Chains
If SC - Conditional Activities is also enabled, you can prevent a child activity from being used directly and allow it only when an SC Chain or SC Conditional Chain calls it.
- Open the child activity that should run only as part of a chain.
- Open its Condition tab.
- Enter this condition:
usage?.scMoreActivitiesChain- Save the activity. Optionally set its locked badge to Chain only so players can understand why direct use is unavailable.
- Add that activity to a step in SC Conditional Chain.
When a user tries to use the child activity directly, the usage data does not
contain scMoreActivitiesChain, so SC - Conditional Activities blocks it.
When a chain calls the same activity, SC - More Activities adds that marker
to the child usage data and the condition passes.
This restriction applies to both SC Chain and SC Conditional Chain because they share the same execution marker. It makes the child activity chain-only; it does not restrict the child to one specific chain or to the conditional variant alone. See SC - Conditional Activities for condition setup, badges, and warning-message controls.
Main Fields
| Field | What it controls | What to watch for |
|---|---|---|
| First step | The step where the flow begins. | If this is empty, the chain cannot run. |
| Step name | The label you see while editing the flow. | This is only for readability. It helps a lot once the flow has several branches. |
| Activity | Which activity this step runs before deciding the next route. | Choose "Decision only (no activity)" if the step should only inspect data and branch. |
| Decide the next step by | Which rule this step uses to branch. | The rest of the step changes depending on the condition type you pick. |
| Routes | Where the flow goes after the step resolves. | Routes can point to another step or to "End flow". |
| Flow policies | Safety rules for depth, cancellation, and child errors. | These settings affect the whole chain, not just one step. |
Condition Types
| Condition type | Use it when | Extra fields | Routes shown |
|---|---|---|---|
| Always continue | The step should always go to the same next step. | Next step only. | Next step |
| Actor property | You want to branch from actor data such as HP, spellcasting data, flags, or another deterministic value. | Actor property path, operator, and value. | When true / When false |
| Last activity result | You want to branch from the result of the most recent child activity. | Result path, operator, and value. | When true / When false |
| Roll | The chain itself should ask for a check, save, skill roll, or custom formula roll. | Roll type, ability or skill when needed, and DC. | On success / On failure |
| Manual choice | The user should pick the branch in a dialog. | A list of options. | One route per option |
Canceling a roll or canceling the manual-choice dialog always ends the flow.
Roll Types
| Roll type | What it does | When to use it |
|---|---|---|
| Ability check | Uses the actor's normal D&D 5e ability check workflow for the chosen ability. | Good for broad tests such as Strength or Intelligence checks. |
| Saving throw | Uses the actor's normal D&D 5e saving throw workflow for the chosen ability. | Use it when the branch depends on passing or failing a save. |
| Skill check | Uses the actor's normal D&D 5e skill check workflow for the chosen skill. | Good for flows such as Athletics contests, Stealth gates, or social checks. |
| Custom formula | Rolls a custom formula and posts a chat message for that roll. | Use it when a normal ability or skill roll is not enough. |
The DC field accepts either a number or a deterministic formula such as
8 + @prof or 10 + @scLast.roll.dice.count. The roll succeeds when its total
meets or exceeds that DC.
Last Activity Result
Last activity result means the result from the most recent step that actually ran an activity.
That rule has two important consequences:
- if a step is Decision only (no activity), it does not clear the previous result
- several decision-only steps in a row can branch from different parts of the same stored result
The result picker shows grouped suggestions, but you can switch to Custom path… whenever you need to type a raw path yourself.
When Decide the next step by is Last activity result, the row is made of three parts:
| Field | What it does | Examples |
|---|---|---|
| Result | Chooses which stored value to inspect. | Attack hit, Roll total (all rolls), Grant check passed, Contest winner. |
| Operator | Compares the stored value against the value field. | =, ≠, >, ≥, <, ≤, includes |
| Value | The expected value for the comparison. | 10, true, false, radiant, @abilities.con.mod, @scLast.roll.sum |
What the picker supports:
- for known result types such as attacks, damage or healing rolls,
sc-grant, andsc-contest, the picker can suggest the most useful grouped paths - Custom path… lets you type any raw path, such as
roll.totals.1orroll.dice.values.2 - the Value field accepts numbers,
trueorfalse, text, and deterministic formulas includesworks on text and lists, so it is useful for cases like tags, damage types, or text fragments
Result Path Reference
Use these paths when you need something more specific than the first suggested options.
For custom or unsupported activity types, only the fields that activity really records will return a value. If a path does not exist in the result, the chain cannot evaluate it.
General Paths
These are the most common fields and are available on every tracked result.
| Shown as | Path | What it means |
|---|---|---|
| Result kind | kind | What the last activity produced, such as attack, damage, healing, grant, or contest. |
| Was a success | success | True when the activity succeeded. |
| Was a failure | failure | True when the activity failed. |
| Main total | total | The main total from the result, when one exists. |
| Was a critical | critical | True when the main roll was a critical. |
| Was a fumble | fumble | True when the main roll was a fumble or natural 1. |
| Target number (DC or AC) | target | The DC or armor class the main roll was compared against. |
| Was canceled | canceled | True when the activity was canceled before finishing. |
| Source activity id | sourceActivity.id | Internal id of the activity that produced the result. |
| Source activity type | sourceActivity.type | Type of the activity that produced the result. |
| Source activity name | sourceActivity.name | Display name of the activity that produced the result. |
| Source item id | sourceActivity.itemId | Id of the item that owns the source activity. |
| Source item UUID | sourceActivity.itemUuid | UUID of the item that owns the source activity. |
| Source actor UUID | sourceActivity.actorUuid | UUID of the actor that used the source activity. |
| Chat message id | use.messageId | Id of the chat message created by the activity, when one exists. |
| Updates applied | use.updateCount | How many document updates the activity applied. |
| Effects created | use.effectCount | How many active effects the activity created. |
| Templates placed | use.templateCount | How many measured templates the activity placed. |
Roll Paths
These are the most useful fields for attack, damage, healing, save, and grant-check style results.
| Shown as | Path | What it means |
|---|---|---|
| Roll total (first roll) | roll.total | Total of the first roll, including modifiers. |
| Roll total (all rolls) | roll.sum | Sum of every roll made by that activity. |
| Total of roll #1 | roll.totals.0 | Total of the first individual roll. Use roll.totals.1, .2, and so on for later rolls. |
| Number of rolls | roll.count | How many separate rolls were made. |
| Roll succeeded | roll.success | True when the roll met its target number. |
| Roll failed | roll.failure | True when the roll missed its target number. |
| Roll was a critical | roll.critical | True when the roll was a critical. |
| Roll was a fumble | roll.fumble | True when the roll was a fumble. |
| Roll target number | roll.target | The DC or AC used for that roll. |
| Roll formula | roll.formula | The formula that was rolled, such as 1d20 + 5. |
| Ability used | roll.ability | Ability key used by the roll, such as str or dex. |
| Skill used | roll.skill | Skill key used by the roll, such as ath or ste. |
| Tool used | roll.tool | Tool key used by the roll when the workflow records one. |
Individual Dice Paths
These fields inspect the kept dice only. Discarded dice from advantage, rerolls, and similar effects are ignored.
| Shown as | Path | What it means |
|---|---|---|
| Dice total (no modifiers) | roll.dice.total | Sum of the dice only, without flat bonuses. |
| Number of dice | roll.dice.count | How many kept dice were recorded across all rolls. |
| First die value | roll.dice.values.0 | Face rolled on the first kept die. Use .1, .2, and so on for later dice. |
| Highest die | roll.dice.max | Highest kept die result. |
| Lowest die | roll.dice.min | Lowest kept die result. |
Attack Paths
Use these when the previous child activity is an attack activity.
| Shown as | Path | What it means |
|---|---|---|
| Attack hit | attack.hit | True when the attack hit its target or rolled a critical. |
| Attack missed | attack.miss | True when the attack missed. |
| Attack roll total | attack.total | Total of the attack roll, including modifiers. |
| Critical hit | attack.critical | True when the attack roll was a critical. |
| Attack fumble | attack.fumble | True when the attack roll was a fumble. |
| Target armor class | attack.target | Armor class the attack was compared against for a single target. |
Grant Paths
Use these when the previous child activity is SC Grant.
| Shown as | Path | What it means |
|---|---|---|
| Grant check passed | activity.checkPassed | True when the grant's gating check succeeded. |
| Grant check DC | activity.check.dc | DC used by the grant check. |
| Grant check total | activity.check.total | Total rolled for the grant check. |
| Documents created | activity.createdCount | How many documents the grant created. |
| Documents updated | activity.updatedCount | How many documents the grant updated. |
| Target actor UUID | activity.actorUuid | UUID of the actor who received the grant. |
| Activity canceled | activity.canceled | True when the grant was canceled before finishing. |
| Cancel reason | activity.reason | Why the grant canceled, such as missing actor or check-canceled. |
Contest Paths
Use these when the previous child activity is SC Contest.
| Shown as | Path | What it means |
|---|---|---|
| Contest winner | activity.winner or contest.winner | Who won: initiator, defender, or empty on a tie. |
| Contest tied | activity.tied or contest.tied | True when the contest ended in a tie. |
| Contest attempt number | activity.attempt | How many attempts were made, including a reroll on ties. |
| Initiator roll total | contest.initiator.total | Total rolled by the initiator. |
| Initiator actor UUID | contest.initiator.actorUuid | UUID of the initiator's actor. |
| Initiator token UUID | contest.initiator.tokenUuid | UUID of the initiator's token. |
| Defender roll total | contest.defender.total | Total rolled by the defender. |
| Defender actor UUID | contest.defender.actorUuid | UUID of the defender's actor. |
| Defender token UUID | contest.defender.tokenUuid | UUID of the defender's token. |
Using @scLast In Formulas
The previous result is also exposed to formulas as @scLast.
That is useful when a later roll should reuse the number produced by an earlier step. A common example is a heal or bonus-damage activity that copies the previous damage total.
This heal formula uses @scLast.roll.sum, so it can read the total rolled by
the previous step.
Practical formula notes:
@scLast.roll.sumis the safest way to reuse the previous total across multi-part rolls@scLast.attack.hitand other booleans resolve as1or0inside formulas@scLastby itself resolves to the previous main numeric total when one is available
Flow Policies
The collapsible Flow policies section controls global safety rules for the chain.
These policies affect the whole chain, not just the currently selected step.
| Policy | What it does | Important detail |
|---|---|---|
| Depth limit | Stops execution when the chain goes deeper than the configured nested limit. | This limit is shared with SC Chain. |
| Stop when a child activity is canceled | Ends the chain if a step's activity returns no result. | This does not change manual-choice or roll cancellation. Those always end the flow. |
| Continue after child errors | Keeps routing even if a child activity is missing or throws an error. | Leave this off unless you intentionally want a fallback branch after a broken child step. |
Example Flow: Attack, Then Damage, Then Reuse The Damage Total
This is a practical setup for a non-technical item builder:
- Create an Attack activity on the item.
- Create a Damage activity on the same item.
- Create a Heal or bonus effect activity that uses
@scLast.roll.sumin its formula if you want it to copy the previous damage total. - In SC Conditional Chain, make the first step run Attack and branch
on Last activity result with
Attack hit = true. - Send the true route to a Damage step and the false route to End flow.
- After Damage, either continue directly to another step or add a new
branch that checks
roll.sum,roll.dice.max, or any other value you need.
SC Contest
SC Contest resolves one roll for the initiating actor and one for a defender, then compares their totals. It supports ability checks, saving throws, skill checks, and custom formulas for either side.
Configure the Defender as the currently targeted token or the initiating actor. When using a target, select exactly one token with a valid actor. Then choose the Tie rule:
- keep the result as a tie
- award the tie to the initiator
- award the tie to the defender
- reroll both sides once, keeping a second tie as a tie
The result is posted to chat and can be inspected by SC Conditional Chain through fields such as contest winner, tie state, and both roll totals.
SC Grant
SC Grant adds configured Items to the activity actor or to exactly one targeted actor. Each grant row accepts an Item or Roll Table UUID and a quantity formula.
To configure it:
- Choose Self or Target as the recipient.
- Add an Item or Roll Table by drag and drop, UUID, or the add control.
- Enter the quantity. Values such as
2,1d4, and@profare supported. - Optionally expand Grant Check and choose an ability or skill check plus its Difficulty Class.
For a Roll Table, quantity means the number of draws. The module grants Item results from those draws and ignores results that cannot resolve to Items. The current user must have permission to update the recipient actor. If an optional check fails, no Items are granted.
SC Advancement
SC Advancement opens the D&D 5e advancement workflow for selected advancement entries on a source Item.
- Drop or paste the UUID of an Item that contains D&D 5e advancements.
- Select one or more advancement entries and levels exposed by that Item.
- Save and use the activity from an actor-owned Item.
At use time, the actor must own the source Item and the current user must have permission to manage that actor. The activity then opens the native D&D 5e Advancement Manager; it does not silently apply advancement choices.
SC Teleport
SC Teleport lets the user choose eligible tokens and then click their destination on the active Scene.
Its Effect tab controls:
- Only self, which skips target selection and teleports the activity actor
- Maximum targets, Allow self, and Target range for normal selection
- Teleport range, measured from the activity actor to the destination
- Keep arrangement or a Cluster radius for multiple tokens
- Snap to grid for the final token positions
Use 0 for an unlimited target or teleport range. After using the activity,
choose the tokens, continue to destination placement, and left-click the
canvas. Right-click or press Escape to cancel. An active GM is required to
perform the Scene update for player-initiated use.
SC Movement
SC Movement pushes or pulls tokens relative to the activity actor. The affected tokens can come from the user's targets, controlled tokens, or the activity actor itself.
Choose Push, Pull, or Either. The last option asks the user which
direction to apply when the activity is used. Distance controls how far the
tokens move, Range limit controls which tokens are eligible, Maximum
targets limits the selection, and Snap to grid rounds destinations to the
grid. A range limit of 0 is unlimited.
Using the activity opens a preview where the user can review eligible tokens before confirming the move. Moving the activity actor itself also requires a direction point on the canvas. An active GM mediates Scene updates initiated by players.
SC Wall
SC Wall creates Foundry Wall documents by placing points on the active Scene. It supports three placement styles:
- Continuous joins each placed point into a connected path.
- Circular uses the placement gesture to create a circle.
- Panels creates separated wall segments using the configured panel size, spacing, and optional maximum panel count.
Configure the maximum number of walls, maximum length, direction relative to the activity actor, and reference range. These distance and count fields accept formulas. You can also choose whether the generated Walls block movement, sight, and sound.
Scene document creation is GM-controlled. Enable Allow player requests only when Item owners should be able to ask an active GM client to create the Walls. The activity actor's token must be present on the active Scene before placement begins.
SC Portal
SC Portal opens a linked entry and exit on the active Scene. A token that enters or clicks a configured side can be asked whether it wants to cross.
Availability: SC Portal is currently implemented on the official
feature/portal-activitybranch and is not included in the public0.9.1release. The workflow below applies to builds that include that feature.
The activity creates Foundry Scene documents rather than moving a token as part of the initial activity use:
- each side is a
Regionwith an SC Portal Region behavior - optional entry and exit art is created as a matching
Tile - both Regions share one portal id, so closing either side removes the pair and their art
Configure A Portal Activity
Add SC Portal to an Item, then configure its Effect tab.
| Field | What it controls | Default or limit |
|---|---|---|
| Placement range | Maximum distance from the acting token to each portal side. Accepts a roll formula. | 30; use 0 for no limit. |
| Maximum distance between sides | Maximum distance from entry to exit. Accepts a roll formula. | Empty means no limit. |
| Shape | The Region shape used by each side. | Square; Circle is also available. |
| Area | The footprint of each side in grid squares. | 1×1 through 4×4. |
| Snap to grid | Aligns both sides and the arriving token to the Scene grid. | Enabled; ignored on gridless Scenes. |
| Avoid occupied spaces | Searches near the exit for room instead of stacking the arriving token on another token. | Enabled; crossing is refused when no nearby space is free. |
| One way | Allows travel only from Entry to Exit. | Disabled. |
| Ask on entry | Prompts a token that enters the Region during movement. | Enabled. |
| Ask on click | Prompts when the user clicks a portal with an eligible owned token inside or next to it. | Enabled. |
| Allow player use | Lets an Item owner ask the active GM to create the portal. | Disabled; the GM client still writes the Scene documents. |
| Maximum crossings | Closes the pair after this many completed crossings. Accepts a roll formula. | Empty or 0 means unlimited. |
| Duration in rounds | Closes the pair after a combat-round deadline, or equivalent world time outside combat. Accepts a roll formula. | 10; use 0 to keep it open. |
| Visible to | Controls visibility of the portal Region overlay. | Everyone, Gamemaster only, or Hidden (art only). |
| Color | Sets the portal Region color on the canvas. | #8A63D2. |
| Entry art / Exit art | Places an optional image or video Tile over each side. | Images and webm, mp4, or ogv video are supported; video loops muted. |
Choose Hidden (art only) when a custom image or video should be the visible portal. The Region remains active and can still be managed by the GM from the Regions layer.
An even-sized area snaps around a grid corner. For example, a 2×2 portal covers four complete grid cells. On a gridless Scene, the module uses the Scene's nominal grid size for the footprint but places each side exactly where you click.
Place The Two Sides
- Activate the intended Scene. If Placement range is greater than
0, select or place the activity actor's token on that Scene. - Use the SC Portal activity.
- In Portal Placement, choose Place on canvas.
- Left-click to place Entry.
- Left-click again to place Exit.
- Review the range and placement summary.
- Choose Open portal.
Right-click stops canvas placement, and Clear sides removes the pending points so you can place them again. Both sides must satisfy Placement range; when configured, they must also satisfy Maximum distance between sides. Changing the active Scene cancels the placement workflow.
Cross A Portal
With Ask on entry enabled, the module uses Foundry's tokenMoveIn Region
event. A token that walks across a portal stops on it and receives the prompt;
declining leaves the token there.
With Ask on click enabled, click the portal with an eligible owned token in or next to it. The module first considers a controlled token, then the current user's assigned character, and finally a single unambiguous owned token already inside the portal.
The prompt goes to the first active player who owns the token. If no active player owner can answer, it goes to the GM. The actual token movement is always performed by the active GM client.
When Avoid occupied spaces is enabled, the destination search expands from the exit until it finds room. If no nearby position is valid, the token stays in place and the crossing is not consumed.
Close A Portal
A portal closes when:
- it spends its final configured crossing
- its duration expires
- a GM chooses Close portal on the whispered chat card
- a GM deletes either side from the Regions layer
Deleting one Region closes the complete pair and removes its optional art
Tiles. A duration of 0 and an empty crossing limit keep the portal open until
a GM closes it.
Restart After Installing Or Updating
Restart the Foundry server after installing or updating a build that includes
SC Portal. Foundry reads the module's custom RegionBehavior document type
from module.json only at server startup.
If the behavior is not registered yet, the portal can still be created and Ask on click continues to work, but walking into it cannot trigger Ask on entry. Existing portal Regions repair their behavior the next time the Scene loads after the restart.
The SC Portal icon uses Magic Portal by Lorc from Game-icons.net under CC BY 3.0.
Activity Creation Flow
SC - More Activities keeps the normal dnd5e activity workflow intact and
extends the creation dialog instead of replacing it.
When supported activity types are present, the dialog is grouped into:
- D&D 5e for native activity types
- Shattered Codex for the built-in SC activity set
- External for third-party modules that register through the SC registry
This matters for both users and builders:
- GMs can distinguish native types from SC or third-party additions
- module authors can register external activity groups without writing directly
into
CONFIG.DND5E.activityTypes - disabled activity types are filtered out of creation and blocked from use
The creation dialog keeps native D&D 5e types visible, then adds a separate Shattered Codex group for the built-in SC activity set.
Module Settings
From Configure Settings > Module Settings > SC - More Activities, the module adds visible settings and menus for both GM administration and personal preview preferences.
| Setting or menu | Scope | What it does |
|---|---|---|
| Debug logging | Client | Logs lifecycle and diagnostic messages to the browser console for your user. |
| Migration backup retention | World, GM | Controls how many migration backups are stored in world settings. Default: 3. Range: 1 to 10. |
| Activity catalog | World, GM | Opens the registered activity catalog and diagnostics window. |
| More Activities migration | World, GM | Opens the preview, apply, export, and restore workflow for legacy more-activities data. |
| Preview colors | Client | Opens the per-user color configuration for teleport, movement, wall, and portal overlays. |
| Documentation | World, GM | Opens the wiki page for this module from inside Foundry. |
| Support the developer | World, GM | Opens the Shattered Codex Patreon support link. |
The module also stores hidden world or client data for disabled activity types, preview colors, and migration backups. Those are managed through the UI and are not intended for direct manual editing.
Activity Catalog
The Activity Catalog is the GM-facing control center for registered activity types.
It includes:
- summary cards for Registered, D&D Ready, Rejected, and Warnings
- filters for search, category, status, and availability
- separate sections for Registered Activities, Rejected Registrations, and Warnings
- actions to Refresh, Copy report, Clear filters, and open Migration
Availability states are important:
- Active means the activity type is available for creation and use
- Disabled means the GM has blocked that type for the world
- Unavailable means the type is not in a state that can be enabled for use
Only activity types that successfully reach the D&D-ready state can be toggled for world use. This makes the catalog useful both as a user control panel and as a diagnostic report for module integrations.
The catalog combines registration state, lifecycle metadata, capability markers, and per-type availability controls in one GM-facing window.
Preview Colors
The Preview colors menu is a client-scoped preference, so each user can pick their own overlay colors without changing the world for everyone else.
It is used by the canvas-oriented workflows:
- SC Teleport
- SC Movement
- SC Wall
- SC Portal
The menu includes:
- separate sections for Teleport, Movement, Wall, and Portal
Fill colorandBorder colorcontrols- a Live Preview area
- reset and save actions
These colors affect preview overlays only. They are not an activity authoring setting and they do not change the underlying activity data.
Preview colors are saved per user, so one GM can change overlay colors without changing the world for everyone else.
Migration from More Activities
SC - More Activities ships with an explicit migration flow for the legacy
more-activities module.
The migration window is GM-only and split into four tabs:
- Overview
- Preview
- Apply
- Backups
Recommended workflow:
- Keep the legacy module enabled only long enough to inspect or migrate old data.
- Open More Activities migration from module settings.
- Run Preview first.
- Review convertible and blocked entries.
- Use Apply migration only after the preview looks correct.
- Export the preview or final report if you need a record.
- Use Restore latest backup if you need to roll back the last migration.
Important limits:
- migration does not run automatically
- a preview is required before apply
- migration backups are stored in world settings
- some blocked or partially compatible legacy entries may still need manual cleanup after conversion
- the module warns when the legacy
more-activitiesmodule is still active
The preview report makes it clear which legacy entries can be converted, which SC type they map to, and what still needs manual review.
Developer Registration API
If you are building another module, register activity types through the SC
registry instead of mutating CONFIG.DND5E.activityTypes directly.
Public API access:
game.modules.get("sc-more-activities")?.apiglobalThis.ShatteredCodex.activitiesfor the published activities API
Main lifecycle hooks:
sc-more-activities.registerActivitiessc-more-activities.registryLockedsc-more-activities.apiReadysc-more-activities.activityRegisteredsc-more-activities.activityAvailabilityChangedsc-more-activities.activityUseStartsc-more-activities.activityUseCompletesc-more-activities.activityUseError
Registration timing:
- register during
Hooks.on("sc-more-activities.registerActivities", ...) - late registrations are rejected after the registry locks during initialization
- if you need the final published API object, listen for
sc-more-activities.apiReady
Minimum registration contract:
moduleIdtypelabelhinticondocumentClass
Your documentClass must provide:
static metadata.typethat matches the registered typestatic availableForItem(...)static localize(...)
Minimal example:
Hooks.on("sc-more-activities.registerActivities", (activities) => {
activities.registerType({
moduleId: "my-module",
type: "my-module-ignite",
label: "MYMODULE.Activity.Ignite.Label",
hint: "MYMODULE.Activity.Ignite.Hint",
icon: "modules/my-module/icons/ignite.svg",
documentClass: MyIgniteActivity,
});
});The public activities API also exposes helper methods such as:
listTypes()listTypeAvailability()setTypeEnabled(type, enabled)getRegistrationReport()createActivityOnItem(item, type, data, options)
Developer Example: SC Simple Sockets
If you want a concrete external-module example, SC - Simple Sockets is the best reference currently in the Shattered Codex module set.
It does not patch sc-more-activities directly. Instead, it keeps the entire
integration inside its own module and registers two external activity types when
both modules are active:
sc-socket-slotsc-socket-extraction
This example focuses on sc-socket-slot, because it shows the full lifecycle
for a custom activity type.
What Files The Example Uses
| File | Role in the integration |
|---|---|
| `scripts/main.js` | Imports the integration and calls `ScMoreActivitiesIntegration.register()` during module startup. |
| `scripts/core/integrations/sc-more-activities/ScMoreActivitiesConstants.js` | Defines hook names, type ids, group metadata, query id, timeout, and icon paths. |
| `scripts/core/integrations/sc-more-activities/ScMoreActivitiesIntegration.js` | Listens to the registration hook, registers types, exposes GM-mediated query handlers, and dispatches socket mutations. |
| `scripts/core/integrations/sc-more-activities/activities/socket-slot/ScMoreActivitiesSocketSlotActivity.js` | Defines the activity document class and its `use()` behavior. |
| `scripts/core/integrations/sc-more-activities/activities/socket-slot/ScMoreActivitiesSocketSlotActivityData.js` | Defines the activity schema stored on the item. |
| `scripts/core/integrations/sc-more-activities/activities/socket-slot/ScMoreActivitiesSocketSlotActivitySheet.js` | Extends the activity sheet and prepares UI context for the custom effect tab. |
| `scripts/core/integrations/sc-more-activities/activities/socket-slot/ScMoreActivitiesSocketSlotActivityService.js` | Runs the real workflow after `super.use()` succeeds. |
| `templates/integrations/sc-more-activities/socket-slot-effect.hbs` | Renders the custom form fields shown on the activity sheet. |
How The Bootstrap Works
SC - Simple Sockets loads the integration from its own scripts/main.js and
registers it at startup:
import { ScMoreActivitiesIntegration } from "./core/integrations/sc-more-activities/ScMoreActivitiesIntegration.js";
ScMoreActivitiesIntegration.register();That register() method does two jobs:
- It listens to
sc-more-activities.registerActivities. - It registers a query handler during
initso socket mutations can be routed through an active GM when needed.
This is important because the integration owns both the activity definition and the mutation flow. The external module is responsible for its own runtime behavior.
The Real Registration Call
Inside ScMoreActivitiesIntegration.js, SC - Simple Sockets registers
sc-socket-slot like this:
return activitiesApi.registerType({
moduleId: Constants.MODULE_ID,
type: SC_MORE_ACTIVITIES_ACTIVITY_TYPES.SOCKET_SLOT,
label: "SCSockets.Integrations.ScMoreActivities.SocketSlot.Title",
hint: "SCSockets.Integrations.ScMoreActivities.SocketSlot.Hint",
icon: SC_MORE_ACTIVITIES_ICONS.SOCKET_SLOT,
documentClass: ScMoreActivitiesSocketSlotActivity,
dataModel: ScMoreActivitiesSocketSlotActivityData,
sheetClass: ScMoreActivitiesSocketSlotActivitySheet,
configurable: true,
category: "sockets",
ui: {
scope: "external",
group: "sockets",
groupId: SC_MORE_ACTIVITIES_GROUP.id,
groupLabel: SC_MORE_ACTIVITIES_GROUP.label,
groupIcon: SC_MORE_ACTIVITIES_GROUP.icon,
groupOrder: SC_MORE_ACTIVITIES_GROUP.order,
order: 140
},
tags: ["sockets", "slot", "inventory"],
compatibility: {
dnd5e: "5.x",
scMoreActivities: { moduleId: "sc-more-activities", required: true },
scSimpleSockets: { moduleId: "sc-simple-sockets", required: true }
},
templates: [
"modules/sc-simple-sockets/templates/integrations/sc-more-activities/socket-slot-effect.hbs"
],
ownership: {
execute: "item-owner",
hostItem: "activity-item",
mutation: "gm-mediated"
},
source: Constants.MODULE_ID
});Why this registration is useful:
ui.scope: "external"places the type in the external registration flowgroupId,groupLabel, andgroupOrdercreate a module-specific activity group in the create dialogdataModel,sheetClass, andtemplatesturn the type into a configurable authoring experience instead of a bare runtime documentownership.mutation: "gm-mediated"matches the real workflow, because socket mutations may need GM execution
The Activity Class
The activity class extends the standard dnd5e activity mixin and connects the
registered type id to the custom schema, metadata, availability check, and
runtime execution:
export class ScMoreActivitiesSocketSlotActivity extends dnd5e.documents.activity.ActivityMixin(
ScMoreActivitiesSocketSlotActivityData
) {
static metadata = Object.freeze(
foundry.utils.mergeObject(super.metadata, {
type: SC_MORE_ACTIVITIES_ACTIVITY_TYPES.SOCKET_SLOT,
img: SC_MORE_ACTIVITIES_ICONS.SOCKET_SLOT,
title: "SCSockets.Integrations.ScMoreActivities.SocketSlot.Title",
hint: "SCSockets.Integrations.ScMoreActivities.SocketSlot.Hint",
sheetClass: ScMoreActivitiesSocketSlotActivitySheet
}, { inplace: false })
);
static availableForItem(item, ...args) {
const base = typeof super.availableForItem === "function"
? super.availableForItem(item, ...args)
: true;
return base && ScMoreActivitiesIntegration.isTypeEnabled(
SC_MORE_ACTIVITIES_ACTIVITY_TYPES.SOCKET_SLOT
);
}
async use(usage = {}, dialog = {}, message = {}) {
const results = await super.use(usage, dialog, message);
if (results === undefined) return results;
return ScMoreActivitiesSocketSlotActivityService.execute(this, { usage, dialog, message, results });
}
}The pattern to copy into your own module is:
- Extend
dnd5e.documents.activity.ActivityMixin(...). - Put the registered type id into
static metadata.type. - Route availability through
availableForItem(...). - Call
super.use(...)first. - Hand off the actual side effects to a dedicated service class.
The Data Model
ScMoreActivitiesSocketSlotActivityData extends
dnd5e.dataModels.activity.BaseActivityData and stores all custom fields under
slot.
Real schema fields in the example include:
slot.operationslot.nameslot.colorslot.cursorImageslot.descriptionslot.conditionslot.targetConditionslot.hiddenslot.deleteGemOnRemovalslot.ignoreMaxSockets
That structure is worth copying because it keeps custom activity state grouped under one schema branch instead of scattering unrelated top-level fields.
The Sheet and Template
ScMoreActivitiesSocketSlotActivitySheet extends
dnd5e.applications.activity.ActivitySheet and injects a custom effect-part
template:
static PARTS = {
...super.PARTS,
effect: {
template: TEMPLATE_PATH,
templates: [...super.PARTS.effect.templates]
}
};That template is
templates/integrations/sc-more-activities/socket-slot-effect.hbs, and it
renders the actual authoring controls for:
- slot operation
- slot name and color
- cursor image
- description
- condition code
- target condition code
- behavior toggles such as hidden, delete on removal, and ignore socket limit
Use this pattern when your custom activity needs real item-authoring UI instead of a small number of primitive fields.
The Runtime Service
The actual socket behavior does not live in the activity class. It lives in
ScMoreActivitiesSocketSlotActivityService.
That service decides whether the configured operation is:
- add a slot to a selected item
- remove one empty slot from the host item
The service also validates the target condition, launches the slot-picker UI
when needed, and hands the mutation back to ScMoreActivitiesIntegration.
That separation matters:
- the activity class stays small and predictable
- the data model only describes stored state
- the service owns workflow branching, validation, dialogs, and user feedback
How GM-Mediated Execution Works
SC - Simple Sockets is a strong example because it shows how to handle
mutations that may require GM authority.
Inside ScMoreActivitiesIntegration.js, the integration:
- Builds a request payload with
activityUuid,itemUuid,operation, andrequestUserId. - Executes directly when the current user is a GM or already has socket-edit permission.
- Falls back to an active GM query using a registered query id when direct execution is not allowed.
- Resolves the request on the GM side and turns the result into a normalized success or failure object.
This is the concrete pattern to follow when your custom activity mutates actors, items, scenes, or other documents that should not be changed blindly by every player client.
Minimal Blueprint For Your Own Module
If you are building a new external activity, the smallest practical file set is:
scripts/main.js
scripts/integrations/sc-more-activities/MyIntegration.js
scripts/integrations/sc-more-activities/MyActivity.js
scripts/integrations/sc-more-activities/MyActivityData.js
scripts/integrations/sc-more-activities/MyActivitySheet.js
scripts/integrations/sc-more-activities/MyActivityService.js
templates/integrations/sc-more-activities/my-activity-effect.hbsBuild it in this order:
- Register an integration class from
scripts/main.js. - Listen to
sc-more-activities.registerActivities. - Call
activitiesApi.registerType(...). - Create a document class with
metadata,availableForItem(...), anduse(...). - Add a data model for your stored fields.
- Add a sheet class and Handlebars template for configuration.
- Move the actual side effects into a service class.
- Add GM-mediated dispatch only if your workflow really needs it.
When To Copy This Pattern
Use the sc-simple-sockets structure when your activity:
- needs custom authoring fields
- performs complex runtime logic after
super.use(...) - may require GM-mediated document changes
- belongs to a module-specific activity group in the create dialog
- should stay fully owned by the integrating module instead of by
sc-more-activities
Notes and Limits
- This module supports only the
dnd5esystem. - It extends native activities instead of replacing them.
- World macros, inline code, hooks, and callbacks still follow their own permission and ownership limits.
- Canvas actions such as teleport, movement, wall placement, and portals rely on GM-mediated scene updates.
- The migration workflow is explicit by design, which is safer than an automatic conversion but still requires review before apply.