|
21 | 21 | dog: Object.freeze({ active: 'HAPPY STATIC. WARM TRAIL. GOOD TRAIL.', complete: 'FACTORY GOOD. YOU GOOD.' }), |
22 | 22 | }); |
23 | 23 |
|
24 | | - return Object.freeze({ SIGNAL_FRAGMENTS, NPC_DIALOGUE }); |
| 24 | + const LEVELS = Object.freeze([ |
| 25 | + Object.freeze({ |
| 26 | + id: 'river-factory', |
| 27 | + number: 1, |
| 28 | + name: 'RIVER FACTORY', |
| 29 | + mode: 'scan', |
| 30 | + seed: 77, |
| 31 | + spawn: Object.freeze({ x: 4, y: 6, facing: 'south' }), |
| 32 | + objectiveLabel: 'SIGNALS', |
| 33 | + completeLabel: 'FACTORY ONLINE', |
| 34 | + briefing: 'Three signal carriers are dark. Explore the river factory, scan for their locations, and recover all three.', |
| 35 | + objectives: SIGNAL_FRAGMENTS, |
| 36 | + gates: Object.freeze([]), |
| 37 | + sign: Object.freeze({ x: 2, y: 3, width: 6, active: 'ROBOTS', complete: 'ONLINE' }), |
| 38 | + npcs: Object.freeze([ |
| 39 | + Object.freeze({ type: 'worker', x: 3, y: 4, facing: 'south', label: 'UNIT-47' }), |
| 40 | + Object.freeze({ type: 'worker', x: 6, y: 4, facing: 'east', label: 'UNIT-12' }), |
| 41 | + Object.freeze({ type: 'scout', x: 8, y: 8, facing: 'south', label: 'RECON-3', patrol: Object.freeze([{x:8,y:8,f:'south'},{x:12,y:8,f:'east'},{x:12,y:6,f:'north'},{x:8,y:6,f:'west'}]) }), |
| 42 | + Object.freeze({ type: 'elder', x: 5, y: 3, facing: 'south', label: 'OVERSEER' }), |
| 43 | + Object.freeze({ type: 'farmer', x: 3, y: 14, facing: 'south', label: 'OLD DALE' }), |
| 44 | + Object.freeze({ type: 'mechanic', x: 9, y: 5, facing: 'north', label: 'SPARKS' }), |
| 45 | + Object.freeze({ type: 'child', x: 6, y: 12, facing: 'south', label: 'LIL BIT' }), |
| 46 | + Object.freeze({ type: 'dog', x: 7, y: 11, facing: 'east', label: 'GOOD BOY' }), |
| 47 | + ]), |
| 48 | + }), |
| 49 | + Object.freeze({ |
| 50 | + id: 'flooded-relay', |
| 51 | + number: 2, |
| 52 | + name: 'FLOODED RELAY', |
| 53 | + mode: 'gates', |
| 54 | + spawn: Object.freeze({ x: 3, y: 10, facing: 'east' }), |
| 55 | + objectiveLabel: 'RELAYS', |
| 56 | + completeLabel: 'CURRENT ROUTED', |
| 57 | + briefing: 'The relay platforms are isolated. Activate each control bank to open the next floodgate and route current across the water.', |
| 58 | + objectives: Object.freeze([ |
| 59 | + Object.freeze({ id: 'intake-relay', name: 'INTAKE RELAY', x: 5, y: 6, visible: true }), |
| 60 | + Object.freeze({ id: 'spillway-relay', name: 'SPILLWAY RELAY', x: 12, y: 14, visible: true }), |
| 61 | + Object.freeze({ id: 'tower-relay', name: 'TOWER RELAY', x: 20, y: 6, visible: true }), |
| 62 | + ]), |
| 63 | + gates: Object.freeze([ |
| 64 | + Object.freeze({ x: 8, y: 10, after: 'intake-relay' }), |
| 65 | + Object.freeze({ x: 16, y: 10, after: 'spillway-relay' }), |
| 66 | + ]), |
| 67 | + sign: Object.freeze({ x: 9, y: 7, width: 7, active: 'RELAY', complete: 'ROUTED' }), |
| 68 | + npcs: Object.freeze([ |
| 69 | + Object.freeze({ type: 'mechanic', x: 3, y: 6, facing: 'east', label: 'VALVE' }), |
| 70 | + Object.freeze({ type: 'worker', x: 11, y: 5, facing: 'south', label: 'PUMP-8' }), |
| 71 | + Object.freeze({ type: 'scout', x: 18, y: 13, facing: 'north', label: 'WADER', patrol: Object.freeze([{x:18,y:13,f:'north'},{x:21,y:13,f:'east'},{x:21,y:9,f:'north'},{x:18,y:9,f:'west'}]) }), |
| 72 | + ]), |
| 73 | + }), |
| 74 | + Object.freeze({ |
| 75 | + id: 'overgrown-archive', |
| 76 | + number: 3, |
| 77 | + name: 'OVERGROWN ARCHIVE', |
| 78 | + mode: 'sequence', |
| 79 | + seed: 191, |
| 80 | + spawn: Object.freeze({ x: 3, y: 10, facing: 'north' }), |
| 81 | + objectiveLabel: 'MEMORY', |
| 82 | + completeLabel: 'ARCHIVE AWAKE', |
| 83 | + briefing: 'The archive terminals answer only in sequence. Speak with its residents, follow the current clue, and wake all three memories.', |
| 84 | + objectives: Object.freeze([ |
| 85 | + Object.freeze({ id: 'root-index', name: 'ROOT INDEX', x: 4, y: 5, visible: true, clue: 'WEST WING · ABOVE THE OLD STONE' }), |
| 86 | + Object.freeze({ id: 'moss-ledger', name: 'MOSS LEDGER', x: 12, y: 6, visible: true, clue: 'CENTRAL COURT · NORTH OF THE BROKEN WALL' }), |
| 87 | + Object.freeze({ id: 'canopy-memory', name: 'CANOPY MEMORY', x: 20, y: 15, visible: true, clue: 'EAST GROVE · BELOW THE LAST ARCH' }), |
| 88 | + ]), |
| 89 | + gates: Object.freeze([]), |
| 90 | + sign: Object.freeze({ x: 9, y: 9, width: 7, active: 'ARCHIVE', complete: 'AWAKE' }), |
| 91 | + npcs: Object.freeze([ |
| 92 | + Object.freeze({ type: 'elder', x: 5, y: 10, facing: 'west', label: 'CURATOR', clue: true }), |
| 93 | + Object.freeze({ type: 'farmer', x: 11, y: 12, facing: 'north', label: 'GROUNDSKEEP', clue: true }), |
| 94 | + Object.freeze({ type: 'scout', x: 19, y: 8, facing: 'south', label: 'INDEXER', clue: true, patrol: Object.freeze([{x:19,y:8,f:'south'},{x:21,y:8,f:'east'},{x:21,y:12,f:'south'},{x:19,y:12,f:'west'}]) }), |
| 95 | + ]), |
| 96 | + }), |
| 97 | + ]); |
| 98 | + |
| 99 | + const LEVEL_IDS = Object.freeze(LEVELS.map(level => level.id)); |
| 100 | + |
| 101 | + function getLevel(levelId) { |
| 102 | + return LEVELS.find(level => level.id === levelId) || LEVELS[0]; |
| 103 | + } |
| 104 | + |
| 105 | + return Object.freeze({ SIGNAL_FRAGMENTS, NPC_DIALOGUE, LEVELS, LEVEL_IDS, getLevel }); |
25 | 106 | }); |
0 commit comments