dopaminejs 1.0.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/dopamine.mjs CHANGED
@@ -1,4 +1,4 @@
1
- class p {
1
+ class g {
2
2
  constructor() {
3
3
  this.listeners = /* @__PURE__ */ new Map();
4
4
  }
@@ -8,28 +8,28 @@ class p {
8
8
  * @param {Function} callback - Callback function
9
9
  * @returns {Function} Unsubscribe function
10
10
  */
11
- on(t, e) {
12
- return this.listeners.has(t) || this.listeners.set(t, /* @__PURE__ */ new Set()), this.listeners.get(t).add(e), () => this.off(t, e);
11
+ on(e, t) {
12
+ return this.listeners.has(e) || this.listeners.set(e, /* @__PURE__ */ new Set()), this.listeners.get(e).add(t), () => this.off(e, t);
13
13
  }
14
14
  /**
15
15
  * Unsubscribe from an event
16
16
  * @param {string} event - Event name
17
17
  * @param {Function} callback - Callback function
18
18
  */
19
- off(t, e) {
20
- this.listeners.has(t) && this.listeners.get(t).delete(e);
19
+ off(e, t) {
20
+ this.listeners.has(e) && this.listeners.get(e).delete(t);
21
21
  }
22
22
  /**
23
23
  * Emit an event
24
24
  * @param {string} event - Event name
25
25
  * @param {*} data - Event data
26
26
  */
27
- emit(t, e) {
28
- this.listeners.has(t) && this.listeners.get(t).forEach((i) => {
27
+ emit(e, t) {
28
+ this.listeners.has(e) && this.listeners.get(e).forEach((s) => {
29
29
  try {
30
- i(e);
31
- } catch (s) {
32
- console.error(`Error in listener for event '${t}':`, s);
30
+ s(t);
31
+ } catch (i) {
32
+ console.error(`Error in listener for event '${e}':`, i);
33
33
  }
34
34
  });
35
35
  }
@@ -40,9 +40,9 @@ class p {
40
40
  this.listeners.clear();
41
41
  }
42
42
  }
43
- class m extends p {
44
- constructor(t, e = {}) {
45
- super(), this.dataService = t, this.player = null, this.achievements = { ...this._initAchievements(), ...e.achievements || {} };
43
+ class x extends g {
44
+ constructor(e, t = {}) {
45
+ super(), this.dataService = e, this.player = null, this.achievements = { ...this._initAchievements(), ...t.achievements || {} };
46
46
  }
47
47
  /**
48
48
  * Initialize the reward system for current player
@@ -86,28 +86,28 @@ class m extends p {
86
86
  * @param {string} reason - Why XP was awarded (for notifications)
87
87
  * @returns {Object} { leveledUp: boolean, newLevel: number, xpGained: number }
88
88
  */
89
- async addXP(t, e = "") {
90
- const i = this.player.level;
91
- this.player.xp += t;
92
- const s = this._calculateLevel(this.player.xp), a = s > i;
93
- return a && (this.player.level = s), await this.save(), this.emit("xp_gained", { amount: t, reason: e, leveledUp: a, newLevel: s }), a && this.emit("level_up", { oldLevel: i, newLevel: s }), { leveledUp: a, newLevel: s, xpGained: t };
89
+ async addXP(e, t = "") {
90
+ const s = this.player.level;
91
+ this.player.xp += e;
92
+ const i = this._calculateLevel(this.player.xp), a = i > s;
93
+ return a && (this.player.level = i), await this.save(), this.emit("xp_gained", { amount: e, reason: t, leveledUp: a, newLevel: i }), a && this.emit("level_up", { oldLevel: s, newLevel: i }), { leveledUp: a, newLevel: i, xpGained: e };
94
94
  }
95
95
  /**
96
96
  * Calculate level from XP (exponential curve)
97
97
  */
98
- _calculateLevel(t) {
99
- const e = Math.floor((1 + Math.sqrt(1 + 8 * t / 50)) / 2);
100
- return Math.max(1, e);
98
+ _calculateLevel(e) {
99
+ const t = Math.floor((1 + Math.sqrt(1 + 8 * e / 50)) / 2);
100
+ return Math.max(1, t);
101
101
  }
102
102
  /**
103
103
  * Get XP needed for next level
104
104
  */
105
105
  getXPForNextLevel() {
106
- const t = this.player.level + 1, e = 50 * t * (t - 1), i = 50 * this.player.level * (this.player.level - 1);
106
+ const e = this.player.level + 1, t = 50 * e * (e - 1), s = 50 * this.player.level * (this.player.level - 1);
107
107
  return {
108
- total: e,
109
- needed: e - this.player.xp,
110
- progress: (this.player.xp - i) / (e - i)
108
+ total: t,
109
+ needed: t - this.player.xp,
110
+ progress: (this.player.xp - s) / (t - s)
111
111
  };
112
112
  }
113
113
  /**
@@ -115,74 +115,74 @@ class m extends p {
115
115
  * @param {string} gameName - Unique ID for the game
116
116
  * @param {Object} result - Game-specific result data
117
117
  */
118
- async recordGame(t, e) {
119
- this.player.stats[t] || (this.player.stats[t] = { totalPlays: 0, highScore: 0 });
120
- const i = this.player.stats[t];
121
- i.totalPlays++, this.player.totalGamesPlayed++, e.score !== void 0 && e.score > i.highScore && (i.highScore = e.score, this.emit("new_high_score", { gameName: t, score: e.score })), Object.keys(e).forEach((a) => {
122
- a !== "score" && (i[a] = (i[a] || 0) + (typeof e[a] == "number" ? e[a] : 0));
118
+ async recordGame(e, t) {
119
+ this.player.stats[e] || (this.player.stats[e] = { totalPlays: 0, highScore: 0 });
120
+ const s = this.player.stats[e];
121
+ s.totalPlays++, this.player.totalGamesPlayed++, t.score !== void 0 && t.score > s.highScore && (s.highScore = t.score, this.emit("new_high_score", { gameName: e, score: t.score })), Object.keys(t).forEach((a) => {
122
+ a !== "score" && (s[a] = (s[a] || 0) + (typeof t[a] == "number" ? t[a] : 0));
123
123
  });
124
- let s = 10;
125
- e.score && (s += Math.floor(e.score / 5)), s = Math.floor(s * this.getStreakMultiplier()), await this.addXP(s, `Played ${t}`), await this.checkAchievements(t, e), await this.save();
124
+ let i = 10;
125
+ t.score && (i += Math.floor(t.score / 5)), i = Math.floor(i * this.getStreakMultiplier()), await this.addXP(i, `Played ${e}`), await this.checkAchievements(e, t), await this.save();
126
126
  }
127
127
  /**
128
128
  * Check and unlock achievements
129
129
  */
130
- async checkAchievements(t, e) {
131
- const i = [];
132
- for (const [s, a] of Object.entries(this.achievements))
133
- this.player.achievements[s] || a.check(this.player, t, e) && (await this.unlockAchievement(s), i.push(a));
134
- return i;
130
+ async checkAchievements(e, t) {
131
+ const s = [];
132
+ for (const [i, a] of Object.entries(this.achievements))
133
+ this.player.achievements[i] || a.check(this.player, e, t) && (await this.unlockAchievement(i), s.push(a));
134
+ return s;
135
135
  }
136
136
  /**
137
137
  * Unlock an achievement
138
138
  */
139
- async unlockAchievement(t) {
140
- const e = this.achievements[t];
141
- return e ? (this.player.achievements[t] = {
139
+ async unlockAchievement(e) {
140
+ const t = this.achievements[e];
141
+ return t ? (this.player.achievements[e] = {
142
142
  unlockedAt: Date.now(),
143
143
  seen: !1
144
- }, await this.addXP(e.xp, `Achievement: ${e.name}`), this.emit("achievement_unlocked", e), await this.save(), !0) : !1;
144
+ }, await this.addXP(t.xp, `Achievement: ${t.name}`), this.emit("achievement_unlocked", t), await this.save(), !0) : !1;
145
145
  }
146
146
  /**
147
147
  * Get all unlocked achievements
148
148
  */
149
149
  getUnlockedAchievements() {
150
- return Object.entries(this.player.achievements).map(([t, e]) => ({
151
- ...this.achievements[t],
152
- id: t,
153
- ...e
150
+ return Object.entries(this.player.achievements).map(([e, t]) => ({
151
+ ...this.achievements[e],
152
+ id: e,
153
+ ...t
154
154
  }));
155
155
  }
156
156
  /**
157
157
  * Get achievements user hasn't seen the notification for yet
158
158
  */
159
159
  getUnseenAchievements() {
160
- return this.getUnlockedAchievements().filter((t) => !t.seen);
160
+ return this.getUnlockedAchievements().filter((e) => !e.seen);
161
161
  }
162
162
  /**
163
163
  * Mark achievements as seen
164
164
  */
165
- async markAchievementsSeen(t) {
166
- for (const e of t)
167
- this.player.achievements[e] && (this.player.achievements[e].seen = !0);
165
+ async markAchievementsSeen(e) {
166
+ for (const t of e)
167
+ this.player.achievements[t] && (this.player.achievements[t].seen = !0);
168
168
  await this.save();
169
169
  }
170
170
  /**
171
171
  * Update daily streak
172
172
  */
173
173
  _updateDailyStreak() {
174
- const t = this._getTodayDateString(), e = this.player.streak.lastPlayDate;
175
- if (e === t)
174
+ const e = this._getTodayDateString(), t = this.player.streak.lastPlayDate;
175
+ if (t === e)
176
176
  return;
177
- const i = this._getYesterdayDateString();
178
- e === i ? (this.player.streak.current++, this.player.streak.current > this.player.streak.longest && (this.player.streak.longest = this.player.streak.current)) : this.player.streak.current = 1, this.player.streak.lastPlayDate = t;
177
+ const s = this._getYesterdayDateString();
178
+ t === s ? (this.player.streak.current++, this.player.streak.current > this.player.streak.longest && (this.player.streak.longest = this.player.streak.current)) : this.player.streak.current = 1, this.player.streak.lastPlayDate = e;
179
179
  }
180
180
  /**
181
181
  * Get streak multiplier for XP
182
182
  */
183
183
  getStreakMultiplier() {
184
- const t = this.player.streak.current;
185
- return t >= 7 ? 2 : t >= 5 ? 1.5 : t >= 3 ? 1.25 : 1;
184
+ const e = this.player.streak.current;
185
+ return e >= 7 ? 2 : e >= 5 ? 1.5 : e >= 3 ? 1.25 : 1;
186
186
  }
187
187
  /**
188
188
  * Get today's date as YYYY-MM-DD string
@@ -194,8 +194,8 @@ class m extends p {
194
194
  * Get yesterday's date as YYYY-MM-DD string
195
195
  */
196
196
  _getYesterdayDateString() {
197
- const t = /* @__PURE__ */ new Date();
198
- return t.setDate(t.getDate() - 1), t.toISOString().split("T")[0];
197
+ const e = /* @__PURE__ */ new Date();
198
+ return e.setDate(e.getDate() - 1), e.toISOString().split("T")[0];
199
199
  }
200
200
  /**
201
201
  * Initialize achievement definitions
@@ -209,54 +209,54 @@ class m extends p {
209
209
  description: "Play your first game",
210
210
  icon: "🎮",
211
211
  xp: 50,
212
- check: (t) => t.totalGamesPlayed >= 1
212
+ check: (e) => e.totalGamesPlayed >= 1
213
213
  },
214
214
  level_5: {
215
215
  name: "Rising Star",
216
216
  description: "Reach level 5",
217
217
  icon: "⭐",
218
218
  xp: 100,
219
- check: (t) => t.level >= 5
219
+ check: (e) => e.level >= 5
220
220
  },
221
221
  level_10: {
222
222
  name: "Expert Player",
223
223
  description: "Reach level 10",
224
224
  icon: "🏆",
225
225
  xp: 250,
226
- check: (t) => t.level >= 10
226
+ check: (e) => e.level >= 10
227
227
  },
228
228
  streak_3: {
229
229
  name: "Dedicated",
230
230
  description: "Play 3 days in a row",
231
231
  icon: "🔥",
232
232
  xp: 100,
233
- check: (t) => t.streak.current >= 3
233
+ check: (e) => e.streak.current >= 3
234
234
  },
235
235
  streak_7: {
236
236
  name: "Unstoppable",
237
237
  description: "Play 7 days in a row",
238
238
  icon: "💥",
239
239
  xp: 300,
240
- check: (t) => t.streak.current >= 7
240
+ check: (e) => e.streak.current >= 7
241
241
  }
242
242
  };
243
243
  }
244
244
  }
245
- class y {
246
- constructor(t = {}) {
247
- this.storage = t.storage || window.localStorage, this.prefix = t.prefix || "dopamine_";
245
+ class w {
246
+ constructor(e = {}) {
247
+ this.storage = e.storage || window.localStorage, this.prefix = e.prefix || "dopamine_";
248
248
  }
249
249
  /**
250
250
  * Save data to local storage
251
251
  * @param {string} key
252
252
  * @param {any} data
253
253
  */
254
- async save(t, e) {
254
+ async save(e, t) {
255
255
  try {
256
- const i = JSON.stringify(e);
257
- return this.storage.setItem(this.prefix + t, i), !0;
258
- } catch (i) {
259
- return console.error("Error saving data:", i), !1;
256
+ const s = JSON.stringify(t);
257
+ return this.storage.setItem(this.prefix + e, s), !0;
258
+ } catch (s) {
259
+ return console.error("Error saving data:", s), !1;
260
260
  }
261
261
  }
262
262
  /**
@@ -264,25 +264,25 @@ class y {
264
264
  * @param {string} key
265
265
  * @param {any} defaultValue
266
266
  */
267
- async load(t, e = null) {
267
+ async load(e, t = null) {
268
268
  try {
269
- const i = this.storage.getItem(this.prefix + t);
270
- return i ? JSON.parse(i) : e;
271
- } catch (i) {
272
- return console.error("Error loading data:", i), e;
269
+ const s = this.storage.getItem(this.prefix + e);
270
+ return s ? JSON.parse(s) : t;
271
+ } catch (s) {
272
+ return console.error("Error loading data:", s), t;
273
273
  }
274
274
  }
275
275
  /**
276
276
  * Clear specific data
277
277
  * @param {string} key
278
278
  */
279
- async clear(t) {
280
- this.storage.removeItem(this.prefix + t);
279
+ async clear(e) {
280
+ this.storage.removeItem(this.prefix + e);
281
281
  }
282
282
  }
283
- class v {
284
- constructor(t) {
285
- this.particleSystem = t, this.container = null, this.xpBar = null, this.levelDisplay = null, this.streakDisplay = null, this.init();
283
+ class S {
284
+ constructor(e) {
285
+ this.particleSystem = e, this.container = null, this.xpBar = null, this.levelDisplay = null, this.streakDisplay = null, this.init();
286
286
  }
287
287
  /**
288
288
  * Initialize UI overlay
@@ -312,234 +312,248 @@ class v {
312
312
  /**
313
313
  * Update XP bar
314
314
  */
315
- updateXP(t, e, i) {
316
- const s = t / i * 100;
317
- this.xpBar.style.width = `${Math.min(100, s)}%`, this.xpText.textContent = `${t} / ${i} XP`, this.xpBar.style.animation = "none", setTimeout(() => {
315
+ updateXP(e, t, s) {
316
+ const i = e / s * 100;
317
+ this.xpBar.style.width = `${Math.min(100, i)}%`, this.xpText.textContent = `${e} / ${s} XP`, this.xpBar.style.animation = "none", setTimeout(() => {
318
318
  this.xpBar.style.animation = "xp-pulse 0.3s ease-out";
319
319
  }, 10);
320
320
  }
321
321
  /**
322
322
  * Update level display
323
323
  */
324
- updateLevel(t) {
325
- this.levelDisplay.textContent = t;
326
- const e = document.getElementById("level-badge");
327
- e.style.animation = "none", setTimeout(() => {
328
- e.style.animation = "level-pulse 0.5s ease-out";
324
+ updateLevel(e) {
325
+ this.levelDisplay.textContent = e;
326
+ const t = document.getElementById("level-badge");
327
+ t.style.animation = "none", setTimeout(() => {
328
+ t.style.animation = "level-pulse 0.5s ease-out";
329
329
  }, 10);
330
330
  }
331
331
  /**
332
332
  * Update streak display
333
333
  */
334
- updateStreak(t) {
335
- this.streakDisplay.textContent = t;
336
- const e = document.getElementById("streak-badge");
337
- t >= 7 ? e.style.background = "linear-gradient(135deg, #ff6b00 0%, #ff4400 100%)" : t >= 3 && (e.style.background = "linear-gradient(135deg, #ff8800 0%, #ff6b00 100%)");
334
+ updateStreak(e) {
335
+ this.streakDisplay.textContent = e;
336
+ const t = document.getElementById("streak-badge");
337
+ e >= 7 ? t.style.background = "linear-gradient(135deg, #ff6b00 0%, #ff4400 100%)" : e >= 3 && (t.style.background = "linear-gradient(135deg, #ff8800 0%, #ff6b00 100%)");
338
338
  }
339
339
  /**
340
340
  * Show achievement unlocked popup
341
341
  */
342
- showAchievement(t) {
343
- const e = document.createElement("div");
344
- e.className = "achievement-popup", e.innerHTML = `
342
+ showAchievement(e) {
343
+ const t = document.createElement("div");
344
+ t.className = "achievement-popup", t.innerHTML = `
345
345
  <div class="achievement-shine"></div>
346
346
  <div class="achievement-content">
347
- <div class="achievement-icon">${t.icon}</div>
347
+ <div class="achievement-icon">${e.icon}</div>
348
348
  <div class="achievement-info">
349
349
  <div class="achievement-title">Achievement Unlocked!</div>
350
- <div class="achievement-name">${t.name}</div>
351
- <div class="achievement-desc">${t.description}</div>
352
- <div class="achievement-xp">+${t.xp} XP</div>
350
+ <div class="achievement-name">${e.name}</div>
351
+ <div class="achievement-desc">${e.description}</div>
352
+ <div class="achievement-xp">+${e.xp} XP</div>
353
353
  </div>
354
354
  </div>
355
- `, document.body.appendChild(e), setTimeout(() => {
356
- const i = e.getBoundingClientRect();
357
- this.particleSystem.confetti(i.left + i.width / 2, i.top + i.height / 2, 40);
355
+ `, document.body.appendChild(t), setTimeout(() => {
356
+ const s = t.getBoundingClientRect();
357
+ this.particleSystem.confetti(s.left + s.width / 2, s.top + s.height / 2, 40);
358
358
  }, 300), setTimeout(() => {
359
- e.style.animation = "slideOut 0.3s ease-in forwards", setTimeout(() => e.remove(), 300);
359
+ t.style.animation = "slideOut 0.3s ease-in forwards", setTimeout(() => t.remove(), 300);
360
360
  }, 4e3);
361
361
  }
362
362
  /**
363
363
  * Show level up screen
364
364
  */
365
- showLevelUp(t, e) {
366
- const i = document.createElement("div");
367
- i.className = "level-up-overlay", i.innerHTML = `
365
+ showLevelUp(e, t) {
366
+ const s = document.createElement("div");
367
+ s.className = "level-up-overlay", s.innerHTML = `
368
368
  <div class="level-up-content">
369
369
  <div class="level-up-title">LEVEL UP!</div>
370
- <div class="level-up-number">${e}</div>
370
+ <div class="level-up-number">${t}</div>
371
371
  <div class="level-up-subtitle">Amazing progress!</div>
372
372
  </div>
373
- `, document.body.appendChild(i), setTimeout(() => {
374
- for (let s = 0; s < 5; s++)
373
+ `, document.body.appendChild(s), setTimeout(() => {
374
+ for (let i = 0; i < 5; i++)
375
375
  setTimeout(() => {
376
376
  const a = Math.random() * window.innerWidth, n = Math.random() * window.innerHeight * 0.6;
377
377
  this.particleSystem.confetti(a, n, 30);
378
- }, s * 200);
378
+ }, i * 200);
379
379
  }, 300), setTimeout(() => {
380
- i.style.opacity = "0", setTimeout(() => i.remove(), 500);
380
+ s.style.opacity = "0", setTimeout(() => s.remove(), 500);
381
381
  }, 2500);
382
382
  }
383
383
  /**
384
384
  * Show floating text (e.g., "+50 XP", "COMBO!")
385
385
  */
386
- showFloatingText(t, e, i, s = "#ffd700", a = "24px") {
386
+ showFloatingText(e, t, s, i = "#ffd700", a = "24px") {
387
387
  const n = document.createElement("div");
388
- n.className = "floating-text", n.textContent = t, n.style.left = e + "px", n.style.top = i + "px", n.style.color = s, n.style.fontSize = a, document.body.appendChild(n), setTimeout(() => n.remove(), 2e3);
388
+ n.className = "floating-text", n.textContent = e, n.style.left = t + "px", n.style.top = s + "px", n.style.color = i, n.style.fontSize = a, document.body.appendChild(n), setTimeout(() => n.remove(), 2e3);
389
389
  }
390
390
  /**
391
391
  * Show combo multiplier
392
392
  */
393
- showCombo(t, e, i) {
394
- this.showFloatingText(`${t}× COMBO!`, e, i, "#ff6b6b", "32px"), this.particleSystem.fire(e, i, 20);
393
+ showCombo(e, t, s) {
394
+ this.showFloatingText(`${e}× COMBO!`, t, s, "#ff6b6b", "32px"), this.particleSystem.fire(t, s, 20);
395
395
  }
396
396
  /**
397
397
  * Show "near miss"indicator
398
398
  */
399
- showNearMiss(t, e) {
400
- this.showFloatingText("CLOSE CALL!", t, e, "#45b7d1", "20px"), this.particleSystem.sparkle(t, e, 15, "#45b7d1");
399
+ showNearMiss(e, t) {
400
+ this.showFloatingText("CLOSE CALL!", e, t, "#45b7d1", "20px"), this.particleSystem.sparkle(e, t, 15, "#45b7d1");
401
401
  }
402
402
  /**
403
403
  * Show lucky moment (random multiplier)
404
404
  */
405
- showLuckyMoment(t, e, i) {
406
- this.showFloatingText(`LUCKY ${t}×!`, e, i, "#ffd700", "36px"), this.particleSystem.starBurst(e, i, 12), this.particleSystem.confetti(e, i, 25);
405
+ showLuckyMoment(e, t, s) {
406
+ this.showFloatingText(`LUCKY ${e}×!`, t, s, "#ffd700", "36px"), this.particleSystem.starBurst(t, s, 12), this.particleSystem.confetti(t, s, 25);
407
407
  }
408
408
  /**
409
409
  * Show generic notification
410
410
  */
411
- showNotification(t, e = "normal") {
412
- const i = window.innerWidth / 2, s = window.innerHeight / 3;
413
- e === "legendary" ? this.showLuckyMoment(t, i, s) : e === "rare" ? this.showCombo(t, i, s) : this.showFloatingText(t, i, s, "#fff", "24px");
411
+ showNotification(e, t = "normal") {
412
+ const s = window.innerWidth / 2, i = window.innerHeight / 3;
413
+ t === "legendary" ? this.showLuckyMoment(e, s, i) : t === "rare" ? this.showCombo(e, s, i) : this.showFloatingText(e, s, i, "#fff", "24px");
414
414
  }
415
415
  /**
416
416
  * Show Game Over Summary
417
417
  */
418
- showSummary(t) {
419
- const e = document.createElement("div");
420
- e.className = "message-box", e.style.display = "flex", e.style.position = "absolute", e.style.top = "50%", e.style.left = "50%", e.style.transform = "translate(-50%, -50%)", e.style.zIndex = "1000";
421
- let i = "";
422
- t.metrics && (i = Object.entries(t.metrics).map(([s, a]) => `<div style="display:flex;justify-content:space-between;width:100%"><span>${s}:</span> <strong>${a}</strong></div>`).join("")), e.innerHTML = `
418
+ showSummary(e) {
419
+ const t = document.createElement("div");
420
+ t.className = "message-box", t.style.display = "flex", t.style.position = "absolute", t.style.top = "50%", t.style.left = "50%", t.style.transform = "translate(-50%, -50%)", t.style.zIndex = "1000";
421
+ let s = "";
422
+ e.metrics && (s = Object.entries(e.metrics).map(([i, a]) => `<div style="display:flex;justify-content:space-between;width:100%"><span>${i}:</span> <strong>${a}</strong></div>`).join("")), t.innerHTML = `
423
423
  <h1>Game Over</h1>
424
- <div style="font-size: 3rem; font-weight: bold; color: #e06020; margin: 10px 0;">${t.score}</div>
424
+ <div style="font-size: 3rem; font-weight: bold; color: #e06020; margin: 10px 0;">${e.score}</div>
425
425
  <div style="width: 100%; margin-bottom: 20px;">
426
- ${i}
426
+ ${s}
427
427
  </div>
428
428
  <button class="btn" onclick="location.reload()">Play Again</button>
429
429
  <button class="btn" onclick="window.location.href='index.html'" style="margin-top: 10px; background: #543847;">Exit</button>
430
- `, document.body.appendChild(e);
430
+ `, document.body.appendChild(t);
431
431
  }
432
432
  }
433
- class u {
434
- constructor(t = {}) {
435
- this.canvasId = t.canvasId || "dopamine-particle-canvas", this.canvas = document.getElementById(this.canvasId), this.canvas || (this.canvas = document.createElement("canvas"), this.canvas.id = this.canvasId, this.canvas.style.position = "fixed", this.canvas.style.top = "0", this.canvas.style.left = "0", this.canvas.style.width = "100%", this.canvas.style.height = "100%", this.canvas.style.pointerEvents = "none", this.canvas.style.zIndex = t.zIndex || "9999", document.body.appendChild(this.canvas)), this.ctx = this.canvas.getContext("2d"), this.particles = [], this.isAnimating = !1, this._resize(), window.addEventListener("resize", () => this._resize());
433
+ class b {
434
+ constructor(e = {}) {
435
+ this.container = e.container ? typeof e.container == "string" ? document.querySelector(e.container) : e.container : document.body, this.canvasId = e.canvasId || "dopamine-particle-canvas", this.canvas = document.getElementById(this.canvasId), this.canvas || (this.canvas = document.createElement("canvas"), this.canvas.id = this.canvasId, this.canvas.style.pointerEvents = "none", this.canvas.style.zIndex = e.zIndex || "9999", this.container === document.body ? (this.canvas.style.position = "fixed", this.canvas.style.top = "0", this.canvas.style.left = "0") : (this.canvas.style.position = "absolute", this.canvas.style.top = "0", this.canvas.style.left = "0", window.getComputedStyle(this.container).position === "static" && (this.container.style.position = "relative")), this.container.appendChild(this.canvas)), this.ctx = this.canvas.getContext("2d"), this.particles = [], this.pool = [], this.sprites = /* @__PURE__ */ new Map(), this.customEffects = /* @__PURE__ */ new Map(), this.isAnimating = !1, this._resize(), window.ResizeObserver && this.container !== document.body ? new ResizeObserver(() => this._resize()).observe(this.container) : window.addEventListener("resize", () => this._resize());
436
436
  }
437
437
  _resize() {
438
- this.canvas.width = window.innerWidth, this.canvas.height = window.innerHeight;
439
- }
440
- /**
441
- * Confetti explosion (for achievements, level ups)
442
- */
443
- confetti(t, e, i = 50) {
444
- const s = ["#ff6b6b", "#4ecdc4", "#45b7d1", "#f7dc6f", "#c06c84", "#6c5ce7"];
445
- for (let a = 0; a < i; a++)
446
- this.particles.push({
447
- x: t,
448
- y: e,
449
- vx: (Math.random() - 0.5) * 10,
450
- vy: (Math.random() - 0.5) * 10 - 5,
451
- rotation: Math.random() * Math.PI * 2,
452
- rotationSpeed: (Math.random() - 0.5) * 0.2,
453
- color: s[Math.floor(Math.random() * s.length)],
454
- size: Math.random() * 8 + 4,
455
- life: 1,
456
- decay: 0.015 + Math.random() * 0.01,
457
- gravity: 0.3,
458
- type: "confetti"
459
- });
460
- this._startAnimation();
438
+ this.container === document.body ? (this.canvas.width = window.innerWidth, this.canvas.height = window.innerHeight) : (this.canvas.width = this.container.clientWidth, this.canvas.height = this.container.clientHeight);
461
439
  }
462
440
  /**
463
- * Sparkle effect (for score milestones, combos)
464
- */
465
- sparkle(t, e, i = 20, s = "#ffd700") {
466
- for (let a = 0; a < i; a++) {
467
- const n = Math.PI * 2 / i * a, r = 2 + Math.random() * 3;
468
- this.particles.push({
469
- x: t,
470
- y: e,
471
- vx: Math.cos(n) * r,
472
- vy: Math.sin(n) * r,
473
- color: s,
474
- size: Math.random() * 4 + 2,
475
- life: 1,
476
- decay: 0.02,
477
- gravity: -0.1,
478
- // Slight upward drift
479
- type: "spark"
480
- });
481
- }
482
- this._startAnimation();
441
+ * Register a custom sprite image
442
+ * @param {string} key
443
+ * @param {string} url
444
+ */
445
+ registerSprite(e, t) {
446
+ const s = new Image();
447
+ s.src = t, this.sprites.set(e, s);
483
448
  }
484
449
  /**
485
- * Coin shower (for collecting coins)
486
- */
487
- coinShower(t, e, i = 10) {
488
- for (let s = 0; s < i; s++)
489
- this.particles.push({
490
- x: t + (Math.random() - 0.5) * 100,
491
- y: e - Math.random() * 50,
492
- vx: (Math.random() - 0.5) * 3,
493
- vy: Math.random() * -2 - 3,
494
- color: "#ffd700",
495
- size: 12,
496
- life: 1,
497
- decay: 0.012,
498
- gravity: 0.4,
499
- type: "coin"
500
- });
501
- this._startAnimation();
450
+ * Register a custom effect
451
+ * @param {string} name
452
+ * @param {Function} callback - (x, y, ...args) => void
453
+ */
454
+ registerEffect(e, t) {
455
+ this.customEffects.set(e, t);
502
456
  }
503
457
  /**
504
- * Fire particles (for streaks, combos)
505
- */
506
- fire(t, e, i = 15) {
507
- const s = ["#ff6b00", "#ff8800", "#ffaa00", "#ff4400"];
508
- for (let a = 0; a < i; a++)
509
- this.particles.push({
510
- x: t + (Math.random() - 0.5) * 20,
511
- y: e,
512
- vx: (Math.random() - 0.5) * 2,
513
- vy: -Math.random() * 3 - 2,
514
- color: s[Math.floor(Math.random() * s.length)],
515
- size: Math.random() * 6 + 3,
516
- life: 1,
517
- decay: 0.025,
518
- gravity: -0.2,
519
- // Upward
520
- type: "fire"
521
- });
522
- this._startAnimation();
458
+ * Play a registered effect
459
+ */
460
+ play(e, t, s, ...i) {
461
+ const a = this.customEffects.get(e);
462
+ a ? a(t, s, ...i) : console.warn(`[DopamineJS] Effect '${e}' not found.`);
523
463
  }
524
464
  /**
525
- * Star burst (for "perfect" moments)
526
- */
527
- starBurst(t, e, i = 8) {
528
- for (let s = 0; s < i; s++) {
529
- const a = Math.PI * 2 / i * s, n = 4;
530
- this.particles.push({
531
- x: t,
532
- y: e,
533
- vx: Math.cos(a) * n,
534
- vy: Math.sin(a) * n,
535
- rotation: a,
536
- color: "#ffffff",
537
- size: 15,
538
- life: 1,
539
- decay: 0.03,
540
- gravity: 0,
541
- type: "star"
542
- });
465
+ * Emit particles with custom config
466
+ * @param {Object} config
467
+ */
468
+ emit(e) {
469
+ const {
470
+ x: t,
471
+ y: s,
472
+ count: i = 10,
473
+ speed: a = 5,
474
+ gravity: n = 0.1,
475
+ decay: o = 0.02,
476
+ life: h = 1,
477
+ color: l = "#ffd700",
478
+ sprite: d = null,
479
+ spread: y = Math.PI * 2,
480
+ angle: v = 0,
481
+ size: f = 5
482
+ } = e;
483
+ for (let p = 0; p < i; p++) {
484
+ const r = this._getParticle(), u = v + (Math.random() - 0.5) * y, m = Math.random() * a;
485
+ r.x = t, r.y = s, r.vx = Math.cos(u) * m, r.vy = Math.sin(u) * m, r.life = h, r.decay = o * (0.8 + Math.random() * 0.4), r.gravity = n, r.color = Array.isArray(l) ? l[Math.floor(Math.random() * l.length)] : l, r.size = f * (0.8 + Math.random() * 0.4), r.sprite = d, r.rotation = Math.random() * Math.PI * 2, r.rotationSpeed = (Math.random() - 0.5) * 0.2, this.particles.push(r);
486
+ }
487
+ this._startAnimation();
488
+ }
489
+ _getParticle() {
490
+ return this.pool.length > 0 ? this.pool.pop() : {};
491
+ }
492
+ _recycleParticle(e) {
493
+ this.pool.push(e);
494
+ }
495
+ // --- Built-in Effects ---
496
+ confetti(e, t, s = 50) {
497
+ const i = ["#ff6b6b", "#4ecdc4", "#45b7d1", "#f7dc6f", "#c06c84", "#6c5ce7"];
498
+ this.emit({
499
+ x: e,
500
+ y: t,
501
+ count: s,
502
+ color: i,
503
+ speed: 10,
504
+ gravity: 0.3,
505
+ decay: 0.015,
506
+ size: 8,
507
+ spread: Math.PI * 2
508
+ });
509
+ }
510
+ coinShower(e, t, s = 10) {
511
+ this.emit({
512
+ x: e,
513
+ y: t,
514
+ count: s,
515
+ color: "#ffd700",
516
+ speed: 4,
517
+ gravity: 0.4,
518
+ decay: 0.012,
519
+ size: 12,
520
+ angle: -Math.PI / 2,
521
+ // Upwards initially
522
+ spread: Math.PI / 2
523
+ });
524
+ }
525
+ sparkle(e, t, s = 20, i = "#ffd700") {
526
+ this.emit({
527
+ x: e,
528
+ y: t,
529
+ count: s,
530
+ color: i,
531
+ speed: 3,
532
+ gravity: -0.05,
533
+ // Float up
534
+ decay: 0.03,
535
+ size: 3
536
+ });
537
+ }
538
+ fire(e, t, s = 15) {
539
+ const i = ["#ff6b00", "#ff8800", "#ffaa00", "#ff4400"];
540
+ this.emit({
541
+ x: e,
542
+ y: t,
543
+ count: s,
544
+ color: i,
545
+ speed: 3,
546
+ gravity: -0.2,
547
+ decay: 0.04,
548
+ size: 5,
549
+ angle: -Math.PI / 2,
550
+ spread: Math.PI / 4
551
+ });
552
+ }
553
+ starBurst(e, t, s = 8) {
554
+ for (let i = 0; i < s; i++) {
555
+ const a = this._getParticle(), n = Math.PI * 2 / s * i, o = 4;
556
+ a.x = e, a.y = t, a.vx = Math.cos(n) * o, a.vy = Math.sin(n) * o, a.life = 1, a.decay = 0.03, a.gravity = 0, a.color = "#ffffff", a.size = 15, a.sprite = null, a.type = "star", a.rotation = n, a.rotationSpeed = 0, this.particles.push(a);
543
557
  }
544
558
  this._startAnimation();
545
559
  }
@@ -548,42 +562,45 @@ class u {
548
562
  }
549
563
  _animate() {
550
564
  this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
551
- for (let t = this.particles.length - 1; t >= 0; t--) {
552
- const e = this.particles[t];
553
- if (e.vy += e.gravity, e.x += e.vx, e.y += e.vy, e.life -= e.decay, e.rotationSpeed && (e.rotation += e.rotationSpeed), e.life <= 0) {
554
- this.particles.splice(t, 1);
565
+ for (let e = this.particles.length - 1; e >= 0; e--) {
566
+ const t = this.particles[e];
567
+ if (t.vy += t.gravity, t.x += t.vx, t.y += t.vy, t.life -= t.decay, t.rotationSpeed && (t.rotation += t.rotationSpeed), t.life <= 0) {
568
+ this._recycleParticle(t), this.particles.splice(e, 1);
555
569
  continue;
556
570
  }
557
- this.ctx.save(), this.ctx.globalAlpha = e.life, this.ctx.fillStyle = e.color, e.type === "confetti" ? (this.ctx.translate(e.x, e.y), this.ctx.rotate(e.rotation), this.ctx.fillRect(-e.size / 2, -e.size / 2, e.size, e.size / 2)) : e.type === "coin" ? (this.ctx.beginPath(), this.ctx.arc(e.x, e.y, e.size, 0, Math.PI * 2), this.ctx.fill(), this.ctx.fillStyle = "#ffee88", this.ctx.beginPath(), this.ctx.arc(e.x - e.size / 3, e.y - e.size / 3, e.size / 3, 0, Math.PI * 2), this.ctx.fill()) : e.type === "star" ? this._drawStar(e.x, e.y, 5, e.size, e.size / 2, e.rotation) : (this.ctx.beginPath(), this.ctx.arc(e.x, e.y, e.size, 0, Math.PI * 2), this.ctx.fill()), this.ctx.restore();
571
+ if (this.ctx.save(), this.ctx.globalAlpha = t.life, this.ctx.translate(t.x, t.y), this.ctx.rotate(t.rotation), t.sprite && this.sprites.has(t.sprite)) {
572
+ const s = this.sprites.get(t.sprite);
573
+ s.complete && this.ctx.drawImage(s, -t.size / 2, -t.size / 2, t.size, t.size);
574
+ } else t.type === "star" ? (this.ctx.fillStyle = t.color, this._drawStarPath(0, 0, 5, t.size, t.size / 2), this.ctx.fill()) : (this.ctx.fillStyle = t.color, this.ctx.beginPath(), this.ctx.arc(0, 0, t.size, 0, Math.PI * 2), this.ctx.fill());
575
+ this.ctx.restore();
558
576
  }
559
577
  this.particles.length > 0 ? requestAnimationFrame(() => this._animate()) : this.isAnimating = !1;
560
578
  }
561
- _drawStar(t, e, i, s, a, n) {
562
- let r = Math.PI / 2 * 3 + n;
563
- const c = Math.PI / i;
564
- this.ctx.beginPath(), this.ctx.moveTo(t, e - s);
565
- for (let d = 0; d < i; d++) {
566
- let l = t + Math.cos(r) * s, h = e + Math.sin(r) * s;
567
- this.ctx.lineTo(l, h), r += c, l = t + Math.cos(r) * a, h = e + Math.sin(r) * a, this.ctx.lineTo(l, h), r += c;
568
- }
569
- this.ctx.lineTo(t, e - s), this.ctx.closePath(), this.ctx.fill();
579
+ _drawStarPath(e, t, s, i, a) {
580
+ let n = Math.PI / 2 * 3, o = e, h = t;
581
+ const l = Math.PI / s;
582
+ this.ctx.beginPath(), this.ctx.moveTo(e, t - i);
583
+ for (let d = 0; d < s; d++)
584
+ o = e + Math.cos(n) * i, h = t + Math.sin(n) * i, this.ctx.lineTo(o, h), n += l, o = e + Math.cos(n) * a, h = t + Math.sin(n) * a, this.ctx.lineTo(o, h), n += l;
585
+ this.ctx.lineTo(e, t - i), this.ctx.closePath();
570
586
  }
571
- /**
572
- * Clear all particles
573
- */
574
587
  clear() {
575
- this.particles = [], this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
588
+ this.particles.forEach((e) => this._recycleParticle(e)), this.particles = [], this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
576
589
  }
577
590
  }
578
- class f {
579
- constructor(t = {}) {
580
- this.audioContext = null, this.storageKey = t.storageKey || "dopamineSoundsMuted", this.muted = localStorage.getItem(this.storageKey) === "true";
591
+ class P {
592
+ constructor(e = {}) {
593
+ this.audioContext = null, this.storageKey = e.storageKey || "dopamineSoundsMuted", this.muted = localStorage.getItem(this.storageKey) === "true", this.assets = /* @__PURE__ */ new Map(), this.soundPack = e.soundPack || "synth", this.customSounds = e.customSounds || {}, Object.keys(this.customSounds).length > 0 && this.preloadSounds(this.customSounds);
581
594
  }
582
595
  /**
583
596
  * Initialize Audio Context (must be called after user interaction)
584
597
  */
585
598
  initAudio() {
586
- this.audioContext || (this.audioContext = new (window.AudioContext || window.webkitAudioContext)());
599
+ if (!this.audioContext) {
600
+ const e = window.AudioContext || window.webkitAudioContext;
601
+ this.audioContext = new e();
602
+ }
603
+ this.audioContext.state === "suspended" && this.audioContext.resume();
587
604
  }
588
605
  /**
589
606
  * Toggle mute state
@@ -592,42 +609,102 @@ class f {
592
609
  toggleMute() {
593
610
  return this.muted = !this.muted, localStorage.setItem(this.storageKey, this.muted), this.muted;
594
611
  }
612
+ /**
613
+ * Register a custom sound URL
614
+ * @param {string} key - Unique identifier (e.g., 'jump', 'win')
615
+ * @param {string} url - Path to audio file
616
+ */
617
+ registerSound(e, t) {
618
+ this.customSounds[e] = t, this.audioContext && this.loadSound(e, t);
619
+ }
620
+ /**
621
+ * Preload multiple sounds
622
+ * @param {Object} soundMap - { key: url }
623
+ */
624
+ async preloadSounds(e) {
625
+ const t = Object.entries(e).map(([s, i]) => this.loadSound(s, i));
626
+ await Promise.allSettled(t);
627
+ }
628
+ /**
629
+ * Load and decode a sound file
630
+ */
631
+ async loadSound(e, t) {
632
+ try {
633
+ if (!this.audioContext)
634
+ return;
635
+ const i = await (await fetch(t)).arrayBuffer(), a = await this.audioContext.decodeAudioData(i);
636
+ this.assets.set(e, a);
637
+ } catch (s) {
638
+ console.warn(`[DopamineJS] Failed to load sound '${e}':`, s);
639
+ }
640
+ }
641
+ /**
642
+ * Play a sound by key (custom) or fallback to synth
643
+ * @param {string} key - 'jump', 'score', 'success', etc.
644
+ */
645
+ async play(e) {
646
+ if (this.muted) return;
647
+ if (this.initAudio(), this.assets.has(e)) {
648
+ this._playBuffer(this.assets.get(e));
649
+ return;
650
+ }
651
+ if (this.customSounds[e] && !this.assets.has(e) && (await this.loadSound(e, this.customSounds[e]), this.assets.has(e))) {
652
+ this._playBuffer(this.assets.get(e));
653
+ return;
654
+ }
655
+ const t = {
656
+ jump: () => this.playJump(!0),
657
+ // true = force synth
658
+ score: () => this.playScore(!0),
659
+ success: () => this.playSuccess(!0),
660
+ click: () => this.playClick(!0),
661
+ error: () => this.playError(!0),
662
+ gameover: () => this.playGameOver(!0)
663
+ };
664
+ t[e] && t[e]();
665
+ }
666
+ _playBuffer(e) {
667
+ const t = this.audioContext.createBufferSource();
668
+ t.buffer = e, t.connect(this.audioContext.destination), t.start(0);
669
+ }
595
670
  /**
596
671
  * Play a synthesized tone
597
- * @param {number} frequency
598
- * @param {number} duration
599
- * @param {string} type - 'sine', 'square', 'sawtooth', 'triangle'
600
- * @param {number} volume
601
672
  */
602
- playTone(t, e, i = "sine", s = 0.3) {
673
+ playTone(e, t, s = "sine", i = 0.3) {
603
674
  if (this.muted) return;
604
675
  this.initAudio();
605
676
  const a = this.audioContext.createOscillator(), n = this.audioContext.createGain();
606
- a.connect(n), n.connect(this.audioContext.destination), a.frequency.value = t, a.type = i, n.gain.setValueAtTime(s, this.audioContext.currentTime), n.gain.exponentialRampToValueAtTime(0.01, this.audioContext.currentTime + e), a.start(this.audioContext.currentTime), a.stop(this.audioContext.currentTime + e);
677
+ a.connect(n), n.connect(this.audioContext.destination), a.frequency.value = e, a.type = s, n.gain.setValueAtTime(i, this.audioContext.currentTime), n.gain.exponentialRampToValueAtTime(0.01, this.audioContext.currentTime + t), a.start(this.audioContext.currentTime), a.stop(this.audioContext.currentTime + t);
607
678
  }
608
- // --- Presets ---
609
- playJump() {
679
+ // --- Presets (Synth) ---
680
+ playJump(e = !1) {
681
+ if (!e && this.assets.has("jump")) return this.play("jump");
610
682
  this.playTone(400, 0.1, "square", 0.2);
611
683
  }
612
- playScore() {
684
+ playScore(e = !1) {
685
+ if (!e && this.assets.has("score")) return this.play("score");
613
686
  this.playTone(800, 0.15, "sine", 0.25), setTimeout(() => this.playTone(1e3, 0.15, "sine", 0.25), 50);
614
687
  }
615
- playGameOver() {
688
+ playGameOver(e = !1) {
689
+ if (!e && this.assets.has("gameover")) return this.play("gameover");
616
690
  this.playTone(300, 0.2, "sawtooth", 0.3), setTimeout(() => this.playTone(200, 0.2, "sawtooth", 0.3), 100), setTimeout(() => this.playTone(150, 0.3, "sawtooth", 0.3), 200);
617
691
  }
618
- playClick() {
692
+ playClick(e = !1) {
693
+ if (!e && this.assets.has("click")) return this.play("click");
619
694
  this.playTone(600, 0.05, "sine", 0.1);
620
695
  }
621
- playSuccess() {
696
+ playSuccess(e = !1) {
697
+ if (!e && this.assets.has("success")) return this.play("success");
622
698
  this.playTone(600, 0.1, "sine", 0.2), setTimeout(() => this.playTone(800, 0.2, "sine", 0.2), 100);
623
699
  }
624
- playError() {
700
+ playError(e = !1) {
701
+ if (!e && this.assets.has("error")) return this.play("error");
625
702
  this.playTone(200, 0.2, "sawtooth", 0.3);
626
703
  }
627
704
  }
628
- class g {
629
- constructor(t = {}) {
630
- this.config = t, this.dataService = new y(t.data || {}), this.rewardSystem = new m(this.dataService, t.rewards || {}), this.soundManager = new f(t.sound || {}), this.particleSystem = new u(t.particles || {}), this.gameUI = new v(this.particleSystem), this._bindEvents();
705
+ class M {
706
+ constructor(e = {}) {
707
+ this.config = e, this.dataService = new w(e.data || {}), this.rewardSystem = new x(this.dataService, e.rewards || {}), this.soundManager = new P(e.sound || {}), this.particleSystem = new b(e.particles || {}), this.gameUI = new S(this.particleSystem), this._bindEvents();
631
708
  }
632
709
  async init() {
633
710
  return await this.rewardSystem.init(), console.log("DopamineJS Initialized 🚀"), {
@@ -638,23 +715,23 @@ class g {
638
715
  };
639
716
  }
640
717
  _bindEvents() {
641
- this.rewardSystem.on("xp_gained", (t) => {
642
- const { total: e, needed: i } = this.rewardSystem.getXPForNextLevel();
643
- this.gameUI.updateXP(this.rewardSystem.player.xp, i, e), t.xpGained > 0;
644
- }), this.rewardSystem.on("level_up", (t) => {
645
- this.gameUI.updateLevel(t.newLevel), this.gameUI.showLevelUp(t.oldLevel, t.newLevel);
646
- }), this.rewardSystem.on("achievement_unlocked", (t) => {
647
- this.gameUI.showAchievement(t);
648
- }), this.rewardSystem.on("new_high_score", (t) => {
649
- this.gameUI.showNotification(`New High Score: ${t.score}!`, "legendary"), this.soundManager.playSuccess();
718
+ this.rewardSystem.on("xp_gained", (e) => {
719
+ const { total: t, needed: s } = this.rewardSystem.getXPForNextLevel();
720
+ this.gameUI.updateXP(this.rewardSystem.player.xp, s, t), e.xpGained > 0;
721
+ }), this.rewardSystem.on("level_up", (e) => {
722
+ this.gameUI.updateLevel(e.newLevel), this.gameUI.showLevelUp(e.oldLevel, e.newLevel);
723
+ }), this.rewardSystem.on("achievement_unlocked", (e) => {
724
+ this.gameUI.showAchievement(e);
725
+ }), this.rewardSystem.on("new_high_score", (e) => {
726
+ this.gameUI.showNotification(`New High Score: ${e.score}!`, "legendary"), this.soundManager.playSuccess();
650
727
  });
651
728
  }
652
729
  }
653
730
  export {
654
- y as DataService,
655
- v as GameUI,
656
- u as ParticleSystem,
657
- m as RewardSystem,
658
- f as SoundManager,
659
- g as default
731
+ w as DataService,
732
+ S as GameUI,
733
+ b as ParticleSystem,
734
+ x as RewardSystem,
735
+ P as SoundManager,
736
+ M as default
660
737
  };