<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.vencord.dev/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AOneko.js</id>
	<title>MediaWiki:Oneko.js - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.vencord.dev/index.php?action=history&amp;feed=atom&amp;title=MediaWiki%3AOneko.js"/>
	<link rel="alternate" type="text/html" href="https://wiki.vencord.dev/index.php?title=MediaWiki:Oneko.js&amp;action=history"/>
	<updated>2026-05-31T18:29:28Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.vencord.dev/index.php?title=MediaWiki:Oneko.js&amp;diff=33&amp;oldid=prev</id>
		<title>Vendicated: Blanked the page</title>
		<link rel="alternate" type="text/html" href="https://wiki.vencord.dev/index.php?title=MediaWiki:Oneko.js&amp;diff=33&amp;oldid=prev"/>
		<updated>2024-03-07T19:53:52Z</updated>

		<summary type="html">&lt;p&gt;Blanked the page&lt;/p&gt;
&lt;a href=&quot;https://wiki.vencord.dev/index.php?title=MediaWiki:Oneko.js&amp;amp;diff=33&amp;amp;oldid=32&quot;&gt;Show changes&lt;/a&gt;</summary>
		<author><name>Vendicated</name></author>
	</entry>
	<entry>
		<id>https://wiki.vencord.dev/index.php?title=MediaWiki:Oneko.js&amp;diff=32&amp;oldid=prev</id>
		<title>Vendicated: Created page with &quot;// oneko.js // Copyright © 2022 adryd // SPDX-License-Identifier: MIT // https://github.com/adryd325/oneko.js  (function oneko() {   const isReducedMotion =     window.matchMedia(`(prefers-reduced-motion: reduce)`) === true ||     window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;    if (isReducedMotion) return;    const nekoEl = document.createElement(&quot;div&quot;);    let nekoPosX = 32;   let nekoPosY = 32;    let mousePosX = 0;   let mousePosY = 0;    l...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.vencord.dev/index.php?title=MediaWiki:Oneko.js&amp;diff=32&amp;oldid=prev"/>
		<updated>2024-03-07T19:51:37Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;// oneko.js // Copyright © 2022 adryd // SPDX-License-Identifier: MIT // https://github.com/adryd325/oneko.js  (function oneko() {   const isReducedMotion =     window.matchMedia(`(prefers-reduced-motion: reduce)`) === true ||     window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;    if (isReducedMotion) return;    const nekoEl = document.createElement(&amp;quot;div&amp;quot;);    let nekoPosX = 32;   let nekoPosY = 32;    let mousePosX = 0;   let mousePosY = 0;    l...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;// oneko.js&lt;br /&gt;
// Copyright © 2022 adryd&lt;br /&gt;
// SPDX-License-Identifier: MIT&lt;br /&gt;
// https://github.com/adryd325/oneko.js&lt;br /&gt;
&lt;br /&gt;
(function oneko() {&lt;br /&gt;
  const isReducedMotion =&lt;br /&gt;
    window.matchMedia(`(prefers-reduced-motion: reduce)`) === true ||&lt;br /&gt;
    window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;&lt;br /&gt;
&lt;br /&gt;
  if (isReducedMotion) return;&lt;br /&gt;
&lt;br /&gt;
  const nekoEl = document.createElement(&amp;quot;div&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  let nekoPosX = 32;&lt;br /&gt;
  let nekoPosY = 32;&lt;br /&gt;
&lt;br /&gt;
  let mousePosX = 0;&lt;br /&gt;
  let mousePosY = 0;&lt;br /&gt;
&lt;br /&gt;
  let frameCount = 0;&lt;br /&gt;
  let idleTime = 0;&lt;br /&gt;
  let idleAnimation = null;&lt;br /&gt;
  let idleAnimationFrame = 0;&lt;br /&gt;
&lt;br /&gt;
  const nekoSpeed = 10;&lt;br /&gt;
  const spriteSets = {&lt;br /&gt;
    idle: [[-3, -3]],&lt;br /&gt;
    alert: [[-7, -3]],&lt;br /&gt;
    scratchSelf: [&lt;br /&gt;
      [-5, 0],&lt;br /&gt;
      [-6, 0],&lt;br /&gt;
      [-7, 0],&lt;br /&gt;
    ],&lt;br /&gt;
    scratchWallN: [&lt;br /&gt;
      [0, 0],&lt;br /&gt;
      [0, -1],&lt;br /&gt;
    ],&lt;br /&gt;
    scratchWallS: [&lt;br /&gt;
      [-7, -1],&lt;br /&gt;
      [-6, -2],&lt;br /&gt;
    ],&lt;br /&gt;
    scratchWallE: [&lt;br /&gt;
      [-2, -2],&lt;br /&gt;
      [-2, -3],&lt;br /&gt;
    ],&lt;br /&gt;
    scratchWallW: [&lt;br /&gt;
      [-4, 0],&lt;br /&gt;
      [-4, -1],&lt;br /&gt;
    ],&lt;br /&gt;
    tired: [[-3, -2]],&lt;br /&gt;
    sleeping: [&lt;br /&gt;
      [-2, 0],&lt;br /&gt;
      [-2, -1],&lt;br /&gt;
    ],&lt;br /&gt;
    N: [&lt;br /&gt;
      [-1, -2],&lt;br /&gt;
      [-1, -3],&lt;br /&gt;
    ],&lt;br /&gt;
    NE: [&lt;br /&gt;
      [0, -2],&lt;br /&gt;
      [0, -3],&lt;br /&gt;
    ],&lt;br /&gt;
    E: [&lt;br /&gt;
      [-3, 0],&lt;br /&gt;
      [-3, -1],&lt;br /&gt;
    ],&lt;br /&gt;
    SE: [&lt;br /&gt;
      [-5, -1],&lt;br /&gt;
      [-5, -2],&lt;br /&gt;
    ],&lt;br /&gt;
    S: [&lt;br /&gt;
      [-6, -3],&lt;br /&gt;
      [-7, -2],&lt;br /&gt;
    ],&lt;br /&gt;
    SW: [&lt;br /&gt;
      [-5, -3],&lt;br /&gt;
      [-6, -1],&lt;br /&gt;
    ],&lt;br /&gt;
    W: [&lt;br /&gt;
      [-4, -2],&lt;br /&gt;
      [-4, -3],&lt;br /&gt;
    ],&lt;br /&gt;
    NW: [&lt;br /&gt;
      [-1, 0],&lt;br /&gt;
      [-1, -1],&lt;br /&gt;
    ],&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  function init() {&lt;br /&gt;
    nekoEl.id = &amp;quot;oneko&amp;quot;;&lt;br /&gt;
    nekoEl.ariaHidden = true;&lt;br /&gt;
    nekoEl.style.width = &amp;quot;32px&amp;quot;;&lt;br /&gt;
    nekoEl.style.height = &amp;quot;32px&amp;quot;;&lt;br /&gt;
    nekoEl.style.position = &amp;quot;fixed&amp;quot;;&lt;br /&gt;
    nekoEl.style.pointerEvents = &amp;quot;none&amp;quot;;&lt;br /&gt;
    nekoEl.style.imageRendering = &amp;quot;pixelated&amp;quot;;&lt;br /&gt;
    nekoEl.style.left = `${nekoPosX - 16}px`;&lt;br /&gt;
    nekoEl.style.top = `${nekoPosY - 16}px`;&lt;br /&gt;
    nekoEl.style.zIndex = Number.MAX_VALUE;&lt;br /&gt;
&lt;br /&gt;
    let nekoFile = &amp;quot;./oneko.gif&amp;quot;&lt;br /&gt;
    const curScript = document.currentScript&lt;br /&gt;
    if (curScript &amp;amp;&amp;amp; curScript.dataset.cat) {&lt;br /&gt;
      nekoFile = curScript.dataset.cat&lt;br /&gt;
    }&lt;br /&gt;
    nekoEl.style.backgroundImage = `url(${nekoFile})`;&lt;br /&gt;
&lt;br /&gt;
    document.body.appendChild(nekoEl);&lt;br /&gt;
&lt;br /&gt;
    document.addEventListener(&amp;quot;mousemove&amp;quot;, function (event) {&lt;br /&gt;
      mousePosX = event.clientX;&lt;br /&gt;
      mousePosY = event.clientY;&lt;br /&gt;
    });&lt;br /&gt;
&lt;br /&gt;
    window.requestAnimationFrame(onAnimationFrame);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  let lastFrameTimestamp;&lt;br /&gt;
&lt;br /&gt;
  function onAnimationFrame(timestamp) {&lt;br /&gt;
    // Stops execution if the neko element is removed from DOM&lt;br /&gt;
    if (!nekoEl.isConnected) {&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
    if (!lastFrameTimestamp) {&lt;br /&gt;
      lastFrameTimestamp = timestamp;&lt;br /&gt;
    }&lt;br /&gt;
    if (timestamp - lastFrameTimestamp &amp;gt; 100) {&lt;br /&gt;
      lastFrameTimestamp = timestamp&lt;br /&gt;
      frame()&lt;br /&gt;
    }&lt;br /&gt;
    window.requestAnimationFrame(onAnimationFrame);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function setSprite(name, frame) {&lt;br /&gt;
    const sprite = spriteSets[name][frame % spriteSets[name].length];&lt;br /&gt;
    nekoEl.style.backgroundPosition = `${sprite[0] * 32}px ${sprite[1] * 32}px`;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function resetIdleAnimation() {&lt;br /&gt;
    idleAnimation = null;&lt;br /&gt;
    idleAnimationFrame = 0;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function idle() {&lt;br /&gt;
    idleTime += 1;&lt;br /&gt;
&lt;br /&gt;
    // every ~ 20 seconds&lt;br /&gt;
    if (&lt;br /&gt;
      idleTime &amp;gt; 10 &amp;amp;&amp;amp;&lt;br /&gt;
      Math.floor(Math.random() * 200) == 0 &amp;amp;&amp;amp;&lt;br /&gt;
      idleAnimation == null&lt;br /&gt;
    ) {&lt;br /&gt;
      let avalibleIdleAnimations = [&amp;quot;sleeping&amp;quot;, &amp;quot;scratchSelf&amp;quot;];&lt;br /&gt;
      if (nekoPosX &amp;lt; 32) {&lt;br /&gt;
        avalibleIdleAnimations.push(&amp;quot;scratchWallW&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      if (nekoPosY &amp;lt; 32) {&lt;br /&gt;
        avalibleIdleAnimations.push(&amp;quot;scratchWallN&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      if (nekoPosX &amp;gt; window.innerWidth - 32) {&lt;br /&gt;
        avalibleIdleAnimations.push(&amp;quot;scratchWallE&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      if (nekoPosY &amp;gt; window.innerHeight - 32) {&lt;br /&gt;
        avalibleIdleAnimations.push(&amp;quot;scratchWallS&amp;quot;);&lt;br /&gt;
      }&lt;br /&gt;
      idleAnimation =&lt;br /&gt;
        avalibleIdleAnimations[&lt;br /&gt;
          Math.floor(Math.random() * avalibleIdleAnimations.length)&lt;br /&gt;
        ];&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    switch (idleAnimation) {&lt;br /&gt;
      case &amp;quot;sleeping&amp;quot;:&lt;br /&gt;
        if (idleAnimationFrame &amp;lt; 8) {&lt;br /&gt;
          setSprite(&amp;quot;tired&amp;quot;, 0);&lt;br /&gt;
          break;&lt;br /&gt;
        }&lt;br /&gt;
        setSprite(&amp;quot;sleeping&amp;quot;, Math.floor(idleAnimationFrame / 4));&lt;br /&gt;
        if (idleAnimationFrame &amp;gt; 192) {&lt;br /&gt;
          resetIdleAnimation();&lt;br /&gt;
        }&lt;br /&gt;
        break;&lt;br /&gt;
      case &amp;quot;scratchWallN&amp;quot;:&lt;br /&gt;
      case &amp;quot;scratchWallS&amp;quot;:&lt;br /&gt;
      case &amp;quot;scratchWallE&amp;quot;:&lt;br /&gt;
      case &amp;quot;scratchWallW&amp;quot;:&lt;br /&gt;
      case &amp;quot;scratchSelf&amp;quot;:&lt;br /&gt;
        setSprite(idleAnimation, idleAnimationFrame);&lt;br /&gt;
        if (idleAnimationFrame &amp;gt; 9) {&lt;br /&gt;
          resetIdleAnimation();&lt;br /&gt;
        }&lt;br /&gt;
        break;&lt;br /&gt;
      default:&lt;br /&gt;
        setSprite(&amp;quot;idle&amp;quot;, 0);&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    idleAnimationFrame += 1;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function frame() {&lt;br /&gt;
    frameCount += 1;&lt;br /&gt;
    const diffX = nekoPosX - mousePosX;&lt;br /&gt;
    const diffY = nekoPosY - mousePosY;&lt;br /&gt;
    const distance = Math.sqrt(diffX ** 2 + diffY ** 2);&lt;br /&gt;
&lt;br /&gt;
    if (distance &amp;lt; nekoSpeed || distance &amp;lt; 48) {&lt;br /&gt;
      idle();&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    idleAnimation = null;&lt;br /&gt;
    idleAnimationFrame = 0;&lt;br /&gt;
&lt;br /&gt;
    if (idleTime &amp;gt; 1) {&lt;br /&gt;
      setSprite(&amp;quot;alert&amp;quot;, 0);&lt;br /&gt;
      // count down after being alerted before moving&lt;br /&gt;
      idleTime = Math.min(idleTime, 7);&lt;br /&gt;
      idleTime -= 1;&lt;br /&gt;
      return;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    let direction;&lt;br /&gt;
    direction = diffY / distance &amp;gt; 0.5 ? &amp;quot;N&amp;quot; : &amp;quot;&amp;quot;;&lt;br /&gt;
    direction += diffY / distance &amp;lt; -0.5 ? &amp;quot;S&amp;quot; : &amp;quot;&amp;quot;;&lt;br /&gt;
    direction += diffX / distance &amp;gt; 0.5 ? &amp;quot;W&amp;quot; : &amp;quot;&amp;quot;;&lt;br /&gt;
    direction += diffX / distance &amp;lt; -0.5 ? &amp;quot;E&amp;quot; : &amp;quot;&amp;quot;;&lt;br /&gt;
    setSprite(direction, frameCount);&lt;br /&gt;
&lt;br /&gt;
    nekoPosX -= (diffX / distance) * nekoSpeed;&lt;br /&gt;
    nekoPosY -= (diffY / distance) * nekoSpeed;&lt;br /&gt;
&lt;br /&gt;
    nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16);&lt;br /&gt;
    nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16);&lt;br /&gt;
&lt;br /&gt;
    nekoEl.style.left = `${nekoPosX - 16}px`;&lt;br /&gt;
    nekoEl.style.top = `${nekoPosY - 16}px`;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  init();&lt;br /&gt;
})();&lt;/div&gt;</summary>
		<author><name>Vendicated</name></author>
	</entry>
</feed>