Quick answer: Frame-based time sources stop when the game pauses. For real-time timers, create the source with time_source_units_seconds and parent it to time_source_global.
A “respawn in 5 seconds” timer uses a frame-based time source. When the player opens a pause menu (and you stop stepping), the timer freezes too.
Frames vs Seconds
// frame-based: counts game frames; pauses when stepping stops
ts = time_source_create(time_source_game, 300, time_source_units_frames, on_done);
// real-time: counts wall-clock seconds; ignores game pause
ts = time_source_create(time_source_global, 5, time_source_units_seconds, on_done);
Pick the parent and units to match the behavior you want.
Parent Choice
time_source_game: ticks with the game. Pauses when game logic pauses. Good for gameplay timers.time_source_global: ticks with real time. Keeps running through pause. Good for UI animations, network timeouts.
Units Choice
time_source_units_frames: count in frames — affected by room speed / delta.time_source_units_seconds: count in real seconds — consistent regardless of frame rate.
Pause-Aware Gameplay Timers
For a gameplay timer that should pause (a power-up duration), keep it frame-based on time_source_game. The freeze-on-pause is correct there. The bug is only when you used that for something that shouldn’t pause.
Verifying
Start a real-time timer, open the pause menu. The timer keeps counting. Gameplay timers correctly freeze. Both resume as expected.
“Choose parent and units deliberately: game+frames pauses, global+seconds doesn’t.”
Wrap timer creation in helper functions named for intent — create_gameplay_timer() vs create_realtime_timer() — so call sites can’t pick the wrong combo.