A Foundry VTT module that handles in-game time progression for Dragonbane/Drakar och Demoner.
  • JavaScript 92.6%
  • CSS 7.4%
Find a file
Tobias Hellgren 41ced37756 Emit coreClock.displayAnimated when the HUD time bar starts animating
Lets add-ons such as scene lighting follow the progress bar in real time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 16:33:33 +02:00
foundry-vtt-autorelease@167c4b41c1 Update README.md, add auto-version submodule 2026-10-10 13:41:38 +02:00
lang Update: Remove all non-time-tracking features to be migrated to their own modules 2026-09-11 19:59:20 +02:00
scripts Emit coreClock.displayAnimated when the HUD time bar starts animating 2026-10-10 16:33:33 +02:00
styles WIP 2026-07-05 16:41:33 +02:00
.gitmodules Update README.md, add auto-version submodule 2026-10-10 13:41:38 +02:00
LICENSE Initial commit 2026-06-28 13:02:59 +02:00
module.json Emit coreClock.displayAnimated when the HUD time bar starts animating 2026-10-10 16:33:33 +02:00
README.md Update README.md 2026-10-10 14:00:59 +02:00

Core Clock

"AI" disclosure

Some or all of the code in this repository was generated with the assistance of LLM-based tools.

AI-generated code is not automatically owned by the person who generated it. No claim of ownership is made over third-party code or material included in this repository.

If you believe any code in this repository infringes your copyright, please contact me with the relevant details and I will review the matter and remove the material if appropriate.

This repository is intended for personal use only. The code is provided "as is", without warranties of any kind. I accept no responsibility or liability for any damage, data loss, security issues or other consequences resulting from its use.

Use this code at your own risk. You have been warned.

About

This is an in-game time progression module for Foundry VTT and the Dragonbane/Drakar och Demoner system which can keep track of time during travelling, combat and normal exploration, based on different rules.

Compatibility

The module has been developed for and tested for Foundry VTT 14.369 and Dragonbane/Drakar och Demoner system version 4.1.1.

Installation

In Foundry VTT, go to Add-on Modules → Install module and enter the manifest url: https://code.chuggybumba.com/thanius/core-clock/raw/branch/main/module.json

Features

  • Time tracker for exploration, travel and combat pacing
  • Slider that shows the phase of the day and can be used to adjust time
  • Can be used with other modules for time tracking

Time Flow

  1. A game rule advances time (HUD click, exploration/idle tick, travel move, or combat round)
  2. The controller either applies it now or puts it in a queue
  3. Quick repeated or multiple updates are aggregated before publish
  4. Time rolls over automatically (rounds -> quarters -> shifts -> diurnals)
  5. Hooks fire so other modules can react

Integration Hooks

  • coreClock.timePreCommit: emitted before pending deltas are committed
  • coreClock.timeCommitted: emitted after a commit is applied
  • coreClock.timeAdvanced: emitted when any time unit advanced
  • coreClock.roundAdvanced: emitted for round advances
  • coreClock.quarterAdvanced: emitted for quarter advances
  • coreClock.shiftAdvanced: emitted for shift advances
  • coreClock.diurnalAdvanced: emitted for diurnal advances

Settings

  • Notification controls: day-pass notifications and broadcast mode
  • Debounce controls: stable delay and max delay window
  • Travel controls: unit/distance and per-diurnal distance state
  • HUD controls: player visibility, compact mode, position, title

Development

Use the API and hooks below to react to time progression from other modules.

1. Subscribe to any time change

const api = game.modules.get("core-clock")?.api;
if (!api) return;

api.on(api.hooks.TIME_ADVANCED, ({ delta, reason, clockState, meta }) => {
  console.log("Core Clock advanced", { delta, reason, clockState, meta });
});

2. Subscribe to specific units

const api = game.modules.get("core-clock")?.api;
if (!api) return;

api.on(api.hooks.ROUND_ADVANCED, (count) => {
  console.log(`Rounds advanced: ${count}`);
});

api.on(api.hooks.QUARTER_ADVANCED, (count) => {
  console.log(`Quarters advanced: ${count}`);
});

api.on(api.hooks.SHIFT_ADVANCED, (count) => {
  console.log(`Shifts advanced: ${count}`);
});

api.on(api.hooks.DIURNAL_ADVANCED, (count) => {
  console.log(`Diurnals advanced: ${count}`);
});

3. Filter by source/reason

const api = game.modules.get("core-clock")?.api;
if (!api) return;

api.on(api.hooks.TIME_ADVANCED, ({ delta, reason }) => {
  if (reason !== "travel") return;
  if (delta.shifts > 0) {
    // Example: react only when travel caused one or more shift passes.
    Hooks.callAll("myModule.travelShiftPassed", delta.shifts);
  }
});

4. Unsubscribe cleanly

const api = game.modules.get("core-clock")?.api;
if (!api) return;

const onTimeAdvanced = ({ delta }) => {
  // Handle event
};

api.on(api.hooks.TIME_ADVANCED, onTimeAdvanced);

// Later, when your module no longer needs the listener:
api.off(api.hooks.TIME_ADVANCED, onTimeAdvanced);

5. Available hook names

const api = game.modules.get("core-clock")?.api;
if (!api) return;

console.log(api.hooks);
// {
//   PRE_COMMIT,
//   COMMITTED,
//   TIME_ADVANCED,
//   SHIFT_ADVANCED,
//   QUARTER_ADVANCED,
//   ROUND_ADVANCED,
//   DIURNAL_ADVANCED,
//   DISPLAY_ANIMATED
// }

DISPLAY_ANIMATED fires when the HUD time bar starts moving to a new time, with { fromMinutes, toMinutes, durationMs } (minutes of day, durationMs is 0 for an instant jump). Use it to run visuals in step with the bar; use TIME_ADVANCED/COMMITTED for game logic.

FAQ

Q: Why the name 'Core Clock'?

A: Well, to be honest, I just wanted a funny name. I was going to name everything abbreviated, where I took the two first letters of Core and the last two letters of Clock.

Q: Are any other systems supported?

A: Probably not. If I ever start to DM a game of DnD or Pathfinder, etc, I'll probably test and add compatibility. My main game is Dragonbane, so that's where the focus is at.

Q: I found a bug! How do I report?

A: Best is to open up an issue on the main repository. I'll do my best to fix these, if I deem it worth my time. This is for fun, after all, and for my own pleasure.

Q: Hey, wait a minute. This code looks awfully AI generated!

A: Well, that's because it is. Please read the disclosure at the top of this README.