- JavaScript 92.6%
- CSS 7.4%
Lets add-ons such as scene lighting follow the progress bar in real time. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> |
||
|---|---|---|
| foundry-vtt-autorelease@167c4b41c1 | ||
| lang | ||
| scripts | ||
| styles | ||
| .gitmodules | ||
| LICENSE | ||
| module.json | ||
| README.md | ||
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
- A game rule advances time (HUD click, exploration/idle tick, travel move, or combat round)
- The controller either applies it now or puts it in a queue
- Quick repeated or multiple updates are aggregated before publish
- Time rolls over automatically (rounds -> quarters -> shifts -> diurnals)
- Hooks fire so other modules can react
Integration Hooks
coreClock.timePreCommit: emitted before pending deltas are committedcoreClock.timeCommitted: emitted after a commit is appliedcoreClock.timeAdvanced: emitted when any time unit advancedcoreClock.roundAdvanced: emitted for round advancescoreClock.quarterAdvanced: emitted for quarter advancescoreClock.shiftAdvanced: emitted for shift advancescoreClock.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.