SC - Conditional Activities
SC - Conditional Activities
Overview
SC - Conditional Activities adds a Condition tab to D&D 5e activity sheets in Foundry VTT.
Use it when an activity should only be available if a JavaScript condition
passes. If the condition returns true, the activity works normally. If it
returns false, the activity is blocked before use and can show a locked-state
badge or warning.
Core behavior:
- adds a Condition tab to supported activity sheets
- evaluates JavaScript before
activity.use() - shows locked-state badges and warnings for unavailable activities
- supports native
dnd5eactivities and activity types added by More Activities
Typical checks:
- actor HP, resources, attributes, or flags
- item equipped, attuned, or identified state
- selected targets
- combat state
- activity type checks
- socket checks on items that also use SC - Simple Sockets
Installation
- In Foundry VTT, open Add-on Modules and install the module with this manifest:
https://github.com/Shattered-Codex/sc-conditional-activities/releases/latest/download/module.json- Enable SC - Conditional Activities in your world.
- Open an item with one or more
dnd5eactivities. - Edit an activity and open the Condition tab.
- Save a condition script on that activity.
Compatibility:
- Foundry VTT
v13tov14 - system:
dnd5e - minimum
dnd5eversion:5.0.0 - compatible with activity types added by More Activities
Module Settings
From Configure Settings > Module Settings > SC - Conditional Activities, you can access:
- Hide unavailable activities in the choice dialog
- Open wiki
- Patreon support
The availability-hiding setting is world-scoped and GM-facing. When enabled, activities that fail their condition are removed from the activity choice dialog instead of staying visible there with a locked label.
Activity Condition
Every supported activity sheet gets a dedicated Condition tab.
The Condition tab includes a JavaScript editor, custom warning and badge controls, a preview area, and a direct link back to the wiki.
The module stores its activity data on these flag paths:
flags.sc-conditional-activities.condition
flags.sc-conditional-activities.warningMessage
flags.sc-conditional-activities.disableWarningMessage
flags.sc-conditional-activities.badgeLabelCondition Tab Controls
The tab does more than store a script. It also controls how the locked state is presented to users.
| Control | What it does | Notes |
|---|---|---|
| Condition editor | Stores the JavaScript that decides whether the activity is currently available. | Accepts a single expression or a full script. |
| Warning message | Sets the warning notification shown when the condition returns false. | Leave blank to use the module default. |
| Disable warning message | Blocks the activity without showing the normal condition-failed warning. | Condition errors still warn so invalid scripts remain visible. |
| Locked badge label | Overrides the visible label shown on blocked activities. | Single line, maximum 36 characters. |
| Preview | Shows the current badge and warning output before saving. | Useful when you customize player-facing wording. |
| Open wiki | Opens this documentation from inside the activity sheet. | Anchors directly to the Activity Condition section. |
Where Locked Activities Appear
By default, blocked activities remain visible so users can understand what exists and why it is unavailable.
The module decorates activity state in:
dnd5eactivity choice dialogs- item sheet activity lists
- actor sheet activity lists
- Tidy actor-sheet activity surfaces
- chat activity controls
If Hide unavailable activities in the choice dialog is enabled, the choice dialog is the exception: blocked activities are filtered out there instead of being shown with a badge.
Writing Conditions
Conditions receive these context variables:
| Variable | What it gives you |
|---|---|
| `activity` | The current activity document. |
| `activityType` | The activity type, such as `attack` or another registered activity type. |
| `item` | The item that owns the activity. |
| `actor` | The actor that owns the item, when available. |
| `user` | The current Foundry user. |
| `usage` | Cloned usage data passed into `activity.use()`. |
| `dialog` | Cloned dialog data passed into `activity.use()`. |
| `message` | Cloned message data passed into `activity.use()`. |
| `rollData` | The owning item's roll data, when available. |
| `source` | The evaluation source, such as UI checks or activity use. |
| `getProperty` | Foundry's property helper. |
| `hasProperty` | Foundry's property existence helper. |
| `deepClone` | Foundry's deep clone helper. |
| `game` | The Foundry `game` object. |
| `moduleId` | The module id: `sc-conditional-activities`. |
There is no dedicated target variable. When you need targets, read them from
user.targets.
You can write a complete script:
return actor?.system?.attributes?.hp?.value > 0;You can also write a single expression:
actor?.system?.attributes?.hp?.value > 0Expression shorthand only works when the whole condition is one expression. If
you use statements such as const, let, if, or await, finish with
return.
This works:
const hp = actor?.system?.attributes?.hp?.value ?? 0;
return hp > 0;This does not work:
const hp = actor?.system?.attributes?.hp?.value ?? 0;
hp > 0;Conditions can be asynchronous. The Simple Sockets examples below use
await.
Searchable Condition Examples
Condition Example Finder
Search only within this example set. Use it to filter by actor, target, combat, flag, equipped, or other condition terms.
Actor Must Be Alive
Allow the activity only while the owning actor has more than 0 HP.
return (actor?.system?.attributes?.hp?.value ?? 0) > 0;Only The GM Can Use This Activity
Restrict the activity to the current GM user.
return user?.isGM === true;Item Must Be Equipped
Only allow the activity while the owning item is equipped.
return item?.system?.equipped === true;Item Must Be Attuned
Gate the activity behind the item's attuned state.
return item?.system?.attuned === true;Item Must Be Identified
Hide the activity behind item identification rules.
return item?.system?.identified === true;Actor Must Have A Minimum Strength Score
Require a minimum Strength score before the activity can be used.
return (actor?.system?.abilities?.str?.value ?? 0) >= 16;Actor Must Have A Specific Item
Allow the activity only if the actor owns an item that matches the required name.
const items = actor?.items?.contents ?? [];
return items.some((ownedItem) => ownedItem.name === "Essence Core");Actor Must Have A Specific Active Effect
Require an Active Effect with a matching name to already be applied to the actor.
const effects = actor?.effects?.contents ?? [];
return effects.some((effect) => effect.name === "Rage");Actor Must Have A Specific Flag
Read a custom actor flag with Foundry's property helper.
return getProperty(actor, "flags.world.canUseAncientPower") === true;Activity Must Be An Attack Activity
Only allow the condition for one activity type.
return activityType === "attack";Require At Least One Target
Block the activity unless the current user has selected a target.
return user?.targets?.size > 0;Require Exactly One Target
Useful for effects that must resolve against one selected target only.
return user?.targets?.size === 1;Selected Target Must Have A Specific Effect
Check the first selected target for a named Active Effect.
const targetActor = Array.from(user?.targets ?? [])[0]?.actor;
const effects = targetActor?.effects?.contents ?? [];
return effects.some((effect) => effect.name === "Marked");Any Selected Target Must Have A Specific Effect
Allow the activity if any selected target matches the required effect.
const targets = Array.from(user?.targets ?? []);
return targets.some((target) =>
(target.actor?.effects?.contents ?? []).some(
(effect) => effect.name === "Marked",
),
);Require Combat To Be Active
Only allow the activity while combat is running.
return Boolean(game.combat?.started);At Least One Occupied Socket
Simple Sockets example. Require at least one occupied socket on the owning item.
const socketsApi = game.modules.get("sc-simple-sockets")?.api?.sockets;
if (!socketsApi) return false;
const slots = await socketsApi.getItemSlots(item);
return slots.some((entry) => entry.hasGem);First Socket Must Be Occupied
Simple Sockets example. Require the first socket slot to contain a gem.
const socketsApi = game.modules.get("sc-simple-sockets")?.api?.sockets;
if (!socketsApi) return false;
const slots = await socketsApi.getItemSlots(item);
return slots[0]?.hasGem === true;At Least Two Occupied Sockets
Simple Sockets example. Require two or more filled sockets on the item.
const socketsApi = game.modules.get("sc-simple-sockets")?.api?.sockets;
if (!socketsApi) return false;
const slots = await socketsApi.getItemSlots(item);
return slots.filter((entry) => entry.hasGem).length >= 2;Specific Gem Name Present
Simple Sockets example. Check whether any socketed gem name includes a keyword.
const socketsApi = game.modules.get("sc-simple-sockets")?.api?.sockets;
if (!socketsApi) return false;
const gems = await socketsApi.getItemGems(item);
return gems.some((gem) => gem.name?.toLowerCase().includes("ruby"));Direct Flag Check For Occupied Socket
Simple Sockets example. Use a direct flag read when you do not need the API helpers.
const sockets = item?.getFlag?.("sc-simple-sockets", "sockets") ?? [];
return sockets.some((slot) => Boolean(slot?.gem));Notes and Limits
- conditions are JavaScript and should be treated like other trusted Foundry scripting surfaces
- empty conditions allow the activity
- falsy results and thrown errors block it
- condition errors switch the UI state to Condition error
- conditions are checked during UI rendering and again during activity use
- async conditions are supported, but slow code can make activity surfaces feel slower because availability is checked during render
- the documentation page is in English, but the module UI is localized for English and Brazilian Portuguese