@gamebob/axon-surge 0.14.0 → 0.16.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.
@@ -1,4 +1,4 @@
1
- class V {
1
+ class W {
2
2
  listeners = /* @__PURE__ */ new Map();
3
3
  on(t, e) {
4
4
  return this.listeners.has(t) || this.listeners.set(t, /* @__PURE__ */ new Set()), this.listeners.get(t).add(e), () => this.off(t, e);
@@ -15,28 +15,41 @@ class V {
15
15
  this.listeners.clear();
16
16
  }
17
17
  }
18
- class W {
18
+ class Y {
19
19
  animationFrameId = null;
20
20
  lastTime = 0;
21
+ nextFrameTime = 0;
21
22
  isRunning = !1;
23
+ fpsLimit = 60;
22
24
  updateCallback;
23
25
  renderCallback;
24
26
  constructor(t, e) {
25
27
  this.updateCallback = t, this.renderCallback = e;
26
28
  }
27
29
  start() {
28
- this.isRunning || (this.isRunning = !0, this.lastTime = performance.now(), this.tick = this.tick.bind(this), this.animationFrameId = requestAnimationFrame(this.tick));
30
+ this.isRunning || (this.isRunning = !0, this.lastTime = performance.now(), this.nextFrameTime = this.lastTime, this.tick = this.tick.bind(this), this.animationFrameId = requestAnimationFrame(this.tick));
29
31
  }
30
32
  stop() {
31
33
  this.isRunning = !1, this.animationFrameId !== null && (cancelAnimationFrame(this.animationFrameId), this.animationFrameId = null);
32
34
  }
35
+ setFpsLimit(t) {
36
+ this.fpsLimit = t, this.lastTime = performance.now(), this.nextFrameTime = this.lastTime;
37
+ }
38
+ getFpsLimit() {
39
+ return this.fpsLimit;
40
+ }
33
41
  tick(t) {
34
42
  if (!this.isRunning) return;
35
- const e = Math.min((t - this.lastTime) / 1e3, 0.1);
36
- this.lastTime = t, this.updateCallback(e), this.renderCallback(), this.animationFrameId = requestAnimationFrame(this.tick);
43
+ const e = 1e3 / this.fpsLimit;
44
+ if (t + 0.25 < this.nextFrameTime) {
45
+ this.animationFrameId = requestAnimationFrame(this.tick);
46
+ return;
47
+ }
48
+ const i = Math.min((t - this.lastTime) / 1e3, 0.1);
49
+ this.lastTime = t, this.nextFrameTime += e, this.nextFrameTime < t - e && (this.nextFrameTime = t + e), this.updateCallback(i), this.renderCallback(), this.animationFrameId = requestAnimationFrame(this.tick);
37
50
  }
38
51
  }
39
- const k = {
52
+ const G = {
40
53
  core: {
41
54
  maxIntegrity: 3,
42
55
  invulnerabilityDuration: 1.5,
@@ -63,7 +76,11 @@ const k = {
63
76
  shield: {
64
77
  blastSpeed: 1600,
65
78
  hitboxRange: 280,
66
- isFanBlast: !1
79
+ protectionArc: Math.PI * 0.25,
80
+ isFanBlast: !1,
81
+ fanBlastInterval: 0.5,
82
+ fanBlastAngle: Math.PI / 4,
83
+ hasFanBlastUpgrade: !1
67
84
  },
68
85
  cluster: {
69
86
  fragmentCount: 6,
@@ -81,14 +98,14 @@ const k = {
81
98
  absorptionSpeed: 680
82
99
  }
83
100
  };
84
- class E {
101
+ class A {
85
102
  static instance;
86
103
  config;
87
104
  constructor() {
88
- this.config = JSON.parse(JSON.stringify(k));
105
+ this.config = JSON.parse(JSON.stringify(G));
89
106
  }
90
107
  static getInstance() {
91
- return E.instance || (E.instance = new E()), E.instance;
108
+ return A.instance || (A.instance = new A()), A.instance;
92
109
  }
93
110
  getConfig() {
94
111
  return this.config;
@@ -106,10 +123,10 @@ class E {
106
123
  this.config.core.maxIntegrity += t;
107
124
  }
108
125
  resetToDefault() {
109
- this.config = JSON.parse(JSON.stringify(k));
126
+ this.config = JSON.parse(JSON.stringify(G));
110
127
  }
111
128
  }
112
- class F {
129
+ class Z {
113
130
  position;
114
131
  radius;
115
132
  integrity;
@@ -122,7 +139,7 @@ class F {
122
139
  powerUpCount = 0;
123
140
  collectedPowerUpColors = [];
124
141
  constructor(t, e) {
125
- const i = E.getInstance().getConfig().core;
142
+ const i = A.getInstance().getConfig().core;
126
143
  this.position = { x: t, y: e }, this.radius = i.radius, this.integrity = i.maxIntegrity, this.maxIntegrity = i.maxIntegrity, this.maxInvulnerabilityDuration = i.invulnerabilityDuration, this.organicSeed = Math.random() * 100;
127
144
  }
128
145
  absorbPowerUpColor(t, e = 0.35) {
@@ -149,7 +166,7 @@ class F {
149
166
  }
150
167
  repairProgress = 0;
151
168
  addKillRepair() {
152
- const t = E.getInstance().getConfig().core.vampirismHealProgressRate;
169
+ const t = A.getInstance().getConfig().core.vampirismHealProgressRate;
153
170
  return t <= 0 ? !1 : (this.repairProgress += t, this.repairProgress >= 1 ? (this.integrity += 1, this.integrity > this.maxIntegrity && (this.maxIntegrity = this.integrity), this.repairProgress = 0, !0) : !1);
154
171
  }
155
172
  heal(t = 1) {
@@ -162,11 +179,11 @@ class F {
162
179
  return this.invulnerabilityTimer > 0 ? !1 : this.integrity > 0 ? (this.integrity -= 1, this.invulnerabilityTimer = this.maxInvulnerabilityDuration, !0) : !1;
163
180
  }
164
181
  reset(t, e) {
165
- const i = E.getInstance().getConfig().core;
182
+ const i = A.getInstance().getConfig().core;
166
183
  this.position = { x: t, y: e }, this.radius = i.radius, this.maxIntegrity = i.maxIntegrity, this.integrity = this.maxIntegrity, this.maxInvulnerabilityDuration = i.invulnerabilityDuration, this.pulsePhase = 0, this.invulnerabilityTimer = 0, this.repairProgress = 0, this.powerUpCount = 0, this.collectedPowerUpColors = [], this.customColor = { r: 0, g: 240, b: 255 };
167
184
  }
168
185
  }
169
- class D {
186
+ class U {
170
187
  id;
171
188
  position = { x: 0, y: 0 };
172
189
  velocity = { x: 0, y: 0 };
@@ -183,6 +200,7 @@ class D {
183
200
  maxSpeed = 200;
184
201
  isStationaryShield = !1;
185
202
  shieldAngle = 0;
203
+ launchDelay = 0;
186
204
  remainingHomingKills = 0;
187
205
  experienceDropPending = !1;
188
206
  isDying = !1;
@@ -208,7 +226,7 @@ class D {
208
226
  this.deathTimer += t, this.deathTimer >= this.maxDeathTimer && (this.active = !1, this.isDying = !1);
209
227
  return;
210
228
  }
211
- if (!(this.isGrabbed || this.isStationaryShield)) {
229
+ if (!(this.launchDelay > 0 && (this.launchDelay = Math.max(0, this.launchDelay - t), this.launchDelay > 0)) && !(this.isGrabbed || this.isStationaryShield)) {
212
230
  if (!this.isThrown && this.maxSpeed > 0) {
213
231
  const e = Math.hypot(this.velocity.x, this.velocity.y);
214
232
  if (e > this.maxSpeed) {
@@ -221,10 +239,10 @@ class D {
221
239
  }
222
240
  }
223
241
  reset() {
224
- this.active = !1, this.isGrabbed = !1, this.isThrown = !1, this.wasManipulated = !1, this.isDying = !1, this.deathType = "none", this.deathTimer = 0, this.sliceAngle = 0, this.isStationaryShield = !1, this.shieldAngle = 0, this.experienceDropPending = !1, this.position = { x: 0, y: 0 }, this.velocity = { x: 0, y: 0 }, this.rotation = 0, this.strategy = null, this.maxSpeed = 200;
242
+ this.active = !1, this.isGrabbed = !1, this.isThrown = !1, this.wasManipulated = !1, this.isDying = !1, this.deathType = "none", this.deathTimer = 0, this.sliceAngle = 0, this.isStationaryShield = !1, this.shieldAngle = 0, this.launchDelay = 0, this.experienceDropPending = !1, this.position = { x: 0, y: 0 }, this.velocity = { x: 0, y: 0 }, this.rotation = 0, this.strategy = null, this.maxSpeed = 200;
225
243
  }
226
244
  }
227
- class G {
245
+ class H {
228
246
  id;
229
247
  definition;
230
248
  position = { x: 0, y: 0 };
@@ -241,7 +259,7 @@ class G {
241
259
  this.active && !this.isGrabbed && !this.isHovered && (this.orbitAngle += t * 0.25, this.position.x = e.x + Math.cos(this.orbitAngle) * this.orbitDistance, this.position.y = e.y + Math.sin(this.orbitAngle) * this.orbitDistance);
242
260
  }
243
261
  }
244
- class Y {
262
+ class $ {
245
263
  pointerPosition = { x: 0, y: 0 };
246
264
  isPointerDown = !1;
247
265
  grabbedEnemy = null;
@@ -302,7 +320,7 @@ class Y {
302
320
  if (this.grabbedEnemy) return this.grabbedEnemy;
303
321
  const i = e ? 50 : 20;
304
322
  for (const s of t) {
305
- if (!s.active || s.isGrabbed || s.isThrown || s.wasManipulated) continue;
323
+ if (!s.active || s.isGrabbed || s.isThrown || s.wasManipulated || s.launchDelay > 0) continue;
306
324
  const a = this.pointerPosition.x - s.position.x, l = this.pointerPosition.y - s.position.y;
307
325
  if (Math.hypot(a, l) <= s.getHitRadius() + i)
308
326
  return s.isGrabbed = !0, this.grabbedEnemy = s, this.dragStart = { ...this.pointerPosition }, this.pointerHistory = [], s;
@@ -340,10 +358,10 @@ class Y {
340
358
  } else if (this.dragStart) {
341
359
  const o = t.position.x - this.dragStart.x, r = t.position.y - this.dragStart.y, c = Math.hypot(o, r);
342
360
  if (c > 5) {
343
- const h = Math.atan2(r, o), u = Math.min(c * 4, 600);
361
+ const h = Math.atan2(r, o), p = Math.min(c * 4, 600);
344
362
  t.velocity = {
345
- x: Math.cos(h) * u,
346
- y: Math.sin(h) * u
363
+ x: Math.cos(h) * p,
364
+ y: Math.sin(h) * p
347
365
  };
348
366
  } else
349
367
  t.velocity = { x: 0, y: 0 }, t.isThrown = !1;
@@ -351,7 +369,7 @@ class Y {
351
369
  if (t.type === "heavy")
352
370
  t.shieldAngle = t.rotation, t.velocity = { x: 0, y: 0 }, t.isStationaryShield = !0, t.isThrown = !1;
353
371
  else if (t.type === "piercer") {
354
- const o = E.getInstance().getConfig().piercer;
372
+ const o = A.getInstance().getConfig().piercer;
355
373
  o.hasHoming && (t.remainingHomingKills = o.homingTargets);
356
374
  }
357
375
  return this.grabbedEnemy = null, this.dragStart = null, this.pointerHistory = [], t;
@@ -363,7 +381,7 @@ class Y {
363
381
  this.grabbedEnemy = null, this.grabbedOrb = null, this.dragStart = null, this.pointerHistory = [], this.isPointerDown = !1;
364
382
  }
365
383
  }
366
- class Z {
384
+ class z {
367
385
  cellSize;
368
386
  grid = /* @__PURE__ */ new Map();
369
387
  constructor(t = 100) {
@@ -385,20 +403,18 @@ class Z {
385
403
  for (let o = s; o <= a; o++)
386
404
  for (let r = l; r <= n; r++) {
387
405
  const c = `${o}:${r}`, h = this.grid.get(c);
388
- h && h.forEach((u) => i.add(u));
406
+ h && h.forEach((p) => i.add(p));
389
407
  }
390
408
  return i;
391
409
  }
392
410
  }
393
- class z {
394
- hitstopTime = 0;
411
+ class J {
395
412
  shakeTime = 0;
396
413
  shakeDuration = 0.14;
397
414
  shakeIntensity = 0;
398
415
  shakeVector = { x: 0, y: 0 };
399
416
  flashAlpha = 0;
400
417
  triggerHitstop(t = 0.06) {
401
- this.hitstopTime = 0;
402
418
  }
403
419
  triggerFlash(t = 0.4) {
404
420
  this.flashAlpha = t;
@@ -411,7 +427,7 @@ class z {
411
427
  }, this.shakeIntensity = s, this.shakeTime = this.shakeDuration;
412
428
  }
413
429
  update(t, e, i) {
414
- this.hitstopTime > 0 && (this.hitstopTime -= t), this.shakeTime > 0 && (this.shakeTime -= t), this.flashAlpha > 0 && (this.flashAlpha = Math.max(0, this.flashAlpha - t * 4)), e.length > 25 && e.splice(0, e.length - 25), i.length > 120 && i.splice(0, i.length - 120);
430
+ this.shakeTime > 0 && (this.shakeTime -= t), this.flashAlpha > 0 && (this.flashAlpha = Math.max(0, this.flashAlpha - t * 4)), e.length > 25 && e.splice(0, e.length - 25), i.length > 120 && i.splice(0, i.length - 120);
415
431
  for (let s = e.length - 1; s >= 0; s--) {
416
432
  const a = e[s];
417
433
  a && (a.lifetime += t, a.position.x += a.velocity.x * t, a.position.y += a.velocity.y * t, a.alpha = 1 - a.lifetime / a.maxLifetime, a.lifetime >= a.maxLifetime && e.splice(s, 1));
@@ -430,7 +446,7 @@ class z {
430
446
  };
431
447
  }
432
448
  }
433
- const P = {
449
+ const D = {
434
450
  es: {
435
451
  title: "AXON SURGE",
436
452
  startButton: "INICIAR ENLACE",
@@ -440,6 +456,7 @@ const P = {
440
456
  languageLabel: "IDIOMA",
441
457
  themeLabel: "TEMA VISUAL",
442
458
  hapticsLabel: "VIBRACIÓN / HÁPTICOS",
459
+ fpsLimitLabel: "LÍMITE DE FPS",
443
460
  hapticsOn: "ACTIVADO",
444
461
  hapticsOff: "DESACTIVADO",
445
462
  creditsJam: "Desarrollado para Mini Jam 216: Axon Surge",
@@ -479,6 +496,10 @@ const P = {
479
496
  pu_piercer_homing_target_desc: "+1 Objetivo para el Corte Buscador",
480
497
  pu_shield_fan_title: "TRIPLE RAGAZO ARC",
481
498
  pu_shield_fan_desc: "Dispara 3 rayos en abanico",
499
+ pu_shield_fan_upgrade_title: "CADENCIA DEL ABANICO",
500
+ pu_shield_fan_upgrade_desc: "+0.35s entre rayos y +15° de apertura",
501
+ pu_shield_arc_title: "ARCO PROTECTOR",
502
+ pu_shield_arc_desc: "+30° de arco de protección",
482
503
  pu_vampirism_unlock_title: "BIO-VAMPIRISMO",
483
504
  pu_vampirism_unlock_desc: "Las bajas reparan vidas dañadas",
484
505
  pu_vampirism_boost_title: "IMPULSO VAMPÍRICO",
@@ -501,6 +522,7 @@ const P = {
501
522
  languageLabel: "LANGUAGE",
502
523
  themeLabel: "VISUAL THEME",
503
524
  hapticsLabel: "HAPTICS / VIBRATION",
525
+ fpsLimitLabel: "FPS LIMIT",
504
526
  hapticsOn: "ENABLED",
505
527
  hapticsOff: "DISABLED",
506
528
  creditsJam: "Developed for Mini Jam 216: Axon Surge",
@@ -540,6 +562,10 @@ const P = {
540
562
  pu_piercer_homing_target_desc: "+1 Target for Seeker Slice",
541
563
  pu_shield_fan_title: "TRIPLE ARC BLAST",
542
564
  pu_shield_fan_desc: "Fires 3 fan beams",
565
+ pu_shield_fan_upgrade_title: "FAN OVERDRIVE",
566
+ pu_shield_fan_upgrade_desc: "+0.35s between beams and +15° spread",
567
+ pu_shield_arc_title: "PROTECTIVE ARC",
568
+ pu_shield_arc_desc: "+30° shield protection arc",
543
569
  pu_vampirism_unlock_title: "BIO-VAMPIRISM",
544
570
  pu_vampirism_unlock_desc: "Kills repair damaged core rings",
545
571
  pu_vampirism_boost_title: "VAMPIRIC SURGE",
@@ -1268,7 +1294,7 @@ const P = {
1268
1294
  pu_core_ring_title: "核心过载",
1269
1295
  pu_core_ring_desc: "+1 生命环"
1270
1296
  }
1271
- }, K = [
1297
+ }, V = [
1272
1298
  "es",
1273
1299
  "en",
1274
1300
  "fr",
@@ -1285,29 +1311,29 @@ const P = {
1285
1311
  "ko",
1286
1312
  "zh"
1287
1313
  ];
1288
- function O(y) {
1289
- return K.includes(y);
1314
+ function w(E) {
1315
+ return V.includes(E);
1290
1316
  }
1291
- const U = "axon_surge_language";
1292
- class J {
1317
+ const B = "axon_surge_language";
1318
+ class X {
1293
1319
  currentLanguage;
1294
1320
  constructor(t) {
1295
1321
  this.currentLanguage = this.detectLanguage(t);
1296
1322
  }
1297
1323
  detectLanguage(t) {
1298
1324
  try {
1299
- const e = localStorage.getItem(U);
1300
- if (e && O(e))
1325
+ const e = localStorage.getItem(B);
1326
+ if (e && w(e))
1301
1327
  return e;
1302
1328
  } catch {
1303
1329
  }
1304
- if (t && O(t))
1330
+ if (t && w(t))
1305
1331
  return t;
1306
1332
  try {
1307
1333
  const e = (document.documentElement.lang || document.body?.getAttribute("lang") || document.documentElement.getAttribute("data-lang") || "").toLowerCase();
1308
1334
  if (e) {
1309
1335
  const i = e.split("-")[0];
1310
- if (i && O(i))
1336
+ if (i && w(i))
1311
1337
  return i;
1312
1338
  }
1313
1339
  } catch {
@@ -1316,7 +1342,7 @@ class J {
1316
1342
  const e = (navigator.language || navigator.languages && navigator.languages[0] || "").toLowerCase();
1317
1343
  if (e) {
1318
1344
  const i = e.split("-")[0];
1319
- if (i && O(i))
1345
+ if (i && w(i))
1320
1346
  return i;
1321
1347
  }
1322
1348
  } catch {
@@ -1324,10 +1350,10 @@ class J {
1324
1350
  return "en";
1325
1351
  }
1326
1352
  setLanguage(t) {
1327
- if (P[t]) {
1353
+ if (D[t]) {
1328
1354
  this.currentLanguage = t;
1329
1355
  try {
1330
- localStorage.setItem(U, t);
1356
+ localStorage.setItem(B, t);
1331
1357
  } catch {
1332
1358
  }
1333
1359
  }
@@ -1336,25 +1362,25 @@ class J {
1336
1362
  return this.currentLanguage;
1337
1363
  }
1338
1364
  translate(t, e) {
1339
- let s = (P[this.currentLanguage] || P.en)[t] || P.en[t] || String(t);
1365
+ let s = (D[this.currentLanguage] || D.en)[t] || D.en[t] || String(t);
1340
1366
  return e && Object.entries(e).forEach(([a, l]) => {
1341
1367
  s = s.replace(`{${a}}`, String(l));
1342
1368
  }), s;
1343
1369
  }
1344
1370
  }
1345
- class $ {
1371
+ class j {
1346
1372
  static update(t, e, i) {
1347
- const s = E.getInstance().getConfig();
1373
+ const s = A.getInstance().getConfig();
1348
1374
  for (let a = t.length - 1; a >= 0; a--) {
1349
1375
  const l = t[a];
1350
1376
  if (l) {
1351
1377
  l.duration += i;
1352
1378
  for (const n of e) {
1353
- if (!n.active || n.isGrabbed || n.isDying || n.isStationaryShield || n.isThrown && n.type === "piercer") continue;
1354
- const o = l.position.x - n.position.x, r = l.position.y - n.position.y, c = Math.hypot(o, r);
1355
- if (c > 2 && c <= l.radius) {
1356
- const h = Math.pow(1 - c / l.radius, 0.7), u = l.pullForce * h, p = Math.atan2(r, o);
1357
- n.velocity.x += Math.cos(p) * u * i, n.velocity.y += Math.sin(p) * u * i, n.position.x += Math.cos(p) * u * i * 0.8, n.position.y += Math.sin(p) * u * i * 0.8;
1379
+ if (!n.active || n.isGrabbed || n.isDying || n.isStationaryShield || n.launchDelay > 0 || n.isThrown && n.type === "piercer") continue;
1380
+ const o = l.position.x - n.position.x, r = l.position.y - n.position.y, c = o * o + r * r, h = Math.sqrt(c);
1381
+ if (h > 2 && c <= l.radius * l.radius) {
1382
+ const p = Math.pow(1 - h / l.radius, 0.7), d = l.pullForce * p, _ = Math.atan2(r, o);
1383
+ n.velocity.x += Math.cos(_) * d * i, n.velocity.y += Math.sin(_) * d * i, n.position.x += Math.cos(_) * d * i * 0.8, n.position.y += Math.sin(_) * d * i * 0.8;
1358
1384
  }
1359
1385
  }
1360
1386
  if (l.duration >= l.maxDuration) {
@@ -1362,11 +1388,11 @@ class $ {
1362
1388
  for (const n of e) {
1363
1389
  if (!n.active || n.isDying) continue;
1364
1390
  const o = n.position.x - l.position.x, r = n.position.y - l.position.y;
1365
- if (Math.hypot(o, r) <= l.radius) {
1366
- const h = Math.atan2(r, o), u = 1200;
1391
+ if (o * o + r * r <= l.radius * l.radius) {
1392
+ const h = Math.atan2(r, o), p = 1200;
1367
1393
  n.isThrown = !0, n.wasManipulated = !0, n.velocity = {
1368
- x: Math.cos(h) * u,
1369
- y: Math.sin(h) * u
1394
+ x: Math.cos(h) * p,
1395
+ y: Math.sin(h) * p
1370
1396
  };
1371
1397
  }
1372
1398
  }
@@ -1376,12 +1402,12 @@ class $ {
1376
1402
  }
1377
1403
  }
1378
1404
  }
1379
- class X {
1405
+ class q {
1380
1406
  static update(t, e, i, s, a, l, n, o, r, c) {
1381
1407
  for (const h of e) {
1382
- if (!h.active || h.isGrabbed || h.isDying) continue;
1383
- const u = t.position.x - h.position.x, p = t.position.y - h.position.y;
1384
- if (Math.hypot(u, p) <= t.getHitboxRadius() + h.radius) {
1408
+ if (!h.active || h.isGrabbed || h.isDying || h.launchDelay > 0) continue;
1409
+ const p = t.position.x - h.position.x, d = t.position.y - h.position.y;
1410
+ if (Math.hypot(p, d) <= t.getHitboxRadius() + h.radius) {
1385
1411
  if (h.active = !1, t.takeDamage()) {
1386
1412
  n.emit("onCoreDamaged", { currentIntegrity: t.integrity }), i.push({
1387
1413
  id: Math.random().toString(),
@@ -1392,16 +1418,16 @@ class X {
1392
1418
  alpha: 1,
1393
1419
  lifetime: 0,
1394
1420
  maxLifetime: 0.8
1395
- }), l.triggerScreenShake({ x: u, y: p }, 25), l.triggerHitstop(0.15), l.triggerFlash(0.6);
1396
- for (const d of e)
1397
- if (d.active && !d.isGrabbed) {
1398
- d.triggerDissolveDeath();
1399
- for (let m = 0; m < 8; m++) {
1400
- const x = Math.random() * Math.PI * 2, A = 100 + Math.random() * 200;
1421
+ }), l.triggerScreenShake({ x: p, y: d }, 25), l.triggerHitstop(0.15), l.triggerFlash(0.6);
1422
+ for (const u of e)
1423
+ if (u.active && !u.isGrabbed && u.launchDelay <= 0) {
1424
+ u.triggerDissolveDeath();
1425
+ for (let g = 0; g < 8; g++) {
1426
+ const f = Math.random() * Math.PI * 2, b = 100 + Math.random() * 200;
1401
1427
  s.push({
1402
1428
  id: Math.random().toString(),
1403
- position: { ...d.position },
1404
- velocity: { x: Math.cos(x) * A, y: Math.sin(x) * A },
1429
+ position: { ...u.position },
1430
+ velocity: { x: Math.cos(f) * b, y: Math.sin(f) * b },
1405
1431
  color: "#00f0ff",
1406
1432
  radius: 3 + Math.random() * 3,
1407
1433
  alpha: 1,
@@ -1427,7 +1453,7 @@ class X {
1427
1453
  }
1428
1454
  }
1429
1455
  }
1430
- class j {
1456
+ class Q {
1431
1457
  execute(t) {
1432
1458
  const { thrownEnemy: e, targetEnemy: i, shockwaves: s, particles: a, floatingTexts: l } = t;
1433
1459
  i.experienceDropPending = !0, i.active = !1, s.push({
@@ -1466,9 +1492,9 @@ class j {
1466
1492
  });
1467
1493
  }
1468
1494
  }
1469
- class q {
1495
+ class tt {
1470
1496
  execute(t) {
1471
- const { thrownEnemy: e, pools: i, shockwaves: s, particles: a, floatingTexts: l, eventBus: n } = t, o = e.position, r = E.getInstance().getConfig();
1497
+ const { thrownEnemy: e, pools: i, shockwaves: s, particles: a, floatingTexts: l, eventBus: n } = t, o = e.position, r = A.getInstance().getConfig();
1472
1498
  i.push({
1473
1499
  id: Math.random().toString(),
1474
1500
  position: { ...o },
@@ -1487,11 +1513,11 @@ class q {
1487
1513
  maxLifetime: 0.6
1488
1514
  });
1489
1515
  for (let c = 0; c < 45; c++) {
1490
- const h = Math.random() * Math.PI * 2, u = 120 + Math.random() * 260;
1516
+ const h = Math.random() * Math.PI * 2, p = 120 + Math.random() * 260;
1491
1517
  a.push({
1492
1518
  id: Math.random().toString(),
1493
1519
  position: { ...o },
1494
- velocity: { x: Math.cos(h) * u, y: Math.sin(h) * u },
1520
+ velocity: { x: Math.cos(h) * p, y: Math.sin(h) * p },
1495
1521
  color: "#39ff14",
1496
1522
  radius: 4 + Math.random() * 5,
1497
1523
  alpha: 1,
@@ -1512,7 +1538,7 @@ class q {
1512
1538
  }), e.experienceDropPending = !0, e.active = !1, n.emit("onPoolCreated", { position: o });
1513
1539
  }
1514
1540
  }
1515
- class Q {
1541
+ class et {
1516
1542
  execute(t) {
1517
1543
  const { thrownEnemy: e, targetEnemy: i, allEnemies: s, shockwaves: a, particles: l, floatingTexts: n } = t, o = i.position;
1518
1544
  e.experienceDropPending = !0, i.experienceDropPending = !0, e.active = !1, i.active = !1, a.push({
@@ -1525,37 +1551,37 @@ class Q {
1525
1551
  lifetime: 0,
1526
1552
  maxLifetime: 0.6
1527
1553
  });
1528
- const r = E.getInstance().getConfig(), c = r.cluster.fragmentCount, h = r.cluster.hasHoming;
1529
- for (let u = 0; u < c; u++) {
1530
- const p = u * Math.PI * 2 / c, _ = 800 + Math.random() * 300, g = {
1531
- x: o.x + Math.cos(p) * 45,
1532
- y: o.y + Math.sin(p) * 45
1554
+ const r = A.getInstance().getConfig(), c = r.cluster.fragmentCount, h = r.cluster.hasHoming;
1555
+ for (let p = 0; p < c; p++) {
1556
+ const d = p * Math.PI * 2 / c, _ = 800 + Math.random() * 300, m = {
1557
+ x: o.x + Math.cos(d) * 45,
1558
+ y: o.y + Math.sin(d) * 45
1533
1559
  };
1534
- let d = p;
1560
+ let u = d;
1535
1561
  if (h) {
1536
- let x = null, A = 1 / 0;
1537
- for (const b of s) {
1538
- if (b === e || b === i || !b.active || b.isGrabbed || b.isDying) continue;
1539
- const I = Math.hypot(b.position.x - g.x, b.position.y - g.y);
1540
- I < A && (A = I, x = b);
1562
+ let f = null, b = 1 / 0;
1563
+ for (const y of s) {
1564
+ if (y === e || y === i || !y.active || y.isGrabbed || y.isDying) continue;
1565
+ const v = Math.hypot(y.position.x - m.x, y.position.y - m.y);
1566
+ v < b && (b = v, f = y);
1541
1567
  }
1542
- x && (d = Math.atan2(x.position.y - g.y, x.position.x - g.x));
1568
+ f && (u = Math.atan2(f.position.y - m.y, f.position.x - m.x));
1543
1569
  }
1544
- const m = M.createEnemy("micro", g, {
1545
- x: g.x + Math.cos(d) * 500,
1546
- y: g.y + Math.sin(d) * 500
1570
+ const g = C.createEnemy("micro", m, {
1571
+ x: m.x + Math.cos(u) * 500,
1572
+ y: m.y + Math.sin(u) * 500
1547
1573
  });
1548
- m.isThrown = !0, m.wasManipulated = !0, m.velocity = {
1549
- x: Math.cos(d) * _,
1550
- y: Math.sin(d) * _
1551
- }, s.push(m);
1574
+ g.isThrown = !0, g.wasManipulated = !0, g.velocity = {
1575
+ x: Math.cos(u) * _,
1576
+ y: Math.sin(u) * _
1577
+ }, s.push(g);
1552
1578
  }
1553
- for (let u = 0; u < 35; u++) {
1554
- const p = Math.random() * Math.PI * 2, _ = 200 + Math.random() * 300;
1579
+ for (let p = 0; p < 35; p++) {
1580
+ const d = Math.random() * Math.PI * 2, _ = 200 + Math.random() * 300;
1555
1581
  l.push({
1556
1582
  id: Math.random().toString(),
1557
1583
  position: { ...o },
1558
- velocity: { x: Math.cos(p) * _, y: Math.sin(p) * _ },
1584
+ velocity: { x: Math.cos(d) * _, y: Math.sin(d) * _ },
1559
1585
  color: "#ffd700",
1560
1586
  radius: 4 + Math.random() * 4,
1561
1587
  alpha: 1,
@@ -1576,9 +1602,9 @@ class Q {
1576
1602
  });
1577
1603
  }
1578
1604
  }
1579
- class tt {
1605
+ class it {
1580
1606
  execute(t) {
1581
- const { thrownEnemy: e, targetEnemy: i, vortices: s, shockwaves: a } = t, l = E.getInstance().getConfig(), n = {
1607
+ const { thrownEnemy: e, targetEnemy: i, vortices: s, shockwaves: a } = t, l = A.getInstance().getConfig(), n = {
1582
1608
  x: (e.position.x + i.position.x) / 2,
1583
1609
  y: (e.position.y + i.position.y) / 2
1584
1610
  };
@@ -1601,22 +1627,22 @@ class tt {
1601
1627
  }), e.triggerDissolveDeath(!0), i.triggerDissolveDeath(!0);
1602
1628
  }
1603
1629
  }
1604
- class et {
1630
+ class st {
1605
1631
  execute(t) {
1606
- const { thrownEnemy: e, targetEnemy: i, allEnemies: s, shockwaves: a, particles: l, floatingTexts: n } = t, o = i.position.x - e.position.x, r = i.position.y - e.position.y, c = Math.atan2(r, o), h = E.getInstance().getConfig().shield, u = h.blastSpeed || 1400, p = h.isFanBlast ? [-Math.PI / 4, 0, Math.PI / 4] : [0];
1607
- for (const _ of p) {
1608
- const g = c + _, d = _ === 0 ? e : M.createEnemy(
1632
+ const { thrownEnemy: e, targetEnemy: i, allEnemies: s, shockwaves: a, particles: l, floatingTexts: n } = t, o = i.position.x - e.position.x, r = i.position.y - e.position.y, c = Math.atan2(r, o), h = A.getInstance().getConfig().shield, p = h.blastSpeed || 1400, d = h.isFanBlast ? [0, -h.fanBlastAngle, h.fanBlastAngle] : [0];
1633
+ for (const [_, m] of d.entries()) {
1634
+ const u = c + m, g = _ === 0 ? e : C.createEnemy(
1609
1635
  "heavy",
1610
1636
  {
1611
- x: e.position.x + Math.cos(g) * 30,
1612
- y: e.position.y + Math.sin(g) * 30
1637
+ x: e.position.x + Math.cos(u) * 30,
1638
+ y: e.position.y + Math.sin(u) * 30
1613
1639
  },
1614
1640
  { x: 0, y: 0 }
1615
1641
  );
1616
- d.isStationaryShield = !1, d.isThrown = !0, d.wasManipulated = !0, d.shieldAngle = g, d.rotation = g, d.velocity = {
1617
- x: Math.cos(g) * u,
1618
- y: Math.sin(g) * u
1619
- }, d !== e && s.push(d);
1642
+ g.isStationaryShield = !1, g.isThrown = !0, g.wasManipulated = !0, g.shieldAngle = u, g.rotation = u, g.launchDelay = h.isFanBlast ? _ * h.fanBlastInterval : 0, g.velocity = {
1643
+ x: Math.cos(u) * p,
1644
+ y: Math.sin(u) * p
1645
+ }, g !== e && s.push(g);
1620
1646
  }
1621
1647
  i.active = !1, i.triggerDissolveDeath(!0), n.push({
1622
1648
  id: Math.random().toString(),
@@ -1630,11 +1656,11 @@ class et {
1630
1656
  size: 24
1631
1657
  });
1632
1658
  for (let _ = 0; _ < 50; _++) {
1633
- const g = (Math.random() - 0.5) * 1.5, d = c + g, m = 300 + Math.random() * 500;
1659
+ const m = (Math.random() - 0.5) * 1.5, u = c + m, g = 300 + Math.random() * 500;
1634
1660
  l.push({
1635
1661
  id: Math.random().toString(),
1636
1662
  position: { ...e.position },
1637
- velocity: { x: Math.cos(d) * m, y: Math.sin(d) * m },
1663
+ velocity: { x: Math.cos(u) * g, y: Math.sin(u) * g },
1638
1664
  color: "#00f5ff",
1639
1665
  radius: 4 + Math.random() * 6,
1640
1666
  alpha: 1,
@@ -1655,25 +1681,25 @@ class et {
1655
1681
  });
1656
1682
  }
1657
1683
  }
1658
- class M {
1684
+ class C {
1659
1685
  static createEnemy(t, e, i) {
1660
- const s = `enemy_${Date.now()}_${Math.random()}`, a = new D(s);
1686
+ const s = `enemy_${Date.now()}_${Math.random()}`, a = new U(s);
1661
1687
  return this.configureEnemy(a, t, e, i), a;
1662
1688
  }
1663
1689
  static configureEnemy(t, e, i, s) {
1664
1690
  t.type = e, t.position = { ...i }, t.active = !0, t.isGrabbed = !1, t.isThrown = !1;
1665
1691
  const a = s.x - i.x, l = s.y - i.y, n = Math.atan2(l, a);
1666
- let o = 70, r = 100, c = 20, h = "#ff2a5f", u = null;
1667
- e === "piercer" ? (o = 95, r = 140, c = 18, h = "#ff2a5f", u = new j()) : e === "spore" ? (o = 65, r = 90, c = 24, h = "#39ff14", u = new q()) : e === "cluster" ? (o = 50, r = 75, c = 26, h = "#ffd700", u = new Q()) : e === "parasite" ? (o = 80, r = 110, c = 22, h = "#9d4edd", u = new tt()) : e === "heavy" ? (o = 35, r = 50, c = 34, h = "#00f5ff", u = new et(), t.rotation = Math.random() * Math.PI * 2) : e === "micro" && (o = 130, r = 160, c = 12, h = "#ffd700"), t.radius = c, t.color = h, t.strategy = u, t.maxSpeed = r, t.velocity = {
1692
+ let o = 70, r = 100, c = 20, h = "#ff2a5f", p = null;
1693
+ e === "piercer" ? (o = 95, r = 140, c = 18, h = "#ff2a5f", p = new Q()) : e === "spore" ? (o = 65, r = 90, c = 24, h = "#39ff14", p = new tt()) : e === "cluster" ? (o = 50, r = 75, c = 26, h = "#ffd700", p = new et()) : e === "parasite" ? (o = 80, r = 110, c = 22, h = "#9d4edd", p = new it()) : e === "heavy" ? (o = 35, r = 50, c = 34, h = "#00f5ff", p = new st(), t.rotation = Math.random() * Math.PI * 2) : e === "micro" && (o = 130, r = 160, c = 12, h = "#ffd700"), t.radius = c, t.color = h, t.strategy = p, t.maxSpeed = r, t.velocity = {
1668
1694
  x: Math.cos(n) * o,
1669
1695
  y: Math.sin(n) * o
1670
1696
  };
1671
1697
  }
1672
1698
  }
1673
- class T {
1699
+ class P {
1674
1700
  static killEnemy(t, e, i, s, a, l) {
1675
1701
  if (!t.active || t.isDying) return;
1676
- const n = E.getInstance().getConfig();
1702
+ const n = A.getInstance().getConfig();
1677
1703
  if (t.experienceDropPending = !0, a.push({
1678
1704
  id: Math.random().toString(),
1679
1705
  position: { ...t.position },
@@ -1696,28 +1722,28 @@ class T {
1696
1722
  t.triggerDissolveDeath(!0);
1697
1723
  const o = n.cluster.fragmentCount, r = n.cluster.hasHoming;
1698
1724
  for (let c = 0; c < o; c++) {
1699
- const h = c * Math.PI * 2 / o, u = 750 + Math.random() * 250, p = {
1725
+ const h = c * Math.PI * 2 / o, p = 750 + Math.random() * 250, d = {
1700
1726
  x: t.position.x + Math.cos(h) * 40,
1701
1727
  y: t.position.y + Math.sin(h) * 40
1702
1728
  };
1703
1729
  let _ = h;
1704
1730
  if (r) {
1705
- let d = null, m = 1 / 0;
1706
- for (const x of l) {
1707
- if (x === t || !x.active || x.isGrabbed || x.isDying) continue;
1708
- const A = Math.hypot(x.position.x - p.x, x.position.y - p.y);
1709
- A < m && (m = A, d = x);
1731
+ let u = null, g = 1 / 0;
1732
+ for (const f of l) {
1733
+ if (f === t || !f.active || f.isGrabbed || f.isDying) continue;
1734
+ const b = Math.hypot(f.position.x - d.x, f.position.y - d.y);
1735
+ b < g && (g = b, u = f);
1710
1736
  }
1711
- d && (_ = Math.atan2(d.position.y - p.y, d.position.x - p.x));
1737
+ u && (_ = Math.atan2(u.position.y - d.y, u.position.x - d.x));
1712
1738
  }
1713
- const g = M.createEnemy("micro", p, {
1714
- x: p.x + Math.cos(_) * 500,
1715
- y: p.y + Math.sin(_) * 500
1739
+ const m = C.createEnemy("micro", d, {
1740
+ x: d.x + Math.cos(_) * 500,
1741
+ y: d.y + Math.sin(_) * 500
1716
1742
  });
1717
- g.isThrown = !0, g.wasManipulated = !0, g.velocity = {
1718
- x: Math.cos(_) * u,
1719
- y: Math.sin(_) * u
1720
- }, l.push(g);
1743
+ m.isThrown = !0, m.wasManipulated = !0, m.velocity = {
1744
+ x: Math.cos(_) * p,
1745
+ y: Math.sin(_) * p
1746
+ }, l.push(m);
1721
1747
  }
1722
1748
  } else t.type === "parasite" ? (t.triggerDissolveDeath(!0), s.push({
1723
1749
  id: Math.random().toString(),
@@ -1729,16 +1755,16 @@ class T {
1729
1755
  })) : t.type === "piercer" ? t.triggerSliceDeath(e, !0) : t.triggerDissolveDeath(!0);
1730
1756
  }
1731
1757
  }
1732
- class it {
1733
- static update(t, e, i, s, a, l, n, o, r, c, h, u, p) {
1734
- let _ = !1;
1735
- for (const g of t)
1736
- if (!(!g.active || !g.isThrown || g.isDying)) {
1737
- if (_ = !0, g.position.x < -120 || g.position.x > c + 120 || g.position.y < -120 || g.position.y > h + 120) {
1738
- if (g.type === "heavy") {
1758
+ class at {
1759
+ static update(t, e, i, s, a, l, n, o, r, c, h, p, d, _) {
1760
+ let m = !1;
1761
+ for (const u of t)
1762
+ if (!(!u.active || !u.isThrown || u.isDying || u.launchDelay > 0)) {
1763
+ if (m = !0, u.position.x < -120 || u.position.x > c + 120 || u.position.y < -120 || u.position.y > h + 120) {
1764
+ if (u.type === "heavy") {
1739
1765
  s.push({
1740
1766
  id: Math.random().toString(),
1741
- position: { ...g.position },
1767
+ position: { ...u.position },
1742
1768
  radius: 20,
1743
1769
  maxRadius: 350,
1744
1770
  color: "#00f5ff",
@@ -1746,12 +1772,12 @@ class it {
1746
1772
  lifetime: 0,
1747
1773
  maxLifetime: 0.6
1748
1774
  });
1749
- for (let d = 0; d < 40; d++) {
1750
- const m = Math.random() * Math.PI * 2, x = 250 + Math.random() * 450;
1775
+ for (let g = 0; g < 40; g++) {
1776
+ const f = Math.random() * Math.PI * 2, b = 250 + Math.random() * 450;
1751
1777
  a.push({
1752
1778
  id: Math.random().toString(),
1753
- position: { ...g.position },
1754
- velocity: { x: Math.cos(m) * x, y: Math.sin(m) * x },
1779
+ position: { ...u.position },
1780
+ velocity: { x: Math.cos(f) * b, y: Math.sin(f) * b },
1755
1781
  color: "#00f5ff",
1756
1782
  radius: 4 + Math.random() * 5,
1757
1783
  alpha: 1,
@@ -1759,44 +1785,44 @@ class it {
1759
1785
  maxLifetime: 0.6
1760
1786
  });
1761
1787
  }
1762
- } else if (g.type === "piercer") {
1763
- const d = E.getInstance().getConfig().piercer;
1764
- if (d.terminalAoERadius > 0) {
1765
- const m = d.terminalAoERadius;
1788
+ } else if (u.type === "piercer") {
1789
+ const g = A.getInstance().getConfig().piercer;
1790
+ if (g.terminalAoERadius > 0) {
1791
+ const f = g.terminalAoERadius;
1766
1792
  s.push({
1767
1793
  id: Math.random().toString(),
1768
- position: { ...g.position },
1794
+ position: { ...u.position },
1769
1795
  radius: 20,
1770
- maxRadius: m,
1796
+ maxRadius: f,
1771
1797
  color: "#ff2a5f",
1772
1798
  alpha: 1,
1773
1799
  lifetime: 0,
1774
1800
  maxLifetime: 0.6
1775
1801
  });
1776
- for (const x of t) {
1777
- if (!x.active || x.isGrabbed || x.isDying) continue;
1778
- const A = x.position.x - g.position.x, b = x.position.y - g.position.y;
1779
- Math.hypot(A, b) <= m && T.killEnemy(x, Math.atan2(b, A), e, i, s, t);
1802
+ for (const b of d.getNearby(u.position, f)) {
1803
+ if (!b.active || b.isGrabbed || b.isDying) continue;
1804
+ const y = b.position.x - u.position.x, v = b.position.y - u.position.y;
1805
+ y * y + v * v <= f * f && P.killEnemy(b, Math.atan2(v, y), e, i, s, t);
1780
1806
  }
1781
1807
  }
1782
1808
  }
1783
- g.active = !1, g.isThrown = !1;
1809
+ u.active = !1, u.isThrown = !1;
1784
1810
  continue;
1785
1811
  }
1786
- for (const d of t) {
1787
- if (d === g || !d.active || d.isGrabbed || d.isDying) continue;
1788
- const m = d.position.x - g.position.x, x = d.position.y - g.position.y;
1789
- if (Math.hypot(m, x) <= g.getHitRadius() + d.getHitRadius()) {
1790
- u.pos = { x: g.position.x, y: g.position.y };
1791
- const b = Math.atan2(g.velocity.y, g.velocity.x);
1792
- if (g.type === "heavy") {
1793
- u.kills++, T.killEnemy(d, g.rotation, e, i, s, t), n.triggerHitstop(0.04), n.triggerScreenShake({ x: m, y: x }, 8);
1794
- for (let I = 0; I < 8; I++) {
1795
- const S = g.rotation + (Math.random() - 0.5), f = 200 + Math.random() * 350;
1812
+ for (const g of d.getNearby(u.position, u.getHitRadius() + 80)) {
1813
+ if (g === u || !g.active || g.isGrabbed || g.isDying || g.launchDelay > 0) continue;
1814
+ const f = g.position.x - u.position.x, b = g.position.y - u.position.y, y = u.getHitRadius() + g.getHitRadius();
1815
+ if (f * f + b * b <= y * y) {
1816
+ p.pos = { x: u.position.x, y: u.position.y };
1817
+ const v = Math.atan2(u.velocity.y, u.velocity.x);
1818
+ if (u.type === "heavy") {
1819
+ p.kills++, P.killEnemy(g, u.rotation, e, i, s, t), n.triggerHitstop(0.04), n.triggerScreenShake({ x: f, y: b }, 8);
1820
+ for (let M = 0; M < 8; M++) {
1821
+ const T = u.rotation + (Math.random() - 0.5), x = 200 + Math.random() * 350;
1796
1822
  a.push({
1797
1823
  id: Math.random().toString(),
1798
- position: { ...d.position },
1799
- velocity: { x: Math.cos(S) * f, y: Math.sin(S) * f },
1824
+ position: { ...g.position },
1825
+ velocity: { x: Math.cos(T) * x, y: Math.sin(T) * x },
1800
1826
  color: "#00f5ff",
1801
1827
  radius: 3 + Math.random() * 4,
1802
1828
  alpha: 1,
@@ -1804,11 +1830,11 @@ class it {
1804
1830
  maxLifetime: 0.4
1805
1831
  });
1806
1832
  }
1807
- p && p();
1808
- } else if (g.type === "piercer") {
1809
- u.kills++, T.killEnemy(d, b, e, i, s, t), n.triggerHitstop(0.05), n.triggerScreenShake({ x: m, y: x }, 7), s.push({
1833
+ _ && _();
1834
+ } else if (u.type === "piercer") {
1835
+ p.kills++, P.killEnemy(g, v, e, i, s, t), n.triggerHitstop(0.05), n.triggerScreenShake({ x: f, y: b }, 7), s.push({
1810
1836
  id: Math.random().toString(),
1811
- position: { ...d.position },
1837
+ position: { ...g.position },
1812
1838
  radius: 10,
1813
1839
  maxRadius: 180,
1814
1840
  color: "#ff2a5f",
@@ -1816,12 +1842,12 @@ class it {
1816
1842
  lifetime: 0,
1817
1843
  maxLifetime: 0.45
1818
1844
  });
1819
- for (let I = 0; I < 16; I++) {
1820
- const S = Math.random() * Math.PI * 2, f = 150 + Math.random() * 300;
1845
+ for (let M = 0; M < 16; M++) {
1846
+ const T = Math.random() * Math.PI * 2, x = 150 + Math.random() * 300;
1821
1847
  a.push({
1822
1848
  id: Math.random().toString(),
1823
- position: { ...d.position },
1824
- velocity: { x: Math.cos(S) * f, y: Math.sin(S) * f },
1849
+ position: { ...g.position },
1850
+ velocity: { x: Math.cos(T) * x, y: Math.sin(T) * x },
1825
1851
  color: "#ff2a5f",
1826
1852
  radius: 3 + Math.random() * 3,
1827
1853
  alpha: 1,
@@ -1829,52 +1855,52 @@ class it {
1829
1855
  maxLifetime: 0.4
1830
1856
  });
1831
1857
  }
1832
- if (g.remainingHomingKills > 0) {
1833
- g.remainingHomingKills--;
1834
- let I = null, S = 1 / 0;
1835
- for (const f of t) {
1836
- if (f === g || f === d || !f.active || f.isGrabbed || f.isDying) continue;
1837
- const v = f.position.x - g.position.x, L = f.position.y - g.position.y, w = Math.hypot(v, L);
1838
- w < S && (S = w, I = f);
1858
+ if (u.remainingHomingKills > 0) {
1859
+ u.remainingHomingKills--;
1860
+ let M = null, T = 1 / 0;
1861
+ for (const x of t) {
1862
+ if (x === u || x === g || !x.active || x.isGrabbed || x.isDying) continue;
1863
+ const L = x.position.x - u.position.x, R = x.position.y - u.position.y, I = Math.hypot(L, R);
1864
+ I < T && (T = I, M = x);
1839
1865
  }
1840
- if (I) {
1841
- const f = Math.atan2(I.position.y - g.position.y, I.position.x - g.position.x), v = Math.hypot(g.velocity.x, g.velocity.y) || 1200;
1842
- g.rotation = f, g.velocity = {
1843
- x: Math.cos(f) * v,
1844
- y: Math.sin(f) * v
1866
+ if (M) {
1867
+ const x = Math.atan2(M.position.y - u.position.y, M.position.x - u.position.x), L = Math.hypot(u.velocity.x, u.velocity.y) || 1200;
1868
+ u.rotation = x, u.velocity = {
1869
+ x: Math.cos(x) * L,
1870
+ y: Math.sin(x) * L
1845
1871
  };
1846
1872
  }
1847
1873
  }
1848
- p && p();
1874
+ _ && _();
1849
1875
  } else {
1850
- const I = g.type === d.type, S = I ? 360 : 250;
1876
+ const M = u.type === g.type, T = M ? 360 : 250;
1851
1877
  s.push({
1852
1878
  id: Math.random().toString(),
1853
- position: { ...u.pos },
1879
+ position: { ...p.pos },
1854
1880
  radius: 15,
1855
- maxRadius: S,
1856
- color: g.color,
1881
+ maxRadius: T,
1882
+ color: u.color,
1857
1883
  alpha: 1,
1858
1884
  lifetime: 0,
1859
1885
  maxLifetime: 0.55
1860
1886
  });
1861
- for (let f = 0; f < 45; f++) {
1862
- const v = Math.random() * Math.PI * 2, L = 200 + Math.random() * 450;
1887
+ for (let x = 0; x < 45; x++) {
1888
+ const L = Math.random() * Math.PI * 2, R = 200 + Math.random() * 450;
1863
1889
  a.push({
1864
1890
  id: Math.random().toString(),
1865
- position: { ...u.pos },
1866
- velocity: { x: Math.cos(v) * L, y: Math.sin(v) * L },
1867
- color: g.color,
1891
+ position: { ...p.pos },
1892
+ velocity: { x: Math.cos(L) * R, y: Math.sin(L) * R },
1893
+ color: u.color,
1868
1894
  radius: 4 + Math.random() * 6,
1869
1895
  alpha: 1,
1870
1896
  lifetime: 0,
1871
1897
  maxLifetime: 0.7
1872
1898
  });
1873
1899
  }
1874
- if (g.strategy) {
1875
- g.strategy.execute({
1876
- thrownEnemy: g,
1877
- targetEnemy: d,
1900
+ if (u.strategy) {
1901
+ u.strategy.execute({
1902
+ thrownEnemy: u,
1903
+ targetEnemy: g,
1878
1904
  allEnemies: t,
1879
1905
  pools: e,
1880
1906
  vortices: i,
@@ -1884,90 +1910,96 @@ class it {
1884
1910
  eventBus: o,
1885
1911
  width: c,
1886
1912
  height: h
1887
- }), u.kills += 2, p && p();
1913
+ }), p.kills += 2, _ && _();
1888
1914
  break;
1889
1915
  }
1890
- if (I) {
1891
- u.kills += 2, n.triggerHitstop(0.14), n.triggerFlash(0.5), n.triggerScreenShake({ x: m, y: x }, 16), l.push({
1916
+ if (M) {
1917
+ p.kills += 2, n.triggerHitstop(0.14), n.triggerFlash(0.5), n.triggerScreenShake({ x: f, y: b }, 16), l.push({
1892
1918
  id: Math.random().toString(),
1893
1919
  text: "COLOR SYNERGY!",
1894
- position: { ...u.pos },
1920
+ position: { ...p.pos },
1895
1921
  velocity: { x: 0, y: -80 },
1896
- color: g.color,
1922
+ color: u.color,
1897
1923
  alpha: 1,
1898
1924
  lifetime: 0,
1899
1925
  maxLifetime: 1.2,
1900
1926
  size: 26
1901
1927
  });
1902
- const f = E.getInstance().getConfig();
1903
- g.type === "spore" ? e.push({
1928
+ const x = A.getInstance().getConfig();
1929
+ u.type === "spore" ? e.push({
1904
1930
  id: Math.random().toString(),
1905
- position: { ...u.pos },
1906
- radius: Math.round(f.toxicPool.baseRadius * 2),
1931
+ position: { ...p.pos },
1932
+ radius: Math.round(x.toxicPool.baseRadius * 2),
1907
1933
  duration: 0,
1908
- maxDuration: f.toxicPool.synergyDuration,
1909
- damage: f.toxicPool.damage * 2
1910
- }) : g.type === "parasite" && i.push({
1934
+ maxDuration: x.toxicPool.synergyDuration,
1935
+ damage: x.toxicPool.damage * 2
1936
+ }) : u.type === "parasite" && i.push({
1911
1937
  id: Math.random().toString(),
1912
- position: { ...u.pos },
1913
- radius: Math.round(f.gravityVortex.baseRadius * 1.8),
1938
+ position: { ...p.pos },
1939
+ radius: Math.round(x.gravityVortex.baseRadius * 1.8),
1914
1940
  duration: 0,
1915
- maxDuration: f.gravityVortex.synergyDuration,
1916
- pullForce: f.gravityVortex.synergyPullForce
1917
- }), T.killEnemy(g, b, e, i, s, t), T.killEnemy(d, b, e, i, s, t);
1941
+ maxDuration: x.gravityVortex.synergyDuration,
1942
+ pullForce: x.gravityVortex.synergyPullForce
1943
+ }), P.killEnemy(u, v, e, i, s, t), P.killEnemy(g, v, e, i, s, t);
1918
1944
  } else
1919
- u.kills += 2, n.triggerHitstop(0.08), n.triggerFlash(0.35), n.triggerScreenShake({ x: m, y: x }, 10), T.killEnemy(g, b, e, i, s, t), T.killEnemy(d, b, e, i, s, t);
1920
- for (const f of t) {
1921
- if (f === g || f === d || !f.active || f.isGrabbed || f.isDying) continue;
1922
- const v = f.position.x - u.pos.x, L = f.position.y - u.pos.y;
1923
- Math.hypot(v, L) <= S && f.type !== "micro" && (T.killEnemy(f, b, e, i, s, t), u.kills++);
1945
+ p.kills += 2, n.triggerHitstop(0.08), n.triggerFlash(0.35), n.triggerScreenShake({ x: f, y: b }, 10), P.killEnemy(u, v, e, i, s, t), P.killEnemy(g, v, e, i, s, t);
1946
+ for (const x of t) {
1947
+ if (x === u || x === g || !x.active || x.isGrabbed || x.isDying) continue;
1948
+ const L = x.position.x - p.pos.x, R = x.position.y - p.pos.y;
1949
+ Math.hypot(L, R) <= T && x.type !== "micro" && (P.killEnemy(x, v, e, i, s, t), p.kills++);
1924
1950
  }
1925
- p && p();
1951
+ _ && _();
1926
1952
  break;
1927
1953
  }
1928
1954
  }
1929
1955
  }
1930
1956
  }
1931
- r.value = u.kills, !_ && u.kills > 0 && (u.kills >= 2 && u.pos && l.push({
1957
+ r.value = p.kills, !m && p.kills > 0 && (p.kills >= 2 && p.pos && l.push({
1932
1958
  id: Math.random().toString(),
1933
- text: `MULTIKILL x${u.kills}!`,
1934
- position: { ...u.pos },
1959
+ text: `MULTIKILL x${p.kills}!`,
1960
+ position: { ...p.pos },
1935
1961
  velocity: { x: 0, y: -90 },
1936
1962
  color: "#ff00dd",
1937
1963
  alpha: 1,
1938
1964
  lifetime: 0,
1939
1965
  maxLifetime: 1.4,
1940
1966
  size: 32
1941
- }), o.emit("onComboUpdated", { combo: r.value }), u.kills = 0, u.pos = null);
1967
+ }), o.emit("onComboUpdated", { combo: r.value }), p.kills = 0, p.pos = null);
1942
1968
  }
1943
1969
  }
1944
- class st {
1970
+ class ot {
1945
1971
  static update(t, e, i, s, a, l, n, o) {
1946
1972
  for (let r = t.length - 1; r >= 0; r--) {
1947
1973
  const c = t[r];
1948
1974
  if (c) {
1949
1975
  c.duration += l;
1950
1976
  for (const h of e) {
1951
- if (!h.active || h.isGrabbed || h.isDying || h.isThrown && h.type === "piercer") continue;
1952
- const u = h.position.x - c.position.x, p = h.position.y - c.position.y;
1953
- Math.hypot(u, p) <= c.radius && (T.killEnemy(h, 0, t, i, s, e), n.kills++, o && o());
1977
+ if (!h.active || h.isGrabbed || h.isDying || h.launchDelay > 0 || h.isThrown && h.type === "piercer") continue;
1978
+ const p = h.position.x - c.position.x, d = h.position.y - c.position.y;
1979
+ p * p + d * d <= c.radius * c.radius && (P.killEnemy(h, 0, t, i, s, e), n.kills++, o && o());
1954
1980
  }
1955
1981
  c.duration >= c.maxDuration && t.splice(r, 1);
1956
1982
  }
1957
1983
  }
1958
1984
  }
1959
1985
  }
1960
- class at {
1961
- static update(t, e, i, s, a, l, n, o, r, c, h, u) {
1962
- for (const p of t)
1963
- if (!(!p.active || !p.isStationaryShield || p.isDying))
1964
- for (const _ of t) {
1965
- if (_ === p || !_.active || _.isGrabbed || _.isDying) continue;
1966
- const g = _.position.x - p.position.x, d = _.position.y - p.position.y;
1967
- if (Math.hypot(g, d) <= p.getHitRadius() + _.getHitRadius()) {
1968
- p.isStationaryShield = !1, p.strategy && p.strategy.execute({
1969
- thrownEnemy: p,
1970
- targetEnemy: _,
1986
+ class nt {
1987
+ static update(t, e, i, s, a, l, n, o, r, c, h, p, d) {
1988
+ const _ = A.getInstance().getConfig().shield.protectionArc;
1989
+ for (const m of t)
1990
+ if (!(!m.active || !m.isStationaryShield || m.isDying))
1991
+ for (const u of p.getNearby(m.position, m.getHitRadius() + 80)) {
1992
+ if (u === m || !u.active || u.isGrabbed || u.isDying || u.launchDelay > 0) continue;
1993
+ const g = u.position.x - m.position.x, f = u.position.y - m.position.y;
1994
+ let b = Math.atan2(f, g) - m.rotation;
1995
+ for (; b < -Math.PI; ) b += Math.PI * 2;
1996
+ for (; b > Math.PI; ) b -= Math.PI * 2;
1997
+ if (Math.abs(b) > _ / 2) continue;
1998
+ const y = m.getHitRadius() + u.getHitRadius();
1999
+ if (g * g + f * f <= y * y) {
2000
+ m.isStationaryShield = !1, m.strategy && m.strategy.execute({
2001
+ thrownEnemy: m,
2002
+ targetEnemy: u,
1971
2003
  allEnemies: t,
1972
2004
  pools: e,
1973
2005
  vortices: i,
@@ -1977,69 +2009,71 @@ class at {
1977
2009
  eventBus: o,
1978
2010
  width: c,
1979
2011
  height: h
1980
- }), r.kills += 2, n.triggerHitstop(0.12), n.triggerScreenShake({ x: g, y: d }, 18), u && u();
2012
+ }), r.kills += 2, n.triggerHitstop(0.12), n.triggerScreenShake({ x: g, y: f }, 18), d && d();
1981
2013
  break;
1982
2014
  }
1983
2015
  }
1984
2016
  }
1985
2017
  }
1986
- class ot {
2018
+ class rt {
1987
2019
  spatialHash;
1988
2020
  eventBus;
1989
2021
  i18n;
1990
2022
  throwState = { kills: 0, pos: null };
1991
2023
  constructor(t, e) {
1992
- this.spatialHash = new Z(100), this.eventBus = t, this.i18n = e;
1993
- }
1994
- update(t, e, i, s, a, l, n, o, r, c, h, u, p, _) {
1995
- this.spatialHash.clear();
1996
- const g = E.getInstance().getConfig().piercer;
1997
- for (const d of i)
1998
- if (d.active && !d.isDying) {
1999
- if (d.isThrown && d.type === "piercer" && g.hasHoming && d.remainingHomingKills > 0) {
2000
- let m = null, x = 1 / 0;
2001
- for (const A of i) {
2002
- if (A === d || !A.active || A.isGrabbed || A.isDying) continue;
2003
- const b = A.position.x - d.position.x, I = A.position.y - d.position.y, S = Math.hypot(b, I);
2004
- S < x && (x = S, m = A);
2024
+ this.spatialHash = new z(100), this.eventBus = t, this.i18n = e;
2025
+ }
2026
+ update(t, e, i, s, a, l, n, o, r, c, h, p, d, _) {
2027
+ const m = A.getInstance().getConfig().piercer;
2028
+ for (const g of i)
2029
+ if (g.active && !g.isDying) {
2030
+ if (g.isThrown && g.type === "piercer" && m.hasHoming && g.remainingHomingKills > 0) {
2031
+ let f = null, b = 1 / 0;
2032
+ for (const y of i) {
2033
+ if (y === g || !y.active || y.isGrabbed || y.isDying) continue;
2034
+ const v = y.position.x - g.position.x, M = y.position.y - g.position.y, T = v * v + M * M;
2035
+ T < b && (b = T, f = y);
2005
2036
  }
2006
- if (m) {
2007
- const A = Math.atan2(m.position.y - d.position.y, m.position.x - d.position.x), b = Math.max(Math.hypot(d.velocity.x, d.velocity.y), 1e3), I = 25 * t, S = Math.atan2(d.velocity.y, d.velocity.x);
2008
- let f = A - S;
2009
- for (; f < -Math.PI; ) f += Math.PI * 2;
2010
- for (; f > Math.PI; ) f -= Math.PI * 2;
2011
- const v = S + Math.sign(f) * Math.min(Math.abs(f), I);
2012
- d.rotation = v, d.velocity = {
2013
- x: Math.cos(v) * b,
2014
- y: Math.sin(v) * b
2037
+ if (f) {
2038
+ const y = Math.atan2(f.position.y - g.position.y, f.position.x - g.position.x), v = Math.max(Math.hypot(g.velocity.x, g.velocity.y), 1e3), M = 25 * t, T = Math.atan2(g.velocity.y, g.velocity.x);
2039
+ let x = y - T;
2040
+ for (; x < -Math.PI; ) x += Math.PI * 2;
2041
+ for (; x > Math.PI; ) x -= Math.PI * 2;
2042
+ const L = T + Math.sign(x) * Math.min(Math.abs(x), M);
2043
+ g.rotation = L, g.velocity = {
2044
+ x: Math.cos(L) * v,
2045
+ y: Math.sin(L) * v
2015
2046
  };
2016
2047
  }
2017
2048
  }
2018
- if (d.isStationaryShield) {
2019
- let m = null, x = 1 / 0;
2020
- for (const A of i) {
2021
- if (A === d || !A.active || A.isGrabbed || A.isDying || A.isStationaryShield) continue;
2022
- const b = A.position.x - d.position.x, I = A.position.y - d.position.y, S = Math.hypot(b, I);
2023
- S < x && (x = S, m = A);
2049
+ if (g.isStationaryShield) {
2050
+ let f = null, b = 1 / 0;
2051
+ for (const y of i) {
2052
+ if (y === g || !y.active || y.isGrabbed || y.isDying || y.isStationaryShield) continue;
2053
+ const v = y.position.x - g.position.x, M = y.position.y - g.position.y, T = v * v + M * M;
2054
+ T < b && (b = T, f = y);
2024
2055
  }
2025
- if (m) {
2026
- let b = Math.atan2(m.position.y - d.position.y, m.position.x - d.position.x) - d.rotation;
2027
- for (; b < -Math.PI; ) b += Math.PI * 2;
2028
- for (; b > Math.PI; ) b -= Math.PI * 2;
2029
- const I = 5 * t;
2030
- d.rotation += Math.sign(b) * Math.min(Math.abs(b), I);
2056
+ if (f) {
2057
+ let v = Math.atan2(f.position.y - g.position.y, f.position.x - g.position.x) - g.rotation;
2058
+ for (; v < -Math.PI; ) v += Math.PI * 2;
2059
+ for (; v > Math.PI; ) v -= Math.PI * 2;
2060
+ const M = 5 * t;
2061
+ g.rotation += Math.sign(v) * Math.min(Math.abs(v), M);
2031
2062
  }
2032
2063
  }
2033
- d.update(t), this.spatialHash.insert(d);
2034
- } else d.active && d.isDying && d.update(t);
2035
- for (let d = l.length - 1; d >= 0; d--) {
2036
- const m = l[d];
2037
- if (!m) continue;
2038
- m.lifetime += t;
2039
- const x = m.lifetime / m.maxLifetime;
2040
- m.radius = m.maxRadius * x, m.alpha = Math.max(0, 1 - x), m.lifetime >= m.maxLifetime && l.splice(d, 1);
2041
- }
2042
- $.update(a, i, t), X.update(
2064
+ g.update(t);
2065
+ } else g.active && g.isDying && g.update(t);
2066
+ for (let g = l.length - 1; g >= 0; g--) {
2067
+ const f = l[g];
2068
+ if (!f) continue;
2069
+ f.lifetime += t;
2070
+ const b = f.lifetime / f.maxLifetime;
2071
+ f.radius = f.maxRadius * b, f.alpha = Math.max(0, 1 - b), f.lifetime >= f.maxLifetime && l.splice(g, 1);
2072
+ }
2073
+ j.update(a, i, t), this.spatialHash.clear();
2074
+ for (const g of i)
2075
+ g.active && !g.isDying && g.launchDelay <= 0 && this.spatialHash.insert(g);
2076
+ q.update(
2043
2077
  e,
2044
2078
  i,
2045
2079
  l,
@@ -2048,9 +2082,9 @@ class ot {
2048
2082
  r,
2049
2083
  this.eventBus,
2050
2084
  h,
2051
- u,
2052
- p
2053
- ), it.update(
2085
+ p,
2086
+ d
2087
+ ), at.update(
2054
2088
  i,
2055
2089
  s,
2056
2090
  a,
@@ -2060,11 +2094,12 @@ class ot {
2060
2094
  r,
2061
2095
  this.eventBus,
2062
2096
  c,
2063
- u,
2064
2097
  p,
2098
+ d,
2065
2099
  this.throwState,
2100
+ this.spatialHash,
2066
2101
  _
2067
- ), st.update(
2102
+ ), ot.update(
2068
2103
  s,
2069
2104
  i,
2070
2105
  a,
@@ -2073,7 +2108,7 @@ class ot {
2073
2108
  t,
2074
2109
  this.throwState,
2075
2110
  _
2076
- ), at.update(
2111
+ ), nt.update(
2077
2112
  i,
2078
2113
  s,
2079
2114
  a,
@@ -2083,17 +2118,20 @@ class ot {
2083
2118
  r,
2084
2119
  this.eventBus,
2085
2120
  this.throwState,
2086
- u,
2087
2121
  p,
2122
+ d,
2123
+ this.spatialHash,
2088
2124
  _
2089
2125
  );
2126
+ const u = 32;
2127
+ l.length > u && l.splice(0, l.length - u);
2090
2128
  }
2091
2129
  }
2092
- class nt {
2130
+ class lt {
2093
2131
  pool = [];
2094
2132
  constructor(t = 500) {
2095
2133
  for (let e = 0; e < t; e++) {
2096
- const i = new D(`pool_enemy_${e}`);
2134
+ const i = new U(`pool_enemy_${e}`);
2097
2135
  this.pool.push(i);
2098
2136
  }
2099
2137
  }
@@ -2101,7 +2139,7 @@ class nt {
2101
2139
  for (const e of this.pool)
2102
2140
  if (!e.active)
2103
2141
  return e.reset(), e;
2104
- const t = new D(`fallback_enemy_${Date.now()}_${Math.random()}`);
2142
+ const t = new U(`fallback_enemy_${Date.now()}_${Math.random()}`);
2105
2143
  return this.pool.push(t), t;
2106
2144
  }
2107
2145
  resetAll() {
@@ -2109,7 +2147,7 @@ class nt {
2109
2147
  t.reset();
2110
2148
  }
2111
2149
  }
2112
- class R {
2150
+ class O {
2113
2151
  static getOffscreenPosition(t, e) {
2114
2152
  const i = Math.floor(Math.random() * 4), s = 70;
2115
2153
  return i === 0 ? { x: Math.random() * t, y: -s } : i === 1 ? { x: t + s, y: Math.random() * e } : i === 2 ? { x: Math.random() * t, y: e + s } : { x: -s, y: Math.random() * e };
@@ -2120,8 +2158,8 @@ class R {
2120
2158
  const r = o * Math.PI * 2 / 18, c = {
2121
2159
  x: e.x + Math.cos(r) * n,
2122
2160
  y: e.y + Math.sin(r) * n
2123
- }, h = t.get(), u = ["piercer", "spore", "cluster", "parasite"], p = u[o % u.length];
2124
- M.configureEnemy(h, p, c, e), h.velocity = {
2161
+ }, h = t.get(), p = ["piercer", "spore", "cluster", "parasite"], d = p[o % p.length];
2162
+ C.configureEnemy(h, d, c, e), h.velocity = {
2125
2163
  x: Math.cos(r + Math.PI) * 55,
2126
2164
  y: Math.sin(r + Math.PI) * 55
2127
2165
  }, a.push(h);
@@ -2136,13 +2174,13 @@ class R {
2136
2174
  const c = {
2137
2175
  x: (Math.random() - 0.5) * 60,
2138
2176
  y: (Math.random() - 0.5) * 60
2139
- }, h = { x: o.x + c.x, y: o.y + c.y }, u = t.get();
2140
- M.configureEnemy(u, "spore", h, s);
2141
- const p = s.x - h.x, _ = s.y - h.y, g = Math.atan2(_, p);
2142
- u.velocity = {
2143
- x: Math.cos(g) * (50 + Math.random() * 20),
2144
- y: Math.sin(g) * (50 + Math.random() * 20)
2145
- }, a.push(u);
2177
+ }, h = { x: o.x + c.x, y: o.y + c.y }, p = t.get();
2178
+ C.configureEnemy(p, "spore", h, s);
2179
+ const d = s.x - h.x, _ = s.y - h.y, m = Math.atan2(_, d);
2180
+ p.velocity = {
2181
+ x: Math.cos(m) * (50 + Math.random() * 20),
2182
+ y: Math.sin(m) * (50 + Math.random() * 20)
2183
+ }, a.push(p);
2146
2184
  }
2147
2185
  return a;
2148
2186
  }
@@ -2153,7 +2191,7 @@ class R {
2153
2191
  x: -60 - o * 40,
2154
2192
  y: n + Math.sin(o * 0.45) * 70
2155
2193
  }, c = t.get();
2156
- M.configureEnemy(c, "cluster", r, s), c.velocity = { x: 75, y: Math.cos(o * 0.45) * 30 }, a.push(c);
2194
+ C.configureEnemy(c, "cluster", r, s), c.velocity = { x: 75, y: Math.cos(o * 0.45) * 30 }, a.push(c);
2157
2195
  }
2158
2196
  return a;
2159
2197
  }
@@ -2163,8 +2201,8 @@ class R {
2163
2201
  const o = n / 14, r = o * Math.PI * 4, c = 120 + o * 450, h = {
2164
2202
  x: e + Math.cos(r) * c,
2165
2203
  y: -60 + Math.sin(r) * c
2166
- }, u = t.get();
2167
- M.configureEnemy(u, "parasite", h, s), a.push(u);
2204
+ }, p = t.get();
2205
+ C.configureEnemy(p, "parasite", h, s), a.push(p);
2168
2206
  }
2169
2207
  return a;
2170
2208
  }
@@ -2175,7 +2213,7 @@ class R {
2175
2213
  x: n ? -60 : e + 60,
2176
2214
  y: r
2177
2215
  }, h = t.get();
2178
- M.configureEnemy(h, "piercer", c, s), h.velocity = {
2216
+ C.configureEnemy(h, "piercer", c, s), h.velocity = {
2179
2217
  x: n ? 70 : -70,
2180
2218
  y: 0
2181
2219
  }, a.push(h);
@@ -2186,14 +2224,14 @@ class R {
2186
2224
  const a = [];
2187
2225
  for (let n = 0; n < 10; n++) {
2188
2226
  const o = { x: -50 - n * 35, y: -50 - n * 35 }, r = t.get();
2189
- M.configureEnemy(r, "spore", o, s), a.push(r);
2227
+ C.configureEnemy(r, "spore", o, s), a.push(r);
2190
2228
  const c = { x: e + 50 + n * 35, y: i + 50 + n * 35 }, h = t.get();
2191
- M.configureEnemy(h, "cluster", c, s), a.push(h);
2229
+ C.configureEnemy(h, "cluster", c, s), a.push(h);
2192
2230
  }
2193
2231
  return a;
2194
2232
  }
2195
2233
  }
2196
- class rt {
2234
+ class ct {
2197
2235
  wave = 1;
2198
2236
  pool;
2199
2237
  spawnTimer = 0;
@@ -2201,7 +2239,7 @@ class rt {
2201
2239
  patternCooldown = 0;
2202
2240
  initialGracePeriod = 6;
2203
2241
  constructor() {
2204
- this.pool = new nt(500);
2242
+ this.pool = new lt(500);
2205
2243
  }
2206
2244
  reset() {
2207
2245
  this.wave = 1, this.spawnTimer = 0, this.waveTimer = 0, this.patternCooldown = 0;
@@ -2219,45 +2257,45 @@ class rt {
2219
2257
  return this.spawnTimer >= n && l < o ? (this.spawnTimer = 0, this.spawnSingleEnemy(i, s, a)) : null;
2220
2258
  }
2221
2259
  spawnSingleEnemy(t, e, i) {
2222
- const s = R.getOffscreenPosition(t, e), a = Math.random();
2260
+ const s = O.getOffscreenPosition(t, e), a = Math.random();
2223
2261
  let l = "piercer";
2224
2262
  a > 0.75 ? l = "heavy" : a > 0.55 ? l = "parasite" : a > 0.35 ? l = "cluster" : a > 0.15 && (l = "spore");
2225
2263
  const n = this.pool.get();
2226
- return M.configureEnemy(n, l, s, i), n;
2264
+ return C.configureEnemy(n, l, s, i), n;
2227
2265
  }
2228
2266
  spawnPatternFormation(t, e, i) {
2229
2267
  const s = Math.random();
2230
- return s < 0.25 ? R.spawnCircleOfDeath(this.pool, i, t, e) : s < 0.5 ? R.spawnDenseCluster(this.pool, t, e, i) : s < 0.75 ? R.spawnSineSnake(this.pool, t, e, i) : R.spawnMarchingWall(this.pool, t, e, i);
2268
+ return s < 0.25 ? O.spawnCircleOfDeath(this.pool, i, t, e) : s < 0.5 ? O.spawnDenseCluster(this.pool, t, e, i) : s < 0.75 ? O.spawnSineSnake(this.pool, t, e, i) : O.spawnMarchingWall(this.pool, t, e, i);
2231
2269
  }
2232
2270
  applyFlockingBehaviors(t, e, i) {
2233
2271
  for (let a = 0; a < t.length; a++) {
2234
2272
  const l = t[a];
2235
2273
  if (!l.active || l.isGrabbed || l.isThrown || l.isDying) continue;
2236
2274
  let n = 0, o = 0, r = 0;
2237
- for (let p = 0; p < t.length; p++) {
2238
- if (a === p) continue;
2239
- const _ = t[p];
2275
+ for (let d = 0; d < t.length; d++) {
2276
+ if (a === d) continue;
2277
+ const _ = t[d];
2240
2278
  if (!_.active || _.isGrabbed || _.isDying) continue;
2241
- const g = l.position.x - _.position.x, d = l.position.y - _.position.y, m = Math.hypot(g, d);
2242
- m > 0 && m < 70 && (n += g / m, o += d / m, r++);
2279
+ const m = l.position.x - _.position.x, u = l.position.y - _.position.y, g = Math.hypot(m, u);
2280
+ g > 0 && g < 70 && (n += m / g, o += u / g, r++);
2243
2281
  }
2244
2282
  r > 0 && (n /= r, o /= r, l.velocity.x += n * 60 * e, l.velocity.y += o * 60 * e);
2245
- const c = i.x - l.position.x, h = i.y - l.position.y, u = Math.hypot(c, h);
2246
- if (u > 0) {
2247
- const p = 80 + Math.min(this.wave * 4, 40);
2248
- l.velocity.x += c / u * p * e, l.velocity.y += h / u * p * e;
2283
+ const c = i.x - l.position.x, h = i.y - l.position.y, p = Math.hypot(c, h);
2284
+ if (p > 0) {
2285
+ const d = 80 + Math.min(this.wave * 4, 40);
2286
+ l.velocity.x += c / p * d * e, l.velocity.y += h / p * d * e;
2249
2287
  }
2250
2288
  if (l.maxSpeed > 0) {
2251
- const p = Math.hypot(l.velocity.x, l.velocity.y);
2252
- if (p > l.maxSpeed) {
2253
- const _ = l.maxSpeed / p;
2289
+ const d = Math.hypot(l.velocity.x, l.velocity.y);
2290
+ if (d > l.maxSpeed) {
2291
+ const _ = l.maxSpeed / d;
2254
2292
  l.velocity.x *= _, l.velocity.y *= _;
2255
2293
  }
2256
2294
  }
2257
2295
  }
2258
2296
  }
2259
2297
  }
2260
- class lt {
2298
+ class ht {
2261
2299
  id;
2262
2300
  position;
2263
2301
  velocity;
@@ -2297,7 +2335,7 @@ class lt {
2297
2335
  }
2298
2336
  }
2299
2337
  }
2300
- const C = {
2338
+ const N = {
2301
2339
  bioluminescent: {
2302
2340
  bgInner: "#081220",
2303
2341
  bgMid: "#050b16",
@@ -2364,22 +2402,22 @@ const C = {
2364
2402
  vortexCore: "#274760",
2365
2403
  vortexMid: "#577c9e"
2366
2404
  }
2367
- }, N = "axon_surge_theme";
2368
- class ct {
2405
+ }, k = "axon_surge_theme";
2406
+ class pt {
2369
2407
  currentTheme = "dark";
2370
2408
  isExplicit = !1;
2371
2409
  targetElement;
2372
2410
  constructor(t, e) {
2373
2411
  e !== void 0 && (this.targetElement = e);
2374
2412
  try {
2375
- const i = localStorage.getItem(N);
2376
- if (i && C[i]) {
2413
+ const i = localStorage.getItem(k);
2414
+ if (i && N[i]) {
2377
2415
  this.currentTheme = i, this.isExplicit = !0, this.applyThemeToDOM();
2378
2416
  return;
2379
2417
  }
2380
2418
  } catch {
2381
2419
  }
2382
- if (t && C[t]) {
2420
+ if (t && N[t]) {
2383
2421
  this.currentTheme = t, this.isExplicit = !0, this.applyThemeToDOM();
2384
2422
  return;
2385
2423
  }
@@ -2389,10 +2427,10 @@ class ct {
2389
2427
  this.targetElement = t, this.isExplicit ? this.applyThemeToDOM() : this.currentTheme = this.detectParentOrSystemTheme();
2390
2428
  }
2391
2429
  setTheme(t) {
2392
- if (C[t]) {
2430
+ if (N[t]) {
2393
2431
  this.currentTheme = t, this.isExplicit = !0, this.applyThemeToDOM();
2394
2432
  try {
2395
- localStorage.setItem(N, t);
2433
+ localStorage.setItem(k, t);
2396
2434
  } catch {
2397
2435
  }
2398
2436
  }
@@ -2400,7 +2438,7 @@ class ct {
2400
2438
  clearExplicitTheme() {
2401
2439
  this.isExplicit = !1;
2402
2440
  try {
2403
- localStorage.removeItem(N);
2441
+ localStorage.removeItem(k);
2404
2442
  } catch {
2405
2443
  }
2406
2444
  this.removeThemeClasses(), this.currentTheme = this.detectParentOrSystemTheme();
@@ -2409,7 +2447,7 @@ class ct {
2409
2447
  return this.isExplicit || (this.currentTheme = this.detectParentOrSystemTheme()), this.currentTheme;
2410
2448
  }
2411
2449
  getPalette() {
2412
- return C[this.getTheme()] || C.dark;
2450
+ return N[this.getTheme()] || N.dark;
2413
2451
  }
2414
2452
  detectParentOrSystemTheme() {
2415
2453
  try {
@@ -2447,7 +2485,7 @@ class ct {
2447
2485
  this.targetElement.classList.add(t);
2448
2486
  }
2449
2487
  }
2450
- class ht {
2488
+ class ut {
2451
2489
  maxDistance = 800;
2452
2490
  maxThickness = 18;
2453
2491
  minThickness = 5;
@@ -2460,50 +2498,50 @@ class ht {
2460
2498
  if (n >= 0 && n <= i && o >= 0 && o <= s) continue;
2461
2499
  const r = Math.min(i, Math.max(0, n)), c = Math.min(s, Math.max(0, o)), h = Math.hypot(n - r, o - c);
2462
2500
  if (h <= 0 || h > this.maxDistance) continue;
2463
- const u = Math.min(1, Math.max(0, h / this.maxDistance)), p = this.minThickness + (this.maxThickness - this.minThickness) * (1 - u), _ = this.minLength + (this.maxLength - this.minLength) * (1 - u), g = 0.55 + (1 - u) * 0.35;
2464
- if (t.save(), t.globalAlpha = g, t.shadowColor = l.color, t.shadowBlur = 14, t.strokeStyle = l.color, t.lineWidth = p, t.lineCap = "round", t.beginPath(), r === 0 || r === i) {
2465
- const d = Math.max(0, c - _ / 2), m = Math.min(s, c + _ / 2);
2466
- t.moveTo(r, d), t.lineTo(r, m);
2501
+ const p = Math.min(1, Math.max(0, h / this.maxDistance)), d = this.minThickness + (this.maxThickness - this.minThickness) * (1 - p), _ = this.minLength + (this.maxLength - this.minLength) * (1 - p), m = 0.55 + (1 - p) * 0.35;
2502
+ if (t.save(), t.globalAlpha = m, t.shadowColor = l.color, t.shadowBlur = 14, t.strokeStyle = l.color, t.lineWidth = d, t.lineCap = "round", t.beginPath(), r === 0 || r === i) {
2503
+ const u = Math.max(0, c - _ / 2), g = Math.min(s, c + _ / 2);
2504
+ t.moveTo(r, u), t.lineTo(r, g);
2467
2505
  } else {
2468
- const d = Math.max(0, r - _ / 2), m = Math.min(i, r + _ / 2);
2469
- t.moveTo(d, c), t.lineTo(m, c);
2506
+ const u = Math.max(0, r - _ / 2), g = Math.min(i, r + _ / 2);
2507
+ t.moveTo(u, c), t.lineTo(g, c);
2470
2508
  }
2471
- t.stroke(), t.strokeStyle = a.effectHighlight, t.lineWidth = Math.max(1.8, p * 0.28), t.globalAlpha = g * 0.9, t.stroke(), t.restore();
2509
+ t.stroke(), t.strokeStyle = a.effectHighlight, t.lineWidth = Math.max(1.8, d * 0.28), t.globalAlpha = m * 0.9, t.stroke(), t.restore();
2472
2510
  }
2473
2511
  }
2474
2512
  }
2475
- class ut {
2513
+ class dt {
2476
2514
  render(t, e, i, s, a, l, n = !1) {
2477
- const o = Math.max(1, a), r = Math.min(1, (o - 1) / 8), c = this.wrapHue(190 + (o - 1) * 34 + Math.sin(s * 0.1) * 5), h = this.wrapHue(c + 42), u = this.wrapHue(c + 150), p = e / 2, _ = i / 2, g = Math.max(e, i) * 0.82, d = t.createRadialGradient(p, _, 20, p, _, g);
2478
- n ? (d.addColorStop(0, `hsl(${c}, 42%, 91%)`), d.addColorStop(0.42, `hsl(${h}, 42%, 86%)`), d.addColorStop(0.78, `hsl(${u}, 38%, 81%)`), d.addColorStop(1, l.bgOuter)) : (d.addColorStop(0, `hsl(${c}, 42%, 11%)`), d.addColorStop(0.42, `hsl(${h}, 48%, 8%)`), d.addColorStop(0.78, `hsl(${u}, 42%, 5%)`), d.addColorStop(1, `hsl(${u}, 48%, 2.5%)`)), t.fillStyle = d, t.fillRect(0, 0, e, i);
2479
- const m = Math.min(e, i) * 0.055;
2515
+ const o = Math.max(1, a), r = Math.min(1, (o - 1) / 8), c = this.wrapHue(190 + (o - 1) * 34 + Math.sin(s * 0.1) * 5), h = this.wrapHue(c + 42), p = this.wrapHue(c + 150), d = e / 2, _ = i / 2, m = Math.max(e, i) * 0.82, u = t.createRadialGradient(d, _, 20, d, _, m);
2516
+ n ? (u.addColorStop(0, `hsl(${c}, 42%, 91%)`), u.addColorStop(0.42, `hsl(${h}, 42%, 86%)`), u.addColorStop(0.78, `hsl(${p}, 38%, 81%)`), u.addColorStop(1, l.bgOuter)) : (u.addColorStop(0, `hsl(${c}, 42%, 11%)`), u.addColorStop(0.42, `hsl(${h}, 48%, 8%)`), u.addColorStop(0.78, `hsl(${p}, 42%, 5%)`), u.addColorStop(1, `hsl(${p}, 48%, 2.5%)`)), t.fillStyle = u, t.fillRect(0, 0, e, i);
2517
+ const g = Math.min(e, i) * 0.055;
2480
2518
  this.drawNebula(
2481
2519
  t,
2482
- e * 0.22 + Math.sin(s * 0.18) * m,
2483
- i * 0.28 + Math.cos(s * 0.15) * m,
2520
+ e * 0.22 + Math.sin(s * 0.18) * g,
2521
+ i * 0.28 + Math.cos(s * 0.15) * g,
2484
2522
  Math.max(e, i) * 0.42,
2485
2523
  c,
2486
2524
  n ? 0.27 : 0.23,
2487
2525
  n
2488
2526
  ), this.drawNebula(
2489
2527
  t,
2490
- e * 0.8 + Math.cos(s * 0.14) * m,
2491
- i * 0.7 + Math.sin(s * 0.17) * m,
2528
+ e * 0.8 + Math.cos(s * 0.14) * g,
2529
+ i * 0.7 + Math.sin(s * 0.17) * g,
2492
2530
  Math.max(e, i) * 0.48,
2493
2531
  h,
2494
2532
  n ? 0.23 : 0.2,
2495
2533
  n
2496
2534
  ), this.drawNebula(
2497
2535
  t,
2498
- e * 0.86 + Math.sin(s * 0.11) * m * 0.7,
2499
- i * 0.16 + Math.cos(s * 0.13) * m * 0.7,
2536
+ e * 0.86 + Math.sin(s * 0.11) * g * 0.7,
2537
+ i * 0.16 + Math.cos(s * 0.13) * g * 0.7,
2500
2538
  Math.max(e, i) * 0.3,
2501
- u,
2539
+ p,
2502
2540
  n ? 0.17 : 0.14,
2503
2541
  n
2504
2542
  ), this.drawSoftFlows(t, e, i, s, c, r, n), this.drawParticleField(t, e, i, s, c, h, o, n);
2505
- const x = t.createRadialGradient(p, _, Math.min(e, i) * 0.28, p, _, g);
2506
- x.addColorStop(0, "rgba(0, 0, 0, 0)"), x.addColorStop(1, n ? "rgba(40, 60, 90, 0.09)" : "rgba(0, 0, 0, 0.2)"), t.fillStyle = x, t.fillRect(0, 0, e, i);
2543
+ const f = t.createRadialGradient(d, _, Math.min(e, i) * 0.28, d, _, m);
2544
+ f.addColorStop(0, "rgba(0, 0, 0, 0)"), f.addColorStop(1, n ? "rgba(40, 60, 90, 0.09)" : "rgba(0, 0, 0, 0.2)"), t.fillStyle = f, t.fillRect(0, 0, e, i);
2507
2545
  }
2508
2546
  drawNebula(t, e, i, s, a, l, n) {
2509
2547
  const o = t.createRadialGradient(e, i, 0, e, i, s), r = n ? 52 : 60;
@@ -2514,16 +2552,16 @@ class ut {
2514
2552
  const o = Math.min(e, i), r = o * 0.035;
2515
2553
  t.globalAlpha = n ? 0.15 : 0.12, t.lineWidth = Math.max(1.3, o * 17e-4), t.lineCap = "round", t.shadowBlur = o * 0.02, t.shadowColor = `hsla(${a}, 85%, ${n ? 52 : 62}%, 0.28)`;
2516
2554
  for (let c = 0; c < 3; c++) {
2517
- const h = (c - 1) * o * 0.075 + Math.sin(s * 0.06 + c) * r, u = c * 28 + l * 18;
2518
- t.strokeStyle = `hsla(${this.wrapHue(a + u)}, ${n ? 78 : 74}%, ${n ? 47 : 62}%, ${0.52 - c * 0.08})`, t.beginPath(), t.moveTo(-o * 0.12, i * 0.2 + h), t.bezierCurveTo(e * 0.2, i * 0.02 + h, e * 0.47, i * 0.2 - h, e * 0.73, i * 0.07 + h), t.bezierCurveTo(e * 0.94, -o * 0.02 + h, e * 1.04, i * 0.16 + h, e * 1.1, i * 0.36 + h), t.stroke(), t.beginPath(), t.moveTo(-o * 0.1, i * 0.8 - h), t.bezierCurveTo(e * 0.2, i * 0.98 - h, e * 0.48, i * 0.8 + h, e * 0.75, i * 0.93 - h), t.bezierCurveTo(e * 0.94, i * 1.02 - h, e * 1.04, i * 0.84 - h, e * 1.1, i * 0.65 - h), t.stroke();
2555
+ const h = (c - 1) * o * 0.075 + Math.sin(s * 0.06 + c) * r, p = c * 28 + l * 18;
2556
+ t.strokeStyle = `hsla(${this.wrapHue(a + p)}, ${n ? 78 : 74}%, ${n ? 47 : 62}%, ${0.52 - c * 0.08})`, t.beginPath(), t.moveTo(-o * 0.12, i * 0.2 + h), t.bezierCurveTo(e * 0.2, i * 0.02 + h, e * 0.47, i * 0.2 - h, e * 0.73, i * 0.07 + h), t.bezierCurveTo(e * 0.94, -o * 0.02 + h, e * 1.04, i * 0.16 + h, e * 1.1, i * 0.36 + h), t.stroke(), t.beginPath(), t.moveTo(-o * 0.1, i * 0.8 - h), t.bezierCurveTo(e * 0.2, i * 0.98 - h, e * 0.48, i * 0.8 + h, e * 0.75, i * 0.93 - h), t.bezierCurveTo(e * 0.94, i * 1.02 - h, e * 1.04, i * 0.84 - h, e * 1.1, i * 0.65 - h), t.stroke();
2519
2557
  }
2520
2558
  t.restore();
2521
2559
  }
2522
2560
  drawParticleField(t, e, i, s, a, l, n, o) {
2523
- const r = 44 + Math.min(24, n * 2), c = e / 2, h = i / 2, u = Math.min(e, i) * 0.17;
2524
- for (let p = 0; p < r; p++) {
2525
- const _ = p + n * 17, g = this.unitNoise(_ * 1.7) * e, d = this.unitNoise(_ * 2.9 + 13) * i, m = Math.hypot(g - c, d - h), x = Math.min(1, Math.max(0, (m - u) / (Math.min(e, i) * 0.28))), A = 0.7 + Math.sin(s * (0.6 + p % 4 * 0.08) + _) * 0.3, b = (o ? 0.34 : 0.3) * x * A, I = 0.65 + p % 3 * 0.45;
2526
- t.fillStyle = `hsla(${p % 3 === 0 ? l : a}, ${o ? 82 : 78}%, ${o ? 40 : 70}%, ${b})`, t.beginPath(), t.arc(g, d, I, 0, Math.PI * 2), t.fill();
2561
+ const r = 44 + Math.min(24, n * 2), c = e / 2, h = i / 2, p = Math.min(e, i) * 0.17;
2562
+ for (let d = 0; d < r; d++) {
2563
+ const _ = d + n * 17, m = this.unitNoise(_ * 1.7) * e, u = this.unitNoise(_ * 2.9 + 13) * i, g = Math.hypot(m - c, u - h), f = Math.min(1, Math.max(0, (g - p) / (Math.min(e, i) * 0.28))), b = 0.7 + Math.sin(s * (0.6 + d % 4 * 0.08) + _) * 0.3, y = (o ? 0.34 : 0.3) * f * b, v = 0.65 + d % 3 * 0.45;
2564
+ t.fillStyle = `hsla(${d % 3 === 0 ? l : a}, ${o ? 82 : 78}%, ${o ? 40 : 70}%, ${y})`, t.beginPath(), t.arc(m, u, v, 0, Math.PI * 2), t.fill();
2527
2565
  }
2528
2566
  }
2529
2567
  unitNoise(t) {
@@ -2533,7 +2571,7 @@ class ut {
2533
2571
  return (t % 360 + 360) % 360;
2534
2572
  }
2535
2573
  }
2536
- class pt {
2574
+ class gt {
2537
2575
  render(t, e, i) {
2538
2576
  if (!e.isActive) return;
2539
2577
  const s = e.getLauncher(), a = e.getTarget();
@@ -2549,16 +2587,16 @@ class pt {
2549
2587
  if (Math.hypot(n, o) > 10) {
2550
2588
  const c = Math.atan2(o, n);
2551
2589
  t.shadowColor = "#ff00dd", t.shadowBlur = 22, t.strokeStyle = "#ff00dd", t.lineWidth = 4, t.setLineDash([12, 8]), t.beginPath(), t.moveTo(s.position.x, s.position.y), t.lineTo(a.position.x, a.position.y), t.stroke(), t.setLineDash([]);
2552
- const h = a.position.x - Math.cos(c) * (a.radius + 10), u = a.position.y - Math.sin(c) * (a.radius + 10);
2553
- t.fillStyle = "#ff00dd", t.beginPath(), t.moveTo(h, u), t.lineTo(h - Math.cos(c - 0.4) * 24, u - Math.sin(c - 0.4) * 24), t.lineTo(h - Math.cos(c + 0.4) * 24, u - Math.sin(c + 0.4) * 24), t.closePath(), t.fill();
2554
- const p = a.radius * (1.8 + Math.cos(i * 10) * 0.3);
2555
- t.strokeStyle = "rgba(255, 0, 221, 0.9)", t.lineWidth = 3.5, t.beginPath(), t.arc(a.position.x, a.position.y, p, 0, Math.PI * 2), t.stroke();
2590
+ const h = a.position.x - Math.cos(c) * (a.radius + 10), p = a.position.y - Math.sin(c) * (a.radius + 10);
2591
+ t.fillStyle = "#ff00dd", t.beginPath(), t.moveTo(h, p), t.lineTo(h - Math.cos(c - 0.4) * 24, p - Math.sin(c - 0.4) * 24), t.lineTo(h - Math.cos(c + 0.4) * 24, p - Math.sin(c + 0.4) * 24), t.closePath(), t.fill();
2592
+ const d = a.radius * (1.8 + Math.cos(i * 10) * 0.3);
2593
+ t.strokeStyle = "rgba(255, 0, 221, 0.9)", t.lineWidth = 3.5, t.beginPath(), t.arc(a.position.x, a.position.y, d, 0, Math.PI * 2), t.stroke();
2556
2594
  }
2557
2595
  }
2558
2596
  t.restore();
2559
2597
  }
2560
2598
  }
2561
- class dt {
2599
+ class _t {
2562
2600
  canvas;
2563
2601
  ctx;
2564
2602
  themeManager;
@@ -2566,20 +2604,20 @@ class dt {
2566
2604
  bgRenderer;
2567
2605
  tutorialArrowRenderer;
2568
2606
  constructor(t, e) {
2569
- this.canvas = t, this.ctx = t.getContext("2d"), this.themeManager = e, this.indicatorRenderer = new ht(), this.bgRenderer = new ut(), this.tutorialArrowRenderer = new pt();
2607
+ this.canvas = t, this.ctx = t.getContext("2d"), this.themeManager = e, this.indicatorRenderer = new ut(), this.bgRenderer = new dt(), this.tutorialArrowRenderer = new gt();
2570
2608
  }
2571
- render(t, e, i, s, a, l, n, o, r, c, h, u = 1, p) {
2609
+ render(t, e, i, s, a, l, n, o, r, c, h, p = 1, d) {
2572
2610
  if (!this.ctx) return;
2573
- const _ = this.themeManager.getPalette(), { width: g, height: d } = this.canvas, m = r.getShakeOffset();
2574
- this.ctx.save(), this.ctx.translate(m.x, m.y), this.bgRenderer.render(
2611
+ const _ = this.themeManager.getPalette(), { width: m, height: u } = this.canvas, g = r.getShakeOffset();
2612
+ this.ctx.save(), this.ctx.translate(g.x, g.y), this.bgRenderer.render(
2575
2613
  this.ctx,
2576
- g,
2577
- d,
2578
- t.pulsePhase,
2614
+ m,
2579
2615
  u,
2616
+ t.pulsePhase,
2617
+ p,
2580
2618
  _,
2581
2619
  this.themeManager.getTheme() === "light"
2582
- ), this.drawExperienceOrbs(i, t.position, t.pulsePhase, _), this.drawToxicPools(s, t.pulsePhase), this.drawGravityVortices(a, t.pulsePhase), this.drawShockwaves(l), this.drawCoreFilaments(t, _), this.drawParticles(n), E.getInstance().getConfig().core.hasOffscreenIndicators && this.indicatorRenderer.render(this.ctx, e, g, d, _), this.drawOrganicEnemies(e, t.pulsePhase, _), p && this.tutorialArrowRenderer.render(this.ctx, p, t.pulsePhase), c ? this.drawPsionicTendril(t.position, c.position, _) : t && this.drawHoverTendril(t.position, h, e, _), this.drawOrganicConsciousnessCore(t, _), this.drawFloatingTexts(o), r.flashAlpha > 0 && (this.ctx.fillStyle = `rgba(255, 255, 255, ${r.flashAlpha})`, this.ctx.fillRect(0, 0, g, d)), this.ctx.restore();
2620
+ ), this.drawExperienceOrbs(i, t.position, t.pulsePhase, _), this.drawToxicPools(s, t.pulsePhase), this.drawGravityVortices(a, t.pulsePhase), this.drawShockwaves(l), this.drawCoreFilaments(t, _), this.drawParticles(n), A.getInstance().getConfig().core.hasOffscreenIndicators && this.indicatorRenderer.render(this.ctx, e, m, u, _), this.drawOrganicEnemies(e, t.pulsePhase, _), d && this.tutorialArrowRenderer.render(this.ctx, d, t.pulsePhase), c ? this.drawPsionicTendril(t.position, c.position, _) : t && this.drawHoverTendril(t.position, h, e, _), this.drawOrganicConsciousnessCore(t, _), this.drawFloatingTexts(o), r.flashAlpha > 0 && (this.ctx.fillStyle = `rgba(255, 255, 255, ${r.flashAlpha})`, this.ctx.fillRect(0, 0, m, u)), this.ctx.restore();
2583
2621
  }
2584
2622
  drawExperienceOrbs(t, e, i, s) {
2585
2623
  if (this.ctx)
@@ -2600,18 +2638,18 @@ class dt {
2600
2638
  o.addColorStop(0, `rgba(57, 255, 20, ${a * 0.9})`), o.addColorStop(0.4, `rgba(16, 185, 129, ${a * 0.65})`), o.addColorStop(0.8, `rgba(5, 80, 45, ${a * 0.35})`), o.addColorStop(1, "rgba(2, 35, 15, 0)"), this.ctx.fillStyle = o, this.ctx.shadowColor = "#39ff14", this.ctx.shadowBlur = 30, this.ctx.beginPath();
2601
2639
  const r = 70;
2602
2640
  for (let c = 0; c <= r; c++) {
2603
- const h = c * Math.PI * 2 / r, u = Math.sin(h * 5 + e * 3) * 14, p = Math.cos(h * 3 - e * 2) * 9, _ = i.radius + u + p, g = l + Math.cos(h) * _, d = n + Math.sin(h) * _;
2604
- c === 0 ? this.ctx.moveTo(g, d) : this.ctx.lineTo(g, d);
2641
+ const h = c * Math.PI * 2 / r, p = Math.sin(h * 5 + e * 3) * 14, d = Math.cos(h * 3 - e * 2) * 9, _ = i.radius + p + d, m = l + Math.cos(h) * _, u = n + Math.sin(h) * _;
2642
+ c === 0 ? this.ctx.moveTo(m, u) : this.ctx.lineTo(m, u);
2605
2643
  }
2606
2644
  this.ctx.closePath(), this.ctx.fill(), this.ctx.strokeStyle = `rgba(57, 255, 20, ${a * 0.8})`, this.ctx.lineWidth = 2.5, this.ctx.beginPath();
2607
2645
  for (let c = 0; c <= r; c++) {
2608
- const h = c * Math.PI * 2 / r, u = Math.sin(h * 6 + e * 4) * 8, p = i.radius * 0.75 + u, _ = l + Math.cos(h) * p, g = n + Math.sin(h) * p;
2609
- c === 0 ? this.ctx.moveTo(_, g) : this.ctx.lineTo(_, g);
2646
+ const h = c * Math.PI * 2 / r, p = Math.sin(h * 6 + e * 4) * 8, d = i.radius * 0.75 + p, _ = l + Math.cos(h) * d, m = n + Math.sin(h) * d;
2647
+ c === 0 ? this.ctx.moveTo(_, m) : this.ctx.lineTo(_, m);
2610
2648
  }
2611
2649
  this.ctx.closePath(), this.ctx.stroke();
2612
2650
  for (let c = 0; c < 6; c++) {
2613
- const h = c * Math.PI * 0.33 + e * 1.5, u = i.radius * 0.5 * (0.3 + Math.sin(e * 2 + c) * 0.3), p = l + Math.cos(h) * u, _ = n + Math.sin(h) * u, g = 3 + Math.sin(e * 3 + c) * 2;
2614
- this.ctx.fillStyle = `rgba(255, 255, 255, ${a * 0.8})`, this.ctx.beginPath(), this.ctx.arc(p, _, Math.max(1, g), 0, Math.PI * 2), this.ctx.fill();
2651
+ const h = c * Math.PI * 0.33 + e * 1.5, p = i.radius * 0.5 * (0.3 + Math.sin(e * 2 + c) * 0.3), d = l + Math.cos(h) * p, _ = n + Math.sin(h) * p, m = 3 + Math.sin(e * 3 + c) * 2;
2652
+ this.ctx.fillStyle = `rgba(255, 255, 255, ${a * 0.8})`, this.ctx.beginPath(), this.ctx.arc(d, _, Math.max(1, m), 0, Math.PI * 2), this.ctx.fill();
2615
2653
  }
2616
2654
  this.ctx.restore();
2617
2655
  }
@@ -2619,8 +2657,9 @@ class dt {
2619
2657
  drawShockwaves(t) {
2620
2658
  if (!this.ctx) return;
2621
2659
  const e = this.themeManager.getTheme() === "light";
2660
+ this.ctx.save();
2622
2661
  for (const i of t) {
2623
- this.ctx.save(), this.ctx.globalAlpha = i.alpha;
2662
+ this.ctx.globalAlpha = i.alpha;
2624
2663
  const s = this.ctx.createRadialGradient(
2625
2664
  i.position.x,
2626
2665
  i.position.y,
@@ -2629,8 +2668,9 @@ class dt {
2629
2668
  i.position.y,
2630
2669
  i.radius
2631
2670
  );
2632
- s.addColorStop(0, e ? "rgba(255, 255, 255, 0.72)" : "rgba(255, 255, 255, 0.4)"), s.addColorStop(0.7, i.color), s.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = s, this.ctx.beginPath(), this.ctx.arc(i.position.x, i.position.y, i.radius, 0, Math.PI * 2), this.ctx.fill(), this.ctx.strokeStyle = e ? i.color : "#ffffff", this.ctx.lineWidth = 4, this.ctx.shadowColor = i.color, this.ctx.shadowBlur = 24, this.ctx.beginPath(), this.ctx.arc(i.position.x, i.position.y, i.radius, 0, Math.PI * 2), this.ctx.stroke(), this.ctx.restore();
2671
+ s.addColorStop(0, e ? "rgba(255, 255, 255, 0.72)" : "rgba(255, 255, 255, 0.4)"), s.addColorStop(0.7, i.color), s.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = s, this.ctx.beginPath(), this.ctx.arc(i.position.x, i.position.y, i.radius, 0, Math.PI * 2), this.ctx.fill(), this.ctx.strokeStyle = e ? i.color : "#ffffff", this.ctx.lineWidth = 4, this.ctx.shadowColor = i.color, this.ctx.shadowBlur = 24, this.ctx.beginPath(), this.ctx.arc(i.position.x, i.position.y, i.radius, 0, Math.PI * 2), this.ctx.stroke();
2633
2672
  }
2673
+ this.ctx.restore();
2634
2674
  }
2635
2675
  drawGravityVortices(t, e) {
2636
2676
  if (!this.ctx) return;
@@ -2641,8 +2681,8 @@ class dt {
2641
2681
  const r = this.ctx.createRadialGradient(n, o, 0, n, o, 60);
2642
2682
  r.addColorStop(0, this.colorWithAlpha(i.vortexCore, a)), r.addColorStop(0.7, this.colorWithAlpha(i.vortexMid, a)), r.addColorStop(1, `rgba(157, 78, 221, ${a * 0.5})`), this.ctx.fillStyle = r, this.ctx.beginPath(), this.ctx.arc(n, o, 60, 0, Math.PI * 2), this.ctx.fill(), this.ctx.strokeStyle = i.parasiteColor, this.ctx.lineWidth = 5, this.ctx.shadowColor = i.parasiteColor, this.ctx.shadowBlur = 32;
2643
2683
  for (let c = 1; c <= 5; c++) {
2644
- const h = l * c / 5, u = e * c * 2.2;
2645
- this.ctx.beginPath(), this.ctx.arc(n, o, h, u, u + Math.PI * 1.5), this.ctx.stroke();
2684
+ const h = l * c / 5, p = e * c * 2.2;
2685
+ this.ctx.beginPath(), this.ctx.arc(n, o, h, p, p + Math.PI * 1.5), this.ctx.stroke();
2646
2686
  }
2647
2687
  this.ctx.restore();
2648
2688
  }
@@ -2679,9 +2719,9 @@ class dt {
2679
2719
  const c = t.radius + 16 + r * 12;
2680
2720
  this.ctx.strokeStyle = a, this.ctx.lineWidth = 2.2, this.ctx.shadowColor = a, this.ctx.shadowBlur = 12, this.ctx.beginPath();
2681
2721
  const h = 60;
2682
- for (let u = 0; u <= h; u++) {
2683
- const p = u * Math.PI * 2 / h, _ = c + Math.sin(p * 4 + t.pulsePhase * 2 + r) * 3, g = i + Math.cos(p) * _, d = s + Math.sin(p) * _;
2684
- u === 0 ? this.ctx.moveTo(g, d) : this.ctx.lineTo(g, d);
2722
+ for (let p = 0; p <= h; p++) {
2723
+ const d = p * Math.PI * 2 / h, _ = c + Math.sin(d * 4 + t.pulsePhase * 2 + r) * 3, m = i + Math.cos(d) * _, u = s + Math.sin(d) * _;
2724
+ p === 0 ? this.ctx.moveTo(m, u) : this.ctx.lineTo(m, u);
2685
2725
  }
2686
2726
  this.ctx.closePath(), this.ctx.stroke();
2687
2727
  }
@@ -2689,9 +2729,9 @@ class dt {
2689
2729
  const r = t.integrity, c = t.radius + 16 + r * 12;
2690
2730
  this.ctx.save(), this.ctx.globalAlpha = Math.max(0.15, t.repairProgress), this.ctx.strokeStyle = a, this.ctx.lineWidth = 2, this.ctx.shadowColor = a, this.ctx.shadowBlur = 8, this.ctx.setLineDash([6, 4]), this.ctx.beginPath();
2691
2731
  const h = 60;
2692
- for (let u = 0; u <= h; u++) {
2693
- const p = u * Math.PI * 2 / h, _ = c + Math.sin(p * 4 + t.pulsePhase * 2 + r) * 3, g = i + Math.cos(p) * _, d = s + Math.sin(p) * _;
2694
- u === 0 ? this.ctx.moveTo(g, d) : this.ctx.lineTo(g, d);
2732
+ for (let p = 0; p <= h; p++) {
2733
+ const d = p * Math.PI * 2 / h, _ = c + Math.sin(d * 4 + t.pulsePhase * 2 + r) * 3, m = i + Math.cos(d) * _, u = s + Math.sin(d) * _;
2734
+ p === 0 ? this.ctx.moveTo(m, u) : this.ctx.lineTo(m, u);
2695
2735
  }
2696
2736
  this.ctx.closePath(), this.ctx.stroke(), this.ctx.restore();
2697
2737
  }
@@ -2699,8 +2739,8 @@ class dt {
2699
2739
  l.addColorStop(0, a), l.addColorStop(0.5, e.nebulaMagenta), l.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = l, this.ctx.beginPath(), this.ctx.arc(i, s, t.radius * 2.2, 0, Math.PI * 2), this.ctx.fill(), this.ctx.save(), this.ctx.translate(i, s), this.ctx.strokeStyle = a, this.ctx.lineWidth = 3, this.ctx.fillStyle = a, this.ctx.shadowColor = a, this.ctx.shadowBlur = 20, this.ctx.beginPath();
2700
2740
  const n = 80;
2701
2741
  for (let r = 0; r <= n; r++) {
2702
- const c = r * Math.PI * 2 / n, h = t.getMembraneRadius(c), u = Math.cos(c) * h, p = Math.sin(c) * h;
2703
- r === 0 ? this.ctx.moveTo(u, p) : this.ctx.lineTo(u, p);
2742
+ const c = r * Math.PI * 2 / n, h = t.getMembraneRadius(c), p = Math.cos(c) * h, d = Math.sin(c) * h;
2743
+ r === 0 ? this.ctx.moveTo(p, d) : this.ctx.lineTo(p, d);
2704
2744
  }
2705
2745
  this.ctx.closePath(), this.ctx.fill(), this.ctx.stroke();
2706
2746
  const o = t.powerUpCount;
@@ -2709,8 +2749,8 @@ class dt {
2709
2749
  for (let r = 0; r < o; r++) {
2710
2750
  const c = r * Math.PI * 2 / o + t.pulsePhase * 0.4, h = t.radius * (0.45 + Math.sin(t.pulsePhase * 2 + r) * 0.15);
2711
2751
  this.ctx.beginPath(), this.ctx.moveTo(0, 0);
2712
- const u = Math.cos(c + Math.sin(t.pulsePhase + r) * 0.4) * (h * 0.6), p = Math.sin(c + Math.cos(t.pulsePhase + r) * 0.4) * (h * 0.6), _ = Math.cos(c) * h, g = Math.sin(c) * h;
2713
- this.ctx.quadraticCurveTo(u, p, _, g), this.ctx.stroke(), this.ctx.fillStyle = a, this.ctx.beginPath(), this.ctx.arc(_, g, 2.5, 0, Math.PI * 2), this.ctx.fill();
2752
+ const p = Math.cos(c + Math.sin(t.pulsePhase + r) * 0.4) * (h * 0.6), d = Math.sin(c + Math.cos(t.pulsePhase + r) * 0.4) * (h * 0.6), _ = Math.cos(c) * h, m = Math.sin(c) * h;
2753
+ this.ctx.quadraticCurveTo(p, d, _, m), this.ctx.stroke(), this.ctx.fillStyle = a, this.ctx.beginPath(), this.ctx.arc(_, m, 2.5, 0, Math.PI * 2), this.ctx.fill();
2714
2754
  }
2715
2755
  }
2716
2756
  this.ctx.fillStyle = e.effectHighlight, this.ctx.beginPath(), this.ctx.arc(0, 0, t.radius * 0.3, 0, Math.PI * 2), this.ctx.fill(), this.ctx.restore(), this.ctx.restore();
@@ -2758,14 +2798,14 @@ class dt {
2758
2798
  const c = s.radius * (1 - o * 0.7);
2759
2799
  this.ctx.fillStyle = i.sporeColor, this.ctx.shadowColor = i.sporeColor, this.ctx.shadowBlur = 20, this.ctx.beginPath(), this.ctx.arc(0, 0, c, 0, Math.PI * 2), this.ctx.fill();
2760
2800
  for (let h = 0; h < 4; h++) {
2761
- const u = h * Math.PI * 0.5 + o * 4, p = c * 0.8 * o;
2762
- this.ctx.fillStyle = i.effectHighlight, this.ctx.beginPath(), this.ctx.arc(Math.cos(u) * p, Math.sin(u) * p, 3, 0, Math.PI * 2), this.ctx.fill();
2801
+ const p = h * Math.PI * 0.5 + o * 4, d = c * 0.8 * o;
2802
+ this.ctx.fillStyle = i.effectHighlight, this.ctx.beginPath(), this.ctx.arc(Math.cos(p) * d, Math.sin(p) * d, 3, 0, Math.PI * 2), this.ctx.fill();
2763
2803
  }
2764
2804
  this.ctx.restore();
2765
2805
  continue;
2766
2806
  } else if (s.deathType === "sliced") {
2767
- const c = o * 24, h = s.sliceAngle + Math.PI / 2, u = Math.cos(h) * c, p = Math.sin(h) * c;
2768
- this.ctx.shadowColor = "#ff2a5f", this.ctx.shadowBlur = 22, this.ctx.fillStyle = a, this.ctx.save(), this.ctx.translate(u, p), this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.8, 0, Math.PI), this.ctx.fill(), this.ctx.restore(), this.ctx.save(), this.ctx.translate(-u, -p), this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.8, Math.PI, Math.PI * 2), this.ctx.fill(), this.ctx.restore(), this.ctx.restore();
2807
+ const c = o * 24, h = s.sliceAngle + Math.PI / 2, p = Math.cos(h) * c, d = Math.sin(h) * c;
2808
+ this.ctx.shadowColor = "#ff2a5f", this.ctx.shadowBlur = 22, this.ctx.fillStyle = a, this.ctx.save(), this.ctx.translate(p, d), this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.8, 0, Math.PI), this.ctx.fill(), this.ctx.restore(), this.ctx.save(), this.ctx.translate(-p, -d), this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.8, Math.PI, Math.PI * 2), this.ctx.fill(), this.ctx.restore(), this.ctx.restore();
2769
2809
  continue;
2770
2810
  }
2771
2811
  }
@@ -2773,16 +2813,16 @@ class dt {
2773
2813
  this.ctx.rotate(s.rotation), this.ctx.beginPath();
2774
2814
  const o = 12;
2775
2815
  for (let r = 0; r <= o; r++) {
2776
- const c = r * Math.PI * 2 / o, h = s.radius * 1.6 + Math.sin(c * 3 + e * 4) * 3, u = s.radius * 0.6 + Math.cos(c * 2 + e * 3) * 2, p = Math.cos(c) * h, _ = Math.sin(c) * u;
2777
- r === 0 ? this.ctx.moveTo(p, _) : this.ctx.lineTo(p, _);
2816
+ const c = r * Math.PI * 2 / o, h = s.radius * 1.6 + Math.sin(c * 3 + e * 4) * 3, p = s.radius * 0.6 + Math.cos(c * 2 + e * 3) * 2, d = Math.cos(c) * h, _ = Math.sin(c) * p;
2817
+ r === 0 ? this.ctx.moveTo(d, _) : this.ctx.lineTo(d, _);
2778
2818
  }
2779
2819
  this.ctx.closePath(), this.ctx.fill(), this.ctx.fillStyle = i.effectHighlight, this.ctx.beginPath(), this.ctx.arc(4, 0, 4, 0, Math.PI * 2), this.ctx.fill();
2780
2820
  } else if (s.type === "spore") {
2781
2821
  this.ctx.beginPath();
2782
2822
  const o = 8;
2783
2823
  for (let r = 0; r < o; r++) {
2784
- const c = r * Math.PI * 2 / o, h = s.radius + Math.sin(c * 4 + e * 3 + s.position.x) * 4, u = Math.cos(c) * h, p = Math.sin(c) * h;
2785
- r === 0 ? this.ctx.moveTo(u, p) : this.ctx.lineTo(u, p);
2824
+ const c = r * Math.PI * 2 / o, h = s.radius + Math.sin(c * 4 + e * 3 + s.position.x) * 4, p = Math.cos(c) * h, d = Math.sin(c) * h;
2825
+ r === 0 ? this.ctx.moveTo(p, d) : this.ctx.lineTo(p, d);
2786
2826
  }
2787
2827
  this.ctx.closePath(), this.ctx.fill(), this.ctx.fillStyle = i.effectHighlight, this.ctx.beginPath(), this.ctx.arc(-4, -4, 5, 0, Math.PI * 2), this.ctx.arc(5, 3, 4, 0, Math.PI * 2), this.ctx.fill();
2788
2828
  } else if (s.type === "cluster") {
@@ -2793,19 +2833,19 @@ class dt {
2793
2833
  this.ctx.beginPath();
2794
2834
  const o = 14;
2795
2835
  for (let r = 0; r <= o; r++) {
2796
- const c = r * Math.PI * 2 / o, h = s.radius + Math.sin(c * 5 - e * 5) * 3, u = Math.cos(c) * h, p = Math.sin(c) * h;
2797
- r === 0 ? this.ctx.moveTo(u, p) : this.ctx.lineTo(u, p);
2836
+ const c = r * Math.PI * 2 / o, h = s.radius + Math.sin(c * 5 - e * 5) * 3, p = Math.cos(c) * h, d = Math.sin(c) * h;
2837
+ r === 0 ? this.ctx.moveTo(p, d) : this.ctx.lineTo(p, d);
2798
2838
  }
2799
2839
  this.ctx.closePath(), this.ctx.fill(), this.ctx.fillStyle = i.bgOuter, this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius * 0.45, 0, Math.PI * 2), this.ctx.fill();
2800
2840
  } else if (s.type === "heavy") {
2801
2841
  this.ctx.rotate(s.rotation);
2802
- const o = Math.PI * 0.75, r = s.radius * 1.35, c = s.radius * 0.75;
2842
+ const o = A.getInstance().getConfig().shield.protectionArc, r = s.radius * 1.35, c = s.radius * 0.75;
2803
2843
  this.ctx.beginPath(), this.ctx.arc(0, 0, r, -o / 2, o / 2, !1);
2804
- const h = Math.cos(o / 2) * c, u = Math.sin(o / 2) * c;
2805
- this.ctx.lineTo(h, u), this.ctx.arc(0, 0, c, o / 2, -o / 2, !0), this.ctx.closePath(), this.ctx.fillStyle = s.isStationaryShield ? i.corePrimary : a, this.ctx.shadowColor = i.corePrimary, this.ctx.shadowBlur = s.isStationaryShield ? 28 : 16, this.ctx.fill(), this.ctx.strokeStyle = i.effectHighlight, this.ctx.lineWidth = 3, this.ctx.beginPath(), this.ctx.arc(0, 0, r + Math.sin(e * 4) * 2, -o / 2 + 0.1, o / 2 - 0.1), this.ctx.stroke();
2806
- for (let p = -2; p <= 2; p++) {
2807
- const _ = p * o / 6, g = Math.cos(_) * (c + 6), d = Math.sin(_) * (c + 6);
2808
- this.ctx.fillStyle = i.effectHighlight, this.ctx.beginPath(), this.ctx.arc(g, d, 3, 0, Math.PI * 2), this.ctx.fill();
2844
+ const h = Math.cos(o / 2) * c, p = Math.sin(o / 2) * c;
2845
+ this.ctx.lineTo(h, p), this.ctx.arc(0, 0, c, o / 2, -o / 2, !0), this.ctx.closePath(), this.ctx.fillStyle = s.isStationaryShield ? i.corePrimary : a, this.ctx.shadowColor = i.corePrimary, this.ctx.shadowBlur = s.isStationaryShield ? 28 : 16, this.ctx.fill(), this.ctx.strokeStyle = i.effectHighlight, this.ctx.lineWidth = 3, this.ctx.beginPath(), this.ctx.arc(0, 0, r + Math.sin(e * 4) * 2, -o / 2 + 0.1, o / 2 - 0.1), this.ctx.stroke();
2846
+ for (let d = -2; d <= 2; d++) {
2847
+ const _ = d * o / 6, m = Math.cos(_) * (c + 6), u = Math.sin(_) * (c + 6);
2848
+ this.ctx.fillStyle = i.effectHighlight, this.ctx.beginPath(), this.ctx.arc(m, u, 3, 0, Math.PI * 2), this.ctx.fill();
2809
2849
  }
2810
2850
  } else
2811
2851
  this.ctx.beginPath(), this.ctx.arc(0, 0, s.radius, 0, Math.PI * 2), this.ctx.fill();
@@ -2813,9 +2853,12 @@ class dt {
2813
2853
  }
2814
2854
  }
2815
2855
  drawParticles(t) {
2816
- if (this.ctx)
2856
+ if (this.ctx) {
2857
+ this.ctx.save();
2817
2858
  for (const e of t)
2818
- this.ctx.save(), this.ctx.globalAlpha = e.alpha, this.ctx.fillStyle = e.color, this.ctx.beginPath(), this.ctx.arc(e.position.x, e.position.y, e.radius, 0, Math.PI * 2), this.ctx.fill(), this.ctx.restore();
2859
+ this.ctx.globalAlpha = e.alpha, this.ctx.fillStyle = e.color, this.ctx.beginPath(), this.ctx.arc(e.position.x, e.position.y, e.radius, 0, Math.PI * 2), this.ctx.fill();
2860
+ this.ctx.restore();
2861
+ }
2819
2862
  }
2820
2863
  drawFloatingTexts(t) {
2821
2864
  if (this.ctx)
@@ -2827,21 +2870,21 @@ class dt {
2827
2870
  const l = this.themeManager.getPalette(), n = this.themeManager.getTheme() === "light";
2828
2871
  for (const o of t) {
2829
2872
  if (!o.active) continue;
2830
- const { x: r, y: c } = o.position, h = o.definition.color, u = o.definition.rarity, p = u === "legendary" ? "#ff00ff" : u === "epic" ? "#ffd700" : u === "rare" ? "#9d4edd" : "#00f5ff", _ = o.radius + Math.sin(e * 6 + o.orbitAngle) * 3;
2831
- if (this.ctx.save(), this.ctx.shadowColor = p, this.ctx.shadowBlur = o.isGrabbed ? 36 : u === "legendary" ? 28 : 16, u === "legendary" || u === "epic") {
2832
- const m = _ + 12, x = this.ctx.createRadialGradient(r, c, _, r, c, m);
2833
- x.addColorStop(0, p), x.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = x, this.ctx.beginPath(), this.ctx.arc(r, c, m, 0, Math.PI * 2), this.ctx.fill();
2873
+ const { x: r, y: c } = o.position, h = o.definition.color, p = o.definition.rarity, d = p === "legendary" ? "#ff00ff" : p === "epic" ? "#ffd700" : p === "rare" ? "#9d4edd" : "#00f5ff", _ = o.radius + Math.sin(e * 6 + o.orbitAngle) * 3;
2874
+ if (this.ctx.save(), this.ctx.shadowColor = d, this.ctx.shadowBlur = o.isGrabbed ? 36 : p === "legendary" ? 28 : 16, p === "legendary" || p === "epic") {
2875
+ const g = _ + 12, f = this.ctx.createRadialGradient(r, c, _, r, c, g);
2876
+ f.addColorStop(0, d), f.addColorStop(1, "rgba(0, 0, 0, 0)"), this.ctx.fillStyle = f, this.ctx.beginPath(), this.ctx.arc(r, c, g, 0, Math.PI * 2), this.ctx.fill();
2834
2877
  }
2835
- const g = this.ctx.createRadialGradient(r, c, 2, r, c, _ * 1.4);
2836
- g.addColorStop(0, l.effectHighlight), g.addColorStop(0.4, h), g.addColorStop(1, n ? "rgba(23, 50, 77, 0.24)" : "rgba(0, 0, 0, 0.5)"), this.ctx.fillStyle = g, this.ctx.beginPath(), this.ctx.arc(r, c, _, 0, Math.PI * 2), this.ctx.fill(), this.ctx.strokeStyle = p, this.ctx.lineWidth = u === "legendary" ? 3.5 : 2.5, this.ctx.beginPath(), this.ctx.arc(r, c, _ + 4, e * 3, e * 3 + Math.PI * 1.2), this.ctx.stroke(), (u === "legendary" || u === "epic") && (this.ctx.strokeStyle = n ? p : l.effectHighlight, this.ctx.lineWidth = 1.5, this.ctx.beginPath(), this.ctx.arc(r, c, _ + 8, -e * 2, -e * 2 + Math.PI * 0.9), this.ctx.stroke()), this.ctx.font = "900 14px Orbitron, sans-serif", this.ctx.textAlign = "center", this.ctx.textBaseline = "middle", this.ctx.fillStyle = l.effectInk, this.ctx.shadowColor = l.effectShadow, this.ctx.shadowBlur = 6, this.ctx.fillText(o.definition.badge, r, c);
2837
- const d = i ? i.translate(o.definition.titleKey) : o.definition.badge;
2838
- this.ctx.textBaseline = "alphabetic", this.ctx.font = "900 16px Orbitron, sans-serif", this.ctx.fillStyle = l.effectInk, this.ctx.shadowColor = p, this.ctx.shadowBlur = 14, this.ctx.fillText(d, r, c - _ - 14), this.ctx.restore();
2878
+ const m = this.ctx.createRadialGradient(r, c, 2, r, c, _ * 1.4);
2879
+ m.addColorStop(0, l.effectHighlight), m.addColorStop(0.4, h), m.addColorStop(1, n ? "rgba(23, 50, 77, 0.24)" : "rgba(0, 0, 0, 0.5)"), this.ctx.fillStyle = m, this.ctx.beginPath(), this.ctx.arc(r, c, _, 0, Math.PI * 2), this.ctx.fill(), this.ctx.strokeStyle = d, this.ctx.lineWidth = p === "legendary" ? 3.5 : 2.5, this.ctx.beginPath(), this.ctx.arc(r, c, _ + 4, e * 3, e * 3 + Math.PI * 1.2), this.ctx.stroke(), (p === "legendary" || p === "epic") && (this.ctx.strokeStyle = n ? d : l.effectHighlight, this.ctx.lineWidth = 1.5, this.ctx.beginPath(), this.ctx.arc(r, c, _ + 8, -e * 2, -e * 2 + Math.PI * 0.9), this.ctx.stroke()), this.ctx.font = "900 14px Orbitron, sans-serif", this.ctx.textAlign = "center", this.ctx.textBaseline = "middle", this.ctx.fillStyle = l.effectInk, this.ctx.shadowColor = l.effectShadow, this.ctx.shadowBlur = 6, this.ctx.fillText(o.definition.badge, r, c);
2880
+ const u = i ? i.translate(o.definition.titleKey) : o.definition.badge;
2881
+ this.ctx.textBaseline = "alphabetic", this.ctx.font = "900 16px Orbitron, sans-serif", this.ctx.fillStyle = l.effectInk, this.ctx.shadowColor = d, this.ctx.shadowBlur = 14, this.ctx.fillText(u, r, c - _ - 14), this.ctx.restore();
2839
2882
  }
2840
2883
  if (i && s) {
2841
2884
  const o = this.canvas.width / 2, r = this.canvas.height / 2 + 210, c = i.translate("rerollButton", { count: a });
2842
2885
  this.ctx.save(), this.ctx.font = "900 14px Orbitron, sans-serif", this.ctx.textAlign = "center", this.ctx.textBaseline = "middle", this.ctx.fillStyle = l.effectPanel, this.ctx.strokeStyle = l.tendrilCyan, this.ctx.lineWidth = 2, this.ctx.shadowColor = l.tendrilCyan, this.ctx.shadowBlur = 12;
2843
- const p = this.ctx.measureText(c).width + 20 * 2, _ = 38;
2844
- this.ctx.beginPath(), this.ctx.roundRect(o - p / 2, r - _ / 2, p, _, 8), this.ctx.fill(), this.ctx.stroke(), this.ctx.fillStyle = l.effectInk, this.ctx.shadowColor = l.effectShadow, this.ctx.shadowBlur = 4, this.ctx.fillText(c, o, r), this.ctx.restore();
2886
+ const d = this.ctx.measureText(c).width + 20 * 2, _ = 38;
2887
+ this.ctx.beginPath(), this.ctx.roundRect(o - d / 2, r - _ / 2, d, _, 8), this.ctx.fill(), this.ctx.stroke(), this.ctx.fillStyle = l.effectInk, this.ctx.shadowColor = l.effectShadow, this.ctx.shadowBlur = 4, this.ctx.fillText(c, o, r), this.ctx.restore();
2845
2888
  }
2846
2889
  }
2847
2890
  colorWithAlpha(t, e) {
@@ -2851,7 +2894,7 @@ class dt {
2851
2894
  return `rgba(${s}, ${a}, ${l}, ${e})`;
2852
2895
  }
2853
2896
  }
2854
- class gt {
2897
+ class mt {
2855
2898
  container;
2856
2899
  i18n;
2857
2900
  waveLabelElement;
@@ -2883,7 +2926,7 @@ class gt {
2883
2926
  this.container.style.display = "none";
2884
2927
  }
2885
2928
  }
2886
- class _t {
2929
+ class ft {
2887
2930
  container;
2888
2931
  i18n;
2889
2932
  onStartCallback;
@@ -2909,7 +2952,7 @@ class _t {
2909
2952
  this.container.style.display = "none";
2910
2953
  }
2911
2954
  }
2912
- class mt {
2955
+ class xt {
2913
2956
  modal;
2914
2957
  card;
2915
2958
  i18n;
@@ -2918,10 +2961,14 @@ class mt {
2918
2961
  onLanguageChangedCallback;
2919
2962
  onCloseCallback;
2920
2963
  hapticsEnabled = !0;
2921
- constructor(t, e, i, s, a, l) {
2922
- this.i18n = e, this.themeManager = i, this.platform = s, this.onLanguageChangedCallback = a, this.onCloseCallback = l;
2923
- const n = localStorage.getItem("axon_surge_haptics");
2924
- n !== null && (this.hapticsEnabled = n === "true"), this.modal = document.createElement("dialog"), this.modal.className = "axon-settings-modal", this.card = document.createElement("div"), this.card.className = "axon-settings-card", this.modal.appendChild(this.card), t.appendChild(this.modal), this.modal.addEventListener("close", () => {
2964
+ fpsLimit = 60;
2965
+ onFpsLimitChangedCallback;
2966
+ constructor(t, e, i, s, a, l, n) {
2967
+ this.i18n = e, this.themeManager = i, this.platform = s, this.onLanguageChangedCallback = a, this.onCloseCallback = l, this.onFpsLimitChangedCallback = n;
2968
+ const o = localStorage.getItem("axon_surge_haptics");
2969
+ o !== null && (this.hapticsEnabled = o === "true");
2970
+ const r = Number(localStorage.getItem("axon_surge_fps_limit"));
2971
+ (r === 30 || r === 60 || r === 120) && (this.fpsLimit = r), this.modal = document.createElement("dialog"), this.modal.className = "axon-settings-modal", this.card = document.createElement("div"), this.card.className = "axon-settings-card", this.modal.appendChild(this.card), t.appendChild(this.modal), this.modal.addEventListener("close", () => {
2925
2972
  this.onCloseCallback && this.onCloseCallback();
2926
2973
  }), this.renderContent();
2927
2974
  }
@@ -2954,13 +3001,13 @@ class mt {
2954
3001
  ko: "한국어 (KO)",
2955
3002
  zh: "中文 (ZH)"
2956
3003
  };
2957
- for (const f of K) {
2958
- const v = document.createElement("option");
2959
- v.value = f, v.textContent = l[f], this.i18n.getLanguage() === f && (v.selected = !0), a.appendChild(v);
3004
+ for (const I of V) {
3005
+ const S = document.createElement("option");
3006
+ S.value = I, S.textContent = l[I], this.i18n.getLanguage() === I && (S.selected = !0), a.appendChild(S);
2960
3007
  }
2961
3008
  a.addEventListener("change", () => {
2962
- const f = a.value;
2963
- this.i18n.setLanguage(f), this.onLanguageChangedCallback && this.onLanguageChangedCallback(f), this.renderContent();
3009
+ const I = a.value;
3010
+ this.i18n.setLanguage(I), this.onLanguageChangedCallback && this.onLanguageChangedCallback(I), this.renderContent();
2964
3011
  });
2965
3012
  const n = document.createElement("span");
2966
3013
  n.className = "axon-select-arrow", n.textContent = "▼", s.appendChild(a), s.appendChild(n), e.appendChild(i), e.appendChild(s);
@@ -2975,57 +3022,78 @@ class mt {
2975
3022
  { id: "dark", label: "DARK" },
2976
3023
  { id: "light", label: "LIGHT" }
2977
3024
  ];
2978
- for (const f of h) {
2979
- const v = document.createElement("button");
2980
- v.type = "button", v.className = `axon-toggle-btn ${this.themeManager.getTheme() === f.id ? "active" : ""}`, v.textContent = f.label, v.addEventListener("click", () => {
2981
- this.themeManager.setTheme(f.id), this.renderContent();
2982
- }), c.appendChild(v);
3025
+ for (const I of h) {
3026
+ const S = document.createElement("button");
3027
+ S.type = "button", S.className = `axon-toggle-btn ${this.themeManager.getTheme() === I.id ? "active" : ""}`, S.textContent = I.label, S.addEventListener("click", () => {
3028
+ this.themeManager.setTheme(I.id), this.renderContent();
3029
+ }), c.appendChild(S);
2983
3030
  }
2984
3031
  o.appendChild(r), o.appendChild(c);
2985
- const u = document.createElement("div");
2986
- u.className = "axon-setting-row";
2987
- const p = document.createElement("span");
2988
- p.textContent = this.i18n.translate("hapticsLabel");
3032
+ const p = document.createElement("div");
3033
+ p.className = "axon-setting-row";
3034
+ const d = document.createElement("span");
3035
+ d.textContent = this.i18n.translate("fpsLimitLabel");
2989
3036
  const _ = document.createElement("div");
2990
3037
  _.className = "axon-toggle-group";
2991
- const g = [
3038
+ const m = [
3039
+ { limit: 30, label: "30 FPS" },
3040
+ { limit: 60, label: "60 FPS" },
3041
+ { limit: 120, label: "120 FPS" }
3042
+ ];
3043
+ for (const I of m) {
3044
+ const S = document.createElement("button");
3045
+ S.type = "button", S.className = `axon-toggle-btn ${this.fpsLimit === I.limit ? "active" : ""}`, S.textContent = I.label, S.addEventListener("click", () => {
3046
+ this.fpsLimit = I.limit, localStorage.setItem("axon_surge_fps_limit", String(I.limit)), this.onFpsLimitChangedCallback?.(I.limit), this.renderContent();
3047
+ }), _.appendChild(S);
3048
+ }
3049
+ p.appendChild(d), p.appendChild(_);
3050
+ const u = document.createElement("div");
3051
+ u.className = "axon-setting-row";
3052
+ const g = document.createElement("span");
3053
+ g.textContent = this.i18n.translate("hapticsLabel");
3054
+ const f = document.createElement("div");
3055
+ f.className = "axon-toggle-group";
3056
+ const b = [
2992
3057
  { enabled: !0, label: this.i18n.translate("hapticsOn") },
2993
3058
  { enabled: !1, label: this.i18n.translate("hapticsOff") }
2994
3059
  ];
2995
- for (const f of g) {
2996
- const v = document.createElement("button");
2997
- v.type = "button", v.className = `axon-toggle-btn ${this.hapticsEnabled === f.enabled ? "active" : ""}`, v.textContent = f.label, v.addEventListener("click", () => {
2998
- this.hapticsEnabled = f.enabled, localStorage.setItem("axon_surge_haptics", String(f.enabled)), this.hapticsEnabled && this.platform.haptics.selectionChanged(), this.renderContent();
2999
- }), _.appendChild(v);
3000
- }
3001
- u.appendChild(p), u.appendChild(_);
3002
- const d = document.createElement("div");
3003
- d.className = "axon-setting-row";
3004
- const m = document.createElement("span");
3005
- m.textContent = this.i18n.translate("tutorialSettingLabel");
3006
- const x = document.createElement("div");
3007
- x.className = "axon-toggle-group";
3008
- const A = localStorage.getItem("axon_surge_show_tutorial") !== "false", b = [
3060
+ for (const I of b) {
3061
+ const S = document.createElement("button");
3062
+ S.type = "button", S.className = `axon-toggle-btn ${this.hapticsEnabled === I.enabled ? "active" : ""}`, S.textContent = I.label, S.addEventListener("click", () => {
3063
+ this.hapticsEnabled = I.enabled, localStorage.setItem("axon_surge_haptics", String(I.enabled)), this.hapticsEnabled && this.platform.haptics.selectionChanged(), this.renderContent();
3064
+ }), f.appendChild(S);
3065
+ }
3066
+ u.appendChild(g), u.appendChild(f);
3067
+ const y = document.createElement("div");
3068
+ y.className = "axon-setting-row";
3069
+ const v = document.createElement("span");
3070
+ v.textContent = this.i18n.translate("tutorialSettingLabel");
3071
+ const M = document.createElement("div");
3072
+ M.className = "axon-toggle-group";
3073
+ const T = localStorage.getItem("axon_surge_show_tutorial") !== "false", x = [
3009
3074
  { enabled: !0, label: this.i18n.translate("hapticsOn") },
3010
3075
  { enabled: !1, label: this.i18n.translate("hapticsOff") }
3011
3076
  ];
3012
- for (const f of b) {
3013
- const v = document.createElement("button");
3014
- v.type = "button", v.className = `axon-toggle-btn ${A === f.enabled ? "active" : ""}`, v.textContent = f.label, v.addEventListener("click", () => {
3015
- localStorage.setItem("axon_surge_show_tutorial", String(f.enabled)), this.renderContent();
3016
- }), x.appendChild(v);
3017
- }
3018
- d.appendChild(m), d.appendChild(x);
3019
- const I = document.createElement("div");
3020
- I.className = "axon-settings-credits", I.textContent = this.i18n.translate("creditsJam");
3021
- const S = document.createElement("button");
3022
- S.type = "button", S.className = "axon-start-button", S.style.padding = "12px 36px", S.style.fontSize = "14px", S.textContent = this.i18n.translate("closeButton"), S.addEventListener("click", () => {
3077
+ for (const I of x) {
3078
+ const S = document.createElement("button");
3079
+ S.type = "button", S.className = `axon-toggle-btn ${T === I.enabled ? "active" : ""}`, S.textContent = I.label, S.addEventListener("click", () => {
3080
+ localStorage.setItem("axon_surge_show_tutorial", String(I.enabled)), this.renderContent();
3081
+ }), M.appendChild(S);
3082
+ }
3083
+ y.appendChild(v), y.appendChild(M);
3084
+ const L = document.createElement("div");
3085
+ L.className = "axon-settings-credits", L.textContent = this.i18n.translate("creditsJam");
3086
+ const R = document.createElement("button");
3087
+ R.type = "button", R.className = "axon-start-button", R.style.padding = "12px 36px", R.style.fontSize = "14px", R.textContent = this.i18n.translate("closeButton"), R.addEventListener("click", () => {
3023
3088
  this.modal.close();
3024
- }), this.card.appendChild(t), this.card.appendChild(e), this.card.appendChild(o), this.card.appendChild(u), this.card.appendChild(d), this.card.appendChild(I), this.card.appendChild(S);
3089
+ }), this.card.appendChild(t), this.card.appendChild(e), this.card.appendChild(o), this.card.appendChild(p), this.card.appendChild(u), this.card.appendChild(y), this.card.appendChild(L), this.card.appendChild(R);
3025
3090
  }
3026
3091
  isHapticsEnabled() {
3027
3092
  return this.hapticsEnabled;
3028
3093
  }
3094
+ getFpsLimit() {
3095
+ return this.fpsLimit;
3096
+ }
3029
3097
  show() {
3030
3098
  this.renderContent(), this.modal.showModal();
3031
3099
  }
@@ -3033,8 +3101,8 @@ class mt {
3033
3101
  this.modal.close();
3034
3102
  }
3035
3103
  }
3036
- const H = "axon_surge_show_tutorial";
3037
- class ft {
3104
+ const K = "axon_surge_show_tutorial";
3105
+ class yt {
3038
3106
  isActive = !1;
3039
3107
  showWarning = !1;
3040
3108
  dummyLauncher = null;
@@ -3043,14 +3111,14 @@ class ft {
3043
3111
  initialTargetPos = { x: 0, y: 0 };
3044
3112
  isTutorialEnabled() {
3045
3113
  try {
3046
- return localStorage.getItem(H) !== "false";
3114
+ return localStorage.getItem(K) !== "false";
3047
3115
  } catch {
3048
3116
  return !0;
3049
3117
  }
3050
3118
  }
3051
3119
  setTutorialEnabled(t) {
3052
3120
  try {
3053
- localStorage.setItem(H, String(t));
3121
+ localStorage.setItem(K, String(t));
3054
3122
  } catch {
3055
3123
  }
3056
3124
  }
@@ -3068,11 +3136,11 @@ class ft {
3068
3136
  this.isActive = !1;
3069
3137
  return;
3070
3138
  }
3071
- this.isActive = !0, this.showWarning = !1, i.length = 0, this.initialLauncherPos = { x: t * 0.28, y: e * 0.28 }, this.initialTargetPos = { x: t * 0.72, y: e * 0.28 }, this.dummyLauncher = M.createEnemy(
3139
+ this.isActive = !0, this.showWarning = !1, i.length = 0, this.initialLauncherPos = { x: t * 0.28, y: e * 0.28 }, this.initialTargetPos = { x: t * 0.72, y: e * 0.28 }, this.dummyLauncher = C.createEnemy(
3072
3140
  "piercer",
3073
3141
  this.initialLauncherPos,
3074
3142
  this.initialTargetPos
3075
- ), this.dummyLauncher.velocity = { x: 0, y: 0 }, this.dummyTarget = M.createEnemy(
3143
+ ), this.dummyLauncher.velocity = { x: 0, y: 0 }, this.dummyTarget = C.createEnemy(
3076
3144
  "spore",
3077
3145
  this.initialTargetPos,
3078
3146
  this.initialLauncherPos
@@ -3091,8 +3159,8 @@ class ft {
3091
3159
  return;
3092
3160
  }
3093
3161
  if (n.wasManipulated) {
3094
- const u = Math.hypot(n.velocity.x, n.velocity.y);
3095
- if (!n.isThrown || u < 70) {
3162
+ const p = Math.hypot(n.velocity.x, n.velocity.y);
3163
+ if (!n.isThrown || p < 70) {
3096
3164
  l && l(), this.showWarning = !0, this.resetDummies(n, o);
3097
3165
  return;
3098
3166
  }
@@ -3100,7 +3168,7 @@ class ft {
3100
3168
  n.triggerDissolveDeath(!0), o.triggerDissolveDeath(!0), this.showWarning = !1, this.isActive = !1, a();
3101
3169
  return;
3102
3170
  }
3103
- (n.position.x < -60 || n.position.x > i + 60 || n.position.y < -60 || n.position.y > s + 60 || u < 40) && (l && l(), this.showWarning = !0, this.resetDummies(n, o));
3171
+ (n.position.x < -60 || n.position.x > i + 60 || n.position.y < -60 || n.position.y > s + 60 || p < 40) && (l && l(), this.showWarning = !0, this.resetDummies(n, o));
3104
3172
  }
3105
3173
  }
3106
3174
  resetDummies(t, e) {
@@ -3110,7 +3178,7 @@ class ft {
3110
3178
  this.isActive = !1, this.showWarning = !1;
3111
3179
  }
3112
3180
  }
3113
- class xt {
3181
+ class Et {
3114
3182
  container;
3115
3183
  i18n;
3116
3184
  tutorialManager;
@@ -3146,7 +3214,7 @@ class xt {
3146
3214
  this.container.style.display = "none";
3147
3215
  }
3148
3216
  }
3149
- class yt {
3217
+ class bt {
3150
3218
  fillElement;
3151
3219
  experienceCount = 0;
3152
3220
  currentLevel = 1;
@@ -3183,7 +3251,7 @@ class yt {
3183
3251
  this.fillElement && this.fillElement.parentElement && (this.fillElement.parentElement.style.display = "none");
3184
3252
  }
3185
3253
  }
3186
- class B {
3254
+ class F {
3187
3255
  static powerUps = [
3188
3256
  {
3189
3257
  id: "spore_radius",
@@ -3195,7 +3263,7 @@ class B {
3195
3263
  rarityWeight: 35,
3196
3264
  color: "#39ff14",
3197
3265
  apply: () => {
3198
- const t = E.getInstance(), e = t.getConfig().toxicPool;
3266
+ const t = A.getInstance(), e = t.getConfig().toxicPool;
3199
3267
  t.updateConfig({
3200
3268
  toxicPool: {
3201
3269
  ...e,
@@ -3215,7 +3283,7 @@ class B {
3215
3283
  rarityWeight: 35,
3216
3284
  color: "#39ff14",
3217
3285
  apply: () => {
3218
- const t = E.getInstance(), e = t.getConfig().toxicPool;
3286
+ const t = A.getInstance(), e = t.getConfig().toxicPool;
3219
3287
  t.updateConfig({
3220
3288
  toxicPool: {
3221
3289
  ...e,
@@ -3235,7 +3303,7 @@ class B {
3235
3303
  rarityWeight: 35,
3236
3304
  color: "#9d4edd",
3237
3305
  apply: () => {
3238
- const t = E.getInstance(), e = t.getConfig().gravityVortex;
3306
+ const t = A.getInstance(), e = t.getConfig().gravityVortex;
3239
3307
  t.updateConfig({
3240
3308
  gravityVortex: {
3241
3309
  ...e,
@@ -3255,7 +3323,7 @@ class B {
3255
3323
  rarityWeight: 35,
3256
3324
  color: "#9d4edd",
3257
3325
  apply: () => {
3258
- const t = E.getInstance(), e = t.getConfig().gravityVortex;
3326
+ const t = A.getInstance(), e = t.getConfig().gravityVortex;
3259
3327
  t.updateConfig({
3260
3328
  gravityVortex: {
3261
3329
  ...e,
@@ -3275,7 +3343,7 @@ class B {
3275
3343
  rarityWeight: 25,
3276
3344
  color: "#9d4edd",
3277
3345
  apply: () => {
3278
- const t = E.getInstance(), e = t.getConfig().gravityVortex;
3346
+ const t = A.getInstance(), e = t.getConfig().gravityVortex;
3279
3347
  t.updateConfig({
3280
3348
  gravityVortex: {
3281
3349
  ...e,
@@ -3295,7 +3363,7 @@ class B {
3295
3363
  rarityWeight: 5,
3296
3364
  color: "#9d4edd",
3297
3365
  apply: () => {
3298
- const t = E.getInstance(), e = t.getConfig().gravityVortex;
3366
+ const t = A.getInstance(), e = t.getConfig().gravityVortex;
3299
3367
  t.updateConfig({
3300
3368
  gravityVortex: {
3301
3369
  ...e,
@@ -3314,7 +3382,7 @@ class B {
3314
3382
  rarityWeight: 5,
3315
3383
  color: "#00f5ff",
3316
3384
  apply: () => {
3317
- const t = E.getInstance(), e = t.getConfig().shield;
3385
+ const t = A.getInstance(), e = t.getConfig().shield;
3318
3386
  t.updateConfig({
3319
3387
  shield: {
3320
3388
  ...e,
@@ -3323,6 +3391,46 @@ class B {
3323
3391
  });
3324
3392
  }
3325
3393
  },
3394
+ {
3395
+ id: "shield_fan_upgrade",
3396
+ titleKey: "pu_shield_fan_upgrade_title",
3397
+ descKey: "pu_shield_fan_upgrade_desc",
3398
+ badge: "+0.35s / +15°",
3399
+ category: "power",
3400
+ rarity: "epic",
3401
+ rarityWeight: 15,
3402
+ color: "#00f5ff",
3403
+ apply: () => {
3404
+ const t = A.getInstance(), e = t.getConfig().shield;
3405
+ t.updateConfig({
3406
+ shield: {
3407
+ ...e,
3408
+ fanBlastInterval: e.fanBlastInterval + 0.35,
3409
+ fanBlastAngle: e.fanBlastAngle + Math.PI / 12,
3410
+ hasFanBlastUpgrade: !0
3411
+ }
3412
+ });
3413
+ }
3414
+ },
3415
+ {
3416
+ id: "shield_arc",
3417
+ titleKey: "pu_shield_arc_title",
3418
+ descKey: "pu_shield_arc_desc",
3419
+ badge: "+30° ARC",
3420
+ category: "defense",
3421
+ rarity: "common",
3422
+ rarityWeight: 35,
3423
+ color: "#00f5ff",
3424
+ apply: () => {
3425
+ const t = A.getInstance(), e = t.getConfig().shield;
3426
+ t.updateConfig({
3427
+ shield: {
3428
+ ...e,
3429
+ protectionArc: Math.min(Math.PI * 1.5, e.protectionArc + Math.PI / 6)
3430
+ }
3431
+ });
3432
+ }
3433
+ },
3326
3434
  {
3327
3435
  id: "cluster_extra",
3328
3436
  titleKey: "pu_cluster_extra_title",
@@ -3333,7 +3441,7 @@ class B {
3333
3441
  rarityWeight: 25,
3334
3442
  color: "#ffcc00",
3335
3443
  apply: () => {
3336
- const t = E.getInstance(), e = t.getConfig().cluster;
3444
+ const t = A.getInstance(), e = t.getConfig().cluster;
3337
3445
  t.updateConfig({
3338
3446
  cluster: {
3339
3447
  ...e,
@@ -3352,7 +3460,7 @@ class B {
3352
3460
  rarityWeight: 5,
3353
3461
  color: "#ffcc00",
3354
3462
  apply: () => {
3355
- const t = E.getInstance(), e = t.getConfig().cluster;
3463
+ const t = A.getInstance(), e = t.getConfig().cluster;
3356
3464
  t.updateConfig({
3357
3465
  cluster: {
3358
3466
  ...e,
@@ -3371,7 +3479,7 @@ class B {
3371
3479
  rarityWeight: 15,
3372
3480
  color: "#ff3366",
3373
3481
  apply: () => {
3374
- const t = E.getInstance(), e = t.getConfig().piercer;
3482
+ const t = A.getInstance(), e = t.getConfig().piercer;
3375
3483
  t.updateConfig({
3376
3484
  piercer: {
3377
3485
  ...e,
@@ -3390,7 +3498,7 @@ class B {
3390
3498
  rarityWeight: 5,
3391
3499
  color: "#ff2a5f",
3392
3500
  apply: () => {
3393
- const t = E.getInstance(), e = t.getConfig().piercer;
3501
+ const t = A.getInstance(), e = t.getConfig().piercer;
3394
3502
  t.updateConfig({
3395
3503
  piercer: {
3396
3504
  ...e,
@@ -3409,7 +3517,7 @@ class B {
3409
3517
  rarityWeight: 5,
3410
3518
  color: "#00f0ff",
3411
3519
  apply: () => {
3412
- const t = E.getInstance(), e = t.getConfig().core;
3520
+ const t = A.getInstance(), e = t.getConfig().core;
3413
3521
  t.updateConfig({
3414
3522
  core: {
3415
3523
  ...e,
@@ -3428,7 +3536,7 @@ class B {
3428
3536
  rarityWeight: 15,
3429
3537
  color: "#ff2a5f",
3430
3538
  apply: () => {
3431
- const t = E.getInstance(), e = t.getConfig().piercer;
3539
+ const t = A.getInstance(), e = t.getConfig().piercer;
3432
3540
  t.updateConfig({
3433
3541
  piercer: {
3434
3542
  ...e,
@@ -3447,7 +3555,7 @@ class B {
3447
3555
  rarityWeight: 15,
3448
3556
  color: "#00f5ff",
3449
3557
  apply: () => {
3450
- const t = E.getInstance(), e = t.getConfig().core;
3558
+ const t = A.getInstance(), e = t.getConfig().core;
3451
3559
  t.updateConfig({
3452
3560
  core: {
3453
3561
  ...e,
@@ -3466,7 +3574,7 @@ class B {
3466
3574
  rarityWeight: 25,
3467
3575
  color: "#00f5ff",
3468
3576
  apply: () => {
3469
- const t = E.getInstance(), e = t.getConfig().core;
3577
+ const t = A.getInstance(), e = t.getConfig().core;
3470
3578
  t.updateConfig({
3471
3579
  core: {
3472
3580
  ...e,
@@ -3485,7 +3593,7 @@ class B {
3485
3593
  rarityWeight: 20,
3486
3594
  color: "#00f5ff",
3487
3595
  apply: (t) => {
3488
- E.getInstance().addCoreRing(1), t && t.addMaxRing(1);
3596
+ A.getInstance().addCoreRing(1), t && t.addMaxRing(1);
3489
3597
  }
3490
3598
  },
3491
3599
  {
@@ -3498,7 +3606,7 @@ class B {
3498
3606
  rarityWeight: 35,
3499
3607
  color: "#00f5ff",
3500
3608
  apply: () => {
3501
- const t = E.getInstance(), e = t.getConfig().magnet;
3609
+ const t = A.getInstance(), e = t.getConfig().magnet;
3502
3610
  t.updateConfig({
3503
3611
  magnet: {
3504
3612
  ...e,
@@ -3517,7 +3625,7 @@ class B {
3517
3625
  rarityWeight: 25,
3518
3626
  color: "#00f5ff",
3519
3627
  apply: () => {
3520
- const t = E.getInstance(), e = t.getConfig().magnet;
3628
+ const t = A.getInstance(), e = t.getConfig().magnet;
3521
3629
  t.updateConfig({
3522
3630
  magnet: {
3523
3631
  ...e,
@@ -3528,7 +3636,7 @@ class B {
3528
3636
  }
3529
3637
  ];
3530
3638
  static getRandomOptions(t = 3) {
3531
- const e = E.getInstance().getConfig(), i = this.powerUps.filter((a) => !(a.id === "vampirism_unlock" && e.core.vampirismHealProgressRate > 0 || a.id === "vampirism_boost" && e.core.vampirismHealProgressRate <= 0 || a.id === "piercer_homing" && e.piercer.hasHoming || a.id === "piercer_homing_target" && !e.piercer.hasHoming || a.id === "vortex_pocket" && e.gravityVortex.hasImplosionLaunch || a.id === "shield_fan" && e.shield.isFanBlast || a.id === "cluster_homing" && e.cluster.hasHoming || a.id === "offscreen_radar" && e.core.hasOffscreenIndicators)), s = [];
3639
+ const e = A.getInstance().getConfig(), i = this.powerUps.filter((a) => !(a.id === "vampirism_unlock" && e.core.vampirismHealProgressRate > 0 || a.id === "vampirism_boost" && e.core.vampirismHealProgressRate <= 0 || a.id === "piercer_homing" && e.piercer.hasHoming || a.id === "piercer_homing_target" && !e.piercer.hasHoming || a.id === "vortex_pocket" && e.gravityVortex.hasImplosionLaunch || a.id === "shield_fan" && e.shield.isFanBlast || a.id === "shield_fan_upgrade" && (!e.shield.isFanBlast || e.shield.hasFanBlastUpgrade) || a.id === "cluster_homing" && e.cluster.hasHoming || a.id === "offscreen_radar" && e.core.hasOffscreenIndicators)), s = [];
3532
3640
  for (let a = 0; a < t && i.length > 0; a++) {
3533
3641
  const l = i.reduce((o, r) => o + r.rarityWeight, 0);
3534
3642
  let n = Math.random() * l;
@@ -3546,7 +3654,7 @@ class B {
3546
3654
  this.powerUps.push(t);
3547
3655
  }
3548
3656
  }
3549
- class Et {
3657
+ class At {
3550
3658
  haptics = {
3551
3659
  impact: async (t) => {
3552
3660
  if ("vibrate" in navigator) {
@@ -3586,7 +3694,125 @@ class Et {
3586
3694
  }
3587
3695
  };
3588
3696
  }
3589
- class At {
3697
+ class vt {
3698
+ enabled;
3699
+ overlay;
3700
+ copyButton;
3701
+ frameStart = 0;
3702
+ lastFrameEnd = 0;
3703
+ updateMs = 0;
3704
+ physicsMs = 0;
3705
+ renderMs = 0;
3706
+ frameMs = 0;
3707
+ fps = 0;
3708
+ fpsLimit = 60;
3709
+ state = "MENU";
3710
+ lastReport = "";
3711
+ slowFrames = 0;
3712
+ lastReportAt = 0;
3713
+ counts = {
3714
+ enemies: 0,
3715
+ particles: 0,
3716
+ shockwaves: 0,
3717
+ pools: 0,
3718
+ vortices: 0,
3719
+ floatingTexts: 0
3720
+ };
3721
+ constructor(t, e) {
3722
+ if (this.enabled = e, !e) {
3723
+ this.overlay = null, this.copyButton = null;
3724
+ return;
3725
+ }
3726
+ const i = document.createElement("pre");
3727
+ i.setAttribute("aria-label", "Performance audit"), i.style.cssText = [
3728
+ "position:fixed",
3729
+ "top:10px",
3730
+ "left:10px",
3731
+ "z-index:10000",
3732
+ "margin:0",
3733
+ "padding:8px 10px",
3734
+ "min-width:220px",
3735
+ "border:1px solid rgba(0,245,255,.55)",
3736
+ "border-radius:6px",
3737
+ "background:rgba(3,8,18,.88)",
3738
+ "color:#b8fbff",
3739
+ "font:12px/1.35 monospace",
3740
+ "pointer-events:none",
3741
+ "white-space:pre"
3742
+ ].join(";"), i.textContent = `PERF AUDIT
3743
+ starting…`, t.appendChild(i), this.overlay = i;
3744
+ const s = document.createElement("button");
3745
+ s.type = "button", s.textContent = "COPY AUDIT", s.style.cssText = [
3746
+ "position:fixed",
3747
+ "top:185px",
3748
+ "left:10px",
3749
+ "z-index:10001",
3750
+ "padding:4px 7px",
3751
+ "border:1px solid rgba(0,245,255,.55)",
3752
+ "border-radius:4px",
3753
+ "background:rgba(3,8,18,.94)",
3754
+ "color:#b8fbff",
3755
+ "font:11px monospace",
3756
+ "cursor:pointer"
3757
+ ].join(";"), s.addEventListener("click", () => {
3758
+ this.copyReport();
3759
+ }), t.appendChild(s), this.copyButton = s;
3760
+ }
3761
+ beginFrame() {
3762
+ this.enabled && (this.frameStart = performance.now());
3763
+ }
3764
+ setFpsLimit(t) {
3765
+ (t === 30 || t === 60 || t === 120) && (this.fpsLimit = t);
3766
+ }
3767
+ setState(t) {
3768
+ this.state = t;
3769
+ }
3770
+ finishUpdate(t, e) {
3771
+ !this.enabled || this.frameStart <= 0 || (this.updateMs = performance.now() - this.frameStart, this.physicsMs = t, this.counts = e);
3772
+ }
3773
+ finishRender(t) {
3774
+ if (!this.enabled || this.frameStart <= 0) return;
3775
+ const e = performance.now();
3776
+ this.renderMs = e - t, this.frameMs = this.lastFrameEnd > 0 ? e - this.lastFrameEnd : e - this.frameStart, this.lastFrameEnd = e;
3777
+ const i = this.frameMs > 0 ? 1e3 / this.frameMs : 0;
3778
+ this.fps = this.fps === 0 ? i : this.fps * 0.9 + i * 0.1, this.frameMs > 20 && this.slowFrames++, e - this.lastReportAt >= 250 && (this.lastReportAt = e, this.renderOverlay());
3779
+ }
3780
+ destroy() {
3781
+ this.overlay?.remove(), this.copyButton?.remove();
3782
+ }
3783
+ async copyReport() {
3784
+ const t = this.lastReport || this.overlay?.textContent || "";
3785
+ try {
3786
+ await navigator.clipboard.writeText(t);
3787
+ } catch {
3788
+ const e = document.createElement("textarea");
3789
+ e.value = t, document.body.appendChild(e), e.select(), document.execCommand("copy"), e.remove();
3790
+ }
3791
+ this.copyButton && (this.copyButton.textContent = "COPIED", window.setTimeout(() => {
3792
+ this.copyButton && (this.copyButton.textContent = "COPY AUDIT");
3793
+ }, 900));
3794
+ }
3795
+ renderOverlay() {
3796
+ if (!this.overlay) return;
3797
+ const t = performance.memory, e = t ? `
3798
+ HEAP ${(t.usedJSHeapSize / 1024 / 1024).toFixed(1)} MB` : "";
3799
+ this.lastReport = [
3800
+ "PERF AUDIT (?debug)",
3801
+ `STATE ${this.state}`,
3802
+ `FPS ${this.fps.toFixed(1)} / CAP ${this.fpsLimit} slow ${this.slowFrames}`,
3803
+ `FRAME ${this.frameMs.toFixed(1)} ms`,
3804
+ `UPDATE ${this.updateMs.toFixed(1)} ms`,
3805
+ `PHYS ${this.physicsMs.toFixed(1)} ms`,
3806
+ `RENDER ${this.renderMs.toFixed(1)} ms`,
3807
+ `ENEMY ${this.counts.enemies}`,
3808
+ `PART ${this.counts.particles} SW ${this.counts.shockwaves}`,
3809
+ `POOL ${this.counts.pools} VTX ${this.counts.vortices}`,
3810
+ `TEXT ${this.counts.floatingTexts}${e}`
3811
+ ].join(`
3812
+ `), this.overlay.textContent = this.lastReport;
3813
+ }
3814
+ }
3815
+ class It {
3590
3816
  container;
3591
3817
  canvas;
3592
3818
  i18n;
@@ -3605,6 +3831,7 @@ class At {
3605
3831
  interactiveTutorial;
3606
3832
  tutorialOverlay;
3607
3833
  progressBar;
3834
+ performanceAudit;
3608
3835
  core;
3609
3836
  enemies = [];
3610
3837
  ambientEnemies = [];
@@ -3618,13 +3845,14 @@ class At {
3618
3845
  isLevelUpActive = !1;
3619
3846
  pendingLevelUps = [];
3620
3847
  debugRerollsEnabled = typeof window < "u" && window.location.hostname === "localhost" && new URLSearchParams(window.location.search).has("debug");
3848
+ debugPerformanceEnabled = typeof window < "u" && new URLSearchParams(window.location.search).has("debug");
3621
3849
  rerollsRemaining = 1;
3622
3850
  score = { value: 0 };
3623
3851
  combo = { value: 0 };
3624
3852
  isRunning = !1;
3625
3853
  isPaused = !1;
3626
3854
  constructor(t) {
3627
- this.container = t.root, this.container.classList.add("axon-game-root"), this.i18n = new J(t.language), this.themeManager = new ct(t.theme, this.container), this.platform = t.platform || new Et(), this.canvas = document.createElement("canvas"), this.canvas.className = "axon-canvas", this.container.appendChild(this.canvas), this.resizeCanvas(), window.addEventListener("resize", () => this.resizeCanvas()), this.eventBus = new V(), this.core = new F(this.canvas.width / 2, this.canvas.height / 2), this.inputManager = new Y(this.canvas), this.physicsEngine = new ot(this.eventBus, this.i18n), this.waveDirector = new rt(), this.renderer = new dt(this.canvas, this.themeManager), this.juice = new z(), this.settingsModal = new mt(
3855
+ this.container = t.root, this.container.classList.add("axon-game-root"), this.i18n = new X(t.language), this.themeManager = new pt(t.theme, this.container), this.platform = t.platform || new At(), this.canvas = document.createElement("canvas"), this.canvas.className = "axon-canvas", this.container.appendChild(this.canvas), this.resizeCanvas(), window.addEventListener("resize", () => this.resizeCanvas()), this.eventBus = new W(), this.core = new Z(this.canvas.width / 2, this.canvas.height / 2), this.inputManager = new $(this.canvas), this.physicsEngine = new rt(this.eventBus, this.i18n), this.waveDirector = new ct(), this.renderer = new _t(this.canvas, this.themeManager), this.juice = new J(), this.settingsModal = new xt(
3628
3856
  this.container,
3629
3857
  this.i18n,
3630
3858
  this.themeManager,
@@ -3632,15 +3860,18 @@ class At {
3632
3860
  (e) => this.onLanguageChanged(e),
3633
3861
  () => {
3634
3862
  this.isPaused = !1;
3863
+ },
3864
+ (e) => {
3865
+ this.gameLoop.setFpsLimit(e), this.performanceAudit.setFpsLimit(e);
3635
3866
  }
3636
- ), this.interactiveTutorial = new ft(), this.tutorialOverlay = new xt(this.container, this.i18n, this.interactiveTutorial), this.hud = new gt(this.container, this.i18n, () => {
3867
+ ), this.interactiveTutorial = new yt(), this.tutorialOverlay = new Et(this.container, this.i18n, this.interactiveTutorial), this.hud = new mt(this.container, this.i18n, () => {
3637
3868
  this.isPaused = !0, this.settingsModal.show();
3638
- }), this.hud.show(), this.progressBar = new yt(this.hud.progressSlot, (e) => {
3869
+ }), this.hud.show(), this.progressBar = new bt(this.hud.progressSlot, (e) => {
3639
3870
  this.waveDirector.wave = e, this.triggerLevelUp(e);
3640
- }), this.startMenu = new _t(this.container, this.i18n, () => this.startGame()), this.initAmbientArena(), this.gameLoop = new W(
3871
+ }), this.performanceAudit = new vt(this.container, this.debugPerformanceEnabled), this.startMenu = new ft(this.container, this.i18n, () => this.startGame()), this.initAmbientArena(), this.gameLoop = new Y(
3641
3872
  (e) => this.update(e),
3642
3873
  () => this.render()
3643
- ), this.setupEvents(), this.gameLoop.start();
3874
+ ), this.gameLoop.setFpsLimit(this.settingsModal.getFpsLimit()), this.performanceAudit.setFpsLimit(this.settingsModal.getFpsLimit()), this.setupEvents(), this.gameLoop.start();
3644
3875
  }
3645
3876
  setLanguage(t) {
3646
3877
  this.i18n.setLanguage(t), this.onLanguageChanged(t);
@@ -3664,7 +3895,7 @@ class At {
3664
3895
  const i = t[e % t.length], s = e * Math.PI * 2 / 16, a = 180 + Math.random() * 220, l = {
3665
3896
  x: this.canvas.width / 2 + Math.cos(s) * a,
3666
3897
  y: this.canvas.height / 2 + Math.sin(s) * a
3667
- }, n = M.createEnemy(i, l, {
3898
+ }, n = C.createEnemy(i, l, {
3668
3899
  x: l.x + Math.sin(s) * 100,
3669
3900
  y: l.y - Math.cos(s) * 100
3670
3901
  });
@@ -3695,12 +3926,20 @@ class At {
3695
3926
  }), this.canvas.addEventListener("touchstart", () => t(!0), { passive: !0 }), this.canvas.addEventListener("touchend", e, { passive: !0 }), this.canvas.addEventListener("touchcancel", e, { passive: !0 });
3696
3927
  }
3697
3928
  startGame() {
3698
- E.getInstance().resetToDefault(), this.score.value = 0, this.combo.value = 0, this.enemies = [], this.ambientEnemies = [], this.pools = [], this.vortices = [], this.shockwaves = [], this.particles = [], this.floatingTexts = [], this.experienceOrbs = [], this.orbitingOrbs = [], this.isLevelUpActive = !1, this.pendingLevelUps = [], this.rerollsRemaining = this.getRerollLimit(), this.core.reset(this.canvas.width / 2, this.canvas.height / 2), this.waveDirector.reset(), this.inputManager.reset(), this.hud.show(), this.hud.update(1, 0), this.progressBar.reset(), this.progressBar.show(), this.isPaused = !1, this.isRunning = !0, this.interactiveTutorial.isTutorialEnabled() ? (this.interactiveTutorial.start(this.canvas.width, this.canvas.height, this.enemies), this.tutorialOverlay.show()) : (this.interactiveTutorial.isActive = !1, this.tutorialOverlay.hide());
3929
+ A.getInstance().resetToDefault(), this.score.value = 0, this.combo.value = 0, this.enemies = [], this.ambientEnemies = [], this.pools = [], this.vortices = [], this.shockwaves = [], this.particles = [], this.floatingTexts = [], this.experienceOrbs = [], this.orbitingOrbs = [], this.isLevelUpActive = !1, this.pendingLevelUps = [], this.rerollsRemaining = this.getRerollLimit(), this.core.reset(this.canvas.width / 2, this.canvas.height / 2), this.waveDirector.reset(), this.inputManager.reset(), this.hud.show(), this.hud.update(1, 0), this.progressBar.reset(), this.progressBar.show(), this.isPaused = !1, this.isRunning = !0, this.interactiveTutorial.isTutorialEnabled() ? (this.interactiveTutorial.start(this.canvas.width, this.canvas.height, this.enemies), this.tutorialOverlay.show()) : (this.interactiveTutorial.isActive = !1, this.tutorialOverlay.hide());
3699
3930
  }
3700
3931
  update(t) {
3701
- if (this.core.update(t), !this.isRunning || this.isPaused) {
3702
- for (const e of this.ambientEnemies)
3703
- e.update(t), e.position.x < -40 && (e.position.x = this.canvas.width + 40), e.position.x > this.canvas.width + 40 && (e.position.x = -40), e.position.y < -40 && (e.position.y = this.canvas.height + 40), e.position.y > this.canvas.height + 40 && (e.position.y = -40);
3932
+ if (this.performanceAudit.beginFrame(), this.performanceAudit.setState(this.isRunning ? this.isPaused ? "PAUSED" : "GAME" : "MENU"), this.core.update(t), !this.isRunning || this.isPaused) {
3933
+ for (const i of this.ambientEnemies)
3934
+ i.update(t), i.position.x < -40 && (i.position.x = this.canvas.width + 40), i.position.x > this.canvas.width + 40 && (i.position.x = -40), i.position.y < -40 && (i.position.y = this.canvas.height + 40), i.position.y > this.canvas.height + 40 && (i.position.y = -40);
3935
+ this.performanceAudit.finishUpdate(0, {
3936
+ enemies: this.ambientEnemies.length,
3937
+ particles: this.particles.length,
3938
+ shockwaves: this.shockwaves.length,
3939
+ pools: this.pools.length,
3940
+ vortices: this.vortices.length,
3941
+ floatingTexts: this.floatingTexts.length
3942
+ });
3704
3943
  return;
3705
3944
  }
3706
3945
  if (this.interactiveTutorial.isActive)
@@ -3715,50 +3954,50 @@ class At {
3715
3954
  () => this.inputManager.forceRelease()
3716
3955
  ), this.tutorialOverlay.updateStep(this.interactiveTutorial.getStep());
3717
3956
  else if (!this.isLevelUpActive) {
3718
- const e = this.waveDirector.update(
3957
+ const i = this.waveDirector.update(
3719
3958
  t,
3720
3959
  this.enemies,
3721
3960
  this.canvas.width,
3722
3961
  this.canvas.height,
3723
3962
  this.core.position
3724
3963
  );
3725
- e && this.enemies.push(e);
3964
+ i && this.enemies.push(i);
3726
3965
  }
3727
3966
  if (this.isLevelUpActive) {
3728
3967
  this.inputManager.tryGrabOrb(this.orbitingOrbs);
3729
- const e = this.inputManager.grabbedOrb;
3730
- !this.inputManager.isPointerDown && e && (e.isGrabbed = !1, this.inputManager.grabbedOrb = null);
3731
- const i = this.inputManager.pointerPosition;
3968
+ const i = this.inputManager.grabbedOrb;
3969
+ !this.inputManager.isPointerDown && i && (i.isGrabbed = !1, this.inputManager.grabbedOrb = null);
3970
+ const s = this.inputManager.pointerPosition;
3732
3971
  if (this.inputManager.isPointerDown && !this.inputManager.grabbedOrb && this.rerollsRemaining > 0) {
3733
- const s = this.canvas.width / 2, a = this.canvas.height / 2 + 210;
3734
- Math.hypot(i.x - s, i.y - a) <= 80 && (this.triggerReroll(), this.inputManager.isPointerDown = !1);
3972
+ const a = this.canvas.width / 2, l = this.canvas.height / 2 + 210;
3973
+ Math.hypot(s.x - a, s.y - l) <= 80 && (this.triggerReroll(), this.inputManager.isPointerDown = !1);
3735
3974
  }
3736
- for (const s of this.orbitingOrbs) {
3737
- const a = i.x - s.position.x, l = i.y - s.position.y;
3738
- if (s.isHovered = Math.hypot(a, l) <= s.radius * 1.5, s === e && this.inputManager.isPointerDown) {
3739
- s.position = { ...this.inputManager.pointerPosition };
3740
- const n = this.core.position.x - s.position.x, o = this.core.position.y - s.position.y;
3741
- if (Math.hypot(n, o) <= this.core.radius + s.radius) {
3742
- s.definition.apply(this.core), this.core.absorbPowerUpColor(s.definition.color, 0.4), this.juice.triggerFlash(0.8), this.juice.triggerScreenShake({ x: n, y: o }, 24);
3743
- const c = this.i18n.translate(s.definition.titleKey);
3975
+ for (const a of this.orbitingOrbs) {
3976
+ const l = s.x - a.position.x, n = s.y - a.position.y;
3977
+ if (a.isHovered = Math.hypot(l, n) <= a.radius * 1.5, a === i && this.inputManager.isPointerDown) {
3978
+ a.position = { ...this.inputManager.pointerPosition };
3979
+ const o = this.core.position.x - a.position.x, r = this.core.position.y - a.position.y;
3980
+ if (Math.hypot(o, r) <= this.core.radius + a.radius) {
3981
+ a.definition.apply(this.core), this.core.absorbPowerUpColor(a.definition.color, 0.4), this.juice.triggerFlash(0.8), this.juice.triggerScreenShake({ x: o, y: r }, 24);
3982
+ const h = this.i18n.translate(a.definition.titleKey);
3744
3983
  this.floatingTexts.push({
3745
3984
  id: Math.random().toString(),
3746
- text: `+ ${c}`,
3985
+ text: `+ ${h}`,
3747
3986
  position: { ...this.core.position },
3748
3987
  velocity: { x: 0, y: -80 },
3749
- color: s.definition.color,
3988
+ color: a.definition.color,
3750
3989
  alpha: 1,
3751
3990
  lifetime: 0,
3752
3991
  maxLifetime: 1.6,
3753
3992
  size: 26
3754
3993
  });
3755
- for (let h = 0; h < 45; h++) {
3756
- const u = Math.random() * Math.PI * 2, p = 200 + Math.random() * 400;
3994
+ for (let p = 0; p < 45; p++) {
3995
+ const d = Math.random() * Math.PI * 2, _ = 200 + Math.random() * 400;
3757
3996
  this.particles.push({
3758
3997
  id: Math.random().toString(),
3759
3998
  position: { ...this.core.position },
3760
- velocity: { x: Math.cos(u) * p, y: Math.sin(u) * p },
3761
- color: s.definition.color,
3999
+ velocity: { x: Math.cos(d) * _, y: Math.sin(d) * _ },
4000
+ color: a.definition.color,
3762
4001
  radius: 4 + Math.random() * 5,
3763
4002
  alpha: 1,
3764
4003
  lifetime: 0,
@@ -3768,37 +4007,49 @@ class At {
3768
4007
  this.inputManager.forceRelease(), this.orbitingOrbs = [], this.presentNextLevelUp();
3769
4008
  }
3770
4009
  } else
3771
- s.update(t, this.core.position);
4010
+ a.update(t, this.core.position);
3772
4011
  }
3773
4012
  }
3774
- !this.isLevelUpActive && this.juice.hitstopTime <= 0 && this.physicsEngine.update(
3775
- t,
3776
- this.core,
3777
- this.enemies,
3778
- this.pools,
3779
- this.vortices,
3780
- this.shockwaves,
3781
- this.particles,
3782
- this.floatingTexts,
3783
- this.juice,
3784
- this.combo,
3785
- this.score,
3786
- this.canvas.width,
3787
- this.canvas.height,
3788
- () => {
3789
- this.core.addKillRepair() && (this.juice.triggerFlash(0.4), this.floatingTexts.push({
3790
- id: Math.random().toString(),
3791
- text: "RING RESTORED!",
3792
- position: { ...this.core.position },
3793
- velocity: { x: 0, y: -60 },
3794
- color: "#00f5ff",
3795
- alpha: 1,
3796
- lifetime: 0,
3797
- maxLifetime: 1.2,
3798
- size: 22
3799
- }));
3800
- }
3801
- ), this.spawnExperienceDrops(), this.isLevelUpActive || this.updateExperienceOrbs(t), this.hud.update(this.progressBar.getLevel(), this.combo.value), this.juice.update(t, this.floatingTexts, this.particles), this.enemies = this.enemies.filter((e) => e.active);
4013
+ let e = 0;
4014
+ if (!this.isLevelUpActive) {
4015
+ const i = this.debugPerformanceEnabled ? performance.now() : 0;
4016
+ this.physicsEngine.update(
4017
+ t,
4018
+ this.core,
4019
+ this.enemies,
4020
+ this.pools,
4021
+ this.vortices,
4022
+ this.shockwaves,
4023
+ this.particles,
4024
+ this.floatingTexts,
4025
+ this.juice,
4026
+ this.combo,
4027
+ this.score,
4028
+ this.canvas.width,
4029
+ this.canvas.height,
4030
+ () => {
4031
+ this.core.addKillRepair() && (this.juice.triggerFlash(0.4), this.floatingTexts.push({
4032
+ id: Math.random().toString(),
4033
+ text: "RING RESTORED!",
4034
+ position: { ...this.core.position },
4035
+ velocity: { x: 0, y: -60 },
4036
+ color: "#00f5ff",
4037
+ alpha: 1,
4038
+ lifetime: 0,
4039
+ maxLifetime: 1.2,
4040
+ size: 22
4041
+ }));
4042
+ }
4043
+ ), e = this.debugPerformanceEnabled ? performance.now() - i : 0;
4044
+ }
4045
+ this.spawnExperienceDrops(), this.isLevelUpActive || this.updateExperienceOrbs(t), this.hud.update(this.progressBar.getLevel(), this.combo.value), this.juice.update(t, this.floatingTexts, this.particles), this.enemies = this.enemies.filter((i) => i.active), this.performanceAudit.finishUpdate(e, {
4046
+ enemies: this.enemies.length,
4047
+ particles: this.particles.length,
4048
+ shockwaves: this.shockwaves.length,
4049
+ pools: this.pools.length,
4050
+ vortices: this.vortices.length,
4051
+ floatingTexts: this.floatingTexts.length
4052
+ });
3802
4053
  }
3803
4054
  triggerLevelUp(t) {
3804
4055
  this.pendingLevelUps.push(t), this.isLevelUpActive || this.presentNextLevelUp();
@@ -3833,18 +4084,18 @@ class At {
3833
4084
  maxLifetime: 0.7
3834
4085
  });
3835
4086
  }
3836
- const e = B.getRandomOptions(3);
4087
+ const e = F.getRandomOptions(3);
3837
4088
  this.orbitingOrbs = e.map((i, s) => {
3838
4089
  const a = s * Math.PI * 2 / e.length;
3839
- return new G(`orb_${Date.now()}_${s}`, i, a);
4090
+ return new H(`orb_${Date.now()}_${s}`, i, a);
3840
4091
  }), this.rerollsRemaining = this.getRerollLimit();
3841
4092
  }
3842
4093
  spawnExperienceDrops() {
3843
4094
  for (const t of this.enemies)
3844
- t.experienceDropPending && (t.experienceDropPending = !1, this.experienceOrbs.push(new lt(t.position)));
4095
+ t.experienceDropPending && (t.experienceDropPending = !1, this.experienceOrbs.push(new ht(t.position)));
3845
4096
  }
3846
4097
  updateExperienceOrbs(t) {
3847
- const e = E.getInstance().getConfig().magnet;
4098
+ const e = A.getInstance().getConfig().magnet;
3848
4099
  for (const i of this.experienceOrbs)
3849
4100
  if (i.active) {
3850
4101
  if (i.isAbsorbing || Math.hypot(
@@ -3871,17 +4122,17 @@ class At {
3871
4122
  triggerReroll() {
3872
4123
  if (this.rerollsRemaining <= 0) return;
3873
4124
  this.rerollsRemaining -= 1, this.juice.triggerFlash(0.4);
3874
- const t = B.getRandomOptions(3);
4125
+ const t = F.getRandomOptions(3);
3875
4126
  this.orbitingOrbs = t.map((e, i) => {
3876
4127
  const s = i * Math.PI * 2 / t.length;
3877
- return new G(`orb_${Date.now()}_${i}`, e, s);
4128
+ return new H(`orb_${Date.now()}_${i}`, e, s);
3878
4129
  });
3879
4130
  }
3880
4131
  render() {
3881
- const t = this.isRunning ? this.enemies : this.ambientEnemies;
4132
+ const t = this.debugPerformanceEnabled ? performance.now() : 0, e = this.isRunning ? this.enemies : this.ambientEnemies;
3882
4133
  this.renderer.render(
3883
4134
  this.core,
3884
- t,
4135
+ e,
3885
4136
  this.experienceOrbs,
3886
4137
  this.pools,
3887
4138
  this.vortices,
@@ -3899,23 +4150,23 @@ class At {
3899
4150
  this.i18n,
3900
4151
  this.rerollsRemaining > 0,
3901
4152
  this.rerollsRemaining
3902
- );
4153
+ ), this.performanceAudit.finishRender(t);
3903
4154
  }
3904
4155
  getRerollLimit() {
3905
4156
  return this.debugRerollsEnabled ? 99 : 1;
3906
4157
  }
3907
4158
  destroy() {
3908
- this.gameLoop.stop(), this.canvas.remove();
4159
+ this.gameLoop.stop(), this.performanceAudit.destroy(), this.canvas.remove();
3909
4160
  }
3910
4161
  }
3911
- function bt(y) {
3912
- return new At(y);
4162
+ function St(E) {
4163
+ return new It(E);
3913
4164
  }
3914
4165
  export {
3915
- Et as BrowserPlatform,
3916
- At as GameEngine,
3917
- K as LANGUAGES,
3918
- ct as ThemeManager,
3919
- bt as createAxonSurge,
3920
- O as isLanguage
4166
+ At as BrowserPlatform,
4167
+ It as GameEngine,
4168
+ V as LANGUAGES,
4169
+ pt as ThemeManager,
4170
+ St as createAxonSurge,
4171
+ w as isLanguage
3921
4172
  };