lunarflu HF Staff commited on
Commit
737539c
·
verified ·
1 Parent(s): 5763680

Add 1 files

Browse files
Files changed (1) hide show
  1. index.html +507 -1081
index.html CHANGED
@@ -3,421 +3,225 @@
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Monstergirl RPG Adventure</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
  <style>
10
- @keyframes fadeIn {
11
- from { opacity: 0; }
12
- to { opacity: 1; }
 
13
  }
14
- @keyframes pulse {
15
- 0% { transform: scale(1); }
16
- 50% { transform: scale(1.05); }
17
- 100% { transform: scale(1); }
18
  }
19
- .fade-in {
20
- animation: fadeIn 0.5s ease-in-out;
21
- }
22
- .pulse {
23
- animation: pulse 1.5s infinite;
24
- }
25
- .health-bar {
26
- transition: width 0.3s ease;
27
- }
28
- .damage-text {
29
- position: absolute;
30
- color: red;
31
- font-weight: bold;
32
- animation: floatUp 1s forwards;
33
- }
34
- @keyframes floatUp {
35
- 0% { transform: translateY(0); opacity: 1; }
36
- 100% { transform: translateY(-50px); opacity: 0; }
37
- }
38
- .game-container {
39
- background-image: url('https://images.unsplash.com/photo-1542273917363-3b1817f69a2d?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80');
40
  background-size: cover;
41
  background-position: center;
42
  }
43
- .dialog-box {
44
- background-color: rgba(0, 0, 0, 0.8);
45
- border: 2px solid gold;
46
- border-radius: 10px;
47
- }
48
  .character-card {
49
  transition: all 0.3s ease;
 
50
  }
51
  .character-card:hover {
52
- transform: translateY(-5px);
53
- box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
 
 
 
 
 
 
 
 
 
 
 
 
 
54
  }
55
- .monstergirl-img {
56
- width: 120px;
57
- height: 120px;
58
- object-fit: cover;
59
- border-radius: 50%;
60
- border: 3px solid #f472b6;
61
- box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
62
  }
63
  </style>
64
  </head>
65
- <body class="bg-gray-900 text-white font-sans">
66
- <div class="game-container min-h-screen flex flex-col items-center justify-center p-4">
67
- <!-- Main Menu -->
68
- <div id="main-menu" class="text-center fade-in">
69
- <h1 class="text-6xl font-bold mb-8 text-pink-400">Monstergirl RPG</h1>
70
- <div class="space-y-4">
71
- <button onclick="startNewGame()" class="bg-pink-600 hover:bg-pink-700 text-white font-bold py-3 px-6 rounded-lg text-xl w-64 transition-all hover:scale-105">
72
- <i class="fas fa-heart mr-2"></i> New Game
73
- </button>
74
- <button onclick="loadGame()" class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-6 rounded-lg text-xl w-64 transition-all hover:scale-105">
75
- <i class="fas fa-folder-open mr-2"></i> Load Game
76
- </button>
77
- <button onclick="showCredits()" class="bg-indigo-600 hover:bg-indigo-700 text-white font-bold py-3 px-6 rounded-lg text-xl w-64 transition-all hover:scale-105">
78
- <i class="fas fa-info-circle mr-2"></i> Credits
79
- </button>
80
- </div>
81
- </div>
82
-
83
- <!-- Character Creation -->
84
- <div id="character-creation" class="hidden text-center w-full max-w-4xl">
85
- <h2 class="text-4xl font-bold mb-8 text-pink-400">Create Your Hero</h2>
86
-
87
- <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
88
- <!-- Warrior -->
89
- <div class="character-card bg-gray-800 p-6 rounded-lg cursor-pointer" onclick="selectClass('warrior')">
90
- <div class="text-5xl mb-4 text-red-500">
91
- <i class="fas fa-shield-alt"></i>
92
- </div>
93
- <h3 class="text-2xl font-bold mb-2">Warrior</h3>
94
- <p class="text-gray-300 mb-4">Strong and resilient, excels in melee combat</p>
95
- <div class="text-left">
96
- <p><i class="fas fa-heart text-red-500 mr-2"></i> High Health</p>
97
- <p><i class="fas fa-fist-raised text-orange-500 mr-2"></i> Strong Attacks</p>
98
- <p><i class="fas fa-running text-blue-500 mr-2"></i> Low Speed</p>
99
- </div>
100
  </div>
101
-
102
- <!-- Mage -->
103
- <div class="character-card bg-gray-800 p-6 rounded-lg cursor-pointer" onclick="selectClass('mage')">
104
- <div class="text-5xl mb-4 text-blue-500">
105
- <i class="fas fa-hat-wizard"></i>
106
- </div>
107
- <h3 class="text-2xl font-bold mb-2">Mage</h3>
108
- <p class="text-gray-300 mb-4">Master of arcane arts, powerful spells</p>
109
- <div class="text-left">
110
- <p><i class="fas fa-bolt text-yellow-500 mr-2"></i> High Magic</p>
111
- <p><i class="fas fa-heart text-red-500 mr-2"></i> Low Health</p>
112
- <p><i class="fas fa-brain text-purple-500 mr-2"></i> Smart</p>
113
- </div>
114
- </div>
115
-
116
- <!-- Rogue -->
117
- <div class="character-card bg-gray-800 p-6 rounded-lg cursor-pointer" onclick="selectClass('rogue')">
118
- <div class="text-5xl mb-4 text-green-500">
119
- <i class="fas fa-user-ninja"></i>
120
  </div>
121
- <h3 class="text-2xl font-bold mb-2">Rogue</h3>
122
- <p class="text-gray-300 mb-4">Stealthy and quick, deadly with daggers</p>
123
- <div class="text-left">
124
- <p><i class="fas fa-tachometer-alt text-green-500 mr-2"></i> High Speed</p>
125
- <p><i class="fas fa-heart text-red-500 mr-2"></i> Medium Health</p>
126
- <p><i class="fas fa-eye-slash text-gray-500 mr-2"></i> Sneaky</p>
127
  </div>
128
  </div>
129
- </div>
130
-
131
- <div class="bg-gray-800 p-6 rounded-lg mb-6">
132
- <h3 class="text-2xl font-bold mb-4">Character Details</h3>
133
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
134
- <div>
135
- <label class="block text-left mb-2">Name:</label>
136
- <input type="text" id="character-name" class="w-full p-2 rounded bg-gray-700 border border-gray-600" placeholder="Enter your name">
137
  </div>
138
- <div>
139
- <label class="block text-left mb-2">Gender:</label>
140
- <select id="character-gender" class="w-full p-2 rounded bg-gray-700 border border-gray-600">
141
- <option value="male">Male</option>
142
- <option value="female">Female</option>
143
- <option value="other">Other</option>
144
- </select>
145
  </div>
146
  </div>
147
  </div>
148
-
149
- <button onclick="finalizeCharacter()" class="bg-pink-600 hover:bg-pink-700 text-white font-bold py-3 px-8 rounded-lg text-xl transition-all hover:scale-105">
150
- <i class="fas fa-heart mr-2"></i> Begin Adventure
151
- </button>
152
- </div>
153
 
154
- <!-- Game Screen -->
155
- <div id="game-screen" class="hidden w-full max-w-6xl">
156
- <div class="flex flex-col md:flex-row gap-6">
157
- <!-- Character Panel -->
158
- <div class="bg-gray-800 bg-opacity-90 rounded-lg p-4 w-full md:w-1/4">
159
- <h3 class="text-xl font-bold mb-4 border-b pb-2">Hero</h3>
160
- <div class="text-center mb-4">
161
- <div class="text-6xl mb-2" id="character-icon">
162
- <i class="fas fa-user"></i>
163
- </div>
164
- <h4 class="text-2xl font-bold" id="character-display-name">Unknown</h4>
165
- <p class="text-gray-300" id="character-display-class">Class: None</p>
166
- </div>
167
-
168
- <div class="mb-4">
169
- <div class="flex justify-between mb-1">
170
- <span>Health</span>
171
- <span id="health-text">100/100</span>
172
- </div>
173
- <div class="w-full bg-gray-700 rounded-full h-4">
174
- <div id="health-bar" class="health-bar bg-red-500 h-4 rounded-full" style="width: 100%"></div>
175
  </div>
176
  </div>
177
-
178
- <div class="mb-4">
179
- <div class="flex justify-between mb-1">
180
- <span>Mana</span>
181
- <span id="mana-text">50/50</span>
182
- </div>
183
- <div class="w-full bg-gray-700 rounded-full h-4">
184
- <div id="mana-bar" class="health-bar bg-blue-500 h-4 rounded-full" style="width: 100%"></div>
185
- </div>
186
- </div>
187
-
188
- <div class="mb-4">
189
- <div class="flex justify-between mb-1">
190
- <span>Experience</span>
191
- <span id="exp-text">0/100</span>
192
- </div>
193
- <div class="w-full bg-gray-700 rounded-full h-4">
194
- <div id="exp-bar" class="health-bar bg-yellow-500 h-4 rounded-full" style="width: 0%"></div>
195
- </div>
196
- </div>
197
-
198
- <div class="grid grid-cols-2 gap-2 mb-4">
199
- <div class="bg-gray-700 p-2 rounded">
200
- <div class="text-sm text-gray-300">Level</div>
201
- <div class="font-bold" id="level-text">1</div>
202
- </div>
203
- <div class="bg-gray-700 p-2 rounded">
204
- <div class="text-sm text-gray-300">Gold</div>
205
- <div class="font-bold" id="gold-text">10</div>
206
- </div>
207
- <div class="bg-gray-700 p-2 rounded">
208
- <div class="text-sm text-gray-300">Attack</div>
209
- <div class="font-bold" id="attack-text">10</div>
210
- </div>
211
- <div class="bg-gray-700 p-2 rounded">
212
- <div class="text-sm text-gray-300">Defense</div>
213
- <div class="font-bold" id="defense-text">5</div>
214
- </div>
215
- </div>
216
-
217
- <button onclick="openInventory()" class="w-full bg-blue-600 hover:bg-blue-700 text-white py-2 rounded mb-2">
218
- <i class="fas fa-backpack mr-2"></i> Inventory
219
- </button>
220
- <button onclick="openQuests()" class="w-full bg-green-600 hover:bg-green-700 text-white py-2 rounded mb-2">
221
- <i class="fas fa-scroll mr-2"></i> Quests
222
- </button>
223
- <button onclick="saveGame()" class="w-full bg-purple-600 hover:bg-purple-700 text-white py-2 rounded">
224
- <i class="fas fa-save mr-2"></i> Save Game
225
- </button>
226
- </div>
227
 
228
- <!-- Main Game Area -->
229
- <div class="flex-1">
230
- <!-- Game Messages -->
231
- <div id="game-messages" class="bg-gray-800 bg-opacity-90 rounded-lg p-4 mb-4 h-40 overflow-y-auto">
232
- <p class="text-pink-300">Welcome to Monstergirl RPG!</p>
233
- <p>Create your character and begin your journey.</p>
234
- </div>
235
-
236
- <!-- Action Buttons -->
237
- <div class="grid grid-cols-2 gap-4 mb-6">
238
- <button onclick="explore()" class="bg-green-600 hover:bg-green-700 text-white font-bold py-3 px-4 rounded-lg transition-all hover:scale-105">
239
- <i class="fas fa-heart mr-2"></i> Meet Girls
240
- </button>
241
- <button onclick="rest()" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg transition-all hover:scale-105">
242
- <i class="fas fa-bed mr-2"></i> Rest
243
- </button>
244
- <button onclick="visitTown()" class="bg-yellow-600 hover:bg-yellow-700 text-white font-bold py-3 px-4 rounded-lg transition-all hover:scale-105">
245
- <i class="fas fa-city mr-2"></i> Visit Town
246
- </button>
247
- <button onclick="train()" class="bg-red-600 hover:bg-red-700 text-white font-bold py-3 px-4 rounded-lg transition-all hover:scale-105">
248
- <i class="fas fa-dumbbell mr-2"></i> Train
249
- </button>
250
- </div>
251
-
252
- <!-- Combat Area -->
253
- <div id="combat-area" class="hidden bg-gray-800 bg-opacity-90 rounded-lg p-6">
254
- <div class="flex flex-col md:flex-row justify-between items-center mb-8">
255
- <!-- Player -->
256
- <div class="text-center mb-6 md:mb-0 relative">
257
- <div class="text-6xl mb-2" id="player-combat-icon">
258
- <i class="fas fa-user"></i>
259
  </div>
260
- <h4 class="text-xl font-bold" id="player-combat-name">Hero</h4>
261
- <div class="w-full bg-gray-700 rounded-full h-3 mt-2">
262
- <div id="player-health-bar" class="health-bar bg-red-500 h-3 rounded-full" style="width: 100%"></div>
 
 
263
  </div>
264
- <div class="text-sm" id="player-health-text">100/100</div>
265
  </div>
266
-
267
- <!-- VS -->
268
- <div class="text-2xl font-bold mx-4 mb-6 md:mb-0">VS</div>
269
-
270
- <!-- Enemy -->
271
- <div class="text-center relative">
272
- <img id="enemy-image" src="" alt="Monstergirl" class="monstergirl-img mx-auto mb-2">
273
- <h4 class="text-xl font-bold" id="enemy-name">Goblin Girl</h4>
274
- <div class="w-full bg-gray-700 rounded-full h-3 mt-2">
275
- <div id="enemy-health-bar" class="health-bar bg-red-500 h-3 rounded-full" style="width: 100%"></div>
276
  </div>
277
- <div class="text-sm" id="enemy-health-text">30/30</div>
278
  </div>
279
- </div>
280
-
281
- <!-- Combat Actions -->
282
- <div id="combat-actions" class="grid grid-cols-2 gap-4">
283
- <button onclick="playerAttack()" class="bg-red-600 hover:bg-red-700 text-white font-bold py-3 px-4 rounded-lg">
284
- <i class="fas fa-heart-broken mr-2"></i> Attack
285
- </button>
286
- <button onclick="playerSpell()" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg">
287
- <i class="fas fa-magic mr-2"></i> Cast Spell
288
- </button>
289
- <button onclick="playerDefend()" class="bg-gray-600 hover:bg-gray-700 text-white font-bold py-3 px-4 rounded-lg">
290
- <i class="fas fa-shield-alt mr-2"></i> Defend
291
- </button>
292
- <button onclick="playerFlee()" class="bg-yellow-600 hover:bg-yellow-700 text-white font-bold py-3 px-4 rounded-lg">
293
- <i class="fas fa-running mr-2"></i> Flee
294
- </button>
295
- </div>
296
- </div>
297
-
298
- <!-- Town Area -->
299
- <div id="town-area" class="hidden bg-gray-800 bg-opacity-90 rounded-lg p-6">
300
- <h3 class="text-2xl font-bold mb-4">Town Square</h3>
301
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
302
- <button onclick="visitShop()" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded-lg">
303
- <i class="fas fa-shopping-cart mr-2"></i> Shop
304
- </button>
305
- <button onclick="visitTavern()" class="bg-yellow-600 hover:bg-yellow-700 text-white font-bold py-3 px-4 rounded-lg">
306
- <i class="fas fa-beer mr-2"></i> Tavern
307
- </button>
308
- <button onclick="visitGuild()" class="bg-purple-600 hover:bg-purple-700 text-white font-bold py-3 px-4 rounded-lg">
309
- <i class="fas fa-scroll mr-2"></i> Adventurer's Guild
310
- </button>
311
- <button onclick="leaveTown()" class="bg-gray-600 hover:bg-gray-700 text-white font-bold py-3 px-4 rounded-lg">
312
- <i class="fas fa-door-open mr-2"></i> Leave Town
313
- </button>
314
  </div>
315
  </div>
316
  </div>
317
- </div>
318
- </div>
319
 
320
- <!-- Inventory Modal -->
321
- <div id="inventory-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
322
- <div class="bg-gray-800 rounded-lg p-6 w-full max-w-2xl max-h-[80vh] overflow-y-auto">
323
- <div class="flex justify-between items-center mb-4">
324
- <h3 class="text-2xl font-bold">Inventory</h3>
325
- <button onclick="closeInventory()" class="text-gray-400 hover:text-white">
326
- <i class="fas fa-times"></i>
327
- </button>
328
- </div>
329
-
330
- <div class="grid grid-cols-2 md:grid-cols-4 gap-4 mb-6">
331
- <div class="bg-gray-700 p-4 rounded-lg text-center">
332
- <div class="text-3xl mb-2"><i class="fas fa-sword"></i></div>
333
- <div class="font-bold">Iron Sword</div>
334
- <div class="text-sm text-gray-300">Attack +5</div>
335
- <button class="mt-2 bg-blue-600 hover:bg-blue-700 text-white py-1 px-3 rounded text-sm">
336
- Equip
337
- </button>
338
- </div>
339
- <div class="bg-gray-700 p-4 rounded-lg text-center">
340
- <div class="text-3xl mb-2"><i class="fas fa-shield-alt"></i></div>
341
- <div class="font-bold">Wooden Shield</div>
342
- <div class="text-sm text-gray-300">Defense +3</div>
343
- <button class="mt-2 bg-blue-600 hover:bg-blue-700 text-white py-1 px-3 rounded text-sm">
344
- Equip
345
- </button>
346
- </div>
347
- <div class="bg-gray-700 p-4 rounded-lg text-center">
348
- <div class="text-3xl mb-2"><i class="fas fa-flask"></i></div>
349
- <div class="font-bold">Health Potion</div>
350
- <div class="text-sm text-gray-300">Restores 30 HP</div>
351
- <button class="mt-2 bg-green-600 hover:bg-green-700 text-white py-1 px-3 rounded text-sm">
352
- Use
353
- </button>
354
  </div>
355
- <div class="bg-gray-700 p-4 rounded-lg text-center">
356
- <div class="text-3xl mb-2"><i class="fas fa-flask"></i></div>
357
- <div class="font-bold">Mana Potion</div>
358
- <div class="text-sm text-gray-300">Restores 20 MP</div>
359
- <button class="mt-2 bg-green-600 hover:bg-green-700 text-white py-1 px-3 rounded text-sm">
360
- Use
361
- </button>
362
  </div>
363
  </div>
364
-
365
- <h4 class="text-xl font-bold mb-3">Equipped Items</h4>
366
- <div class="grid grid-cols-2 gap-4">
367
- <div class="bg-gray-700 p-3 rounded-lg">
368
- <div class="flex items-center">
369
- <div class="text-2xl mr-3"><i class="fas fa-sword"></i></div>
370
- <div>
371
- <div class="font-bold">Iron Sword</div>
372
- <div class="text-sm text-gray-300">Attack +5</div>
373
- </div>
 
 
 
374
  </div>
375
- </div>
376
- <div class="bg-gray-700 p-3 rounded-lg">
377
- <div class="flex items-center">
378
- <div class="text-2xl mr-3"><i class="fas fa-shield-alt"></i></div>
379
- <div>
380
- <div class="font-bold">Wooden Shield</div>
381
- <div class="text-sm text-gray-300">Defense +3</div>
382
- </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  </div>
384
  </div>
385
- </div>
386
- </div>
387
- </div>
388
 
389
- <!-- Credits Modal -->
390
- <div id="credits-modal" class="hidden fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
391
- <div class="bg-gray-800 rounded-lg p-6 w-full max-w-md">
392
- <div class="flex justify-between items-center mb-4">
393
- <h3 class="text-2xl font-bold">Credits</h3>
394
- <button onclick="hideCredits()" class="text-gray-400 hover:text-white">
395
- <i class="fas fa-times"></i>
396
- </button>
397
- </div>
398
-
399
- <div class="space-y-4">
400
- <div>
401
- <h4 class="text-xl font-bold text-pink-400">Monstergirl RPG</h4>
402
- <p class="text-gray-300">Created with HTML, CSS, and JavaScript</p>
403
- </div>
404
-
405
- <div>
406
- <h4 class="font-bold">Developer</h4>
407
- <p class="text-gray-300">Your Name Here</p>
408
- </div>
409
-
410
- <div>
411
- <h4 class="font-bold">Special Thanks</h4>
412
- <ul class="list-disc list-inside text-gray-300">
413
- <li>Tailwind CSS</li>
414
- <li>Font Awesome</li>
415
- <li>All the wonderful monstergirl artists</li>
416
- </ul>
417
- </div>
418
-
419
- <div class="pt-4 border-t border-gray-700">
420
- <p class="text-sm text-gray-400">© 2023 All Rights Reserved</p>
421
  </div>
422
  </div>
423
  </div>
@@ -427,767 +231,389 @@
427
  <script>
428
  // Game State
429
  const gameState = {
430
- player: {
431
- name: '',
432
- class: '',
433
- gender: '',
434
- level: 1,
435
- exp: 0,
436
- expToNextLevel: 100,
437
- health: 100,
438
- maxHealth: 100,
439
- mana: 50,
440
- maxMana: 50,
441
- attack: 10,
442
- defense: 5,
443
- gold: 10,
444
- inventory: [
445
- { name: 'Iron Sword', type: 'weapon', attack: 5, icon: 'fa-sword' },
446
- { name: 'Wooden Shield', type: 'shield', defense: 3, icon: 'fa-shield-alt' },
447
- { name: 'Health Potion', type: 'consumable', effect: 'heal', amount: 30, icon: 'fa-flask' },
448
- { name: 'Mana Potion', type: 'consumable', effect: 'mana', amount: 20, icon: 'fa-flask' }
449
- ],
450
- equipped: {
451
- weapon: { name: 'Iron Sword', type: 'weapon', attack: 5, icon: 'fa-sword' },
452
- shield: { name: 'Wooden Shield', type: 'shield', defense: 3, icon: 'fa-shield-alt' }
453
- }
454
  },
455
- currentEnemy: null,
456
- inCombat: false,
457
- gameMessages: []
 
458
  };
459
 
460
- // Cute Monstergirl Enemies with images
461
- const enemies = [
462
- {
463
- name: 'Goblin Girl',
464
- health: 30,
465
- maxHealth: 30,
466
- attack: 8,
467
- defense: 2,
468
- exp: 20,
469
- gold: 5,
470
- image: 'https://i.imgur.com/JK7Wf0x.jpg',
471
- description: 'A mischievous green-skinned girl with pointy ears and a playful attitude.'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472
  },
473
- {
474
- name: 'Catgirl',
475
- health: 25,
476
- maxHealth: 25,
477
- attack: 9,
478
- defense: 2,
479
- exp: 22,
480
- gold: 7,
481
- image: 'https://i.imgur.com/VQ5Zf3E.jpg',
482
- description: 'A feline-human hybrid with cute ears and tail who loves to play.'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
483
  },
484
- {
485
- name: 'Bunny Girl',
486
- health: 35,
487
- maxHealth: 35,
488
- attack: 7,
489
- defense: 3,
490
- exp: 25,
491
- gold: 8,
492
- image: 'https://i.imgur.com/8X9vY7H.jpg',
493
- description: 'A fluffy-eared girl who hops around with boundless energy.'
494
- },
495
- {
496
- name: 'Fox Girl',
497
- health: 28,
498
- maxHealth: 28,
499
- attack: 10,
500
- defense: 2,
501
- exp: 24,
502
- gold: 9,
503
- image: 'https://i.imgur.com/3RkLZ2t.jpg',
504
- description: 'A cunning kitsune with multiple tails and a playful trickster nature.'
505
- },
506
- {
507
- name: 'Slime Girl',
508
- health: 45,
509
- maxHealth: 45,
510
- attack: 6,
511
- defense: 6,
512
- exp: 28,
513
- gold: 10,
514
- image: 'https://i.imgur.com/qM9cB1P.jpg',
515
- description: 'A gelatinous girl who can change her shape at will, very squishy!'
516
- },
517
- {
518
- name: 'Dragon Girl',
519
- health: 60,
520
- maxHealth: 60,
521
- attack: 15,
522
- defense: 8,
523
- exp: 50,
524
- gold: 25,
525
- image: 'https://i.imgur.com/7wGpL0z.jpg',
526
- description: 'A powerful draconic beauty with scales, wings, and a fiery personality.'
527
- },
528
- {
529
- name: 'Wolf Girl',
530
- health: 40,
531
- maxHealth: 40,
532
- attack: 11,
533
- defense: 4,
534
- exp: 30,
535
- gold: 12,
536
- image: 'https://i.imgur.com/5tNf8Yq.jpg',
537
- description: 'A wild girl with wolf ears and tail, fiercely loyal to her pack.'
538
- },
539
- {
540
- name: 'Mermaid',
541
- health: 35,
542
- maxHealth: 35,
543
- attack: 8,
544
- defense: 5,
545
- exp: 26,
546
- gold: 15,
547
- image: 'https://i.imgur.com/9XvLQ2f.jpg',
548
- description: 'A beautiful sea maiden with a fish tail, sings enchanting melodies.'
549
- },
550
- {
551
- name: 'Angel',
552
- health: 50,
553
- maxHealth: 50,
554
- attack: 12,
555
- defense: 7,
556
- exp: 40,
557
- gold: 20,
558
- image: 'https://i.imgur.com/4kL9s2r.jpg',
559
- description: 'A celestial being with pure white wings and a divine presence.'
560
- },
561
- {
562
- name: 'Demon Girl',
563
- health: 45,
564
- maxHealth: 45,
565
- attack: 14,
566
- defense: 5,
567
- exp: 38,
568
- gold: 18,
569
- image: 'https://i.imgur.com/2sVp7Qk.jpg',
570
- description: 'A seductive temptress with horns and a tail, full of mischief.'
571
- },
572
- {
573
- name: 'Vampire Girl',
574
- health: 42,
575
- maxHealth: 42,
576
- attack: 13,
577
- defense: 6,
578
- exp: 35,
579
- gold: 22,
580
- image: 'https://i.imgur.com/1wX9vY7.jpg',
581
- description: 'An elegant nocturnal beauty with sharp fangs and a taste for blood.'
582
- },
583
- {
584
- name: 'Ghost Girl',
585
- health: 30,
586
- maxHealth: 30,
587
- attack: 9,
588
- defense: 8,
589
- exp: 25,
590
- gold: 10,
591
- image: 'https://i.imgur.com/3RtLZ2t.jpg',
592
- description: 'A translucent spirit girl who can phase through walls and objects.'
593
- },
594
- {
595
- name: 'Centaur Girl',
596
- health: 55,
597
- maxHealth: 55,
598
- attack: 12,
599
- defense: 9,
600
- exp: 45,
601
- gold: 25,
602
- image: 'https://i.imgur.com/7vGpL0z.jpg',
603
- description: 'A majestic half-human half-horse girl with incredible strength.'
604
- },
605
- {
606
- name: 'Lamia',
607
- health: 48,
608
- maxHealth: 48,
609
- attack: 13,
610
- defense: 7,
611
- exp: 42,
612
- gold: 20,
613
- image: 'https://i.imgur.com/5sNf8Yq.jpg',
614
- description: 'A serpentine beauty with a long snake tail, both alluring and dangerous.'
615
- },
616
- {
617
- name: 'Harpy',
618
- health: 38,
619
- maxHealth: 38,
620
- attack: 11,
621
- defense: 4,
622
- exp: 32,
623
- gold: 15,
624
- image: 'https://i.imgur.com/9YvLQ2f.jpg',
625
- description: 'A winged girl with talons who can soar through the skies.'
626
- }
627
- ];
628
-
629
- // Game Functions
630
- function startNewGame() {
631
- document.getElementById('main-menu').classList.add('hidden');
632
- document.getElementById('character-creation').classList.remove('hidden');
633
- addGameMessage('Begin your adventure by creating your character.');
634
- }
635
 
636
- function selectClass(characterClass) {
637
- const cards = document.querySelectorAll('.character-card');
638
- cards.forEach(card => card.classList.remove('ring-2', 'ring-pink-400'));
639
-
640
- const selectedCard = document.querySelector(`.character-card:nth-child(${characterClass === 'warrior' ? 1 : characterClass === 'mage' ? 2 : 3})`);
641
- selectedCard.classList.add('ring-2', 'ring-pink-400');
642
-
643
- gameState.player.class = characterClass;
644
-
645
- // Update stats based on class
646
- if (characterClass === 'warrior') {
647
- gameState.player.maxHealth = 120;
648
- gameState.player.health = 120;
649
- gameState.player.attack = 12;
650
- gameState.player.defense = 8;
651
- gameState.player.mana = 30;
652
- gameState.player.maxMana = 30;
653
- } else if (characterClass === 'mage') {
654
- gameState.player.maxHealth = 70;
655
- gameState.player.health = 70;
656
- gameState.player.attack = 8;
657
- gameState.player.defense = 3;
658
- gameState.player.mana = 80;
659
- gameState.player.maxMana = 80;
660
- } else if (characterClass === 'rogue') {
661
- gameState.player.maxHealth = 90;
662
- gameState.player.health = 90;
663
- gameState.player.attack = 10;
664
- gameState.player.defense = 5;
665
- gameState.player.mana = 50;
666
- gameState.player.maxMana = 50;
667
  }
668
-
669
- addGameMessage(`You selected the ${characterClass} class.`);
670
  }
671
 
672
- function finalizeCharacter() {
673
- const nameInput = document.getElementById('character-name');
674
- const genderSelect = document.getElementById('character-gender');
675
-
676
- if (!nameInput.value.trim()) {
677
- addGameMessage('Please enter a name for your character.', 'error');
678
- return;
679
- }
680
-
681
- if (!gameState.player.class) {
682
- addGameMessage('Please select a class for your character.', 'error');
683
- return;
684
- }
685
-
686
- gameState.player.name = nameInput.value.trim();
687
- gameState.player.gender = genderSelect.value;
688
-
689
- // Start the game
690
- document.getElementById('character-creation').classList.add('hidden');
691
- document.getElementById('game-screen').classList.remove('hidden');
692
-
693
- // Update character display
694
- updateCharacterDisplay();
695
-
696
- addGameMessage(`Welcome, ${gameState.player.name} the ${gameState.player.class}! Your adventure begins now.`, 'success');
697
- }
698
 
699
- function updateCharacterDisplay() {
700
- // Update character panel
701
- document.getElementById('character-display-name').textContent = gameState.player.name;
702
- document.getElementById('character-display-class').textContent = `Class: ${capitalizeFirstLetter(gameState.player.class)}`;
703
-
704
- // Update stats
705
- document.getElementById('health-text').textContent = `${gameState.player.health}/${gameState.player.maxHealth}`;
706
- document.getElementById('mana-text').textContent = `${gameState.player.mana}/${gameState.player.maxMana}`;
707
- document.getElementById('exp-text').textContent = `${gameState.player.exp}/${gameState.player.expToNextLevel}`;
708
- document.getElementById('level-text').textContent = gameState.player.level;
709
- document.getElementById('gold-text').textContent = gameState.player.gold;
710
- document.getElementById('attack-text').textContent = gameState.player.attack + (gameState.player.equipped.weapon ? gameState.player.equipped.weapon.attack : 0);
711
- document.getElementById('defense-text').textContent = gameState.player.defense + (gameState.player.equipped.shield ? gameState.player.equipped.shield.defense : 0);
712
-
713
- // Update health bar
714
- const healthPercent = (gameState.player.health / gameState.player.maxHealth) * 100;
715
- document.getElementById('health-bar').style.width = `${healthPercent}%`;
716
-
717
- // Update mana bar
718
- const manaPercent = (gameState.player.mana / gameState.player.maxMana) * 100;
719
- document.getElementById('mana-bar').style.width = `${manaPercent}%`;
720
-
721
- // Update exp bar
722
- const expPercent = (gameState.player.exp / gameState.player.expToNextLevel) * 100;
723
- document.getElementById('exp-bar').style.width = `${expPercent}%`;
724
-
725
- // Update character icon based on class
726
- const characterIcon = document.getElementById('character-icon');
727
- const playerCombatIcon = document.getElementById('player-combat-icon');
728
-
729
- if (gameState.player.class === 'warrior') {
730
- characterIcon.innerHTML = '<i class="fas fa-shield-alt text-red-500"></i>';
731
- playerCombatIcon.innerHTML = '<i class="fas fa-shield-alt text-red-500"></i>';
732
- } else if (gameState.player.class === 'mage') {
733
- characterIcon.innerHTML = '<i class="fas fa-hat-wizard text-blue-500"></i>';
734
- playerCombatIcon.innerHTML = '<i class="fas fa-hat-wizard text-blue-500"></i>';
735
- } else if (gameState.player.class === 'rogue') {
736
- characterIcon.innerHTML = '<i class="fas fa-user-ninja text-green-500"></i>';
737
- playerCombatIcon.innerHTML = '<i class="fas fa-user-ninja text-green-500"></i>';
738
- }
739
-
740
- // Update player combat name
741
- document.getElementById('player-combat-name').textContent = gameState.player.name;
742
- }
743
 
744
- function addGameMessage(message, type = 'info') {
745
- const messagesDiv = document.getElementById('game-messages');
746
- const messageElement = document.createElement('p');
 
 
 
 
 
 
 
 
 
 
 
 
747
 
748
- if (type === 'error') {
749
- messageElement.className = 'text-red-400';
750
- } else if (type === 'success') {
751
- messageElement.className = 'text-green-400';
752
- } else if (type === 'warning') {
753
- messageElement.className = 'text-yellow-400';
754
- } else {
755
- messageElement.className = 'text-gray-300';
756
- }
757
 
758
- messageElement.textContent = message;
759
- messagesDiv.appendChild(messageElement);
760
- messagesDiv.scrollTop = messagesDiv.scrollHeight;
761
 
762
- // Add to game state for saving
763
- gameState.gameMessages.push(message);
764
  }
765
 
766
- function explore() {
767
- if (gameState.inCombat) {
768
- addGameMessage('You are already in combat!', 'error');
769
- return;
770
- }
771
-
772
- // 70% chance to find an enemy
773
- if (Math.random() < 0.7) {
774
- startCombat();
775
- } else {
776
- // 30% chance to find something else
777
- const randomEvent = Math.random();
 
 
 
 
 
 
 
 
 
 
 
 
 
778
 
779
- if (randomEvent < 0.5) {
780
- // Found gold
781
- const goldFound = Math.floor(Math.random() * 10) + 5;
782
- gameState.player.gold += goldFound;
783
- updateCharacterDisplay();
784
- addGameMessage(`You found ${goldFound} gold coins on the ground!`, 'success');
785
- } else {
786
- // Found a health potion
787
- gameState.player.inventory.push({
788
- name: 'Health Potion',
789
- type: 'consumable',
790
- effect: 'heal',
791
- amount: 30,
792
- icon: 'fa-flask'
793
  });
794
- addGameMessage('You found a Health Potion!', 'success');
795
- }
796
- }
797
- }
798
-
799
- function startCombat() {
800
- gameState.inCombat = true;
801
-
802
- // Select a random enemy
803
- const randomEnemyIndex = Math.floor(Math.random() * enemies.length);
804
- gameState.currentEnemy = {...enemies[randomEnemyIndex]};
805
-
806
- // Update combat UI
807
- document.getElementById('combat-area').classList.remove('hidden');
808
- document.getElementById('enemy-name').textContent = gameState.currentEnemy.name;
809
- document.getElementById('enemy-health-text').textContent = `${gameState.currentEnemy.health}/${gameState.currentEnemy.maxHealth}`;
810
- document.getElementById('enemy-health-bar').style.width = '100%';
811
- document.getElementById('enemy-image').src = gameState.currentEnemy.image;
812
- document.getElementById('enemy-image').alt = gameState.currentEnemy.name;
813
-
814
- // Update player stats in combat
815
- document.getElementById('player-health-text').textContent = `${gameState.player.health}/${gameState.player.maxHealth}`;
816
- const healthPercent = (gameState.player.health / gameState.player.maxHealth) * 100;
817
- document.getElementById('player-health-bar').style.width = `${healthPercent}%`;
818
-
819
- addGameMessage(`You encounter a ${gameState.currentEnemy.name}! ${gameState.currentEnemy.description}`, 'warning');
820
- }
821
-
822
- function playerAttack() {
823
- if (!gameState.inCombat || !gameState.currentEnemy) {
824
- addGameMessage('There is nothing to attack!', 'error');
825
- return;
826
- }
827
-
828
- // Calculate player damage
829
- const playerAttackPower = gameState.player.attack + (gameState.player.equipped.weapon ? gameState.player.equipped.weapon.attack : 0);
830
- const damage = Math.max(1, playerAttackPower - Math.floor(gameState.currentEnemy.defense / 2));
831
-
832
- // Apply damage to enemy
833
- gameState.currentEnemy.health -= damage;
834
-
835
- // Update enemy health bar
836
- const enemyHealthPercent = (gameState.currentEnemy.health / gameState.currentEnemy.maxHealth) * 100;
837
- document.getElementById('enemy-health-bar').style.width = `${Math.max(0, enemyHealthPercent)}%`;
838
- document.getElementById('enemy-health-text').textContent = `${Math.max(0, gameState.currentEnemy.health)}/${gameState.currentEnemy.maxHealth}`;
839
-
840
- // Show damage text
841
- showDamageText(document.querySelector('#combat-area .relative:last-child'), damage);
842
-
843
- addGameMessage(`You attack the ${gameState.currentEnemy.name} for ${damage} damage!`, 'success');
844
-
845
- // Check if enemy is defeated
846
- if (gameState.currentEnemy.health <= 0) {
847
- enemyDefeated();
848
- return;
849
- }
850
-
851
- // Enemy attacks back
852
- setTimeout(() => {
853
- enemyAttack();
854
- }, 1000);
855
- }
856
-
857
- function playerSpell() {
858
- if (!gameState.inCombat || !gameState.currentEnemy) {
859
- addGameMessage('There is nothing to attack!', 'error');
860
- return;
861
- }
862
-
863
- if (gameState.player.mana < 15) {
864
- addGameMessage('Not enough mana to cast a spell!', 'error');
865
  return;
866
  }
867
 
868
- // Use mana
869
- gameState.player.mana -= 15;
870
- updateCharacterDisplay();
 
871
 
872
- // Calculate spell damage (more powerful than regular attack)
873
- let spellDamage;
874
- if (gameState.player.class === 'mage') {
875
- spellDamage = Math.max(3, 15 + Math.floor(Math.random() * 10));
 
 
 
876
  } else {
877
- spellDamage = Math.max(3, 10 + Math.floor(Math.random() * 5));
878
- }
879
-
880
- // Apply damage to enemy
881
- gameState.currentEnemy.health -= spellDamage;
882
-
883
- // Update enemy health bar
884
- const enemyHealthPercent = (gameState.currentEnemy.health / gameState.currentEnemy.maxHealth) * 100;
885
- document.getElementById('enemy-health-bar').style.width = `${Math.max(0, enemyHealthPercent)}%`;
886
- document.getElementById('enemy-health-text').textContent = `${Math.max(0, gameState.currentEnemy.health)}/${gameState.currentEnemy.maxHealth}`;
887
-
888
- // Show damage text
889
- showDamageText(document.querySelector('#combat-area .relative:last-child'), spellDamage, 'blue');
890
-
891
- addGameMessage(`You cast a spell on the ${gameState.currentEnemy.name} for ${spellDamage} damage!`, 'success');
892
-
893
- // Check if enemy is defeated
894
- if (gameState.currentEnemy.health <= 0) {
895
- enemyDefeated();
896
- return;
897
  }
898
-
899
- // Enemy attacks back
900
- setTimeout(() => {
901
- enemyAttack();
902
- }, 1000);
903
  }
904
 
905
- function playerDefend() {
906
- if (!gameState.inCombat || !gameState.currentEnemy) {
907
- addGameMessage('There is nothing to defend against!', 'error');
908
- return;
909
- }
 
 
 
 
 
 
 
 
910
 
911
- addGameMessage(`You take a defensive stance, reducing damage from the next attack.`, 'info');
 
 
912
 
913
- // Enemy attacks with reduced damage
914
- setTimeout(() => {
915
- // Calculate enemy damage (reduced by 50% when defending)
916
- const enemyDamage = Math.max(1, Math.floor((gameState.currentEnemy.attack - (gameState.player.defense + (gameState.player.equipped.shield ? gameState.player.equipped.shield.defense : 0))) / 2));
917
-
918
- // Apply damage to player
919
- gameState.player.health -= enemyDamage;
920
 
921
- // Update player health bar
922
- const healthPercent = (gameState.player.health / gameState.player.maxHealth) * 100;
923
- document.getElementById('player-health-bar').style.width = `${Math.max(0, healthPercent)}%`;
924
- document.getElementById('player-health-text').textContent = `${Math.max(0, gameState.player.health)}/${gameState.player.maxHealth}`;
925
- document.getElementById('health-bar').style.width = `${Math.max(0, healthPercent)}%`;
926
- document.getElementById('health-text').textContent = `${Math.max(0, gameState.player.health)}/${gameState.player.maxHealth}`;
927
-
928
- // Show damage text
929
- showDamageText(document.querySelector('#combat-area .relative:first-child'), enemyDamage);
930
-
931
- addGameMessage(`The ${gameState.currentEnemy.name} attacks you for ${enemyDamage} damage (reduced by your defense)!`, 'warning');
932
 
933
- // Check if player is defeated
934
- if (gameState.player.health <= 0) {
935
- playerDefeated();
936
  }
937
- }, 1000);
938
- }
939
-
940
- function playerFlee() {
941
- if (!gameState.inCombat || !gameState.currentEnemy) {
942
- addGameMessage('There is nothing to flee from!', 'error');
943
- return;
944
- }
945
-
946
- // 60% chance to flee successfully
947
- if (Math.random() < 0.6) {
948
- addGameMessage(`You successfully fled from the ${gameState.currentEnemy.name}!`, 'success');
949
- endCombat();
950
- } else {
951
- addGameMessage(`You failed to flee! The ${gameState.currentEnemy.name} attacks you!`, 'error');
952
 
953
- // Enemy attacks
954
- setTimeout(() => {
955
- enemyAttack();
956
- }, 1000);
957
- }
958
- }
959
-
960
- function enemyAttack() {
961
- if (!gameState.inCombat || !gameState.currentEnemy) return;
962
-
963
- // Calculate enemy damage
964
- const enemyDamage = Math.max(1, gameState.currentEnemy.attack - (gameState.player.defense + (gameState.player.equipped.shield ? gameState.player.equipped.shield.defense : 0)));
965
-
966
- // Apply damage to player
967
- gameState.player.health -= enemyDamage;
968
-
969
- // Update player health bar
970
- const healthPercent = (gameState.player.health / gameState.player.maxHealth) * 100;
971
- document.getElementById('player-health-bar').style.width = `${Math.max(0, healthPercent)}%`;
972
- document.getElementById('player-health-text').textContent = `${Math.max(0, gameState.player.health)}/${gameState.player.maxHealth}`;
973
- document.getElementById('health-bar').style.width = `${Math.max(0, healthPercent)}%`;
974
- document.getElementById('health-text').textContent = `${Math.max(0, gameState.player.health)}/${gameState.player.maxHealth}`;
975
-
976
- // Show damage text
977
- showDamageText(document.querySelector('#combat-area .relative:first-child'), enemyDamage);
978
-
979
- addGameMessage(`The ${gameState.currentEnemy.name} attacks you for ${enemyDamage} damage!`, 'warning');
980
-
981
- // Check if player is defeated
982
- if (gameState.player.health <= 0) {
983
- playerDefeated();
984
- }
985
- }
986
-
987
- function enemyDefeated() {
988
- addGameMessage(`You defeated the ${gameState.currentEnemy.name}!`, 'success');
989
-
990
- // Gain experience and gold
991
- gameState.player.exp += gameState.currentEnemy.exp;
992
- gameState.player.gold += gameState.currentEnemy.gold;
993
 
994
- addGameMessage(`Gained ${gameState.currentEnemy.exp} experience and ${gameState.currentEnemy.gold} gold.`, 'success');
 
995
 
996
- // Check for level up
997
- checkLevelUp();
 
998
 
999
- // End combat
1000
- endCombat();
1001
  }
1002
 
1003
- function playerDefeated() {
1004
- addGameMessage(`You were defeated by the ${gameState.currentEnemy.name}!`, 'error');
1005
- addGameMessage('You wake up in town, having lost some gold and experience.', 'warning');
1006
-
1007
- // Penalty for dying
1008
- gameState.player.exp = Math.max(0, gameState.player.exp - 10);
1009
- gameState.player.gold = Math.max(0, gameState.player.gold - 5);
1010
-
1011
- // Restore some health
1012
- gameState.player.health = Math.floor(gameState.player.maxHealth * 0.3);
1013
-
1014
- // Update display
1015
- updateCharacterDisplay();
1016
 
1017
- // End combat
1018
- endCombat();
1019
- }
1020
-
1021
- function endCombat() {
1022
- gameState.inCombat = false;
1023
- gameState.currentEnemy = null;
1024
- document.getElementById('combat-area').classList.add('hidden');
1025
- }
1026
-
1027
- function checkLevelUp() {
1028
- if (gameState.player.exp >= gameState.player.expToNextLevel) {
1029
- gameState.player.level++;
1030
- gameState.player.exp -= gameState.player.expToNextLevel;
1031
- gameState.player.expToNextLevel = Math.floor(gameState.player.expToNextLevel * 1.2);
1032
-
1033
- // Improve stats
1034
- gameState.player.maxHealth += 10;
1035
- gameState.player.health = gameState.player.maxHealth;
1036
- gameState.player.maxMana += 5;
1037
- gameState.player.mana = gameState.player.maxMana;
1038
- gameState.player.attack += 2;
1039
- gameState.player.defense += 1;
1040
-
1041
- addGameMessage(`Level up! You are now level ${gameState.player.level}!`, 'success');
1042
- addGameMessage('Your stats have improved!', 'info');
1043
 
1044
- updateCharacterDisplay();
1045
- }
1046
- }
1047
-
1048
- function rest() {
1049
- if (gameState.inCombat) {
1050
- addGameMessage('You cannot rest while in combat!', 'error');
1051
- return;
1052
- }
1053
-
1054
- // Restore health and mana
1055
- const healthRestored = Math.floor(gameState.player.maxHealth * 0.3);
1056
- const manaRestored = Math.floor(gameState.player.maxMana * 0.3);
1057
-
1058
- gameState.player.health = Math.min(gameState.player.maxHealth, gameState.player.health + healthRestored);
1059
- gameState.player.mana = Math.min(gameState.player.maxMana, gameState.player.mana + manaRestored);
1060
-
1061
- addGameMessage(`You rest and recover ${healthRestored} health and ${manaRestored} mana.`, 'success');
1062
- updateCharacterDisplay();
1063
- }
1064
-
1065
- function visitTown() {
1066
- if (gameState.inCombat) {
1067
- addGameMessage('You cannot visit town while in combat!', 'error');
1068
- return;
1069
  }
1070
 
1071
- document.getElementById('town-area').classList.remove('hidden');
1072
- addGameMessage('You enter the town square.', 'info');
1073
- }
1074
-
1075
- function leaveTown() {
1076
- document.getElementById('town-area').classList.add('hidden');
1077
- addGameMessage('You leave the town.', 'info');
1078
  }
1079
 
1080
- function visitShop() {
1081
- addGameMessage('The shop is currently closed. Come back later!', 'info');
1082
- }
1083
-
1084
- function visitTavern() {
1085
- addGameMessage('You enjoy a drink at the tavern and hear rumors of a dragon girl in the mountains.', 'info');
1086
- }
1087
-
1088
- function visitGuild() {
1089
- addGameMessage('The Adventurer\'s Guild has no quests available right now.', 'info');
1090
- }
1091
-
1092
- function train() {
1093
- if (gameState.inCombat) {
1094
- addGameMessage('You cannot train while in combat!', 'error');
1095
- return;
1096
- }
1097
-
1098
- // Training costs gold but improves stats
1099
- if (gameState.player.gold < 5) {
1100
- addGameMessage('You need at least 5 gold to train!', 'error');
1101
- return;
1102
- }
1103
-
1104
- gameState.player.gold -= 5;
1105
 
1106
- // Random stat improvement
1107
- const statToImprove = ['attack', 'defense'][Math.floor(Math.random() * 2)];
1108
- const improvement = 1;
1109
-
1110
- if (statToImprove === 'attack') {
1111
- gameState.player.attack += improvement;
1112
- addGameMessage(`After training, your attack increased by ${improvement}! (Cost: 5 gold)`, 'success');
1113
- } else {
1114
- gameState.player.defense += improvement;
1115
- addGameMessage(`After training, your defense increased by ${improvement}! (Cost: 5 gold)`, 'success');
1116
  }
1117
-
1118
- updateCharacterDisplay();
1119
- }
1120
-
1121
- function openInventory() {
1122
- document.getElementById('inventory-modal').classList.remove('hidden');
1123
  }
1124
 
1125
- function closeInventory() {
1126
- document.getElementById('inventory-modal').classList.add('hidden');
1127
- }
1128
-
1129
- function openQuests() {
1130
- addGameMessage('You have no active quests at the moment.', 'info');
1131
- }
1132
-
1133
- function saveGame() {
1134
- localStorage.setItem('monstergirlRpgSave', JSON.stringify(gameState));
1135
- addGameMessage('Game saved successfully!', 'success');
1136
- }
1137
-
1138
- function loadGame() {
1139
- const savedGame = localStorage.getItem('monstergirlRpgSave');
1140
 
1141
- if (savedGame) {
1142
- try {
1143
- const parsedGame = JSON.parse(savedGame);
1144
- Object.assign(gameState, parsedGame);
1145
-
1146
- document.getElementById('main-menu').classList.add('hidden');
1147
- document.getElementById('game-screen').classList.remove('hidden');
1148
-
1149
- updateCharacterDisplay();
1150
- addGameMessage(`Welcome back, ${gameState.player.name}! Game loaded successfully.`, 'success');
1151
- } catch (e) {
1152
- addGameMessage('Failed to load saved game.', 'error');
1153
- }
1154
- } else {
1155
- addGameMessage('No saved game found.', 'error');
 
 
 
 
 
 
 
 
 
 
1156
  }
1157
  }
1158
 
1159
- function showCredits() {
1160
- document.getElementById('credits-modal').classList.remove('hidden');
1161
- }
1162
-
1163
- function hideCredits() {
1164
- document.getElementById('credits-modal').classList.add('hidden');
1165
- }
1166
-
1167
- function showDamageText(element, damage, color = 'red') {
1168
- const damageText = document.createElement('div');
1169
- damageText.className = 'damage-text';
1170
- damageText.style.color = color;
1171
- damageText.textContent = `-${damage}`;
1172
- damageText.style.left = '50%';
1173
- damageText.style.transform = 'translateX(-50%)';
1174
-
1175
- element.appendChild(damageText);
1176
-
1177
- // Remove after animation
1178
- setTimeout(() => {
1179
- damageText.remove();
1180
- }, 1000);
1181
- }
1182
-
1183
- function capitalizeFirstLetter(string) {
1184
- return string.charAt(0).toUpperCase() + string.slice(1);
1185
- }
1186
-
1187
- // Initialize game
1188
- document.addEventListener('DOMContentLoaded', () => {
1189
- addGameMessage('Welcome to Monstergirl RPG!');
1190
- });
1191
  </script>
1192
  <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=lunarflu/rpg" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
1193
  </html>
 
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Monster Girl Academy: Heartstrings</title>
7
  <script src="https://cdn.tailwindcss.com"></script>
8
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
  <style>
10
+ @keyframes float {
11
+ 0% { transform: translateY(0px); }
12
+ 50% { transform: translateY(-10px); }
13
+ 100% { transform: translateY(0px); }
14
  }
15
+ .floating {
16
+ animation: float 3s ease-in-out infinite;
 
 
17
  }
18
+ .bg-academy {
19
+ background-image: url('https://images.unsplash.com/photo-1588072432836-e10032774350?q=80&w=2072&auto=format&fit=crop');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  background-size: cover;
21
  background-position: center;
22
  }
 
 
 
 
 
23
  .character-card {
24
  transition: all 0.3s ease;
25
+ transform-style: preserve-3d;
26
  }
27
  .character-card:hover {
28
+ transform: scale(1.05) rotateY(5deg);
29
+ box-shadow: 0 10px 25px rgba(0,0,0,0.2);
30
+ }
31
+ .stat-bar {
32
+ height: 6px;
33
+ transition: width 0.5s ease;
34
+ }
35
+ .dialogue-box {
36
+ min-height: 200px;
37
+ background: rgba(255, 255, 255, 0.9);
38
+ border-radius: 15px;
39
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
40
+ }
41
+ .choice-btn {
42
+ transition: all 0.2s ease;
43
  }
44
+ .choice-btn:hover {
45
+ transform: translateY(-3px);
46
+ box-shadow: 0 5px 10px rgba(0,0,0,0.1);
47
+ }
48
+ .character-portrait {
49
+ filter: drop-shadow(0 5px 10px rgba(0,0,0,0.2));
 
50
  }
51
  </style>
52
  </head>
53
+ <body class="bg-gray-100 font-sans">
54
+ <!-- Main Game Container -->
55
+ <div class="container mx-auto px-4 py-8 max-w-6xl">
56
+ <!-- Header -->
57
+ <header class="bg-purple-900 text-white rounded-xl p-6 mb-8 shadow-lg bg-academy relative overflow-hidden">
58
+ <div class="absolute inset-0 bg-black opacity-40"></div>
59
+ <div class="relative z-10 flex flex-col items-center">
60
+ <h1 class="text-4xl md:text-5xl font-bold mb-2 text-center floating">Monster Girl Academy: Heartstrings</h1>
61
+ <p class="text-xl text-purple-200 mb-4 text-center">Where bonds transcend species</p>
62
+ <div class="flex space-x-4">
63
+ <button id="newGameBtn" class="bg-pink-600 hover:bg-pink-700 text-white px-6 py-2 rounded-full font-semibold transition">New Game</button>
64
+ <button id="loadGameBtn" class="bg-indigo-600 hover:bg-indigo-700 text-white px-6 py-2 rounded-full font-semibold transition">Load Game</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  </div>
66
+ </div>
67
+ </header>
68
+
69
+ <!-- Game Area (initially hidden) -->
70
+ <div id="gameArea" class="hidden">
71
+ <!-- Top Bar - Game Info -->
72
+ <div class="bg-white rounded-xl p-4 mb-6 shadow-md flex flex-wrap justify-between items-center">
73
+ <div class="flex items-center space-x-4 mb-2 sm:mb-0">
74
+ <div class="bg-yellow-100 p-2 rounded-lg">
75
+ <i class="fas fa-calendar-day text-yellow-600"></i>
76
+ <span id="gameDay" class="font-semibold ml-1">Day 1</span>
 
 
 
 
 
 
 
 
77
  </div>
78
+ <div class="bg-blue-100 p-2 rounded-lg">
79
+ <i class="fas fa-clock text-blue-600"></i>
80
+ <span id="gameTime" class="font-semibold ml-1">Morning</span>
 
 
 
81
  </div>
82
  </div>
83
+ <div class="flex items-center space-x-4">
84
+ <div class="bg-green-100 p-2 rounded-lg">
85
+ <i class="fas fa-coins text-green-600"></i>
86
+ <span id="gameMoney" class="font-semibold ml-1">100</span>
 
 
 
 
87
  </div>
88
+ <div class="bg-red-100 p-2 rounded-lg">
89
+ <i class="fas fa-heart text-red-600"></i>
90
+ <span id="gameEnergy" class="font-semibold ml-1">10/10</span>
 
 
 
 
91
  </div>
92
  </div>
93
  </div>
 
 
 
 
 
94
 
95
+ <!-- Main Content Area -->
96
+ <div class="flex flex-col lg:flex-row gap-6">
97
+ <!-- Left Side - Characters -->
98
+ <div class="w-full lg:w-1/4">
99
+ <div class="bg-white rounded-xl p-4 shadow-md mb-6">
100
+ <h2 class="text-xl font-bold mb-4 text-purple-800 border-b pb-2">Your Connections</h2>
101
+ <div id="characterList" class="space-y-4">
102
+ <!-- Characters will be dynamically added here -->
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  </div>
104
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
105
 
106
+ <div class="bg-white rounded-xl p-4 shadow-md">
107
+ <h2 class="text-xl font-bold mb-4 text-purple-800 border-b pb-2">Your Stats</h2>
108
+ <div class="space-y-3">
109
+ <div>
110
+ <p class="text-sm font-medium text-gray-700 mb-1">Charm <span class="float-right">50%</span></p>
111
+ <div class="w-full bg-gray-200 rounded-full h-1.5">
112
+ <div class="bg-pink-500 h-1.5 rounded-full stat-bar" style="width: 50%"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  </div>
114
+ </div>
115
+ <div>
116
+ <p class="text-sm font-medium text-gray-700 mb-1">Intelligence <span class="float-right">30%</span></p>
117
+ <div class="w-full bg-gray-200 rounded-full h-1.5">
118
+ <div class="bg-blue-500 h-1.5 rounded-full stat-bar" style="width: 30%"></div>
119
  </div>
 
120
  </div>
121
+ <div>
122
+ <p class="text-sm font-medium text-gray-700 mb-1">Courage <span class="float-right">70%</span></p>
123
+ <div class="w-full bg-gray-200 rounded-full h-1.5">
124
+ <div class="bg-yellow-500 h-1.5 rounded-full stat-bar" style="width: 70%"></div>
125
+ </div>
126
+ </div>
127
+ <div>
128
+ <p class="text-sm font-medium text-gray-700 mb-1">Empathy <span class="float-right">40%</span></p>
129
+ <div class="w-full bg-gray-200 rounded-full h-1.5">
130
+ <div class="bg-green-500 h-1.5 rounded-full stat-bar" style="width: 40%"></div>
131
  </div>
 
132
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  </div>
134
  </div>
135
  </div>
 
 
136
 
137
+ <!-- Center - Main Game View -->
138
+ <div class="w-full lg:w-2/4">
139
+ <div class="bg-white rounded-xl p-6 shadow-md mb-6 dialogue-box">
140
+ <div id="mainEvent" class="text-center py-8">
141
+ <h2 class="text-2xl font-bold text-purple-900 mb-4">Welcome to Monster Girl Academy</h2>
142
+ <p class="text-gray-700 mb-6">As the first human student admitted to this prestigious academy for magical beings, you'll navigate complex relationships with fascinating creatures from all walks of life. Each choice shapes your story and determines who you'll become by year's end.</p>
143
+ <button id="startAdventureBtn" class="bg-purple-600 hover:bg-purple-700 text-white px-8 py-3 rounded-full font-semibold text-lg transition">Begin Your Journey</button>
144
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
145
  </div>
146
+
147
+ <div id="choicesContainer" class="grid grid-cols-1 md:grid-cols-2 gap-4 hidden">
148
+ <!-- Choices will be dynamically added here -->
 
 
 
 
149
  </div>
150
  </div>
151
+
152
+ <!-- Right Side - Calendar and Notifications -->
153
+ <div class="w-full lg:w-1/4">
154
+ <div class="bg-white rounded-xl p-4 shadow-md mb-6">
155
+ <h2 class="text-xl font-bold mb-4 text-purple-800 border-b pb-2">Academy Calendar</h2>
156
+ <div class="grid grid-cols-7 gap-1 text-center mb-2">
157
+ <div class="text-xs font-semibold">S</div>
158
+ <div class="text-xs font-semibold">M</div>
159
+ <div class="text-xs font-semibold">T</div>
160
+ <div class="text-xs font-semibold">W</div>
161
+ <div class="text-xs font-semibold">T</div>
162
+ <div class="text-xs font-semibold">F</div>
163
+ <div class="text-xs font-semibold">S</div>
164
  </div>
165
+ <div class="grid grid-cols-7 gap-1 text-center">
166
+ <!-- Calendar days will be dynamically added here -->
167
+ <div class="p-1 text-xs opacity-30">29</div>
168
+ <div class="p-1 text-xs opacity-30">30</div>
169
+ <div class="p-1 text-xs opacity-30">31</div>
170
+ <div class="p-1 text-xs border rounded-full bg-purple-100 font-semibold">1</div>
171
+ <div class="p-1 text-xs">2</div>
172
+ <div class="p-1 text-xs">3</div>
173
+ <div class="p-1 text-xs">4</div>
174
+ <div class="p-1 text-xs">5</div>
175
+ <div class="p-1 text-xs">6</div>
176
+ <div class="p-1 text-xs">7</div>
177
+ <div class="p-1 text-xs">8</div>
178
+ <div class="p-1 text-xs">9</div>
179
+ <div class="p-1 text-xs">10</div>
180
+ <div class="p-1 text-xs">11</div>
181
+ <div class="p-1 text-xs">12</div>
182
+ <div class="p-1 text-xs">13</div>
183
+ <div class="p-1 text-xs">14</div>
184
+ <div class="p-1 text-xs">15</div>
185
+ <div class="p-1 text-xs">16</div>
186
+ <div class="p-1 text-xs">17</div>
187
+ <div class="p-1 text-xs">18</div>
188
+ <div class="p-1 text-xs">19</div>
189
+ <div class="p-1 text-xs">20</div>
190
+ <div class="p-1 text-xs">21</div>
191
+ <div class="p-1 text-xs">22</div>
192
+ <div class="p-1 text-xs">23</div>
193
+ <div class="p-1 text-xs">24</div>
194
+ <div class="p-1 text-xs">25</div>
195
+ <div class="p-1 text-xs">26</div>
196
+ <div class="p-1 text-xs">27</div>
197
+ <div class="p-1 text-xs">28</div>
198
+ <div class="p-1 text-xs">29</div>
199
+ <div class="p-1 text-xs">30</div>
200
+ <div class="p-1 text-xs opacity-30">1</div>
201
+ <div class="p-1 text-xs opacity-30">2</div>
202
+ </div>
203
+ <div class="mt-4 pt-2 border-t">
204
+ <h3 class="font-semibold text-sm mb-2">Upcoming Events</h3>
205
+ <ul class="text-xs space-y-1">
206
+ <li class="flex items-center"><span class="w-2 h-2 bg-pink-500 rounded-full mr-2"></span> Moonlight Festival - Week 2</li>
207
+ <li class="flex items-center"><span class="w-2 h-2 bg-blue-500 rounded-full mr-2"></span> Midterms - Week 6</li>
208
+ <li class="flex items-center"><span class="w-2 h-2 bg-green-500 rounded-full mr-2"></span> Sports Day - Week 8</li>
209
+ </ul>
210
  </div>
211
  </div>
 
 
 
212
 
213
+ <div class="bg-white rounded-xl p-4 shadow-md">
214
+ <h2 class="text-xl font-bold mb-4 text-purple-800 border-b pb-2">Notifications</h2>
215
+ <div id="notifications" class="space-y-3">
216
+ <div class="p-2 bg-blue-50 rounded-lg text-sm">
217
+ <p class="font-medium">Welcome to Monster Girl Academy!</p>
218
+ <p class="text-xs text-gray-600">Find your dorm in the West Wing</p>
219
+ </div>
220
+ <div class="p-2 bg-yellow-50 rounded-lg text-sm">
221
+ <p class="font-medium">Orientation at 10AM</p>
222
+ <p class="text-xs text-gray-600">Main Hall, don't be late!</p>
223
+ </div>
224
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  </div>
226
  </div>
227
  </div>
 
231
  <script>
232
  // Game State
233
  const gameState = {
234
+ day: 1,
235
+ time: 'Morning',
236
+ energy: 10,
237
+ maxEnergy: 10,
238
+ money: 100,
239
+ stats: {
240
+ charm: 50,
241
+ intelligence: 30,
242
+ courage: 70,
243
+ empathy: 40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  },
245
+ relationships: {},
246
+ currentEvent: null,
247
+ eventHistory: [],
248
+ flags: {}
249
  };
250
 
251
+ // Monster Girls Database
252
+ const monstergirls = {
253
+ seraphina: {
254
+ id: 'seraphina',
255
+ name: 'Seraphina',
256
+ species: 'Lamia',
257
+ title: 'The Serpent Prodigy',
258
+ personality: 'Intelligent, ambitious, but socially awkward',
259
+ initialStats: {
260
+ trust: 30,
261
+ affection: 20,
262
+ curiosity: 60,
263
+ respect: 50
264
+ },
265
+ image: 'lamia.png',
266
+ color: 'bg-green-100',
267
+ textColor: 'text-green-800',
268
+ borderColor: 'border-green-300',
269
+ likes: ['Ancient history', 'Intellectual debates', 'Quiet libraries'],
270
+ dislikes: ['Small talk', 'Disorganization', 'Loud noises'],
271
+ events: [
272
+ {
273
+ id: 'library_encounter',
274
+ title: 'Unexpected Study Partner',
275
+ description: 'You find Seraphina surrounded by ancient tomes in the library. She seems frustrated with a particularly difficult text.',
276
+ choices: [
277
+ {
278
+ text: 'Offer to help with the research',
279
+ requirements: { intelligence: 40 },
280
+ outcomes: [
281
+ { type: 'stat', target: 'seraphina', stat: 'trust', change: 10 },
282
+ { type: 'stat', target: 'seraphina', stat: 'affection', change: 5 },
283
+ { type: 'stat', target: 'player', stat: 'intelligence', change: 5 },
284
+ { type: 'flag', id: 'helped_seraphina_research', value: true }
285
+ ]
286
+ },
287
+ {
288
+ text: 'Ask if she wants to take a break and get some air',
289
+ outcomes: [
290
+ { type: 'stat', target: 'seraphina', stat: 'affection', change: -5 },
291
+ { type: 'dialogue', text: "Seraphina glares at you. 'I don't have time for breaks. Some of us take our studies seriously.'" }
292
+ ]
293
+ },
294
+ {
295
+ text: 'Quietly sit nearby and study your own materials',
296
+ outcomes: [
297
+ { type: 'stat', target: 'seraphina', stat: 'respect', change: 5 },
298
+ { type: 'dialogue', text: "Seraphina glances at you occasionally, seeming to appreciate your quiet diligence." }
299
+ ]
300
+ }
301
+ ]
302
+ },
303
+ // More events for Seraphina...
304
+ ]
305
  },
306
+ marigold: {
307
+ id: 'marigold',
308
+ name: 'Marigold',
309
+ species: 'Slimegirl',
310
+ title: 'The Bubbly Alchemist',
311
+ personality: 'Cheerful, curious, but easily distracted',
312
+ initialStats: {
313
+ trust: 50,
314
+ affection: 40,
315
+ curiosity: 70,
316
+ respect: 30
317
+ },
318
+ image: 'slime.png',
319
+ color: 'bg-blue-100',
320
+ textColor: 'text-blue-800',
321
+ borderColor: 'border-blue-300',
322
+ likes: ['New experiences', 'Sweet treats', 'Colorful things'],
323
+ dislikes: ['Being ignored', 'Boring routines', 'Hot temperatures'],
324
+ events: [
325
+ {
326
+ id: 'lab_accident',
327
+ title: 'Sticky Situation',
328
+ description: 'Marigold has accidentally turned herself bright pink during an alchemy experiment and is panicking about how to fix it.',
329
+ choices: [
330
+ {
331
+ text: 'Help her find the antidote in the alchemy books',
332
+ requirements: { intelligence: 30 },
333
+ outcomes: [
334
+ { type: 'stat', target: 'marigold', stat: 'trust', change: 15 },
335
+ { type: 'stat', target: 'player', stat: 'intelligence', change: 5 },
336
+ { type: 'dialogue', text: "'You're so smart!' Marigold bubbles happily as you find the solution. 'Let's make the antidote together!'" }
337
+ ]
338
+ },
339
+ {
340
+ text: 'Tell her the pink actually looks cute on her',
341
+ outcomes: [
342
+ { type: 'stat', target: 'marigold', stat: 'affection', change: 10 },
343
+ { type: 'dialogue', text: "Marigold giggles and wobbles excitedly. 'You really think so? Maybe I'll stay pink for a while longer!'" }
344
+ ]
345
+ },
346
+ {
347
+ text: 'Report the accident to the professor',
348
+ outcomes: [
349
+ { type: 'stat', target: 'marigold', stat: 'trust', change: -10 },
350
+ { type: 'stat', target: 'marigold', stat: 'affection', change: -15 },
351
+ { type: 'dialogue', text: "'Snitches get stitches!' Marigold pouts as the professor scolds her. She seems really upset with you." }
352
+ ]
353
+ }
354
+ ]
355
+ },
356
+ // More events for Marigold...
357
+ ]
358
  },
359
+ // More monster girls...
360
+ };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
 
362
+ // Initialize relationships
363
+ function initRelationships() {
364
+ for (const girlId in monstergirls) {
365
+ gameState.relationships[girlId] = { ...monstergirls[girlId].initialStats };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
366
  }
 
 
367
  }
368
 
369
+ // DOM Elements
370
+ const newGameBtn = document.getElementById('newGameBtn');
371
+ const loadGameBtn = document.getElementById('loadGameBtn');
372
+ const gameArea = document.getElementById('gameArea');
373
+ const startAdventureBtn = document.getElementById('startAdventureBtn');
374
+ const mainEvent = document.getElementById('mainEvent');
375
+ const choicesContainer = document.getElementById('choicesContainer');
376
+ const characterList = document.getElementById('characterList');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
377
 
378
+ // Event Listeners
379
+ newGameBtn.addEventListener('click', startNewGame);
380
+ loadGameBtn.addEventListener('click', loadGame);
381
+ startAdventureBtn.addEventListener('click', beginAdventure);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
 
383
+ // Game Functions
384
+ function startNewGame() {
385
+ // Reset game state
386
+ gameState.day = 1;
387
+ gameState.time = 'Morning';
388
+ gameState.energy = 10;
389
+ gameState.money = 100;
390
+ gameState.stats = {
391
+ charm: 50,
392
+ intelligence: 30,
393
+ courage: 70,
394
+ empathy: 40
395
+ };
396
+ gameState.eventHistory = [];
397
+ gameState.flags = {};
398
 
399
+ initRelationships();
400
+
401
+ // Show game area
402
+ gameArea.classList.remove('hidden');
 
 
 
 
 
403
 
404
+ // Update UI
405
+ updateGameInfo();
406
+ renderCharacterList();
407
 
408
+ // Start with first event
409
+ triggerEvent('welcome_event');
410
  }
411
 
412
+ function loadGame() {
413
+ // In a real game, this would load from localStorage
414
+ alert('Load game functionality would go here! For now, starting a new game.');
415
+ startNewGame();
416
+ }
417
+
418
+ function beginAdventure() {
419
+ triggerEvent('orientation_event');
420
+ }
421
+
422
+ function triggerEvent(eventId) {
423
+ // Special events
424
+ if (eventId === 'welcome_event') {
425
+ mainEvent.innerHTML = `
426
+ <div class="flex flex-col items-center">
427
+ <img src="https://i.imgur.com/JQl1D1X.png" alt="Academy Gates" class="w-full max-w-md rounded-lg mb-4 character-portrait">
428
+ <h2 class="text-2xl font-bold text-purple-900 mb-4">The Academy Gates</h2>
429
+ <p class="text-gray-700 mb-4">The towering gates of Monster Girl Academy loom before you, their intricate ironwork depicting scenes of legendary creatures. As the first human student, you're not sure what to expect from this year.</p>
430
+ <p class="text-gray-700 mb-6">A cheerful harpy flies down to greet you. "Welcome! Orientation starts in an hour at the Main Hall. Until then, feel free to explore the grounds!"</p>
431
+ <div class="flex space-x-4">
432
+ <button class="event-choice-btn bg-purple-600 hover:bg-purple-700 text-white px-6 py-2 rounded-full font-semibold transition" data-choice="explore">Explore the Campus</button>
433
+ <button class="event-choice-btn bg-gray-600 hover:bg-gray-700 text-white px-6 py-2 rounded-full font-semibold transition" data-choice="dorm">Go Straight to Your Dorm</button>
434
+ </div>
435
+ </div>
436
+ `;
437
 
438
+ // Add event listeners to choice buttons
439
+ document.querySelectorAll('.event-choice-btn').forEach(btn => {
440
+ btn.addEventListener('click', function() {
441
+ const choice = this.getAttribute('data-choice');
442
+ if (choice === 'explore') {
443
+ triggerEvent('campus_exploration');
444
+ } else {
445
+ triggerEvent('dorm_settle');
446
+ }
 
 
 
 
 
447
  });
448
+ });
449
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
450
  return;
451
  }
452
 
453
+ // Find a random event from any girl
454
+ const availableGirls = Object.values(monstergirls).filter(girl =>
455
+ !gameState.eventHistory.includes(girl.events[0].id)
456
+ );
457
 
458
+ if (availableGirls.length > 0) {
459
+ const randomGirl = availableGirls[Math.floor(Math.random() * availableGirls.length)];
460
+ const girlEvent = randomGirl.events[0];
461
+ gameState.currentEvent = girlEvent;
462
+ gameState.eventHistory.push(girlEvent.id);
463
+
464
+ displayEvent(girlEvent, randomGirl);
465
  } else {
466
+ // No more events (shouldn't happen in demo)
467
+ mainEvent.innerHTML = `
468
+ <div class="text-center py-8">
469
+ <h2 class="text-2xl font-bold text-purple-900 mb-4">End of Demo</h2>
470
+ <p class="text-gray-700 mb-6">This concludes our preview of Monster Girl Academy: Heartstrings. In the full game, you'd experience dozens more events, deeper relationships, and multiple endings with each character.</p>
471
+ <button onclick="startNewGame()" class="bg-purple-600 hover:bg-purple-700 text-white px-8 py-3 rounded-full font-semibold text-lg transition">Play Again</button>
472
+ </div>
473
+ `;
 
 
 
 
 
 
 
 
 
 
 
 
474
  }
 
 
 
 
 
475
  }
476
 
477
+ function displayEvent(event, girl) {
478
+ mainEvent.innerHTML = `
479
+ <div class="flex flex-col md:flex-row items-center md:items-start">
480
+ <img src="https://i.imgur.com/${girl.image || 'JQl1D1X.png'}" alt="${girl.name}" class="w-full max-w-xs rounded-lg mb-4 md:mb-0 md:mr-6 character-portrait">
481
+ <div>
482
+ <div class="flex items-center mb-2">
483
+ <h2 class="text-2xl font-bold ${girl.textColor}">${girl.name}</h2>
484
+ <span class="ml-2 px-2 py-1 text-xs rounded-full ${girl.color} ${girl.textColor}">${girl.species}</span>
485
+ </div>
486
+ <p class="text-gray-700 mb-4">${event.description}</p>
487
+ </div>
488
+ </div>
489
+ `;
490
 
491
+ // Display choices
492
+ choicesContainer.innerHTML = '';
493
+ choicesContainer.classList.remove('hidden');
494
 
495
+ event.choices.forEach((choice, index) => {
496
+ const choiceBtn = document.createElement('button');
497
+ choiceBtn.className = `choice-btn bg-white hover:bg-gray-50 border ${girl.borderColor} text-gray-800 px-4 py-3 rounded-lg font-medium text-left`;
498
+ choiceBtn.textContent = choice.text;
 
 
 
499
 
500
+ // Check requirements
501
+ let meetsRequirements = true;
502
+ if (choice.requirements) {
503
+ for (const stat in choice.requirements) {
504
+ if (gameState.stats[stat] < choice.requirements[stat]) {
505
+ meetsRequirements = false;
506
+ choiceBtn.className = `choice-btn bg-gray-100 border border-gray-200 text-gray-400 px-4 py-3 rounded-lg font-medium text-left cursor-not-allowed`;
507
+ choiceBtn.title = `Requires ${stat} ${choice.requirements[stat]}`;
508
+ }
509
+ }
510
+ }
511
 
512
+ if (meetsRequirements) {
513
+ choiceBtn.addEventListener('click', () => handleChoice(choice, girl));
 
514
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
515
 
516
+ choicesContainer.appendChild(choiceBtn);
517
+ });
518
+ }
519
+
520
+ function handleChoice(choice, girl) {
521
+ // Apply outcomes
522
+ choice.outcomes.forEach(outcome => {
523
+ if (outcome.type === 'stat') {
524
+ if (outcome.target === 'player') {
525
+ gameState.stats[outcome.stat] += outcome.change;
526
+ gameState.stats[outcome.stat] = Math.max(0, Math.min(100, gameState.stats[outcome.stat]));
527
+ } else {
528
+ gameState.relationships[girl.id][outcome.stat] += outcome.change;
529
+ gameState.relationships[girl.id][outcome.stat] = Math.max(0, Math.min(100, gameState.relationships[girl.id][outcome.stat]));
530
+ }
531
+ } else if (outcome.type === 'flag') {
532
+ gameState.flags[outcome.id] = outcome.value;
533
+ } else if (outcome.type === 'dialogue') {
534
+ // Show dialogue (simplified for demo)
535
+ alert(outcome.text);
536
+ }
537
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
538
 
539
+ // Advance time
540
+ advanceTime();
541
 
542
+ // Update UI
543
+ updateGameInfo();
544
+ renderCharacterList();
545
 
546
+ // Trigger next event
547
+ triggerEvent('random');
548
  }
549
 
550
+ function advanceTime() {
551
+ // Simplified time system for demo
552
+ const times = ['Morning', 'Afternoon', 'Evening', 'Night'];
553
+ const currentIndex = times.indexOf(gameState.time);
 
 
 
 
 
 
 
 
 
554
 
555
+ if (currentIndex < times.length - 1) {
556
+ gameState.time = times[currentIndex + 1];
557
+ } else {
558
+ gameState.time = 'Morning';
559
+ gameState.day++;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
560
 
561
+ // Restore some energy each new day
562
+ gameState.energy = Math.min(gameState.maxEnergy, gameState.energy + 5);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
563
  }
564
 
565
+ // Spend energy
566
+ gameState.energy = Math.max(0, gameState.energy - 2);
 
 
 
 
 
567
  }
568
 
569
+ function updateGameInfo() {
570
+ document.getElementById('gameDay').textContent = `Day ${gameState.day}`;
571
+ document.getElementById('gameTime').textContent = gameState.time;
572
+ document.getElementById('gameMoney').textContent = gameState.money;
573
+ document.getElementById('gameEnergy').textContent = `${gameState.energy}/${gameState.maxEnergy}`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574
 
575
+ // Update stat bars
576
+ for (const stat in gameState.stats) {
577
+ const statElements = document.querySelectorAll(`.stat-bar[data-stat="${stat}"]`);
578
+ statElements.forEach(el => {
579
+ el.style.width = `${gameState.stats[stat]}%`;
580
+ });
 
 
 
 
581
  }
 
 
 
 
 
 
582
  }
583
 
584
+ function renderCharacterList() {
585
+ characterList.innerHTML = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
586
 
587
+ for (const girlId in monstergirls) {
588
+ const girl = monstergirls[girlId];
589
+ const relationship = gameState.relationships[girlId];
590
+
591
+ const girlCard = document.createElement('div');
592
+ girlCard.className = `character-card ${girl.color} ${girl.borderColor} border-2 p-3 rounded-lg flex items-center`;
593
+
594
+ // Calculate overall relationship percentage (simplified)
595
+ const totalStats = Object.values(relationship).reduce((a, b) => a + b, 0);
596
+ const relationshipPercent = Math.floor(totalStats / (Object.keys(relationship).length * 100) * 100);
597
+
598
+ girlCard.innerHTML = `
599
+ <div class="w-12 h-12 rounded-full ${girl.color} border-2 ${girl.borderColor} mr-3 flex-shrink-0 overflow-hidden">
600
+ <img src="https://i.imgur.com/${girl.image || 'JQl1D1X.png'}" alt="${girl.name}" class="w-full h-full object-cover">
601
+ </div>
602
+ <div class="flex-grow">
603
+ <h3 class="font-semibold ${girl.textColor}">${girl.name}</h3>
604
+ <p class="text-xs text-gray-600">${girl.species}</p>
605
+ <div class="w-full bg-gray-200 rounded-full h-1.5 mt-1">
606
+ <div class="h-1.5 rounded-full ${girl.borderColor.replace('border', 'bg')}" style="width: ${relationshipPercent}%"></div>
607
+ </div>
608
+ </div>
609
+ `;
610
+
611
+ characterList.appendChild(girlCard);
612
  }
613
  }
614
 
615
+ // Initialize
616
+ initRelationships();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
617
  </script>
618
  <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=lunarflu/rpg" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
619
  </html>