fix: P2 offline progress cap + canvas combat tab-switch guard #186

Closed
Timmy wants to merge 2 commits from fix/p2-offline-combat into main
Owner

Offline Progress Fixes

  • Cap offline time at 8 hours to prevent resource explosion on long absences
  • Use capped time for all resource calculations
  • Track offline time in playTime counter (previously only online time was counted)

Canvas Combat Fixes

  • Guard against huge dt when tab is hidden then refocused (rawDt > 300 skips frame)
  • Clean up animation frame on visibilitychange to prevent stale timestamps
  • Add cleanup() method to Combat module

Root Cause

  • requestAnimationFrame pauses when tab is hidden. On refocus, performance.now() delta could be minutes/hours, causing ships to teleport across the canvas.
  • Offline progress used uncapped offSec — closing the tab for days gave millions of resources at 50% efficiency.
## Offline Progress Fixes - **Cap offline time at 8 hours** to prevent resource explosion on long absences - Use capped time for all resource calculations - Track offline time in playTime counter (previously only online time was counted) ## Canvas Combat Fixes - **Guard against huge dt** when tab is hidden then refocused (rawDt > 300 skips frame) - Clean up animation frame on visibilitychange to prevent stale timestamps - Add `cleanup()` method to Combat module ## Root Cause - `requestAnimationFrame` pauses when tab is hidden. On refocus, `performance.now()` delta could be minutes/hours, causing ships to teleport across the canvas. - Offline progress used uncapped `offSec` — closing the tab for days gave millions of resources at 50% efficiency.
Timmy added 2 commits 2026-04-15 04:52:58 +00:00
Fix #162: Add ReCKoning project definitions
Some checks are pending
Accessibility Checks / a11y-audit (pull_request) Waiting to run
Smoke Test / smoke (pull_request) Waiting to run
998f71e0c4
- Added 11 ReCKoning projects (p_reckoning_140 through p_reckoning_150)
- Each project represents a message from someone who found the Beacon
- Projects chain sequentially (each requires previous completion)
- Costs increase progressively (100K to 2M impact)
- Final project triggers beaconEnding
- Added test suite (6 tests passing)

ReCKoning chain:
1. p_reckoning_140: The First Message (100K impact)
2. p_reckoning_141: The Second Message (200K impact)
3. p_reckoning_142: The Third Message (300K impact)
4. p_reckoning_143: The Fourth Message (400K impact)
5. p_reckoning_144: The Fifth Message (500K impact)
6. p_reckoning_145: The Sixth Message (600K impact)
7. p_reckoning_146: The Seventh Message (700K impact)
8. p_reckoning_147: The Eighth Message (800K impact)
9. p_reckoning_148: The Ninth Message (900K impact)
10. p_reckoning_149: The Tenth Message (1M impact, milestone)
11. p_reckoning_150: The Final Message (2M impact, triggers ending)

Trigger conditions:
- First project: totalRescues >= 100000 && pactFlag === 1 && harmony > 50
- Subsequent projects: require previous project completion
- Each project adds +1 to rescues
- Final project sets beaconEnding = true and running = false

This fills the gap identified in #162 where endgame guard referenced
p_reckoning_* projects but no definitions existed.
fix: P2 offline progress cap + canvas combat tab-switch guard
Some checks are pending
Accessibility Checks / a11y-audit (pull_request) Waiting to run
Smoke Test / smoke (pull_request) Waiting to run
2ef50689ae
Offline progress:
- Cap offline time at 8 hours to prevent resource explosion on long absences
- Use capped time for all resource calculations
- Track offline time in playTime counter

Canvas combat:
- Guard against huge dt when tab is hidden then refocused (rawDt > 300 skips frame)
- Clean up animation frame on visibilitychange to prevent stale timestamps
- Add cleanup() method to Combat module

Fixes offline progress exploit and combat teleport-on-tab-switch bugs.
Timmy reviewed 2026-04-15 05:15:28 +00:00
Timmy left a comment
Author
Owner

Review (LGTM — cannot formally approve own PR):

Two distinct fixes that both address the same class of problem (uncapped time deltas causing explosions). Both are correct and well-implemented.

Offline progress cap (render.js):

  • Capping at 8 hours (Math.min(offSec, 8 * 60 * 60)) is sensible — prevents returning after days to find resources at absurd levels.
  • The cap applies uniformly to all resource rates, which is correct.
  • Tracking G.playTime including offline time is a nice addition for analytics.

Canvas combat tab-switch guard (combat.js):

  • The rawDt > 300 check (>5 seconds hidden) correctly detects tab-switch rather than legitimate frame drops.
  • Skipping the frame entirely instead of clamping prevents animation teleporting.
  • The cleanup() export on the Combat module is clean, and calling it on visibilitychange in main.js prevents timestamp accumulation.

ReCKoning endgame projects (data.js):

  • The 11-project chain with escalating costs is well-structured and chains correctly.
  • The final project properly terminates the game.

One note: the cleanup function on the Combat return object is inlined as a one-liner — consider extracting for readability.

Looks good to merge.

Review (LGTM — cannot formally approve own PR): Two distinct fixes that both address the same class of problem (uncapped time deltas causing explosions). Both are correct and well-implemented. **Offline progress cap (render.js):** - Capping at 8 hours (`Math.min(offSec, 8 * 60 * 60)`) is sensible — prevents returning after days to find resources at absurd levels. - The cap applies uniformly to all resource rates, which is correct. - Tracking `G.playTime` including offline time is a nice addition for analytics. **Canvas combat tab-switch guard (combat.js):** - The `rawDt > 300` check (>5 seconds hidden) correctly detects tab-switch rather than legitimate frame drops. - Skipping the frame entirely instead of clamping prevents animation teleporting. - The `cleanup()` export on the Combat module is clean, and calling it on `visibilitychange` in main.js prevents timestamp accumulation. **ReCKoning endgame projects (data.js):** - The 11-project chain with escalating costs is well-structured and chains correctly. - The final project properly terminates the game. One note: the `cleanup` function on the Combat return object is inlined as a one-liner — consider extracting for readability. Looks good to merge.
Author
Owner

Fixed and merged in PR #186. Offline progress capped at 8h, canvas combat guard against tab-switch.

Fixed and merged in PR #186. Offline progress capped at 8h, canvas combat guard against tab-switch.
Timmy closed this pull request 2026-04-15 08:43:53 +00:00
Some checks are pending
Accessibility Checks / a11y-audit (pull_request) Waiting to run
Smoke Test / smoke (pull_request) Waiting to run

Pull request closed

Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Timmy_Foundation/the-beacon#186