Magnet Radius
The magnet radius is the world-space distance around the ship within which XP orbs (and other magnetic pickups) start accelerating toward the player on their own. It is the primary lever the player has over passive XP throughput — every other pickup behavior layers on top of it.
The stat — ship.magnetRange
ship.magnetRange is a flat number of world units stored on the ship state (engine/core/state.ts). The base value is 100 at run start. It is consumed every frame inside the XP-orb update loop:
const mR = ship.magnetRange || 100;
const mRsq = mR * mR;If the stat is somehow zero or missing at the read site, the loop falls back to 100 so the magnet never silently disappears mid-run. The squared form mRsq is used for the per-orb distance test to avoid a sqrt on every orb every frame.
Three-layer pull model
Each orb’s per-frame logic in engine/world/xp-orbs.ts::update() resolves through three magnet layers, in order:
-
Layer 1 — snap-on (
dist < 20). Any orb inside a 20-px radius is collected immediately, with no acceleration ramp at all. This guarantees the player never has to wait for the magnet curve to finish when an orb is essentially on top of them. -
Layer 2 — quadratic base pull (
dsq < magnetRange²). InsidemagnetRangebut outside the snap-on ring, the orb is pulled with speed:pullPct = 1 - dist / magnetRange pullSpeed = CFG.MAGNET_SPEED * 0.4 * (0.1 + pullPct² * 0.9)CFG.MAGNET_SPEEDis 234 (seeengine/core/config/_gameplay.ts); the XP-orb path applies a 0.4 multiplier so XP feels lighter than coin/heart pickups. The0.1 + pullPct² * 0.9curve means orbs at the edge of the magnet ring drift slowly (~10 % speed) and accelerate quadratically as they close on the ship. Each frame’s contribution accumulates in_pullAccum; once that running total crosses 4, the orb flips its_collectedflag and promotes to layer 3. -
Layer 3 — exponential lock-on (
_flags[i] & 2). Once an orb has been pulled long enough to flip, its velocity is zeroed and replaced with rigid tracking:accelSpeed = 200 * 3^_magTime_magTimeis the seconds since the flip, so the speed triples every second of lock-on. The per-frame movement fraction is clamped to 0.95 of the remaining distance so the orb cannot tunnel past the ship before the contact test fires.
Direct contact (dsq < (shipR + orbR)²) collects the orb regardless of which layer it is in.
The Magnet modifier
The Magnet modifier (data/modifiers.ts, id magnet, max level 20, common rarity, utility category) grants +40 flat units of magnetRange per rank:
{ stat: 'magnetRange', mode: 'flat', base: 40, perLevel: 0, k: -1 }So rank 1 takes the effective radius from the ~130-unit baseline (100 base + any ship-card adders) to ~170; rank 20 stacks an additional +800 units on top of whatever the build started with. Because the stat is flat-additive, Magnet is purely a footprint multiplier — it does not change the pull curve shape, just the radius at which layer 2 starts engaging. Bigger magnet means more orbs sitting in the slow-pull tail at any moment, which raises the rate that orbs reach the layer-2→3 promotion threshold.
The description string +40 pickup magnet range per rank is the in-game tooltip; the actual effect entry is the source of truth.
Magnet pickups and triggerGlobalMagnet()
The ring-based pull model is bypassed entirely by magnet pickups — collectibles that fire a global vacuum event. In the bridge tick (engine/bridge.ts), a magnet collect event calls:
xpOrbs.triggerGlobalMagnet();
game._magnetIconTimer = 1.5;triggerGlobalMagnet() walks every active orb in the pool and sets _flags[i] |= 2 (the _collected bit), resets _magTime to zero, and zeros velocity. Every orb on the map is now in layer 3, accelerating exponentially toward the ship regardless of distance. The HUD shows the magnet icon for 1.5 s as feedback.
Boss death and the Scrap Pile destructible’s magnet-pulse synergy (15 % chance on break, in engine/world/props.ts) call the same primitive — the global vacuum is the shared “absorb the field” beat across multiple systems.
Build implications
- Wide-magnet builds trade slot economy for passive throughput. The XP enters the player at the same rate as any other build (the merge passes and per-orb cap mean orb count, not orb count × magnet area, gates throughput), but the player can ignore positioning for orb pickup almost entirely.
- Narrow-magnet builds force the player to drive over kills, which has a positioning cost in dense waves but leaves more upgrade slots for damage and survival modifiers.
- Magnet-pickup synergies (Scrap Pile pulse, boss-death vacuum) are unaffected by
magnetRange; they always pull every orb on the map. A run with zero Magnet modifier ranks still gets the full benefit of a magnet pickup.
See also
- XP orb mechanics — the full per-frame orb pipeline including merge passes and the per-orb XP cap.
- The Magnet modifier entry in
data/modifiers.tsfor the exact effect schema and rank progression. CFG.MAGNET_SPEEDinengine/core/config/_gameplay.tsfor the global pull-speed tuning lever.