123
edits
Vendicated (talk | contribs) No edit summary |
Vendicated (talk | contribs) No edit summary |
||
Line 3: | Line 3: | ||
// SPDX-License-Identifier: MIT | // SPDX-License-Identifier: MIT | ||
// https://github.com/adryd325/oneko.js | // https://github.com/adryd325/oneko.js | ||
// compiled to es5 with babel because mediawiki is insane and needs es5 | |||
(function oneko() { | (function oneko() { | ||
var isReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)") === true || window.matchMedia("(prefers-reduced-motion: reduce)").matches === true; | |||
if (isReducedMotion) return; | if (isReducedMotion) return; | ||
var nekoEl = document.createElement("div"); | |||
var nekoPosX = 32; | |||
var nekoPosY = 32; | |||
var mousePosX = 0; | |||
var mousePosY = 0; | |||
var frameCount = 0; | |||
var idleTime = 0; | |||
var idleAnimation = null; | |||
var idleAnimationFrame = 0; | |||
var nekoSpeed = 10; | |||
var spriteSets = { | |||
idle: [[-3, -3]], | idle: [[-3, -3]], | ||
alert: [[-7, -3]], | alert: [[-7, -3]], | ||
scratchSelf: [ | scratchSelf: [[-5, 0], [-6, 0], [-7, 0]], | ||
scratchWallN: [[0, 0], [0, -1]], | |||
scratchWallS: [[-7, -1], [-6, -2]], | |||
scratchWallE: [[-2, -2], [-2, -3]], | |||
scratchWallW: [[-4, 0], [-4, -1]], | |||
scratchWallN: [ | |||
scratchWallS: [ | |||
scratchWallE: [ | |||
scratchWallW: [ | |||
tired: [[-3, -2]], | tired: [[-3, -2]], | ||
sleeping: [ | sleeping: [[-2, 0], [-2, -1]], | ||
N: [[-1, -2], [-1, -3]], | |||
NE: [[0, -2], [0, -3]], | |||
E: [[-3, 0], [-3, -1]], | |||
N: [ | SE: [[-5, -1], [-5, -2]], | ||
S: [[-6, -3], [-7, -2]], | |||
SW: [[-5, -3], [-6, -1]], | |||
W: [[-4, -2], [-4, -3]], | |||
NE: [ | NW: [[-1, 0], [-1, -1]] | ||
E: [ | |||
SE: [ | |||
S: [ | |||
SW: [ | |||
W: [ | |||
NW: [ | |||
}; | }; | ||
function init() { | function init() { | ||
nekoEl.id = "oneko"; | nekoEl.id = "oneko"; | ||
Line 96: | Line 46: | ||
nekoEl.style.pointerEvents = "none"; | nekoEl.style.pointerEvents = "none"; | ||
nekoEl.style.imageRendering = "pixelated"; | nekoEl.style.imageRendering = "pixelated"; | ||
nekoEl.style.left = | nekoEl.style.left = "".concat(nekoPosX - 16, "px"); | ||
nekoEl.style.top = | nekoEl.style.top = "".concat(nekoPosY - 16, "px"); | ||
nekoEl.style.zIndex = Number.MAX_VALUE; | nekoEl.style.zIndex = Number.MAX_VALUE; | ||
var nekoFile = "https://wiki.vencord.dev/images/8/8c/Oneko.gif"; | |||
var curScript = document.currentScript; | |||
if (curScript && curScript.dataset.cat) { | if (curScript && curScript.dataset.cat) { | ||
nekoFile = curScript.dataset.cat; | nekoFile = curScript.dataset.cat; | ||
} | } | ||
nekoEl.style.backgroundImage = | nekoEl.style.backgroundImage = "url(".concat(nekoFile, ")"); | ||
document.body.appendChild(nekoEl); | document.body.appendChild(nekoEl); | ||
document.addEventListener("mousemove", function (event) { | document.addEventListener("mousemove", function (event) { | ||
mousePosX = event.clientX; | mousePosX = event.clientX; | ||
mousePosY = event.clientY; | mousePosY = event.clientY; | ||
}); | }); | ||
window.requestAnimationFrame(onAnimationFrame); | window.requestAnimationFrame(onAnimationFrame); | ||
} | } | ||
var lastFrameTimestamp; | |||
function onAnimationFrame(timestamp) { | function onAnimationFrame(timestamp) { | ||
// Stops execution if the neko element is removed from DOM | // Stops execution if the neko element is removed from DOM | ||
Line 133: | Line 77: | ||
window.requestAnimationFrame(onAnimationFrame); | window.requestAnimationFrame(onAnimationFrame); | ||
} | } | ||
function setSprite(name, frame) { | function setSprite(name, frame) { | ||
var sprite = spriteSets[name][frame % spriteSets[name].length]; | |||
nekoEl.style.backgroundPosition = | nekoEl.style.backgroundPosition = "".concat(sprite[0] * 32, "px ").concat(sprite[1] * 32, "px"); | ||
} | } | ||
function resetIdleAnimation() { | function resetIdleAnimation() { | ||
idleAnimation = null; | idleAnimation = null; | ||
idleAnimationFrame = 0; | idleAnimationFrame = 0; | ||
} | } | ||
function idle() { | function idle() { | ||
idleTime += 1; | idleTime += 1; | ||
// every ~ 20 seconds | // every ~ 20 seconds | ||
if ( | if (idleTime > 10 && Math.floor(Math.random() * 200) == 0 && idleAnimation == null) { | ||
var avalibleIdleAnimations = ["sleeping", "scratchSelf"]; | |||
if (nekoPosX < 32) { | if (nekoPosX < 32) { | ||
avalibleIdleAnimations.push("scratchWallW"); | avalibleIdleAnimations.push("scratchWallW"); | ||
Line 166: | Line 103: | ||
avalibleIdleAnimations.push("scratchWallS"); | avalibleIdleAnimations.push("scratchWallS"); | ||
} | } | ||
idleAnimation = | idleAnimation = avalibleIdleAnimations[Math.floor(Math.random() * avalibleIdleAnimations.length)]; | ||
} | } | ||
switch (idleAnimation) { | switch (idleAnimation) { | ||
case "sleeping": | case "sleeping": | ||
Line 199: | Line 132: | ||
idleAnimationFrame += 1; | idleAnimationFrame += 1; | ||
} | } | ||
function frame() { | function frame() { | ||
frameCount += 1; | frameCount += 1; | ||
var diffX = nekoPosX - mousePosX; | |||
var diffY = nekoPosY - mousePosY; | |||
var distance = Math.sqrt(Math.pow(diffX, 2) + Math.pow(diffY, 2)); | |||
if (distance < nekoSpeed || distance < 48) { | if (distance < nekoSpeed || distance < 48) { | ||
idle(); | idle(); | ||
return; | return; | ||
} | } | ||
idleAnimation = null; | idleAnimation = null; | ||
idleAnimationFrame = 0; | idleAnimationFrame = 0; | ||
if (idleTime > 1) { | if (idleTime > 1) { | ||
setSprite("alert", 0); | setSprite("alert", 0); | ||
Line 221: | Line 150: | ||
return; | return; | ||
} | } | ||
var direction; | |||
direction = diffY / distance > 0.5 ? "N" : ""; | direction = diffY / distance > 0.5 ? "N" : ""; | ||
direction += diffY / distance < -0.5 ? "S" : ""; | direction += diffY / distance < -0.5 ? "S" : ""; | ||
Line 228: | Line 156: | ||
direction += diffX / distance < -0.5 ? "E" : ""; | direction += diffX / distance < -0.5 ? "E" : ""; | ||
setSprite(direction, frameCount); | setSprite(direction, frameCount); | ||
nekoPosX -= diffX / distance * nekoSpeed; | |||
nekoPosX -= | nekoPosY -= diffY / distance * nekoSpeed; | ||
nekoPosY -= | |||
nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16); | nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16); | ||
nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16); | nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16); | ||
nekoEl.style.left = "".concat(nekoPosX - 16, "px"); | |||
nekoEl.style.left = | nekoEl.style.top = "".concat(nekoPosY - 16, "px"); | ||
nekoEl.style.top = | |||
} | } | ||
init(); | init(); | ||
})(); | })(); |