Skip to content

Macros

Calendaria automates macros through trigger configuration and event-attached macros.


Configure macros to run automatically when calendar events occur. Access them via the Macros tab in the settings panel.

TriggerDescription
DawnFires at sunrise
DuskFires at sunset
MiddayFires at noon
MidnightFires at midnight
New DayFires when the day changes

Run macros when seasons change.

  • Specific season: Fires when entering that season
  • All Seasons: Fires on any season change

Run macros when moon phases change.

  • Moon: Specific moon or “All Moons”
  • Phase: Specific phase or “All Phases”

Calendar notes can have an attached macro that executes when the event triggers.

  • 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.

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.

// Event trigger context
const { event } = scope;
console.log(event.id); // Note page ID
console.log(event.name); // Note name
console.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
}

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 seconds
console.log(components); // { year, month, dayOfMonth, hour, minute, ... }
const { trigger, previous, current, calendar } = scope;
console.log(trigger); // "newDay"
console.log(previous.year); // Previous date components
console.log(current.year); // Current date components
console.log(calendar); // Active calendar object
const { trigger, previous, current, previousSeason, currentSeason, calendar } = scope;
console.log(trigger); // "seasonChange"
console.log(previous); // Previous date components
console.log(current); // Current date components
console.log(previousSeason); // Previous season object { name, ... }
console.log(currentSeason); // Current season object { name, ... }
console.log(calendar); // Active calendar object
const { trigger, moon } = scope;
console.log(trigger); // "moonPhaseChange"
console.log(moon.moonIndex); // Moon index
console.log(moon.moonName); // Moon name
console.log(moon.previousPhaseIndex);
console.log(moon.previousPhaseName);
console.log(moon.currentPhaseIndex);
console.log(moon.currentPhaseName);

// Advance 1 hour
await CALENDARIA.api.advanceTime({ hour: 1 });
// Advance 8 hours (long rest)
await CALENDARIA.api.advanceTime({ hour: 8 });
// Advance 1 day
await CALENDARIA.api.advanceTime({ day: 1 });
// Jump to specific date
await CALENDARIA.api.jumpToDate({ year: 1492, month: 5, day: 15 });
// Advance to next sunrise
await CALENDARIA.api.advanceTimeToPreset('sunrise');
// Advance to next sunset
await CALENDARIA.api.advanceTimeToPreset('sunset');
// Force the cinematic overlay when advancing
await CALENDARIA.api.advanceTime({ day: 7 }, { cinematic: true });
await CALENDARIA.api.jumpToDate({ year: 1492, month: 5, day: 15 }, { cinematic: true });
// Toggle the real-time clock on/off
CALENDARIA.api.toggleClock();
// Start the clock (if not already running)
if (!CALENDARIA.api.isClockRunning()) CALENDARIA.api.startClock();
// Stop the clock
CALENDARIA.api.stopClock();
// Check current clock speed (game seconds per real second)
const speed = CALENDARIA.api.getClockSpeed();
ui.notifications.info(`Clock speed: ${speed}x`);
// Show current date/time
const now = CALENDARIA.api.getCurrentDateTime();
const formatted = CALENDARIA.api.formatDate(now, 'datetime24');
ChatMessage.create({ content: `<b>Current Time:</b> ${formatted}` });
// Show weather
const weather = CALENDARIA.api.getCurrentWeather();
ChatMessage.create({
content: `<b>Weather:</b> ${weather.label}, ${weather.temperature}`
});
// Show moon phase
const phase = CALENDARIA.api.getMoonPhase(0);
ChatMessage.create({ content: `<b>Moon:</b> ${phase.name}` });
// Show season
const season = CALENDARIA.api.getCurrentSeason();
ChatMessage.create({ content: `<b>Season:</b> ${season.name}` });
// 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}!`);
}
// Create a quick note
const 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 events
const 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}`);
}
// Set specific weather
await 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 zone
await CALENDARIA.api.generateWeather();
// Get forecast (synchronous, returns the forecast array)
const forecast = CALENDARIA.api.getWeatherForecast({ days: 7 });
// Clear all weather history
await CALENDARIA.api.clearWeatherHistory({ all: true });
// Clear future history only
await CALENDARIA.api.clearWeatherHistory({ future: true });

See API Reference and Hooks.