Offline Progress & Saves

How offline catch-up replays your run, the offline cap, death handling, and cloud saves.

On this page

Leave with combat running and the game replays the time you were away the next time you load. This is not a statistical estimate — it is the real engine ticked forward, so the outcome is exactly what would have happened if you had left the tab open. That includes finding loot, gaining levels, clearing dungeons, using potions, taking durability damage — and dying.

When offline catch-up runs

The replay runs only if combat was active when you exited. If you stopped combat, sat in town, or were on a safe tile, offline time produces zero progress — you come back exactly as you left.

if (offlineSeconds <= 0 || !combatWasActive || heldAtBoss) → zero-progress summary, no replay

heldAtBoss is the one extra case: a dungeon run parked on a first-clear boss waiting for your “Start Fight” can’t progress a single tick, so the replay is skipped outright instead of spinning through hours of empty ticks.

How the replay works

Catch-up steps the simulation in fixed 1/20-second ticks (20 tps) — the same rate as live play:

steps = floor(offlineSeconds / (1 / 20))   // = offlineSeconds × 20

Each tick runs the full stepSimulation, so every mechanic behaves normally: attacks, respawns, potions, DoTs, buff expiry, drops, auto-sell, crafting completion, and death. Because it is the real engine, the result is exact and can be dangerous — a long absence in a fight you can’t sustain will replay your death, not hand-wave it.

What does and doesn’t carry over

The hero never travels during a replay — except while auto-exploring, where it moves on to the next tile after each clear exactly as in live play (the recap shows an “Areas explored” row and lists the clear reward items). Otherwise it is the tile you left on, fought over and over. Everything the kill pipeline normally does happens with it, including camp-quest progress and slot cooldowns and Region Resonance kill quotas. An Endless Delve run you logged out of mid-descent keeps descending (its kills still grant no XP).

The one system held back is monster hunts: a mark never shows itself during the replay, so a hunt can only be finished in live play. The scout timer itself is wall-clock and does complete while you’re away, as do smith/witch commissions and bedroom construction (those three run whether or not combat was active).

Early-stop condition

The replay stops fighting early on this, so you can react instead of replaying past a decision:

TriggerWhat happens
Tile unlocked (not while auto-exploring)Combat is suspended so the unlock modal can show; it is running again when you take over.

A death ends combat as it does in live play. See Death for what it costs.

Winding down to full health

Neither ends the replay outright. Once combat is suspended, the remaining offline time keeps ticking as out-of-combat regeneration (HERO_OUT_OF_COMBAT_REGEN_RATE = 1/60, so a full bar takes 60 seconds) until your health is back at 100%, and only then does the replay finish. You never come back standing on a corpse or on the sliver of health a tile clear left you with — as long as enough offline time was left to heal it. The same applies to a death: the replay idles through the respawn regeneration before it stops.

The recap prompt

When you load, an offline-progress recap summarizes kills, levels, gold, XP, dungeon clears, deaths, and found items. It is suppressed for absences of 5 minutes or less (OFFLINE_PROMPT_MIN_SECONDS = 5 × 60), and also skipped if nothing meaningful changed:

show recap  ⇔  offlineSeconds > 300  AND combatWasActive  AND (any of:
              kills, levels, gold≠0, dungeon clears, xp, deaths, found items,
              or Resonance quota progress)

A tab you leave open in the background counts as away too. Your hero fights on live, under the same offline cap as after closing the game: once the cap is used up it rests until you switch back. Then the fight on screen simply carries on from where it is now (nothing is replayed), and the same recap sums up the time the tab was away under the same rules.

Items you listed on the Trading Board sell while you are away. The recap then adds a Trading Board row (how many sold, gold received) and shows up for that alone, even after a short absence or with combat off.

The offline cap

Offline time is clamped so it can’t accrue indefinitely:

maxOffline = 8 hours × (1 + 0.10 × offlineCapLevel)

The base cap is 8 hours (MAX_OFFLINE_SECONDS). The Offline Cap Bedroom upgrade adds +10% per level up to level 10, doubling the cap to 16 hours at max.

Offline Cap levelMultiplierMax offline
0×1.08 h
5×1.512 h
10 (max)×2.016 h

Worked example — level 10: 8 h × (1 + 0.10 × 10) = 8 × 2.0 = 16 hours. Anything beyond 16 hours of real absence is discarded; the replay only ever simulates up to the cap.

Saves

PropertyValue
StorageCloud-only (Supabase backend) — no local save file
Slots5 per account (SAVE_SLOT_COUNT)
Save format version4 (SAVE_VERSION) — mismatched versions are rejected as incompatible on load
Autosave pollEvery 1 second, change-detecting
In-combat write throttleAt most once per 15 seconds
Out-of-combat writesDebounced (only when the save signature actually changes)
On tab closeA final guarded save fires on beforeunload

A change-detecting poll runs every second; idle regen never changes the save signature, so it never schedules a redundant write. In-combat changes are throttled to one write per 15 seconds, and out-of-combat changes are debounced.

What a slot shows in the main menu

Each filled slot carries one combined hero line plus the save time:

Level 34 Berserker - Fighting in Cursed Swamp (12)
Last Save on <timestamp in your language's format>

The location is the region (or dungeon, or the Endless Delve (Level N)) with the tile’s effective rank in brackets. If combat was not running when the slot was last saved, the line reads Level 34 Berserker - idling instead.

Game version

Every save records the game version it was last written with. The slot card only shows it when it differs from the game’s version.

  • Older save: the slot shows an Update badge. Loading it opens a prompt with a one-line summary of each release since that version and what happens to your save data; Update & Load migrates it.
  • Newer save (made with a newer game build): the slot shows Too new and loading is blocked. The save is not touched.

When a new version is released while the game is open, the tab notices (on focus, or every 10 minutes): in the main menu it reloads by itself, and before a slot starts it reloads instead of loading. In game a New Version Available prompt offers Reload now (saves first, then reloads) or Later.

Single active session per character

Each character can only be actively played in one session at a time. When a session loads a character it claims the slot, and there are two layers enforcing exclusivity:

  1. Instant broadcast — a realtime channel (char:<user>:<slot>) tells any older session that a new one has claimed the character, bouncing it to the menu.
  2. Guarded write — every autosave is a conditional update that only succeeds while this session still owns the slot. If another session has claimed it, the write returns superseded and the losing session returns to the menu instead of clobbering the newer save.

The last session to load a character always wins. The guarded write is the source of truth, so correctness holds even if the instant broadcast is never delivered (e.g. a suspended mobile tab).

Anonymous guest sessions are supported (a real backend user with no email), and can later be upgraded in place to a full account without migrating any save data.

Settings

The Settings modal opens from the in-game menu (the button in the bottom-right corner). It mixes two scopes: most toggles ride along in the character’s save, while audio and language belong to the account.

Per-character settings

These are stored in the save file, so they follow the character rather than the browser:

SettingWhat it does
Show the next item after sellingKeeps the sell flow moving through a haul
Show a sell confirmation in inventoryConfirm prompt on single inventory sales
Skip camp to world mapSwitching to the Camp tab opens the world map straight away instead of the camp scene
Show detailed combat-log linesPer-swing hits, misses, blocks, casts and status. Drops, XP/gold and system messages always show
Show first-time helpA Help window opens the first time you visit each tab or panel
Default town tab on loadWhich town tab a freshly loaded character lands on
Default inventory sortSort mode applied on load
Default inventory filterFilter applied on load

Next to Show first-time help sits a Reset help overlays button: it clears the “seen” record for this character, so every Help window opens again on its next visit.

Audio & language (account-wide)

The Audio group carries a master switch and volume plus separate enable/volume pairs for music, sound effects (hits, blocks, misses, potions, buttons, level-ups) and ambience (a background bed per region, dungeon and delve, with a tension layer while you fight). Those four buses and the game language live in one cloud row per account, not on the character and not on the device, so they follow you across every character and every browser you sign in from. The cloud row wins over whatever the device had cached the moment you sign in.

Two settings are deliberately not in this modal: the auto-potion threshold and the loot filter both live on the Combat config card (the filter is also reachable from the inventory toolbar).

The leaderboard

Served by the get_leaderboard RPC and opened from the in-game menu (the hamburger button). It lists the top 10 characters in four columns:

ColumnValue
RankPosition in the sorted list
NameHero name
LevelHero level
DelveDeepest Endless Delve level ever reached (0 if never delved)

Sorting is level descending, then delve highscore descending, then name. Only confirmed, registered accounts are eligible: guest characters and unconfirmed sign-ups are filtered out. Your own row is highlighted.

Installing the game

The game ships a web app manifest and a service worker, so browsers offer their normal Install app / Add to Home Screen option. Installed, it launches in its own standalone window with its own icon instead of a browser tab.

The installed game keeps its game files on your device (art, icons, maps, about 320 MB). Shortly after the first launch it downloads them once in the background; a small panel in the corner shows the progress and says when they are saved, and you can play meanwhile. From then on the game loads them from the device instead of the server. After an update it downloads only the files that changed (a small update does this without the panel). If a download is cut off, the next launch carries on where it stopped. A game opened in a normal browser tab downloads nothing extra.

It is still not an offline app: playing needs a connection to the game server, which runs the game; only the files are local. Every launch still checks for a new version, so you always play the current one. Your heroes are unaffected, they live on the server.

See also

  • Bedroom Upgrades — the Offline Cap upgrade that raises the 8 h → 16 h ceiling.
  • Death — what a death costs, including during an offline replay.