towmasjan commited on
Commit
b70affe
·
verified ·
1 Parent(s): 77179e0

Upload folder using huggingface_hub

Browse files
Files changed (1) hide show
  1. index.html +920 -19
index.html CHANGED
@@ -1,19 +1,920 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <title>SIN CITY 3000 - RPG</title>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Share+Tech+Mono&display=swap"
10
+ rel="stylesheet">
11
+ <style>
12
+ :root {
13
+ --neon-pink: #ff2a6d;
14
+ --neon-blue: #05d9e8;
15
+ --neon-green: #00ff9d;
16
+ --neon-yellow: #f9c80e;
17
+ --bg-dark: #01012b;
18
+ --bg-panel: #020238;
19
+ --text-main: #d1f7ff;
20
+ --glass: rgba(5, 217, 232, 0.1);
21
+ --border-glow: 0 0 10px var(--neon-blue);
22
+ }
23
+
24
+ * {
25
+ box-sizing: border-box;
26
+ margin: 0;
27
+ padding: 0;
28
+ scrollbar-width: thin;
29
+ scrollbar-color: var(--neon-blue) var(--bg-dark);
30
+ }
31
+
32
+ body {
33
+ background-color: #000;
34
+ background-image:
35
+ radial-gradient(circle at 50% 50%, #1a1a40 0%, #000 100%),
36
+ linear-gradient(0deg, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0) 50%, rgba(0, 0, 0, 0.9) 100%);
37
+ color: var(--text-main);
38
+ font-family: 'Share Tech Mono', monospace;
39
+ height: 100vh;
40
+ overflow: hidden;
41
+ display: flex;
42
+ flex-direction: column;
43
+ position: relative;
44
+ }
45
+
46
+ /* CRT Overlay Effect */
47
+ body::after {
48
+ content: " ";
49
+ display: block;
50
+ position: absolute;
51
+ top: 0;
52
+ left: 0;
53
+ bottom: 0;
54
+ right: 0;
55
+ background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));
56
+ z-index: 100;
57
+ background-size: 100% 2px, 3px 100%;
58
+ pointer-events: none;
59
+ }
60
+
61
+ /* Header */
62
+ header {
63
+ display: flex;
64
+ justify-content: space-between;
65
+ align-items: center;
66
+ padding: 1rem 2rem;
67
+ border-bottom: 2px solid var(--neon-pink);
68
+ background: rgba(0, 0, 0, 0.8);
69
+ z-index: 10;
70
+ box-shadow: 0 0 20px rgba(255, 42, 109, 0.3);
71
+ }
72
+
73
+ .brand {
74
+ font-family: 'Orbitron', sans-serif;
75
+ font-size: 1.8rem;
76
+ font-weight: 900;
77
+ color: var(--neon-pink);
78
+ text-transform: uppercase;
79
+ letter-spacing: 3px;
80
+ text-shadow: 2px 2px 0px var(--neon-blue);
81
+ animation: glitch 3s infinite;
82
+ }
83
+
84
+ .anycoder-link {
85
+ font-family: 'Orbitron', sans-serif;
86
+ color: var(--neon-green);
87
+ text-decoration: none;
88
+ font-size: 0.9rem;
89
+ border: 1px solid var(--neon-green);
90
+ padding: 0.5rem 1rem;
91
+ transition: all 0.3s ease;
92
+ text-transform: uppercase;
93
+ }
94
+
95
+ .anycoder-link:hover {
96
+ background: var(--neon-green);
97
+ color: #000;
98
+ box-shadow: 0 0 15px var(--neon-green);
99
+ }
100
+
101
+ /* Main Layout */
102
+ main {
103
+ flex: 1;
104
+ display: grid;
105
+ grid-template-columns: 300px 1fr 300px;
106
+ gap: 1rem;
107
+ padding: 1rem;
108
+ max-width: 1600px;
109
+ margin: 0 auto;
110
+ width: 100%;
111
+ position: relative;
112
+ z-index: 5;
113
+ }
114
+
115
+ /* Panels */
116
+ .panel {
117
+ background: var(--bg-panel);
118
+ border: 1px solid var(--neon-blue);
119
+ padding: 1rem;
120
+ position: relative;
121
+ box-shadow: inset 0 0 20px rgba(5, 217, 232, 0.1);
122
+ display: flex;
123
+ flex-direction: column;
124
+ }
125
+
126
+ .panel::before {
127
+ content: '';
128
+ position: absolute;
129
+ top: -2px;
130
+ left: -2px;
131
+ right: -2px;
132
+ bottom: -2px;
133
+ background: linear-gradient(45deg, var(--neon-pink), transparent, var(--neon-blue));
134
+ z-index: -1;
135
+ opacity: 0.3;
136
+ }
137
+
138
+ .panel-header {
139
+ font-family: 'Orbitron', sans-serif;
140
+ color: var(--neon-blue);
141
+ border-bottom: 1px solid var(--neon-blue);
142
+ padding-bottom: 0.5rem;
143
+ margin-bottom: 1rem;
144
+ text-transform: uppercase;
145
+ font-size: 1.2rem;
146
+ display: flex;
147
+ justify-content: space-between;
148
+ align-items: center;
149
+ }
150
+
151
+ /* Left Panel: Stats */
152
+ .stat-row {
153
+ display: flex;
154
+ justify-content: space-between;
155
+ align-items: center;
156
+ margin-bottom: 1rem;
157
+ font-size: 1.1rem;
158
+ }
159
+
160
+ .stat-label {
161
+ color: var(--neon-green);
162
+ }
163
+
164
+ .stat-value {
165
+ color: #fff;
166
+ font-weight: bold;
167
+ }
168
+
169
+ .health-bar-container {
170
+ width: 100%;
171
+ height: 10px;
172
+ background: #333;
173
+ margin-top: 5px;
174
+ border: 1px solid #555;
175
+ }
176
+
177
+ .health-bar-fill {
178
+ height: 100%;
179
+ background: var(--neon-pink);
180
+ width: 100%;
181
+ transition: width 0.3s ease;
182
+ box-shadow: 0 0 10px var(--neon-pink);
183
+ }
184
+
185
+ .inventory-list {
186
+ list-style: none;
187
+ margin-top: 1rem;
188
+ flex: 1;
189
+ overflow-y: auto;
190
+ }
191
+
192
+ .inventory-item {
193
+ padding: 0.5rem;
194
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
195
+ display: flex;
196
+ align-items: center;
197
+ gap: 10px;
198
+ }
199
+
200
+ .inventory-item i {
201
+ color: var(--neon-yellow);
202
+ }
203
+
204
+ /* Center Panel: Game Log / Scene */
205
+ .scene-display {
206
+ flex: 1;
207
+ overflow-y: auto;
208
+ margin-bottom: 1rem;
209
+ padding-right: 10px;
210
+ font-size: 1.1rem;
211
+ line-height: 1.6;
212
+ }
213
+
214
+ .log-entry {
215
+ margin-bottom: 1.5rem;
216
+ animation: fadeIn 0.5s ease;
217
+ }
218
+
219
+ .log-entry.system {
220
+ color: var(--neon-green);
221
+ font-style: italic;
222
+ border-left: 3px solid var(--neon-green);
223
+ padding-left: 10px;
224
+ }
225
+
226
+ .log-entry.danger {
227
+ color: var(--neon-pink);
228
+ border-left: 3px solid var(--neon-pink);
229
+ padding-left: 10px;
230
+ }
231
+
232
+ .log-entry.narrative {
233
+ color: var(--text-main);
234
+ }
235
+
236
+ .typing-cursor::after {
237
+ content: '█';
238
+ animation: blink 1s infinite;
239
+ color: var(--neon-blue);
240
+ margin-left: 5px;
241
+ }
242
+
243
+ /* Action Area */
244
+ .actions-grid {
245
+ display: grid;
246
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
247
+ gap: 1rem;
248
+ margin-top: auto;
249
+ }
250
+
251
+ .action-btn {
252
+ background: transparent;
253
+ border: 1px solid var(--neon-blue);
254
+ color: var(--neon-blue);
255
+ padding: 1rem;
256
+ font-family: 'Orbitron', sans-serif;
257
+ font-size: 1rem;
258
+ cursor: pointer;
259
+ transition: all 0.2s;
260
+ text-transform: uppercase;
261
+ position: relative;
262
+ overflow: hidden;
263
+ }
264
+
265
+ .action-btn:hover {
266
+ background: var(--neon-blue);
267
+ color: #000;
268
+ box-shadow: 0 0 20px var(--neon-blue);
269
+ }
270
+
271
+ .action-btn:disabled {
272
+ border-color: #555;
273
+ color: #555;
274
+ cursor: not-allowed;
275
+ box-shadow: none;
276
+ }
277
+
278
+ /* Right Panel: Visuals/Data */
279
+ .visual-feed {
280
+ height: 200px;
281
+ border: 1px solid var(--neon-pink);
282
+ margin-bottom: 1rem;
283
+ background: #000;
284
+ display: flex;
285
+ align-items: center;
286
+ justify-content: center;
287
+ overflow: hidden;
288
+ position: relative;
289
+ }
290
+
291
+ .visual-icon {
292
+ font-size: 5rem;
293
+ color: var(--neon-pink);
294
+ animation: pulse 2s infinite;
295
+ z-index: 2;
296
+ }
297
+
298
+ .grid-bg {
299
+ position: absolute;
300
+ width: 200%;
301
+ height: 200%;
302
+ background-image:
303
+ linear-gradient(var(--glass) 1px, transparent 1px),
304
+ linear-gradient(90deg, var(--glass) 1px, transparent 1px);
305
+ background-size: 20px 20px;
306
+ transform: perspective(500px) rotateX(60deg) translateY(-100px) translateZ(-200px);
307
+ animation: gridMove 20s linear infinite;
308
+ }
309
+
310
+ .status-log {
311
+ font-size: 0.8rem;
312
+ color: #888;
313
+ font-family: monospace;
314
+ }
315
+
316
+ .status-line {
317
+ margin-bottom: 4px;
318
+ }
319
+
320
+ /* Animations */
321
+ @keyframes glitch {
322
+ 0% {
323
+ text-shadow: 2px 2px 0px var(--neon-blue);
324
+ transform: translate(0);
325
+ }
326
+
327
+ 20% {
328
+ text-shadow: -2px -2px 0px var(--neon-pink);
329
+ transform: translate(-2px, 2px);
330
+ }
331
+
332
+ 40% {
333
+ text-shadow: 2px -2px 0px var(--neon-green);
334
+ transform: translate(2px, -2px);
335
+ }
336
+
337
+ 60% {
338
+ text-shadow: -2px 2px 0px var(--neon-blue);
339
+ transform: translate(-2px, 2px);
340
+ }
341
+
342
+ 80% {
343
+ text-shadow: 2px 2px 0px var(--neon-pink);
344
+ transform: translate(2px, -2px);
345
+ }
346
+
347
+ 100% {
348
+ text-shadow: 2px 2px 0px var(--neon-blue);
349
+ transform: translate(0);
350
+ }
351
+ }
352
+
353
+ @keyframes blink {
354
+
355
+ 0%,
356
+ 100% {
357
+ opacity: 1;
358
+ }
359
+
360
+ 50% {
361
+ opacity: 0;
362
+ }
363
+ }
364
+
365
+ @keyframes fadeIn {
366
+ from {
367
+ opacity: 0;
368
+ transform: translateY(10px);
369
+ }
370
+
371
+ to {
372
+ opacity: 1;
373
+ transform: translateY(0);
374
+ }
375
+ }
376
+
377
+ @keyframes pulse {
378
+ 0% {
379
+ transform: scale(1);
380
+ text-shadow: 0 0 10px var(--neon-pink);
381
+ }
382
+
383
+ 50% {
384
+ transform: scale(1.1);
385
+ text-shadow: 0 0 30px var(--neon-pink);
386
+ }
387
+
388
+ 100% {
389
+ transform: scale(1);
390
+ text-shadow: 0 0 10px var(--neon-pink);
391
+ }
392
+ }
393
+
394
+ @keyframes gridMove {
395
+ 0% {
396
+ transform: perspective(500px) rotateX(60deg) translateY(0) translateZ(-200px);
397
+ }
398
+
399
+ 100% {
400
+ transform: perspective(500px) rotateX(60deg) translateY(100px) translateZ(-200px);
401
+ }
402
+ }
403
+
404
+ /* Responsive */
405
+ @media (max-width: 1024px) {
406
+ main {
407
+ grid-template-columns: 1fr;
408
+ grid-template-rows: auto 1fr auto;
409
+ height: auto;
410
+ overflow-y: auto;
411
+ }
412
+
413
+ body {
414
+ overflow: auto;
415
+ height: auto;
416
+ }
417
+
418
+ .visual-feed {
419
+ display: none;
420
+ }
421
+
422
+ /* Hide visual on mobile to save space */
423
+ .panel {
424
+ min-height: 300px;
425
+ }
426
+
427
+ .panel:first-child {
428
+ order: 2;
429
+ }
430
+
431
+ .panel:nth-child(2) {
432
+ order: 1;
433
+ min-height: 50vh;
434
+ }
435
+
436
+ .panel:last-child {
437
+ order: 3;
438
+ }
439
+ }
440
+ </style>
441
+ </head>
442
+
443
+ <body>
444
+
445
+ <header>
446
+ <div class="brand"><i class="fa-solid fa-city"></i> Sin City 3000</div>
447
+ <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with
448
+ anycoder</a>
449
+ </header>
450
+
451
+ <main>
452
+ <!-- Left Panel: Character Stats -->
453
+ <aside class="panel">
454
+ <div class="panel-header">
455
+ <span><i class="fa-solid fa-user-astronaut"></i> Status</span>
456
+ <span id="player-class">Mercenary</span>
457
+ </div>
458
+
459
+ <div class="stat-row">
460
+ <span class="stat-label">HP</span>
461
+ <div style="flex:1; margin-left: 10px; text-align: right;">
462
+ <span id="hp-val" class="stat-value">100/100</span>
463
+ <div class="health-bar-container">
464
+ <div id="hp-bar" class="health-bar-fill"></div>
465
+ </div>
466
+ </div>
467
+ </div>
468
+
469
+ <div class="stat-row">
470
+ <span class="stat-label">Credits</span>
471
+ <span class="stat-value" style="color: var(--neon-yellow);">¥ <span id="credits-val">50</span></span>
472
+ </div>
473
+
474
+ <div class="stat-row">
475
+ <span class="stat-label">Street Cred</span>
476
+ <span class="stat-value" style="color: var(--neon-pink);"><span id="rep-val">0</span></span>
477
+ </div>
478
+
479
+ <div class="panel-header" style="margin-top: 1rem;">
480
+ <span><i class="fa-solid fa-microchip"></i> Inventory</span>
481
+ </div>
482
+ <ul class="inventory-list" id="inventory-list">
483
+ <!-- Items injected here -->
484
+ </ul>
485
+ </aside>
486
+
487
+ <!-- Center Panel: Narrative -->
488
+ <section class="panel">
489
+ <div class="panel-header">
490
+ <span><i class="fa-solid fa-terminal"></i> Neural Link</span>
491
+ <span style="font-size: 0.8rem; opacity: 0.7;">V.3.0.1 connected</span>
492
+ </div>
493
+
494
+ <div class="scene-display" id="game-log">
495
+ <!-- Game text goes here -->
496
+ </div>
497
+
498
+ <div class="actions-grid" id="actions-container">
499
+ <!-- Buttons injected here -->
500
+ </div>
501
+ </section>
502
+
503
+ <!-- Right Panel: World Data -->
504
+ <aside class="panel">
505
+ <div class="panel-header">
506
+ <span><i class="fa-solid fa-satellite-dish"></i> Environment</span>
507
+ </div>
508
+
509
+ <div class="visual-feed">
510
+ <div class="grid-bg"></div>
511
+ <i id="scene-icon" class="fa-solid fa-biohazard visual-icon"></i>
512
+ </div>
513
+
514
+ <div class="panel-header" style="font-size: 1rem;">System Log</div>
515
+ <div class="status-log" id="system-log">
516
+ <div class="status-line">> Initializing biosystems... OK</div>
517
+ <div class="status-line">> Connecting to CityNet... OK</div>
518
+ <div class="status-line">> Location detected: Sector 7 Slums</div>
519
+ <div class="status-line">> Weather: Acid Rain</div>
520
+ </div>
521
+ </aside>
522
+ </main>
523
+
524
+ <script>
525
+ // --- Game State ---
526
+ const gameState = {
527
+ hp: 100,
528
+ maxHp: 100,
529
+ credits: 100,
530
+ rep: 10,
531
+ inventory: ['Data Deck', 'Stimpak'],
532
+ flags: {}, // For story tracking
533
+ currentScene: 'start'
534
+ };
535
+
536
+ // --- Story Data ---
537
+ const scenes = {
538
+ 'start': {
539
+ text: "You wake up face down in a puddle of neon-reflecting sludge. Your head is throbbing—a side effect of the cheap neural implant you installed last night. The alleyway smells of ozone and rotting synth-meat. Sirens wail in the distance, growing louder. You need to move.",
540
+ icon: "fa-skull",
541
+ choices: [
542
+ { text: "Check pockets & run", action: 'flee_alley' },
543
+ { text: "Hide in the dumpster", action: 'hide_dumpster' },
544
+ { text: "Scan for network signals", action: 'scan_network', req: { item: 'Data Deck' } }
545
+ ]
546
+ },
547
+ 'flee_alley': {
548
+ text: "You scramble to your feet and sprint towards the main street. A flying patrol drone sweeps a red laser across the spot you just left. Close call. You emerge into the neon chaos of Sector 7 Market. Hawkers are selling everything from illegal memory chips to synthetic organs.",
549
+ icon: "fa-person-running",
550
+ choices: [
551
+ { text: "Visit the Ripperdoc", action: 'ripperdoc' },
552
+ { text: "Enter the 'Binary Bar'", action: 'bar' },
553
+ { text: "Look for a job board", action: 'job_board' }
554
+ ]
555
+ },
556
+ 'hide_dumpster': {
557
+ text: "You dive into the trash. It's gross, but effective. Two NCPD officers run past, weapons drawn. Once they're gone, you climb out. You find a discarded energy cell in the trash.",
558
+ icon: "fa-trash-can",
559
+ effect: () => { addItem('Energy Cell'); },
560
+ choices: [
561
+ { text: "Go to the Market", action: 'flee_alley' }
562
+ ]
563
+ },
564
+ 'scan_network': {
565
+ text: "You jack into a loose cable hanging from the wall. Your vision floods with green code. You intercept a police dispatch: 'Suspect heading to Sector 7'. You also manage to siphon a few credits from an unsecured vending machine nearby.",
566
+ icon: "fa-wifi",
567
+ effect: () => { addCredits(50); addRep(5); },
568
+ choices: [
569
+ { text: "Disconnect & Run", action: 'flee_alley' }
570
+ ]
571
+ },
572
+ 'ripperdoc': {
573
+ text: "Dr. Chrome's clinic is a blood-stained basement. He looks at you with cybernetic eyes that zoom in and out. 'You look like slag, kid. Need a tune-up? Or maybe something... lethal?'",
574
+ icon: "fa-user-doctor",
575
+ choices: [
576
+ { text: "Heal (50 Credits)", action: 'heal', cost: 50 },
577
+ { text: "Buy Combat Chip (200 Credits)", action: 'buy_chip', cost: 200 },
578
+ { text: "Leave", action: 'hub_return' }
579
+ ]
580
+ },
581
+ 'bar': {
582
+ text: "The Binary Bar is loud. Bass thumps in your chest. A holographic dancer flickers on the stage. A shady fixer in the corner signals you over.",
583
+ icon: "fa-martini-glass-citrus",
584
+ choices: [
585
+ { text: "Talk to the Fixer", action: 'talk_fixer' },
586
+ { text: "Buy a drink (10 Credits)", action: 'buy_drink', cost: 10 },
587
+ { text: "Leave", action: 'hub_return' }
588
+ ]
589
+ },
590
+ 'talk_fixer': {
591
+ text: "'Name's Vex. I got a job. A corpo courier is passing through the lower levels. Intercept him, get the package. Pays 500. Interested?'",
592
+ icon: "fa-user-secret",
593
+ choices: [
594
+ { text: "Accept Job", action: 'mission_courier' },
595
+ { text: "Refuse", action: 'hub_return' }
596
+ ]
597
+ },
598
+ 'mission_courier': {
599
+ text: "You ambush the courier in a transit tunnel. He draws a pistol. Combat initiated!",
600
+ icon: "fa-gun",
601
+ type: 'combat',
602
+ enemy: { name: 'Corpo Courier', hp: 30, damage: 10 },
603
+ choices: [
604
+ { text: "Attack with Fists", action: 'combat_attack' },
605
+ { text: "Use Stimpak", action: 'combat_heal', req: { item: 'Stimpak' } },
606
+ { text: "Hack his gun", action: 'combat_hack', req: { item: 'Data Deck' } }
607
+ ]
608
+ },
609
+ 'job_board': {
610
+ text: "The digital board flickers. Most jobs are trash collection or organ harvesting. One stands out: 'Beta Tester needed for experimental reflex booster. High risk.'",
611
+ icon: "fa-clipboard-list",
612
+ choices: [
613
+ { text: "Take the risk", action: 'experiment' },
614
+ { text: "Back to Market", action: 'hub_return' }
615
+ ]
616
+ },
617
+ 'experiment': {
618
+ text: "You plug into the test terminal. A surge of electricity fries your nerves but rewires your reflexes. You take 20 damage but gain Street Cred.",
619
+ icon: "fa-bolt",
620
+ effect: () => { takeDamage(20); addRep(20); },
621
+ choices: [
622
+ { text: "Stumble away", action: 'hub_return' }
623
+ ]
624
+ },
625
+ 'hub_return': {
626
+ text: "You are back in the center of Sector 7 Market. The neon lights buzz overhead.",
627
+ icon: "fa-store",
628
+ choices: [
629
+ { text: "Visit Ripperdoc", action: 'ripperdoc' },
630
+ { text: "Visit Bar", action: 'bar' },
631
+ { text: "Job Board", action: 'job_board' }
632
+ ]
633
+ },
634
+ 'game_over': {
635
+ text: "CRITICAL SYSTEM FAILURE. Your vitals have ceased. Your story ends here in the gutter of Sin City 3000.",
636
+ icon: "fa-skull-crossbones",
637
+ choices: [
638
+ { text: "Reboot System", action: 'restart' }
639
+ ]
640
+ },
641
+ 'combat_win': {
642
+ text: "The courier drops. You grab the package. It's heavy. Inside is a prototype chip. You wire Vex, and the credits transfer instantly.",
643
+ icon: "fa-trophy",
644
+ effect: () => { addCredits(500); addRep(50); addItem('Proto-Chip'); },
645
+ choices: [
646
+ { text: "Return to Market", action: 'hub_return' }
647
+ ]
648
+ }
649
+ };
650
+
651
+ // --- Engine Functions ---
652
+
653
+ function initGame() {
654
+ updateHUD();
655
+ renderScene('start');
656
+ logSystem("System initialized. User: Guest.");
657
+ }
658
+
659
+ function updateHUD() {
660
+ // Stats
661
+ document.getElementById('hp-val').innerText = `${gameState.hp}/${gameState.maxHp}`;
662
+ document.getElementById('hp-bar').style.width = `${(gameState.hp / gameState.maxHp) * 100}%`;
663
+ document.getElementById('credits-val').innerText = gameState.credits;
664
+ document.getElementById('rep-val').innerText = gameState.rep;
665
+
666
+ // Inventory
667
+ const invList = document.getElementById('inventory-list');
668
+ invList.innerHTML = '';
669
+ if(gameState.inventory.length === 0) {
670
+ invList.innerHTML = '<li class="inventory-item" style="opacity:0.5">Empty</li>';
671
+ } else {
672
+ gameState.inventory.forEach(item => {
673
+ const li = document.createElement('li');
674
+ li.className = 'inventory-item';
675
+ let icon = 'fa-box';
676
+ if(item === 'Data Deck') icon = 'fa-laptop-code';
677
+ if(item === 'Stimpak') icon = 'fa-syringe';
678
+ if(item === 'Energy Cell') icon = 'fa-battery-full';
679
+ li.innerHTML = `<i class="fa-solid ${icon}"></i> ${item}`;
680
+ invList.appendChild(li);
681
+ });
682
+ }
683
+ }
684
+
685
+ function logSystem(msg) {
686
+ const log = document.getElementById('system-log');
687
+ const div = document.createElement('div');
688
+ div.className = 'status-line';
689
+ div.innerText = `> ${msg}`;
690
+ log.prepend(div);
691
+ if(log.children.length > 6) log.lastChild.remove();
692
+ }
693
+
694
+ function addItem(item) {
695
+ if(!gameState.inventory.includes(item)) {
696
+ gameState.inventory.push(item);
697
+ logText(`System: Acquired [${item}]`, 'system');
698
+ updateHUD();
699
+ }
700
+ }
701
+
702
+ function removeItem(item) {
703
+ const index = gameState.inventory.indexOf(item);
704
+ if (index > -1) {
705
+ gameState.inventory.splice(index, 1);
706
+ updateHUD();
707
+ }
708
+ }
709
+
710
+ function addCredits(amount) {
711
+ gameState.credits += amount;
712
+ logText(`System: Transfer received ¥${amount}`, 'system');
713
+ updateHUD();
714
+ }
715
+
716
+ function addRep(amount) {
717
+ gameState.rep += amount;
718
+ logText(`System: Street Cred increased +${amount}`, 'system');
719
+ updateHUD();
720
+ }
721
+
722
+ function takeDamage(amount) {
723
+ gameState.hp -= amount;
724
+ if(gameState.hp <= 0) {
725
+ gameState.hp = 0;
726
+ renderScene('game_over');
727
+ }
728
+ updateHUD();
729
+ // Flash red
730
+ document.body.style.boxShadow = "inset 0 0 50px red";
731
+ setTimeout(() => document.body.style.boxShadow = "none", 200);
732
+ }
733
+
734
+ function heal(amount) {
735
+ gameState.hp = Math.min(gameState.maxHp, gameState.hp + amount);
736
+ updateHUD();
737
+ }
738
+
739
+ // --- Rendering ---
740
+
741
+ function logText(text, type = 'narrative') {
742
+ const display = document.getElementById('game-log');
743
+ const div = document.createElement('div');
744
+ div.className = `log-entry ${type}`;
745
+
746
+ if(type === 'narrative') {
747
+ div.classList.add('typing-cursor');
748
+ // Typewriter effect
749
+ let i = 0;
750
+ const speed = 20;
751
+ function typeWriter() {
752
+ if (i < text.length) {
753
+ div.textContent += text.charAt(i);
754
+ i++;
755
+ display.scrollTop = display.scrollHeight; // Auto scroll
756
+ setTimeout(typeWriter, speed);
757
+ } else {
758
+ div.classList.remove('typing-cursor');
759
+ }
760
+ }
761
+ display.appendChild(div);
762
+ typeWriter();
763
+ } else {
764
+ div.textContent = text;
765
+ display.appendChild(div);
766
+ display.scrollTop = display.scrollHeight;
767
+ }
768
+ }
769
+
770
+ function renderScene(sceneKey) {
771
+ const scene = scenes[sceneKey];
772
+ gameState.currentScene = sceneKey;
773
+
774
+ // Update visual
775
+ const iconElement = document.getElementById('scene-icon');
776
+ iconElement.className = `fa-solid ${scene.icon || 'fa-circle-question'} visual-icon`;
777
+
778
+ // Execute effects if any
779
+ if(scene.effect) {
780
+ scene.effect();
781
+ // If effect killed player, stop here
782
+ if(gameState.hp <= 0) return;
783
+ }
784
+
785
+ // Log text
786
+ logText(scene.text);
787
+
788
+ // Render Buttons
789
+ const actionsContainer = document.getElementById('actions-container');
790
+ actionsContainer.innerHTML = '';
791
+
792
+ if (scene.type === 'combat') {
793
+ handleCombat(scene);
794
+ return;
795
+ }
796
+
797
+ scene.choices.forEach(choice => {
798
+ const btn = document.createElement('button');
799
+ btn.className = 'action-btn';
800
+
801
+ let label = choice.text;
802
+ let disabled = false;
803
+
804
+ // Check requirements
805
+ if(choice.req) {
806
+ if(choice.req.item && !gameState.inventory.includes(choice.req.item)) {
807
+ disabled = true;
808
+ label += ` [Req: ${choice.req.item}]`;
809
+ }
810
+ }
811
+ // Check costs
812
+ if(choice.cost) {
813
+ if(gameState.credits < choice.cost) {
814
+ disabled = true;
815
+ }
816
+ }
817
+
818
+ btn.innerText = label;
819
+ btn.disabled = disabled;
820
+
821
+ btn.onclick = () => {
822
+ if(choice.cost) addCredits(-choice.cost);
823
+ if(choice.action === 'restart') {
824
+ location.reload();
825
+ } else {
826
+ renderScene(choice.action);
827
+ }
828
+ };
829
+ actionsContainer.appendChild(btn);
830
+ });
831
+ }
832
+
833
+ // Simple Combat Logic
834
+ let currentEnemy = null;
835
+
836
+ function handleCombat(scene) {
837
+ currentEnemy = { ...scene.enemy }; // Clone enemy
838
+ const actionsContainer = document.getElementById('actions-container');
839
+
840
+ // Create attack buttons dynamically based on loop
841
+ renderCombatButtons(scene);
842
+ }
843
+
844
+ function renderCombatButtons(scene) {
845
+ const actionsContainer = document.getElementById('actions-container');
846
+ actionsContainer.innerHTML = '';
847
+
848
+ scene.choices.forEach(choice => {
849
+ const btn = document.createElement('button');
850
+ btn.className = 'action-btn';
851
+
852
+ let label = choice.text;
853
+ let disabled = false;
854
+
855
+ if(choice.req && choice.req.item && !gameState.inventory.includes(choice.req.item)) {
856
+ disabled = true;
857
+ label += ` [Missing: ${choice.req.item}]`;
858
+ }
859
+
860
+ btn.innerText = label;
861
+ btn.disabled = disabled;
862
+
863
+ btn.onclick = () => {
864
+ combatRound(choice.action, scene);
865
+ };
866
+
867
+ actionsContainer.appendChild(btn);
868
+ });
869
+ }
870
+
871
+ function combatRound(action, scene) {
872
+ // Player Turn
873
+ let playerDmg = 0;
874
+ let logMsg = "";
875
+
876
+ if(action === 'combat_attack') {
877
+ playerDmg = Math.floor(Math.random() * 10) + 5;
878
+ logMsg = `You punch the enemy for ${playerDmg} damage!`;
879
+ } else if (action === 'combat_heal') {
880
+ heal(30);
881
+ removeItem('Stimpak');
882
+ logMsg = "You injected a Stimpak. +30 HP.";
883
+ } else if (action === 'combat_hack') {
884
+ playerDmg = 20;
885
+ logMsg = "Hack successful! Weapon backfire caused 20 damage.";
886
+ }
887
+
888
+ if(playerDmg > 0) {
889
+ currentEnemy.hp -= playerDmg;
890
+ logText(logMsg, 'danger');
891
+ } else {
892
+ logText(logMsg, 'system');
893
+ }
894
+
895
+ // Check Enemy Death
896
+ if(currentEnemy.hp <= 0) {
897
+ logText("Enemy defeated!", 'system');
898
+ setTimeout(() => renderScene('combat_win'), 1000);
899
+ return;
900
+ }
901
+
902
+ // Enemy Turn
903
+ setTimeout(() => {
904
+ const enemyDmg = Math.floor(Math.random() * currentEnemy.damage);
905
+ takeDamage(enemyDmg);
906
+ logText(`${currentEnemy.name} hits you for ${enemyDmg} damage!`, 'danger');
907
+
908
+ if(gameState.hp > 0) {
909
+ renderCombatButtons(scene); // Refresh buttons
910
+ }
911
+ }, 800);
912
+ }
913
+
914
+ // Boot
915
+ window.onload = initGame;
916
+
917
+ </script>
918
+ </body>
919
+
920
+ </html>