orbit/data/gates.json

61 lines
9.3 KiB
JSON
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"_comment": "JUMP GATES — the galaxy's highway layer (js/galaxy/JumpNetwork.js for the network, js/galaxy/SystemGenerator.js → layoutGates for the in-system placement). NETWORK: every system holds between minGates and maxGates jump gates; every gate jumps to one of the system's `neighborPool` nearest stars on the 2-D map (the roster's x/y plane). The network is a degree-limited spanning tree of that neighbor graph (tree edges run BOTH ways); `shortcuts` is OFF — no mesh, no one-way links, no closed loops: the tree has EXACTLY ONE route between any two systems, so the galaxy reads as a MAZE of dead ends and long hauls. Strong connectivity still holds by construction (a bidirected tree — from any star you can reach any other, no closed systems, no trapped sets), and every jump is to a nearby star with a RETURN gate (the destination's gate pointing back — the player can always jump back the way they came). No system ever holds more than maxGates gates. A BARREN system (objectCount → 0, no planets/stations) is a DEAD-END LEAF of the tree — exactly one gate, in and out the same way (JumpNetwork takes the barren set from the per-system composition roll and never lets a barren node adopt children; the repair pass prefers non-barren attach targets). PLACEMENT (anchored systems): each gate sits within `anchorTetherLevel` tether range of an ANCHOR — a PLANET, or the home world in the starting system — EXACTLY that range from it (the radius comes from data/tether.json — level 1 = 5120 px), so the player can reach it on a starting tether from that world; the tether rule is hard by construction. Free-space stations are deliberately NOT anchors: the build console lives on a WORLD, so every gate must be tether-reachable from a planet the player can build and expand out from (the composition roll demotes a station to a planet when a system's budget would otherwise run out, guaranteeing the anchor exists). Candidates are tried in facing quality (ray-circle intersection → circle point aimed at the star → ±75° scan) so each gate is on the target side of its anchor (within 90° of the system→star bearing) — the direction rule is soft, so a gate reads as 'facing that star' without the exact ray always being free. PLACEMENT (barren systems — no anchor, data/systems.json → objectCount.barren): the single gate sits ON the ray from the center toward its destination, `barrenDistance` px out (stepped outward within the minRadius..maxRadius band if the gap forces it), facing its destination; its payload is 12 asteroid clusters drifting inside the gate's level-1 tether (data/asteroids.json → barren). ACTIVITY: every gate record carries `active` (DEFAULT FALSE — the activation mechanic is future work). When a gate is activated, a level-1 tether (5120 px, data/tether.json) attaches to it: an active gate is a TETHER ANCHOR in its own right. In a barren system that tether is the player's entire room to move (the player arrives AT the gate — the center is empty: the star is invisible flavor, never rendered); in an anchored system it simply adds another anchor circle. A gate keeps `size` + `clearance` (px, center-to-center) from any solid disc (planets + free-space stations + the home world), 2·size + `gateGap` from any other gate, and stays between `minRadius` and `maxRadius` from the center. size = the gate's keepout radius (px). shipClearance = the ship's keepout from the gate (the solid rule, like planets). theme.color = the HUD/compass color (an inactive gate renders dimmed). typeLabel = the discovery/compass label. texture/frameWidth/frameHeight = the spritesheet (assets/images/jumpgate.png, 256×256 frames): frame 0 = the gate body (ring + pylons, drawn static), frame 1 = the active swirl (see swirl); sprite scale = (size×2)/frameWidth puts the ring's outer edge on the keepout disc. A missing sheet falls back to the built-in procedural gate (console note).",
"enabled": true,
"minGates": 1,
"maxGates": 3,
"neighborPool": 8,
"shortcuts": false,
"size": 96,
"texture": "assets/images/jumpgate.png",
"frameWidth": 256,
"frameHeight": 256,
"shipClearance": 50,
"clearance": 256,
"gateGap": 192,
"minRadius": 2048,
"maxRadius": 20480,
"anchorTetherLevel": 1,
"barrenDistance": 8192,
"typeLabel": "Jump Gate",
"theme": { "color": "#5fd4ff" },
"swirl": {
"_comment": "ACTIVE-GATE SWIRL — frame 1 of `texture` (the swirling energy disc that fills the gate's mouth). Shown only when the gate is active (activation below): it spins slowly CLOCKWISE at spinSpeed (rad/s — one revolution every 2π/spinSpeed s) and its alpha breathes between alphaMin and alphaMax, one breath cycle every 2π/breathRate s. Dormant gates show only frame 0 — the body is always drawn at full alpha, and the swirl's absence is the 'this one is live' tell.",
"spinSpeed": 0.3,
"alphaMin": 0.6,
"alphaMax": 0.9,
"breathRate": 1.8
},
"activation": {
"_comment": "ACTIVATION (the SYSTEM research category — js/research/SystemCategory.js builds the per-system tree from this): '{system} Map' is granted the moment the player is in the system (duration 0 — 'starting'), and 'Unlock {system} Jumpgates' (researchDuration, in research.timeUnit seconds) becomes researchable once EVERY NAV point of the system is discovered (the central body, all planets, all space stations, all jump gates — the scene's discoverable set minus the asteroid clusters; data/game.json → discovery.distance). Completing it activates the system's gates AND the return gates in the systems they connect to — and per the ACTIVITY rule above, each activated gate anchors a level-`tetherLevel` tether at its own position (a TETHER ANCHOR in its own right; that tether saves/restores with the run's tether list). The label/description copy is templated: `{system}` is replaced with the system name.",
"researchDuration": 45,
"tetherLevel": 1,
"mapTech": {
"label": "{system} Map",
"description": "Added the Solar System of {system} to the onboard NAV System. Discover all NAV points to unlock the system Jumpgates."
},
"gatesTech": {
"label": "Unlock {system} Jumpgates",
"description": "With system NAV data complete, we have enough information to plot courses through this system's jumpgates."
}
},
"jump": {
"_comment": "THE JUMP (GameScene.jumpThroughGate): CLICK FLOW — a click on ANY gate opens the GATE COMM WINDOW (GameScene.openGateCommsPanel → the shared comms panel, js/ui/CommsPanel.js, in its gate variant: the LINK line reads ACTIVE/DORMANT, CANCEL just closes it) and REQUEST JUMP — a grayed ghost while the gate is dormant or with `enabled` off — transports the run to the connected system; the save pipeline in miniature (captureState → swap in the destination system + arrival position → prepareLoad → scene restart), so discovery/research/builds/minerals/playtime/activatedGates all carry over. ARRIVAL: the ship materialises near the destination's RETURN gate — the gate in the destination whose destination is the system just left (returnGateFor, js/galaxy/JumpTravel.js) — offset back along its facing (the gate faces the star we came from) by radius + shipClearance + ship radius + `arrivalGap`, i.e. just clear of its keepout, inside its activated-gate tether (per ACTIVITY above). One-way SHORTCUT jumps have no return gate (JumpNetwork: tree edges run both ways, shortcuts don't) — those land on the destination's star (its home-tether origin). The jump plays a full-screen one-shot clip (`video`, cover-scaled over the theme background) between the two systems — the destination is already staged behind it, so the scene restarts the moment the clip ends (or errors, or stalls); `videoVolume` is 0..1 (0 = silent). A DOUBLE-CLICK (two quick presses) skips the rest of the clip, same as the landing/takeoff clips. If `video` is empty/missing the jump falls back to the short `jumpDelayMs` cut. `enabled` is the feature switch; dormantToast is the dormant-state copy (dev/jump-travel.test.mjs pins its {system} placeholder); the toasts are templated ({dest}/{system}).",
"enabled": true,
"arrivalGap": 128,
"video": "assets/videos/jump.mp4",
"videoVolume": 1,
"jumpDelayMs": 420,
"toast": "JUMP — {dest}",
"dormantToast": "JUMP GATE DORMANT — CHART {system} TO ACTIVATE ITS JUMP GATES",
"miningToast": "CANNOT JUMP WHILE MINING"
},
"route": {
"_comment": "ROUTE (js/galaxy/Route.js + GameScene): the player's plotted course to a SET DESTINATION (SYSTEM tab of the MAP console). The run persists only the destination (systemId + objectId); the path from the current system is derived (planRoute — the jump network is a spanning tree, so it is the unique route). While a route is active, the compass shows its NEXT point — the current system's jump gate toward the destination — in ORANGE (compassColor), replacing that gate's ordinary cyan arrow; the gate is shown even while still UNDISCOVERED (it is the thing to find). On arrival at the destination the route clears (reachedToast); a jump to any other system re-plots from the detour (replotToast). setToast fires when the destination is set ({dest}/{hops}).",
"compassColor": "#ff8c1a",
"typeLabel": "Route Gate",
"setToast": "DESTINATION SET — {dest} · {hops} HOP(S)",
"reachedToast": "DESTINATION REACHED — {dest}",
"replotToast": "ROUTE RE-PLOTTED — {hops} HOP(S) TO {dest}"
}
}