Macros
Calendaria supports macro automation through Trigger Configuration and Event-Attached Macros.
Macro Triggers
Section titled “Macro Triggers”Configure macros to execute automatically when calendar events occur. Access via Settings Panel > Macros tab (GM only).
Global Triggers
Section titled “Global Triggers”| Trigger | Description |
|---|---|
| Dawn | Fires at sunrise |
| Dusk | Fires at sunset |
| Midday | Fires at noon |
| Midnight | Fires at midnight |
| New Day | Fires when the day changes |
Season Triggers
Section titled “Season Triggers”Execute macros when seasons change:
- Specific season: Fires when entering that season
- All Seasons: Fires on any season change
Moon Phase Triggers
Section titled “Moon Phase Triggers”Execute macros when moon phases change:
- Moon: Specific moon or “All Moons”
- Phase: Specific phase or “All Phases”
Event-Attached Macros
Section titled “Event-Attached Macros”Calendar notes can have an attached macro that executes when the event triggers.
Trigger Conditions
Section titled “Trigger Conditions”- Event’s start time is reached
- Multi-day events fire daily with progress data
Notes with the Silent flag will not trigger macros or notifications.
The Scope Parameter
Section titled “The Scope Parameter”When Calendaria triggers a macro, it passes context data through Foundry’s scope parameter. This is a standard Foundry feature. When macros are executed programmatically (rather than manually clicked), the caller can provide a scope object containing relevant data.
Inside your macro, access this data by destructuring from scope:
const { event, trigger } = scope;The scope variable is automatically available in your macro code. You don’t need to define or import it.
Context Data
Section titled “Context Data”// Event trigger contextconst { event } = scope;console.log(event.id); // Note page IDconsole.log(event.name); // Note nameconsole.log(event.flagData); // Full note data (startDate, endDate, categories, etc.)
// Multi-day progress context (if applicable)const { trigger, progress } = scope;if (trigger === 'multiDayProgress') { console.log(progress.currentDay); // Current day number console.log(progress.totalDays); // Total event duration console.log(progress.percentage); // Completion percentage console.log(progress.isFirstDay); // boolean console.log(progress.isLastDay); // boolean}Global Trigger Context
Section titled “Global Trigger Context”Macros executed via global triggers receive context data:
Time Threshold Triggers (dawn, dusk, midday, midnight)
Section titled “Time Threshold Triggers (dawn, dusk, midday, midnight)”const { trigger, worldTime, components, calendar } = scope;console.log(trigger); // "sunrise", "sunset", "midday", "midnight"console.log(worldTime); // Current world time in secondsconsole.log(components); // { year, month, dayOfMonth, hour, minute, ... }New Day Trigger
Section titled “New Day Trigger”const { trigger, previous, current, calendar } = scope;console.log(trigger); // "newDay"console.log(previous.year); // Previous date componentsconsole.log(current.year); // Current date componentsconsole.log(calendar); // Active calendar objectSeason Change Trigger
Section titled “Season Change Trigger”const { trigger, previous, current, previousSeason, currentSeason, calendar } = scope;console.log(trigger); // "seasonChange"console.log(previous); // Previous date componentsconsole.log(current); // Current date componentsconsole.log(previousSeason); // Previous season object { name, ... }console.log(currentSeason); // Current season object { name, ... }console.log(calendar); // Active calendar objectMoon Phase Trigger
Section titled “Moon Phase Trigger”const { trigger, moon } = scope;console.log(trigger); // "moonPhaseChange"console.log(moon.moonIndex); // Moon indexconsole.log(moon.moonName); // Moon nameconsole.log(moon.previousPhaseIndex);console.log(moon.previousPhaseName);console.log(moon.currentPhaseIndex);console.log(moon.currentPhaseName);Example Macros
Section titled “Example Macros”Time Control
Section titled “Time Control”// Advance 1 hourawait CALENDARIA.api.advanceTime({ hour: 1 });
// Advance 8 hours (long rest)await CALENDARIA.api.advanceTime({ hour: 8 });
// Advance 1 dayawait CALENDARIA.api.advanceTime({ day: 1 });
// Jump to specific dateawait CALENDARIA.api.jumpToDate({ year: 1492, month: 5, day: 15 });
// Advance to next sunriseawait CALENDARIA.api.advanceTimeToPreset('sunrise');
// Advance to next sunsetawait CALENDARIA.api.advanceTimeToPreset('sunset');
// Force the cinematic overlay when advancingawait CALENDARIA.api.advanceTime({ day: 7 }, { cinematic: true });await CALENDARIA.api.jumpToDate({ year: 1492, month: 5, day: 15 }, { cinematic: true });Clock Control
Section titled “Clock Control”// Toggle the real-time clock on/offCALENDARIA.api.toggleClock();
// Start the clock (if not already running)if (!CALENDARIA.api.isClockRunning()) CALENDARIA.api.startClock();
// Stop the clockCALENDARIA.api.stopClock();
// Check current clock speed (game seconds per real second)const speed = CALENDARIA.api.getClockSpeed();ui.notifications.info(`Clock speed: ${speed}x`);Display Information
Section titled “Display Information”// Show current date/timeconst now = CALENDARIA.api.getCurrentDateTime();const formatted = CALENDARIA.api.formatDate(now, 'datetime24');ChatMessage.create({ content: `<b>Current Time:</b> ${formatted}` });
// Show weatherconst weather = CALENDARIA.api.getCurrentWeather();ChatMessage.create({ content: `<b>Weather:</b> ${weather.label}, ${weather.temperature}`});
// Show moon phaseconst phase = CALENDARIA.api.getMoonPhase(0);ChatMessage.create({ content: `<b>Moon:</b> ${phase.name}` });
// Show seasonconst season = CALENDARIA.api.getCurrentSeason();ChatMessage.create({ content: `<b>Season:</b> ${season.name}` });Check Conditions
Section titled “Check Conditions”// Is it night?const isNight = CALENDARIA.api.isNighttime();ui.notifications.info(isNight ? 'It is nighttime' : 'It is daytime');
// Is it a rest day?if (CALENDARIA.api.isRestDay()) { ui.notifications.info('Today is a rest day');}
// Is it a festival?if (CALENDARIA.api.isFestivalDay()) { const festival = CALENDARIA.api.getCurrentFestival(); ui.notifications.info(`Today is ${festival.name}!`);}Notes Management
Section titled “Notes Management”// Create a quick noteconst now = CALENDARIA.api.getCurrentDateTime();await CALENDARIA.api.createNote({ name: 'Session Note', content: '<p>Something important happened here.</p>', startDate: { year: now.year, month: now.month, day: now.dayOfMonth }, allDay: true});
// Get today's eventsconst notes = CALENDARIA.api.getNotesForDate(now.year, now.month, now.dayOfMonth);if (notes.length > 0) { const list = notes.map((n) => n.name).join(', '); ui.notifications.info(`Today: ${list}`);}Weather Control
Section titled “Weather Control”// Set specific weatherawait CALENDARIA.api.setWeather('thunderstorm', { temperature: 55 });
// Override wind and precipitation on top of a preset (morning period only)await CALENDARIA.api.setWeather('cloudy', { period: 'morning', temperature: 11, wind: { speed: 2, direction: 'SW', forced: false }, // speed 0-5; direction: compass string ('SW') or degrees (225) precipitation: { type: null, intensity: 0 } // type: null|drizzle|rain|snow|sleet|hail});
// Generate weather from climate zoneawait CALENDARIA.api.generateWeather();
// Get forecastconst forecast = await CALENDARIA.api.getWeatherForecast({ days: 7 });
// Clear all weather historyawait CALENDARIA.api.clearWeatherHistory({ all: true });
// Clear future history onlyawait CALENDARIA.api.clearWeatherHistory({ future: true });For Developers
Section titled “For Developers”See API Reference and Hooks.