PageSourceSearch

https://pupwife.com/scripts/dependencies/fishFoodJumpscare.js

js pupwife.com collected 2026-09-30 15:05:09 UTC 5,315 bytes, 182 lines download raw bytes

1/**
2 * Fish Food Jumpscare System
3 * Plays a FNAF jumpscare at milestone fish food counts.
4 */
5(function () {
6  'use strict';
7
8  if (window.FishFoodJumpscare || window.__fishFoodJumpscare) return;
9
10  var MILESTONES = [666, 5000];
11  var STORAGE_KEY = 'pupwife_fishfood_jumpscare_done';
12  var JUMPSCARE_IMAGE = 'https://gifdb.com/images/high/fnaf-jumpscare-gif-file-360kb-80yj5ynuvdla1brr.webp';
13  var JUMPSCARE_SOUND = 'https://raw.githubusercontent.com/pupwife/pupwife.github.io/main/songs/fnafscream.mp3';
14  var JUMPSCARE_DURATION_MS = 2500;
15
16  var active = false;
17  var debug = false;
18
19  function getCurrentCount() {
20    return window.__puppyFoodCounter ? window.__puppyFoodCounter.count : 0;
21  }
22
23  function getNextMilestone(count) {
24    for (var i = 0; i < MILESTONES.length; i++) {
25      if (count < MILESTONES[i] && !hasTriggered(MILESTONES[i])) {
26        return MILESTONES[i];
27      }
28    }
29    return null;
30  }
31
32  function logDebug() {
33    if (!debug) return;
34    var count = getCurrentCount();
35    var next = getNextMilestone(count);
36    console.log(
37      '🐟 Fish food count: ' + count + (next ? '/' + next : '') +
38      ' | Mode: ' + (debug ? 'DEBUG' : 'NORMAL') +
39      ' | Triggered: ' + JSON.stringify(getTriggeredMilestones())
40    );
41  }
42
43  function getTriggeredMilestones() {
44    try {
45      var raw = localStorage.getItem(STORAGE_KEY);
46      if (!raw) return {};
47      var parsed = JSON.parse(raw);
48      return parsed && typeof parsed === 'object' ? parsed : {};
49    } catch (e) {
50      return {};
51    }
52  }
53
54  function hasTriggered(milestone) {
55    return !!getTriggeredMilestones()[String(milestone)];
56  }
57
58  function markMilestoneDone(milestone) {
59    var done = getTriggeredMilestones();
60    done[String(milestone)] = true;
61    try {
62      localStorage.setItem(STORAGE_KEY, JSON.stringify(done));
63    } catch (e) {}
64  }
65
66  function injectShakeStyle() {
67    if (document.getElementById('fishfood-jumpscare-style')) return;
68    var style = document.createElement('style');
69    style.id = 'fishfood-jumpscare-style';
70    style.textContent =
71      '@keyframes fishfood-jumpscare-shake {' +
72      '0%, 100% { transform: translate(0, 0); }' +
73      '10% { transform: translate(-8px, 4px); }' +
74      '20% { transform: translate(8px, -4px); }' +
75      '30% { transform: translate(-6px, -6px); }' +
76      '40% { transform: translate(6px, 6px); }' +
77      '50% { transform: translate(-4px, 2px); }' +
78      '60% { transform: translate(4px, -2px); }' +
79      '70% { transform: translate(-2px, 4px); }' +
80      '80% { transform: translate(2px, -4px); }' +
81      '90% { transform: translate(-1px, 1px); }' +
82      '}' +
83      'html.fishfood-jumpscare-shake {' +
84      'animation: fishfood-jumpscare-shake 0.15s infinite;' +
85      '}';
86    document.head.appendChild(style);
87  }
88
89  function playJumpscare(milestone, options) {
90    options = options || {};
91    if (active) return;
92    active = true;
93    if (options.saveMilestone !== false && typeof milestone === 'number') {
94      markMilestoneDone(milestone);
95    }
96    injectShakeStyle();
97
98    var overlay = document.createElement('div');
99    overlay.id = 'jumpscare-overlay';
100    overlay.style.cssText =
101      'position:fixed;' +
102      'top:0;' +
103      'left:0;' +
104      'width:100vw;' +
105      'height:100vh;' +
106      'background:black;' +
107      'z-index:999999;' +
108      'display:flex;' +
109      'align-items:center;' +
110      'justify-content:center;' +
111      'overflow:hidden;';
112
113    var img = document.createElement('img');
114    img.src = JUMPSCARE_IMAGE;
115    img.alt = '';
116    img.setAttribute('aria-hidden', 'true');
117    img.style.cssText = 'max-width:100%;max-height:100%;object-fit:contain;';
118
119    overlay.appendChild(img);
120    document.body.appendChild(overlay);
121    document.documentElement.classList.add('fishfood-jumpscare-shake');
122
123    try {
124      var audio = new Audio(JUMPSCARE_SOUND);
125      audio.volume = 1;
126      audio.play().catch(function () {});
127    } catch (e) {}
128
129    setTimeout(function () {
130      overlay.remove();
131      document.documentElement.classList.remove('fishfood-jumpscare-shake');
132      active = false;
133    }, JUMPSCARE_DURATION_MS);
134  }
135
136  function checkMilestones(count) {
137    if (typeof count !== 'number' || !isFinite(count)) return;
138
139    for (var i = 0; i < MILESTONES.length; i++) {
140      var milestone = MILESTONES[i];
141      if (count === milestone && !hasTriggered(milestone)) {
142        playJumpscare(milestone);
143        return;
144      }
145    }
146  }
147
148  function onCollected() {
149    if (!window.__puppyFoodCounter) return;
150    logDebug();
151    checkMilestones(window.__puppyFoodCounter.count);
152  }
153
154  window.addEventListener('fishfood:collected', onCollected);
155
156  var api = {
157    milestones: MILESTONES.slice(),
158    check: checkMilestones,
159    test: function () {
160      playJumpscare(null, { saveMilestone: false });
161    },
162    enableDebug: function (enabled) {
163      debug = enabled !== false;
164      logDebug();
165      return debug;
166    },
167    status: function () {
168      var count = getCurrentCount();
169      return {
170        count: count,
171        milestones: MILESTONES.slice(),
172        triggered: getTriggeredMilestones(),
173        nextMilestone: getNextMilestone(count),
174        debug: debug,
175        active: active
176      };
177    }
178  };
179
180  window.FishFoodJumpscare = api;
181  window.__fishFoodJumpscare = api;
182})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.