Shattered Codex

Wiki

Modules/SC - Conditional AE

SC - Conditional AE

Foundry v13-v14System D&D 5eFree

SC - Conditional AE

Overview

SC - Conditional AE extends the D&D 5e Active Effect workflow in three practical ways:

  • a dedicated Condition tab on Active Effect sheets
  • an optional Formula column for activation-time rolls
  • a macro execution change that can run when an effect turns on or off

In practice, this lets you build effects that:

  • only apply while a JavaScript condition returns true
  • roll a fresh number when the effect activates and write that result into the normal change value
  • trigger a world macro when the effect is enabled, disabled, removed, or becomes available again after suppression

If a native condition evaluates to false, the effect is suppressed and its changes do not apply.

FeatureWhat it doesWhere you use it
Condition tabRuns JavaScript to decide whether the Active Effect is currently available.Active Effect sheet
Formula columnRolls a formula at activation time and writes the rolled total into the standard change value.Active Effect changes table
Macro execution changeExecutes a world macro when the effect turns on or off.Active Effect changes table

Compatibility and Installation

This module is free and released.

Install it through Foundry with this manifest URL:

code
https://github.com/Shattered-Codex/sc-conditional-ae/releases/latest/download/module.json

Requirements:

  • Foundry VTT v13 and v14
  • system: dnd5e
  • dnd5e system version 4.0.0+
  • recommended compatibility helper: libWrapper

Optional adjacent integrations:

  • DAE compatibility expressions and legacy DAE condition flags
  • Aura Effects fallback typing when Aura Effects is not active

After installing:

  1. Enable SC - Conditional AE in your world.
  2. Open Configure Settings > Module Settings.
  3. Find SC - Conditional AE and click Open settings.
  4. Turn on the features you want before editing your Active Effects.

Module Settings

The module registers a dedicated settings window under Configure Settings > Module Settings > SC - Conditional AE > Open settings.

SettingScopeDefaultWhat it does
Enable formula columnWorldOnAdds the Formula column to Active Effect changes and enables activation-time rolls. Requires reload.
Post formula roll chat cardWorldOffPosts a chat card with a roll button instead of rolling immediately when a formula-backed effect activates or a suppressed conditional effect becomes available again.
Show condition tabWorldOnAdds the Condition tab to Active Effect configuration sheets. Requires reload.
Enable debug loggingClientOffLogs condition evaluation, suppression refreshes, and activation transitions to the browser console.
DocumentationMenu-Opens this wiki page from Foundry.
Support the developerMenu-Opens the Patreon support page.

If DAE is active, Foundry may show a libWrapper warning in the browser console. The module settings text and implementation both treat that as a warning, not as a confirmed functional break.

Condition Tab

When Show condition tab is enabled, Active Effect sheets gain a dedicated Condition tab.

The tab does more than store code. It also exposes a current-evaluation panel, an inactive-state badge label, and a target-application behavior selector.

Condition tab
The native Condition tab adds a code editor, current evaluation preview, badge label field, and target-application behavior selector.
1 / 2
ControlWhat it doesWhy it matters
Current evaluationShows whether the condition is currently true, false, empty, or throwing an error, plus the returned value, evaluation context, and effect state.Lets you debug the rule against the current actor or item before you close the sheet.
Condition badge labelStores a short label shown on inactive effects.Useful when a suppressed effect should explain why it is not active without opening the effect.
When applied to a targetControls whether a target application reapplies the current Active Effect, stacks a duplicate, or follows DAE stacking rules when DAE is active.Important when the same source effect can be applied to a target more than once.
Condition editorStores the native JavaScript condition or the adapted DAE compatibility expression.This is the rule that decides whether the effect is available.
Open wikiLinks from the sheet directly to this documentation section.Keeps the authoring workflow close to the explanation.

Writing Conditions

You can write a full script:

js
return (actor?.system?.attributes?.hp?.value ?? 0) > 0;

You can also write a single expression:

js
(actor?.system?.attributes?.hp?.value ?? 0) > 0

Expression shorthand only works when the whole condition is one expression. If you use statements such as const, let, or if, finish with return.

This works:

js
const hp = actor?.system?.attributes?.hp?.value ?? 0;
return hp > 0;

This does not work:

js
const hp = actor?.system?.attributes?.hp?.value ?? 0;
hp > 0;

Native SC - Conditional AE conditions are synchronous. If the condition returns a Promise or tries to rely on async work, the module treats it as an error and suppresses the effect.

Conditions receive these native context variables:

VariableWhat it gives youNotes
`effect`The current Active Effect document.Useful for reading effect flags or metadata.
`actor`The actor affected by the effect.This is the main actor-side data source for most conditions.
`targetActor`The actor affected by the effect.In native JavaScript mode this currently resolves to the affected actor, not to a live selected target.
`item`The owning or origin item when one can be resolved.Useful for transferred item effects and item-state checks such as equipped or attuned.
`origin`The resolved effect origin document when one exists.Can be an actor, item, or Active Effect depending on the source.
`originActor`The actor behind the resolved origin, when one exists.Useful when the origin is an item or Active Effect owned by another actor.
`user`The current Foundry user.Available, but target-selection logic is not a reliable long-lived Active Effect driver.
`rollData`The affected actor's roll data.Built lazily from the affected actor so ordinary conditions do not do extra prep work.
`source`A cloned snapshot of the current effect data.Useful when you need raw effect data without mutating the document.
`getProperty`Foundry's property helper.Useful for deep flag or system reads.
`hasProperty`Foundry's property-existence helper.Useful when you want a presence check without reading the value first.
`deepClone`Foundry's deep clone helper.Mostly useful for complex compatibility or debugging logic.
`game`The global Foundry `game` object.Useful for combat, module checks, user state, or world-level data.

There is no dedicated native target variable for current target selection. Target-sensitive rules are usually a better fit for SC - Conditional Activities than for a long-lived Active Effect.

When Conditions Are Evaluated

Condition timing is the part that most often causes confusion.

TriggerWhat the module doesWhat it means for your rule
While editing the effectThe Current evaluation panel runs the condition against the current sheet context.You can preview whether the rule is true, false, empty, or erroring before saving.
During Active Effect applicationIf the effect is enabled but the condition is false, the module skips applying that effect's changes.A false condition suppresses the effect instead of partially applying it.
When the actor, owned item, or effect data changesThe module schedules an actor refresh, reevaluates conditioned effects, and rerenders effect surfaces.Actor HP, item state, flags, and similar data-driven rules can turn an effect on or off as data changes.
When a previously suppressed effect becomes availableIf the effect is still enabled, the module can trigger formula activation and `on` macro execution.Conditional reactivation is a real activation event for formulas and macro hooks.
When current target selection changesThere is no dedicated refresh hook for live target selection changes.Rules based on `user.targets` can go stale until some actor, item, or effect update forces reevaluation.

An Active Effect that depends on a live selected target is usually the wrong surface.

Why:

  • the native condition context does not build a dedicated target-selection pipeline
  • targetActor currently resolves to the actor affected by the effect
  • the module refreshes on actor, item, and effect changes, not on every target selection change

That is why an Active Effect usually should not own a rule such as "this bonus works only against my current selected target." That kind of rule belongs to an activity-time workflow instead.

Use this decision table:

NeedBest toolWhy
The effect depends on actor HP, combat state, flags, equipped state, or other actor or item data.SC - Conditional AEThose values participate naturally in the module's refresh and suppression flow.
The rule depends on the currently selected target, chosen usage data, or activity-use context.SC - Conditional ActivitiesActivity-side conditions can inspect current use context at the moment of use instead of relying on a long-lived Active Effect refresh.
The effect needs a fresh random numeric value when it becomes active.SC - Conditional AE formula columnFormula-backed changes roll at activation time and store the total in the normal Value field.
The effect should trigger follow-up automation when it turns on or off.SC - Conditional AE macro execution changeMacro changes receive structured on/off context without needing a second automation layer.

Searchable Condition Examples

Condition Example Finder

Search only within this example set. Use it to filter by actor, item, flag, combat, socket, or GM terms.

14 / 14 examples

Actor Must Be Alive

Allow the effect only while the affected actor has more than 0 HP.

Example Code
return (actor?.system?.attributes?.hp?.value ?? 0) > 0;

Actor Must Be Bloodied

Enable the effect only while the actor is at or below half HP.

Example Code
const hp = actor?.system?.attributes?.hp?.value ?? 0;
const maxHp = actor?.system?.attributes?.hp?.max ?? 0;
return maxHp > 0 && hp <= maxHp / 2;

Actor Must Be Below Half HP

A stricter version that requires the actor to be below half HP, not exactly at half.

Example Code
const hp = actor?.system?.attributes?.hp?.value ?? 0;
const maxHp = actor?.system?.attributes?.hp?.max ?? 0;
return maxHp > 0 && hp < maxHp / 2;

Item Must Be Equipped

Use this when the effect belongs to an item and should only work while that item is equipped.

Example Code
return item?.system?.equipped === true;

Item Must Be Attuned

Gate the effect behind the item's attunement state.

Example Code
return item?.system?.attunement === 2;

Actor Must Have A Minimum Strength Score

Require a minimum Strength score before the effect applies.

Example Code
return (actor?.system?.abilities?.str?.value ?? 0) >= 16;

Actor Must Have A Specific Item

Allow the effect only if the actor owns an item that matches the required name.

Example Code
const items = actor?.items?.contents ?? [];
return items.some((ownedItem) => ownedItem.name === "Essence Core");

Actor Must Have A Specific Active Effect

Require an existing Active Effect with a matching name on the actor.

Example Code
const effects = actor?.effects?.contents ?? [];
return effects.some((existingEffect) => existingEffect.name === "Rage");

Actor Must Have A Specific Flag

Read a custom actor flag through Foundry's property helper.

Example Code
return getProperty(actor, "flags.world.canUseAncientPower") === true;

Only The GM Can Benefit From The Effect

Restrict the effect to the current GM user.

Example Code
return user?.isGM === true;

Effect Must Only Apply During Combat

Allow the effect only while combat exists in the current world state.

Example Code
return Boolean(game?.combat);

At Least One Occupied Socket

Simple Sockets example. Require at least one occupied socket on the owning item.

Example Code
const sockets = item?.getFlag?.("sc-simple-sockets", "sockets") ?? [];
return sockets.some((slot) => Boolean(slot?.gem || slot?._gemData));

At Least Two Occupied Sockets

Simple Sockets example. Require two or more filled sockets on the owning item.

Example Code
const sockets = item?.getFlag?.("sc-simple-sockets", "sockets") ?? [];
const occupied = sockets.filter((slot) => Boolean(slot?.gem || slot?._gemData));
return occupied.length >= 2;

Any Socketed Gem Name Contains Ruby

Simple Sockets example. Match a gem name without relying on async API helpers.

Example Code
const sockets = item?.getFlag?.("sc-simple-sockets", "sockets") ?? [];
return sockets.some((slot) =>
  (slot?.gem?.name ?? slot?._gemData?.name ?? "").toLowerCase().includes("ruby"),
);

The Simple Sockets examples use direct flag reads because the native condition engine is synchronous.

Rule Patterns

Practical Patterns

Rule Patterns and Timing

These examples show not just what to write, but when the rule is evaluated and where the pattern does or does not fit.

Reliable Patternnative JSstate-driven

Gate The Effect On Actor Or Item State

This is the classic Conditional AE use case: check HP, equipped state, attunement, combat state, flags, or another piece of actor or item data that belongs to the effect context itself.

Best For

Owning actor and item data such as HP, equipped state, attunement, flags, and combat-state checks.

Timing

Reevaluated during actor refreshes caused by actor, item, or effect document updates.

Result

If the condition is false, the effect stays enabled as a document but its changes are suppressed.

Caution

Do not use this pattern when the rule depends on a live selected target.

javascript
return item?.system?.equipped === true
  && (actor?.system?.attributes?.hp?.value ?? 0) > 0;
Activation Patternformulaactivation-time

Roll A Formula When The Effect Comes Online

Use a formula-backed change when the number should be decided at activation time instead of being stored as a fixed value ahead of time.

Best For

Variable bonuses or penalties that should roll when the effect activates or becomes available again.

Timing

Triggered when the effect activates, re-enables, or becomes available after being condition-suppressed.

Result

The rolled total is written into the standard Value field for that change.

Caution

If the effect is turned off and back on later, it can roll again.

code
Attribute Key: system.attributes.hp.tempmax
Mode: Add
Value: 0
Formula: 1d4 + 1
Avoid This Patterntargetingstale-state risk

Do Not Depend On Current Selected Targets

A rule that keys off whoever is targeted right now is unstable on a long-lived Active Effect because target selection changes do not continuously trigger reevaluation.

Best For

Very rare cases. Most target-dependent rules belong on the activity side instead.

Timing

This only uses target state from the moment the effect happens to be evaluated.

Result

The effect can appear to follow target selection once, then stay stale until some actor, item, or effect update forces a refresh.

Caution

If current target choice matters, move the rule to SC - Conditional Activities.

javascript
return user?.targets?.size === 1;

Formula-Backed Changes

When Enable formula column is enabled, eligible non-custom Active Effect changes can store an extra formula alongside the normal value.

Use this when you want the effect to roll at activation time instead of hard-coding the final number.

Example setup:

code
Attribute Key: system.attributes.hp.tempmax
Mode: Add
Value: 0
Formula: -2d6

Typical runtime flow:

StepWhat happensNotes
1. Effect activatesThe module checks whether the effect is active and not suppressed.This also applies when a previously suppressed conditional effect becomes available.
2. Responsible user handles the rollAn active non-GM owner is preferred first; otherwise the active GM handles it.The module only prompts the responsible user.
3. Formula is confirmed or rolled from chatThe user can roll immediately or from chat if **Post formula roll chat card** is enabled.The module can show a Foundry roll dialog or a chat-card request flow.
4. Result is written into ValueThe rolled total replaces the standard change value for that activation.The formula remains stored separately as the rule source.
5. Later reactivation can rerollDisabling and re-enabling the effect, or regaining availability after suppression, can trigger a fresh roll.Use this only when rerolling later is the intended behavior.
Formula column
The extra Formula column sits alongside the standard change fields and is available only when the setting is enabled.
1 / 4

Macro Execution Changes

To execute a world macro from an Active Effect, add a change with:

  • Key: cae.macro.execute
  • Mode: Custom
  • Value: a macro name or UUID, followed by optional arguments

Example:

code
Apply Rage "fire" 2

That tries to execute the world macro Apply Rage and passes fire and 2 as arguments.

Macro execution scope:

FieldWhat it contains
`action``on` when the effect activates, `off` when the effect is disabled or deleted.
`actor`The actor that owns the active effect at runtime.
`token`The actor's token object when one can be resolved.
`effect`The current Active Effect document.
`item`The owning or origin item when one can be resolved.
`origin`The resolved origin document when one can be resolved.
`change`The specific Active Effect change row that triggered the macro.
`args`The full macro argument array, starting with `action` and ending with `lastArg`.
`macroArgs`Only the parsed arguments that came after the macro name or UUID.
`lastArg`A DAE-style summary object with actor, token, item, origin, and effect references.
`speaker`The chat speaker object for the actor or token.
`user`The current Foundry user.

Important runtime notes:

  • sc-conditional-ae.macro.execute is also supported as a legacy key
  • macro.execute is supported when DAE is not active
  • if DAE is active, DAE remains responsible for macro.execute
  • if an enabled effect was suppressed and later becomes available again, the module can trigger the on macro from the conditional activation flow
  • a condition becoming false does not by itself emit an off macro unless the effect is also disabled or deleted

Compatibility Notes

IntegrationBehavior
DAE condition flagsReads legacy `flags.dae.enableCondition` and `flags.dae.disableCondition` values and surfaces them through the native Condition tab.
DAE expression syntaxSupports compatibility expressions that use `@` roll-data references plus DAE helpers such as `dae.eval(...)` and `dae.roll(...)`.
DAE stacking behaviorThe **When applied to a target** selector can expose **Same as DAE** when DAE is active.
DAE macro changesAdds `cae.macro.execute` to DAE specials and avoids taking over `macro.execute` when DAE is active.
DAE warning textThe module settings UI explicitly documents the possible `libWrapper` console warning as a warning, not a confirmed break.
Aura EffectsRegisters a fallback Active Effect type for Aura Effects data when that module is not active.

Troubleshooting

The effect never applies

Check these first:

  1. Confirm the Condition tab currently resolves to true.
  2. Verify the code is valid JavaScript.
  3. Remove any async logic from the native condition.
  4. If the effect came from DAE, verify the compatibility expression still makes sense for the actor's current data.

The Formula column is missing

  1. Make sure Enable formula column is on.
  2. Reload the world after changing that setting.

The macro does not run

  1. Confirm the change key is cae.macro.execute.
  2. Confirm the change mode is Custom.
  3. Make sure the referenced macro exists in world macros.
  4. Check whether the effect is being suppressed by its condition.

The effect seems stuck to an old target state

That is expected for target-selection-driven rules on long-lived Active Effects.

Check these points:

  1. Native SC - Conditional AE conditions do not continuously refresh when user.targets changes.
  2. targetActor currently resolves to the affected actor, not to the current selected target.
  3. If the rule depends on the live selected target, move it to SC - Conditional Activities instead.

I see a DAE or libWrapper warning in the browser console

If behavior is otherwise correct, treat that as a warning first. The module explicitly documents this case in its settings UI because both modules touch the Active Effect pipeline when DAE is active.

Notes and Limits

  • native JavaScript conditions are synchronous
  • empty conditions allow the effect
  • thrown errors suppress the effect
  • actor, owned item, and effect document updates participate in reevaluation; live target selection changes do not
  • formula-backed values are activation-time values, not continuously live formulas
  • target- or use-context-driven rules belong on an activity-time condition surface instead of a long-lived Active Effect