A dark, mysterious five-act ARG built around hidden archives and forgotten witnesses.

Commit 58283b6a

58283b6a8b63Merged

Fenria-Aspen <[email protected]> · 1 month ago · 1 file · +1 added

Description

Add comprehensive game state management system

Details

Commit
58283b6a8b63
Parent
4ed257bbb2d7

assets/js/state.jsaddedView file

1+// Game state management system
2+
3+const GameState = {
4+ // Core progression
5+ currentAct: 0,
6+ currentPage: 'landing',
7+ completedActs: new Set(),
8+
9+ // Player inventory
10+ inventory: {
11+ items: new Map(),
12+ totalItems: 0
13+ },
14+
15+ // Evidence collected
16+ evidence: {
17+ documents: new Map(),
18+ audioLogs: new Map(),
19+ photographs: new Map(),
20+ connections: [] // Links between evidence pieces
21+ },
22+
23+ // Decrypted messages
24+ decrypted: new Map(),
25+
26+ // Puzzles solved
27+ solvedPuzzles: new Set(),
28+ attemptedPuzzles: new Map(), // Track wrong answers
29+
30+ // Discovered locations/sections
31+ unlockedSections: new Set(['landing', 'act1']),
32+ discoveredSecrets: new Set(),
33+
34+ // Time tracking
35+ startTime: null,
36+ sessionTime: 0,
37+
38+ // Endings discovered
39+ endingsFound: new Set(),
40+
41+ // Initialize state from localStorage
42+ init() {
43+ const saved = localStorage.getItem('hollow-archive-state');
44+ if (saved) {
45+ try {
46+ const data = JSON.parse(saved);
47+ Object.assign(this, data);
48+ this.completedActs = new Set(data.completedActs || []);
49+ this.solvedPuzzles = new Set(data.solvedPuzzles || []);
50+ this.unlockedSections = new Set(data.unlockedSections || ['landing', 'act1']);
51+ this.discoveredSecrets = new Set(data.discoveredSecrets || []);
52+ this.endingsFound = new Set(data.endingsFound || []);
53+ this.inventory.items = new Map(data.inventory?.items || []);
54+ this.evidence.documents = new Map(data.evidence?.documents || []);
55+ this.evidence.audioLogs = new Map(data.evidence?.audioLogs || []);
56+ this.evidence.photographs = new Map(data.evidence?.photographs || []);
57+ this.decrypted = new Map(data.decrypted || []);
58+ } catch (e) {
59+ console.warn('Failed to load saved state:', e);
60+ }
61+ }
62+ this.startTime = this.startTime || Date.now();
63+ },
64+
65+ // Save state to localStorage
66+ save() {
67+ const data = {
68+ currentAct: this.currentAct,
69+ currentPage: this.currentPage,
70+ completedActs: Array.from(this.completedActs),
71+ solvedPuzzles: Array.from(this.solvedPuzzles),
72+ unlockedSections: Array.from(this.unlockedSections),
73+ discoveredSecrets: Array.from(this.discoveredSecrets),
74+ endingsFound: Array.from(this.endingsFound),
75+ inventory: {
76+ items: Array.from(this.inventory.items),
77+ totalItems: this.inventory.totalItems
78+ },
79+ evidence: {
80+ documents: Array.from(this.evidence.documents),
81+ audioLogs: Array.from(this.evidence.audioLogs),
82+ photographs: Array.from(this.evidence.photographs),
83+ connections: this.evidence.connections
84+ },
85+ decrypted: Array.from(this.decrypted),
86+ startTime: this.startTime
87+ };
88+ localStorage.setItem('hollow-archive-state', JSON.stringify(data));
89+ },
90+
91+ // Add item to inventory
92+ addItem(id, item) {
93+ this.inventory.items.set(id, {
94+ ...item,
95+ acquiredAt: Date.now()
96+ });
97+ this.inventory.totalItems++;
98+ this.save();
99+ },
100+
101+ // Add evidence
102+ addEvidence(id, evidence, type = 'documents') {
103+ this.evidence[type].set(id, {
104+ ...evidence,
105+ discoveredAt: Date.now()
106+ });
107+ this.save();
108+ },
109+
110+ // Link evidence together
111+ linkEvidence(id1, id2, description) {
112+ this.evidence.connections.push({
113+ id1, id2, description,
114+ linkedAt: Date.now()
115+ });
116+ this.save();
117+ },
118+
119+ // Mark puzzle as solved
120+ solvePuzzle(puzzleId) {
121+ this.solvedPuzzles.add(puzzleId);
122+ this.save();
123+ },
124+
125+ // Record wrong attempt
126+ recordAttempt(puzzleId, answer) {
127+ if (!this.attemptedPuzzles.has(puzzleId)) {
128+ this.attemptedPuzzles.set(puzzleId, []);
129+ }
130+ this.attemptedPuzzles.get(puzzleId).push({
131+ answer,
132+ timestamp: Date.now()
133+ });
134+ },
135+
136+ // Unlock new section
137+ unlockSection(sectionId) {
138+ this.unlockedSections.add(sectionId);
139+ this.save();
140+ },
141+
142+ // Discover secret
143+ discoverSecret(secretId) {
144+ this.discoveredSecrets.add(secretId);
145+ this.save();
146+ },
147+
148+ // Record ending
149+ recordEnding(endingId) {
150+ this.endingsFound.add(endingId);
151+ this.save();
152+ },
153+
154+ // Get game completion percentage
155+ getCompletion() {
156+ const maxActs = 5;
157+ const maxSecrets = 12;
158+ const maxEndings = 3;
159+ const totalMax = maxActs + maxSecrets + maxEndings;
160+
161+ const currentTotal = this.completedActs.size + this.discoveredSecrets.size + this.endingsFound.size;
162+ return Math.round((currentTotal / totalMax) * 100);
163+ },
164+
165+ // Reset game
166+ reset() {
167+ if (confirm('Reset all progress? This cannot be undone.')) {
168+ localStorage.removeItem('hollow-archive-state');
169+ location.reload();
170+ }
171+ }
172+};
173+
174+// Initialize on load
175+document.addEventListener('DOMContentLoaded', () => {
176+ GameState.init();
177+});