Tune jumpgate activation research duration to 20 s
- Reduce data/gates.json activation.researchDuration from 45 s to 20 s so the "Unlock Jumpgates" tech completes faster once all NAV points are discovered. - Update SystemCategory.js doc comment and fallback default to match the new duration. - Adjust system-category.test.mjs assertions (duration, save/restore remaining-time math) to the 20 s value.
This commit is contained in:
parent
20d8fcb0ef
commit
6ecf199da5
|
|
@ -36,7 +36,7 @@
|
|||
},
|
||||
"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 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 map label/description copy is templated: `{system}` is replaced with the system name. The gates tech's label is FIXED (no `{system}`) — the console's node button is too narrow for the system name; the map tech carries it.",
|
||||
"researchDuration": 45,
|
||||
"researchDuration": 20,
|
||||
"tetherLevel": 1,
|
||||
"mapTech": {
|
||||
"label": "{system} Map",
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* SYSTEM tab — categories flagged `dynamic` in research.json, built at
|
||||
* runtime by js/research/SystemCategory.js; copy + duration in
|
||||
* data/gates.json → activation):
|
||||
* - config: the activation section (45 s research, the two tech's
|
||||
* - config: the activation section (20 s research, the two tech's
|
||||
* label/description templates with their `{system}` placeholder);
|
||||
* - buildSystemTree: the tree contract (ids embed the system id, the
|
||||
* map tech granted on entry, the jumpgate tech gated by the chart),
|
||||
|
|
@ -44,7 +44,7 @@ const research = read('research.json');
|
|||
check('gates: activation section present', !!gates.activation && typeof gates.activation === 'object');
|
||||
check('gates: researchDuration is a positive number (seconds — research.timeUnit)',
|
||||
typeof gates.activation?.researchDuration === 'number' && gates.activation.researchDuration > 0);
|
||||
check('gates: the 45 s brief duration', gates.activation?.researchDuration === 45);
|
||||
check('gates: the 20 s brief duration', gates.activation?.researchDuration === 20);
|
||||
check('gates: tetherLevel ≥ 1 (an activated gate anchors a tether — ACTIVITY)',
|
||||
Number.isInteger(gates.activation?.tetherLevel) && gates.activation.tetherLevel >= 1);
|
||||
check('gates: mapTech label template names the system',
|
||||
|
|
@ -106,8 +106,8 @@ check('tree: map tech — icon from the procedural glyph roster', map.icon === '
|
|||
check('tree: gates tech — the brief label + copy',
|
||||
gNode.label === 'Unlock Jumpgates' &&
|
||||
gNode.description === "With system NAV data complete, we have enough information to plot courses through this system's jumpgates.");
|
||||
check('tree: gates tech — 45 s, requires the map, the activation effect',
|
||||
gNode.duration === 45 && JSON.stringify(gNode.requires) === JSON.stringify([mapId]) && gNode.effects?.activateGates === true);
|
||||
check('tree: gates tech — 20 s, requires the map, the activation effect',
|
||||
gNode.duration === 20 && JSON.stringify(gNode.requires) === JSON.stringify([mapId]) && gNode.effects?.activateGates === true);
|
||||
check('tree: map tech declares the gates tech in its unlocks', JSON.stringify(map.unlocks?.research ?? []) === JSON.stringify([gatesId]));
|
||||
|
||||
check('tree: issues(tree) is clean', Array.isArray(issues(tree)) && issues(tree).length === 0);
|
||||
|
|
@ -132,16 +132,16 @@ chartComplete = true;
|
|||
check('hooks: chart complete → the gates tech is researchable', isAvailable(tree, state, gatesId));
|
||||
|
||||
// -- the full run: one project at a time, save/restore -------------------
|
||||
state.start(SYSTEM_CATEGORY, gatesId, 45_000, 0);
|
||||
state.start(SYSTEM_CATEGORY, gatesId, 20_000, 0);
|
||||
check('run: the in-flight project is the gates tech', state.getActive()?.id === gatesId);
|
||||
check('run: a second project is refused (one at a time)', state.start(SYSTEM_CATEGORY, gatesId, 1000, 0) === false);
|
||||
const saved = state.toJSON(20_000); // saved 20 s into the 45 s project
|
||||
const saved = state.toJSON(8_000); // saved 8 s into the 20 s project
|
||||
const restored = new ResearchState();
|
||||
for (const k of saved.unlocked) restored.unlock(...k.split('::'));
|
||||
restored.restoreActive(saved.active, 900_000); // reloaded later
|
||||
check('run: save carries the remaining time (45 s − 20 s = 25 s)', saved.active?.remainingMs === 25_000);
|
||||
check('run: restore keeps the project in flight (25 s left)',
|
||||
restored.getActive()?.id === gatesId && restored.progress(900_000).fraction < 1 && restored.progress(925_000).fraction >= 1);
|
||||
check('run: save carries the remaining time (20 s − 8 s = 12 s)', saved.active?.remainingMs === 12_000);
|
||||
check('run: restore keeps the project in flight (12 s left)',
|
||||
restored.getActive()?.id === gatesId && restored.progress(900_000).fraction < 1 && restored.progress(912_000).fraction >= 1);
|
||||
|
||||
// -- the chart gate: NAV points + completion ------------------------------
|
||||
// A NON-home system (no homeName — its center is empty, the star is
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
* └ "Unlock Jumpgates" requires the map + EVERY NAV
|
||||
* point of the system discovered
|
||||
* (the availability hook below);
|
||||
* 45 s (data/gates.json →
|
||||
* 20 s (data/gates.json →
|
||||
* activation.researchDuration);
|
||||
* completing it activates the
|
||||
* system's gates AND the return
|
||||
|
|
@ -122,7 +122,7 @@ export function buildSystemTree(o = {}) {
|
|||
const systemName = String(o.systemName ?? systemId);
|
||||
const mapId = systemNodeId(systemId, MAP_NODE);
|
||||
const gatesId = systemNodeId(systemId, GATES_NODE);
|
||||
const duration = Math.max(0, Number(config.get('gates.activation.researchDuration', 45)) || 0);
|
||||
const duration = Math.max(0, Number(config.get('gates.activation.researchDuration', 20)) || 0);
|
||||
const isComplete = typeof o.isComplete === 'function' ? o.isComplete : () => false;
|
||||
|
||||
// No system name — the detail panel has room, the node button doesn't:
|
||||
|
|
|
|||
Loading…
Reference in New Issue