Skip to content

Fuel

Each race the race server judges costs 1 fuel. The tank holds 10 and one point comes back every 6 minutes. Fuel replaced interstitial ads: the rewarded fuel ad is now the game’s main ad. The design is in docs/2026-11-08-progression-design.md; the numbers are estimates to tune after playtesting.

Race Cost
Career event (any mode, wagers included) 1
Boss fight, best of 3 1 for the fight, paid on round 1
Tournament 1 for the whole bracket, paid on round 1
Quick race 1
Results’ Retry 1, it is a new race
Flashback (story tutorial) free, the server does not judge it
Online heat free for now

A series costs once so a 3-round boss fight is not three times the price of an event. “Keep rounds won” after a lost boss fight re-races the decider as a later round, so it costs no fuel either.

player/fuel/fuel.ts holds them, with no Phaser, so the server and the game run the same code. The tank is GarageState.fuel: an amount at a time since (milliseconds, the server’s clock). Nothing ticks: readFuel(tank, now) adds one point per FUEL_REGEN_MS passed since since, up to FUEL_MAX, and says how long the next point takes. A save without a tank reads as full.

  • spendFuel folds the regen into the amount, keeps the part-earned point in since and takes 1. At 0 it refuses with NO_FUEL.
  • applyFuelAd adds FUEL_PER_AD (2), never past the top, at most FUEL_ADS_PER_DAY (3) per UTC day. The count and date live in the tank. A full tank refuses the ad.
  • fillFuel fills the tank. addXp (player/level/xp.ts) calls it when the XP crosses a level, and the goldFuel garage action calls it for 30 gold (see Gold).

tests/fuel.test.ts covers regen, the cap, spending at 0, the ad cap and the level-up fill.

  • start in party/src/api/raceApi.ts spends the fuel when it hands out a ticket (party/src/race/raceFuel.ts), before it enters a series, so a refusal leaves a running boss fight alone. The answer carries the garage, so the game shows the new amount at once.
  • The fuel ad is the fuelAd garage action. Like the daily bonus it is an ad reward (AD_REWARDS in party/src/api/garageApi.ts): it spends one ad credit that AdMob’s server-side verification gave the account, so a client cannot claim an ad it did not watch.
  • The game cannot set its own fuel: fuel is not one of the fields its sync sends (player/garageSync.ts). Moving the phone’s clock changes what the top bar shows, never what the server spends.
  • Top bar (menu/topBar/fuelGauge.ts): a can, 7/10 and the wait for the next point, refreshed each second from the local garage copy and the phone’s clock.
  • Fuel guard (ui/fuelGuard.ts): whenFuelled runs before every way into a race that costs fuel (career event, boss, quick race, Results’ Retry), after the blown-engine guard. With an empty tank it opens a dialog with the wait, plus “Watch an ad” for +2 while a rewarded ad is loaded and the day’s 3 are not used up. With at least 30 gold it also offers “Fill the tank” for gold. A paid ad or a bought tank starts the race at once.
  • Gold: tapping the fuel or the gold in the top bar opens the gold dialog, which also fills the tank (see Gold). Its gold ad counts apart from the 3 fuel ads.
  • When the phone’s clock is ahead of the server, the top bar can show fuel the server does not have; the server refuses the ticket and the race runs unjudged, like any race without a ticket.