Torn Fast Keno

Speeds up Keno animations

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name         Torn Fast Keno
// @namespace    https://www.torn.com/
// @version      1.0.0
// @description  Speeds up Keno animations
// @match        https://www.torn.com/page.php?sid=keno*
// @run-at       document-start
// @grant        none
// @author       WinterValor [3945658]
// @license      MIT
// ==/UserScript==

(function () {
  "use strict";

  const SPEED_MULTIPLIER = 5;          // 5x faster
  const SCALE = 1 / SPEED_MULTIPLIER;  // delay * SCALE
  const MIN_DELAY_MS = 16;             // don’t go below ~1 frame

  // Only scale timers that originate from keno.js (based on stack trace)
  function isKenoCaller() {
    try {
      const stack = new Error().stack || "";
      // Matches ".../casino/keno/js/keno.js?v=..." etc.
      return stack.includes("casino/keno/js/keno.js") || stack.includes("keno.js");
    } catch {
      return false;
    }
  }

  function scaleDelay(delay) {
    if (typeof delay !== "number" || !isFinite(delay) || delay <= 0) return delay;
    const scaled = Math.max(MIN_DELAY_MS, Math.round(delay * SCALE));
    return scaled;
  }

  // Patch timers early so keno.js inherits the behavior
  const _setTimeout = window.setTimeout.bind(window);
  const _setInterval = window.setInterval.bind(window);

  window.setTimeout = function (fn, delay, ...args) {
    const d = isKenoCaller() ? scaleDelay(delay) : delay;
    return _setTimeout(fn, d, ...args);
  };

  window.setInterval = function (fn, delay, ...args) {
    const d = isKenoCaller() ? scaleDelay(delay) : delay;
    return _setInterval(fn, d, ...args);
  };

  // OPTIONAL: also speed up jQuery animations inside the Keno container.
  // (Reveals are already sped up by setInterval; this just makes the UI transitions snappier.)
  function patchJQueryWhenReady() {
    const $ = window.jQuery;
    if (!$ || !$.fn) return;

    const inKeno = (jqObj) => {
      const el = jqObj && jqObj[0];
      if (!el) return false;
      // Only elements within the keno game container
      return (el.closest && el.closest("#kenoGame")) || el.id === "kenoGame";
    };

    const patchDurationArg = (jqObj, dur) => {
      if (typeof dur !== "number") return dur;
      if (!inKeno(jqObj)) return dur;
      return Math.max(MIN_DELAY_MS, Math.round(dur * SCALE));
    };

    // animate
    const _animate = $.fn.animate;
    $.fn.animate = function (props, speed, easing, callback) {
      const newSpeed = patchDurationArg(this, speed);
      return _animate.call(this, props, newSpeed, easing, callback);
    };

    // slideDown / slideUp
    const _slideDown = $.fn.slideDown;
    $.fn.slideDown = function (speed, easing, callback) {
      const newSpeed = patchDurationArg(this, speed);
      return _slideDown.call(this, newSpeed, easing, callback);
    };

    const _slideUp = $.fn.slideUp;
    $.fn.slideUp = function (speed, easing, callback) {
      const newSpeed = patchDurationArg(this, speed);
      return _slideUp.call(this, newSpeed, easing, callback);
    };

    // fadeIn / fadeOut
    const _fadeIn = $.fn.fadeIn;
    $.fn.fadeIn = function (speed, easing, callback) {
      const newSpeed = patchDurationArg(this, speed);
      return _fadeIn.call(this, newSpeed, easing, callback);
    };

    const _fadeOut = $.fn.fadeOut;
    $.fn.fadeOut = function (speed, easing, callback) {
      const newSpeed = patchDurationArg(this, speed);
      return _fadeOut.call(this, newSpeed, easing, callback);
    };
  }

  // Poll briefly until jQuery exists (it loads early, but not at document-start)
  const jqPoll = window.setInterval(() => {
    if (window.jQuery) {
      window.clearInterval(jqPoll);
      patchJQueryWhenReady();
    }
  }, 50);
})();