Skip to content

How It Works

A token is processed only if all of the following are true:

  • The actor type is character or npc (other types are ignored).
  • The actor has current HP greater than 0 (downed and dead tokens have effects cleared).
  • The actor carries the flags.tokenlightcondition.initialized flag. The first time the module sees a fresh token, it sets this flag and triggers an initial calculation on the next pass.

All other tokens (vehicles, hazards, group actors, dead NPCs) are skipped entirely.

The GM client listens to a set of canvas hooks. Each trigger queues either a single-token or all-tokens recalculation:

HookScopeTrigger
createTokenSingleToken dropped on the scene
updateTokenSinglehidden flag toggled
updateTokenAll tokensAny of light.bright, light.dim, light.luminosity, light.angle, light.rotation changed on a token
moveTokenSingleToken movement; uses the resolved end-of-waypoint position
createAmbientLight / updateAmbientLight / deleteAmbientLightAll tokensAmbient light placed, edited, or removed
updateSceneAll tokensenvironment.darknessLevel or environment.globalLight changed on the active scene

Player clients do not run calculations. They receive the resulting actor flag updates and render the HUD indicator from flags.tokenlightcondition.lightLevel.

Recalculations honour the Delay Calculations setting. At zero delay, calculations fire immediately. Above zero, each trigger restarts a timer and a burst of events resolves in a single calculation.

Single-token and all-tokens timers are independent. A second all-tokens refresh started while the first is still running is skipped, not queued.

Once a token’s new light level differs from its stored flags.tokenlightcondition.lightLevel, the change is added to an in-memory queue keyed by token id. The queue:

  • Schedules itself on the next animation frame via requestAnimationFrame.
  • Discards stale entries.
  • Processes each token in turn: clear existing module effects, apply the new effect if the level is dark or dim, then write the new lightLevel flag.

This batching prevents the createActiveEffect / deleteActiveEffect hooks fired by Foundry from re-entering the calculation pipeline and causing infinite loops.

Trigger sourceBehaviour
Token movement or hidden toggleRecalculate that one token
Token light property changeRecalculate every eligible token
Ambient light or scene environment changeRecalculate every eligible token

Setting Add Token Effects off or flipping the toolbar button off both stop effect application, but they differ in how cleanup happens. See Active Effects and Scene Control Toggle.