A Foundry VTT module that tracks how long everyone takes on their turn and shows the running average in front of their name — in the players list, the combat tracker, or both. The GM decides which.
Nobody has to do anything to make it work: timing starts when an encounter starts and the average appears once a turn has been recorded.
-
In the Foundry VTT setup screen, go to the Add-on Modules tab
-
Click Install Module
-
Paste the following URL into the Manifest URL field at the bottom of the window:
https://github.com/sagarc03/average-turn-time/releases/latest/download/module.json -
Click Install
Once installed, launch your world, open Settings > Manage Modules, enable Average Turn Time, and click Save Module Settings.
- Foundry VTT V14+
Each turn is timed from the moment it starts to the moment the encounter advances to the next combatant. When the turn ends, that duration is folded into a running average for two things at once:
- The user who owns the combatant — so the players list can show "how long does Alex take?"
- The combatant itself — so the combat tracker can show "how long does this NPC take?"
Timing runs on the GM's client only, which is the single writer for the stored averages. Foundry syncs them out, so every player sees the same numbers.
The badge shows the average, not the current turn: 42s, 1:05, 1:02:03. Hover it for the turn count behind the average.
The GM gets a stopwatch button in the combat tracker's control row. Clicking it posts the current averages to chat as a table, ranked slowest first:
| Name | Average | Turns |
|---|---|---|
| Blake | 1:30 | 4 |
| Alex | 30s | 7 |
| Casey | 12s | 6 |
The report mirrors the Show Average In setting — if you display averages in the players list, the post is about players; set it to Both and the post carries a section for each. Whether players see the post is controlled by Posted Report Visibility.
The button only appears for the GM. To post from a macro or hotbar instead — including outside of combat — use game.modules.get("average-turn-time").api.post().
All settings are world-level — the GM sets them, and they apply to everyone.
Show Average In — Where the badge appears. Options: Players list, Combat tracker, Both, Nowhere. Default: Players list. "Nowhere" keeps tracking silently, so the data is still there via the API.
Posted Report Visibility — Who sees a report posted with the combat tracker button. Options: Everyone, GM only. Default: Everyone.
Track NPC Turns — Whether NPC turns count toward the averages. Default: on. Turns for NPCs nobody owns are credited to the active GM, so the GM's own row reflects the time they spend running monsters.
Maximum Turn Length (seconds) — Turns longer than this are discarded rather than averaged in. Default: 600 (10 minutes). This is what keeps a snack break or an encounter left open overnight from wrecking the numbers.
Reset Each Combat — Clear all recorded times when a new encounter begins. Default: off, so averages accumulate across the campaign.
const api = game.modules.get("average-turn-time")?.api;| Method | Description |
|---|---|
api.getStats() |
Raw stats: { users, combatants }, each keyed by id to { count, totalMs } |
api.getUserAverage(userId) |
Formatted average for a user, or null |
api.getCombatantAverage(combatantId) |
Formatted average for a combatant, or null |
api.post() |
Post the current averages to chat (GM only) |
api.reset() |
Clear all recorded turn times (GM only) |
Waiting for the API from another module:
Hooks.once("averageTurnTimeReady", (api) => {
// API is guaranteed to be available here
});This module contains AI-generated code. The author personally understands and maintains all of it, and the source is available in this repository for review.
The first time a GM loads a new version, Foundry shows a disclosure dialog. Until a GM accepts it the module stays inert — no timing, no badges, no button. Accepting is per version, so a version bump asks again; declining offers to open Module Management so you can disable it.
- A GM who reloads mid-turn drops that one sample — the clock is in memory, which is deliberate: the alternative is recording a bogus multi-hour turn.
- Rewinding the turn order records a sample for the turn being rewound past.
- Pausing the game does not pause the turn clock.
See CONTRIBUTING.md for local development setup and instructions.