Macros
Calendaria automates macros through trigger configuration and event-attached macros.
Macro triggers
Section titled “Macro triggers”Configure macros to run automatically when calendar events occur. Access them via the Macros tab in the settings panel.
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”Run 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”Run 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
The Silent flag suppresses the chat announcement for a single-event start trigger; the attached macro still runs. Silent skips the entire multi-day daily-progress path, so neither the progress notification nor its macro runs there.
The scope parameter
Section titled “The scope parameter”Calendaria passes context data to a macro through Foundry’s scope parameter. When a macro runs programmatically rather than from a manual click, the caller provides a scope object with 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 run from 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 forecast (synchronous, returns the forecast array)const forecast = 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.