Greasy Fork

MoshMages' Cookie Clicker Mods

Makes it easier.

当前为 2020-12-12 提交的版本,查看 最新版本

// ==UserScript==
// @name         MoshMages' Cookie Clicker Mods
// @version      1.10.2
// @description  Makes it easier.
// @author       [email protected]
// @match        *orteil.dashnet.org/cookieclicker/*
// @grant        none
// @namespace https://gist.github.com/moshmage/792ac013a8fb0b23d39f491261ebdb90
// ==/UserScript==
(() => {

  const options = {
    enable: false,
    enableQueue: true,
    autoBuyUpgrades: true,

    autoClickShimmers: true,
    avoidWrathCookie: false,

    disableBuyIfBuffs: true,
    killWrinkles: true,
    killGoldenWrinkles: false,

    preventBuildingDeBuff: true,
    preventClot: true,
    preventRuin: true,

    tickSpeedMs: 50,
    clickCookie: true,
  }

  setTimeout(() =>  {
    const bigCookie = document.querySelector(`#bigCookie`);
    const centerSection = document.querySelector(`#centerArea`);
    const game = document.querySelector(`#game`);
    const comments = document.querySelector(`#comments`);
    const _Game = window.Game || {tooltip: {}, shimmers: [], wrinklers: [], buffs: [], goldenCookieBuildingBuffs: {}, Has: (s) => {}, hasGod: (s) => {}, ObjectsById: [], cookies: 0, buyMode: 1, buyBulk: 1};
    const wrinkleEl = document.createElement(`div`);
    const wrinklerScoreToggle = document.createElement(`div`);

    const mouseEvent = (node, eventType) => {
      const clickEvent = document.createEvent('MouseEvents');
      clickEvent.initEvent(eventType, true, true);
      node.dispatchEvent(clickEvent);
    }

    const unwantedEffects = Object.entries(_Game.goldenCookieBuildingBuffs).map(([name, [good, bad]]) => bad.toLowerCase());

    const killWrinkle = (wrinkle) => wrinkle.hp-- && wrinkle.hp > 0 && killWrinkle(wrinkle);

    const updateWrinkleScore = () => {
      const score =
        _Game.wrinklers
          .filter(w => w.sucked > 0)
          .map(w => !w.type && w.sucked || w.sucked * 3)
          .reduce(((p, c) => p+c), 0);
      let percent = 10;

      if (_Game.Has(`Wrinklerspawn`))
        percent += 5;

      if (_Game.Has(`Sacrilegious corruption`))
        percent += 5;

      if (_Game.hasGod) {
        const level = _Game.hasGod(`scorn`);
        if (level)
          percent += +(Math.abs(level - 4) * .05).toFixed(2).substring(2);
      }

      wrinkleEl.querySelector(`div`).innerHTML = `${window.Beautify(score + ((score/100)*percent))}<br/><span style="font-size:50%">wrinkled cookies</span>`;
    }

    const killWrinkles = () => {
      _Game
        .wrinklers
        .filter(({close, phase, hp}) => phase && close === 1 && hp)
        .forEach(killWrinkle);
    }

    const tickAction = () => {
      if (!options.enable) return;

      if (options.clickCookie)
        bigCookie.click()

      const buyThing = (selector) => {
        const things = document.querySelectorAll(selector);
        if (things.length)
          things[0].click();
      }

      if (options.autoClickShimmers)
        _Game.shimmers.forEach(shimmer => (!options.avoidWrathCookie || options.avoidWrathCookie && !shimmer.wrath) && shimmer.pop());

      const hasWrinklers = _Game.wrinklers.some(w => w.phase > 0);
      if (hasWrinklers) {
        if (options.killWrinkles) killWrinkles();
        else {
          updateWrinkleScore();

          if (wrinklerScoreToggle.style.display !== `block`)
            wrinklerScoreToggle.style.display = `block`;

        }
      } else if (wrinklerScoreToggle.style.display === `block`) {
        wrinklerScoreToggle.style.display = `none`;
        wrinkleEl.style.display = `none`;
      }


      const buffs = document.querySelectorAll(`#buffs *`).length;
      if (!options.disableBuyIfBuffs || options.disableBuyIfBuffs && !buffs) {
        if (options.autoBuyUpgrades)
          buyThing(`#upgrades .enabled`);

        if (options.enableQueue) {
          const firstOnQueue = document.querySelector(`[data-q-item]`);
          if (firstOnQueue)
            firstOnQueue.clickAction();

        }

      }

      setTimeout(() => tickAction(), options.tickSpeedMs);
    }

    const onoff = (pointer) => pointer && `ON` || `OFF`;

    const makeListingOption = (name, desc, id, key, cb) => {
      const listing = document.createElement(`div`);
      listing.classList.add(`listing`);

      const option = document.createElement(`a`);
      option.classList.add(`option`);

      if (key) {
        if (!options[key]) option.classList.add(`off`);
        else option.classList.remove(`off`);
      }

      option.setAttribute(`id`, id);
      option.textContent = `${name} ${key && onoff(options[key]) || ``}`;

      option.addEventListener(`click`, (ev) => {
        if (key) {
          options[key] = !options[key];
          option.textContent = `${name} ${onoff(options[key])}`;

          localStorage.setItem(`acmoptions`, JSON.stringify(options));

          if (!options[key]) option.classList.add(`off`);
          else option.classList.remove(`off`);
        }

        if (cb) cb(ev, key);
      });

      const label = document.createElement(`label`);
      label.textContent = desc && `(${desc})` || ``;

      if (name) listing.appendChild(option);
      if (desc) listing.appendChild(label);

      return listing;
    }

    const makeSlider = (name, min, max, increment, key) => {
      const listing = document.createElement(`div`);
      listing.classList.add(`listing`);

      const slider = document.createElement(`div`);
      slider.classList.add(`sliderBox`);

      const label = document.createElement(`div`);
      label.style.float = `left`;
      label.textContent = name;

      const value = document.createElement(`div`);
      value.style.float = `right`;
      value.textContent = options[key];

      const option = document.createElement(`input`);
      option.setAttribute(`type`, `range`);
      option.setAttribute(`min`, min);
      option.setAttribute(`max`, max);
      option.setAttribute(`step`, increment);
      option.style.clear = `both`;
      option.value = options[key];

      option.addEventListener(`change`, (ev) => {
        options[key] = +ev.target.value;
        localStorage.setItem(`acmoptions`, JSON.stringify(options));
        value.textContent = options[key];
      });

      slider.appendChild(label);
      slider.appendChild(value);
      slider.appendChild(option);
      listing.appendChild(slider);

      return listing;
    }

    const makeTitle = (title) => {
      const element = document.createElement(`div`)
      element.classList.add(`title`);
      element.textContent = title;

      return element;
    }

    const makeAscensionButton = (text, style = {}) => {
      style = {position: `absolute`, fontSize: `14px`, fontWeight: `bold`, fontFamily: `Georgia`, color: `#fff`, textShadow: `0px -1px 1px #09f,0px 1px 1px #f04`, cursor: `pointer`, zIndex: `1000`, display: `block`, ...style};
      const button = document.createElement(`div`);
      button.classList.add(`roundedPanel`);
      Object.entries(style).forEach(([key, val]) => button.style[key] = val);
      button.textContent = text;
      return button;
    }

    const makePage = (title = ``, buttonText = ``, buttonStyle = {}) => {
      const style = {display: `none`, position: `absolute`, zIndex: `100`, left: `0`, right: `0`, top: `0`, bottom: `0`};

      const page = document.createElement(`div`);
      page.setAttribute(`id`, buttonText);
      Object.entries(style).forEach(([key, val]) => page.style[key] = val);

      const closePageButton = document.createElement(`div`);
      closePageButton.classList.add(`close`, `menuClose`);
      closePageButton.textContent = `x`;
      closePageButton.setAttribute(`data-close`, buttonText);

      const pageTitle = document.createElement(`div`);
      pageTitle.classList.add(`section`);
      pageTitle.textContent = title;

      const openPage = () => {
        const close = centerSection.querySelector(`.close:not([data-close="${buttonText}"])`);
        if (close) close.click();

        game.classList.add(`onMenu`);
        page.style.display = `block`;
      }

      const closePage = (removeMenu = true) => {
        if (removeMenu) game.classList.remove(`onMenu`);
        page.style.display = `none`;
      }


      closePageButton.addEventListener(`click`, closePage);

      const pageButton = makeAscensionButton(buttonText, buttonStyle);
      pageButton.addEventListener(`click`, () => {
        if (page.style.display === `block`)
          closePage();
        else openPage();
      });

      comments.appendChild(pageButton);
      comments
        .querySelectorAll(`.button`)
        .forEach(el => el.addEventListener(`click`, () => closePage(false)));

      page.appendChild(closePageButton);
      page.appendChild(pageTitle);

      page.closeEl = closePageButton;
      page.pageButtonEl = pageButton;

      return page;
    }

    const makeSubSection = (title = ``) => {
      const subsection = document.createElement(`div`);
      subsection.classList.add(`subsection`);
      subsection.appendChild(makeTitle(title));

      return subsection;
    }

    const buildUI = () => {

      const startTickAction = () => {
        if (options.enable) tickAction();
      }

      const toggleQueueUI = () => {

      }

      Object.assign(options, JSON.parse(localStorage.getItem(`acmoptions`) || `{}`));

      const modMenu = makePage(`MoshMages' Madness`, `Mod`, {top: `4.5rem`, right: `auto`, left: `6rem`});
      const subsection = makeSubSection(`Global`);

      subsection.appendChild(makeListingOption(`Enable`, `enable/disable auto click abilities`, `enable-madness`, `enable`, function() { startTickAction() }))
      subsection.appendChild(makeSlider(`Tick speed (ms)`, 50, 1000, 10, `tickSpeedMs`));

      subsection.appendChild(makeTitle(`Auto click`));
      subsection.appendChild(makeListingOption(`Big cookie`, `click the big cookie`, `enable-cookie-click`, `clickCookie`));
      subsection.appendChild(makeListingOption(`Shimmers`, ``, `auto-shimmer`, `autoClickShimmers`));
      subsection.appendChild(makeListingOption(`Avoid wrath cookies`, ``, `auto-shimmer`, `avoidWrathCookie`));

      subsection.appendChild(makeTitle(`Auto buy`));
      subsection.appendChild(makeListingOption(`Wait for buff end`, `will not buy if buffs are active`, `auto-buff-wait`, `disableBuyIfBuffs`));
      subsection.appendChild(makeListingOption(`Product queue`, `enable product buy queue`, `auto-build`, `enableQueue`, function() { toggleQueueUI(); }));
      subsection.appendChild(makeListingOption(`Upgrades`, `buy first upgrade available`, `auto-upgrade`, `autoBuyUpgrades`));

      subsection.appendChild(makeTitle(`Wrinklers`))
      subsection.appendChild(makeListingOption(`Kill wrinklers`, ``, `auto-wrinkler`, `killWrinkles`));
      subsection.appendChild(makeListingOption(`Kill Golden wrinklers`, ``, `auto-golden-wrinkler`, `killGoldenWrinkles`));

      subsection.appendChild(makeTitle(`Debuffs`));
      subsection.appendChild(makeListingOption(`Prevent clot`, ``, `auto-avoid-clot-ruin`, `preventClot`));
      subsection.appendChild(makeListingOption(`Prevent ruin`, ``, `auto-avoid-ruin`, `preventRuin`));
      subsection.appendChild(makeListingOption(`Prevent building debuffs`, ``, `auto-avoid-building-debuffs`, `preventBuildingDeBuff`));

      modMenu.appendChild(subsection);


      const queueEl = makePage(`Product buy queue`, `Queue`, {top: `4.5rem`, left: `10rem`});
      const queueHelp = makeSubSection(`Queue status`);
      const queueListEl = makeSubSection(`List`);
      queueHelp.appendChild(makeListingOption(``, `Will attempt to buy the first item on this list with the selected bulk type; click the listing to remove.`, ``, ``));
      queueEl.appendChild(queueHelp);
      queueEl.appendChild(queueListEl);

      document.querySelectorAll(`#products .product`)
        .forEach((el, i) => {
          const name = el.querySelector(`.title`).textContent;
          const button = makeAscensionButton(`+`, {left: `1rem`, top: `.1rem`, transform: `scale(.7)`});
          const product = _Game.ObjectsById[i];

          button.setAttribute(`q`, i.toString());

          button.addEventListener(`click`, (oev) => {
            oev.cancelBubble = true;
            oev.preventDefault();

            const removeListingEl = () => queueListEl.removeChild(document.querySelector(`[data-q-item="${i.toString()}"]`));
            const listing = makeListingOption(name, `${_Game.buyMode === 1 ? `buy` : `sell`} ${_Game.buyBulk} worth ${window.Beautify(product.getSumPrice(_Game.buyBulk))}c`, ``, ``, removeListingEl);

            listing.setAttribute(`data-q-item`, i.toString());
            listing.setAttribute(`data-q-qty`, _Game.buyBulk);
            listing.setAttribute(`data-q-mode`, _Game.buyMode);

            const buyAndRemove = () => {

              const qty = +listing.getAttribute(`data-q-qty`);
              const mode = +listing.getAttribute(`data-q-mode`);

              if (mode === 1 && product.getSumPrice(qty) > _Game.cookies) return;
              if (mode === -1 && product.amount < qty)
                return removeListingEl();
              if (mode === 1)
                product.buy(qty);
              else product.sell(qty);

              removeListingEl();
            }

            listing.clickAction = buyAndRemove;
            queueListEl.appendChild(listing);
          })

          el.appendChild(button);
        });


      centerSection.appendChild(modMenu);
      centerSection.appendChild(queueEl);

      modMenu.pageButtonEl.click();

      wrinkleEl.classList.add(`title`);
      wrinkleEl.setAttribute(`id`, `wrinkle-bits`);
      wrinkleEl.style.bottom = `10%`
      wrinkleEl.style.textAlign = `center`;
      wrinkleEl.style.position = `absolute`;
      wrinkleEl.style.width = `100%`;
      wrinkleEl.style.background = `rgba(0,0,0,.4)`;
      wrinkleEl.style.padding = `5px 0 5px 0`;
      wrinkleEl.style.zIndex = `2000`;
      wrinkleEl.style.display = `none`;

      wrinkleEl.appendChild(document.createElement(`div`));

      const wrinklePop = document.createElement(`a`);
      wrinklePop.classList.add(`option`);
      wrinklePop.textContent = `exterminate`;
      wrinklePop.addEventListener(`click`, () => {
        killWrinkles();
      });


      const wrinklerScoreToggleHolder = document.createElement(`div`);
      wrinklerScoreToggleHolder.style.bottom = `9rem`;
      wrinklerScoreToggleHolder.style.right = `.5rem`;
      wrinklerScoreToggleHolder.style.position = `absolute`;
      wrinklerScoreToggleHolder.style.zIndex = `2001`;
      wrinklerScoreToggleHolder.style.transform = `scale(.8)`

      wrinklerScoreToggle.classList.add(`crate`, `upgrade`, `heavenly`);
      wrinklerScoreToggle.style.backgroundPosition = `-1248px -576px`;
      wrinklerScoreToggle.style.cursor = `pointer`;
      wrinklerScoreToggle.style.display = `none`;

      wrinklerScoreToggleHolder.appendChild(wrinklerScoreToggle);


      wrinklerScoreToggle.addEventListener(`click`, () => {
        wrinkleEl.style.display = wrinkleEl.style.display === `block` ? `none` : `block`;
        updateWrinkleScore();

        if (wrinkleEl.style.display === `block`)
          wrinklerScoreToggle.classList.add(`enabled`);
        else wrinklerScoreToggle.classList.remove(`enabled`);
      });

      const leftSection = document.querySelector(`#sectionLeft`);

      wrinkleEl.appendChild(wrinklePop);
      leftSection.appendChild(wrinkleEl);
      leftSection.appendChild(wrinklerScoreToggleHolder);

      if (options.enable)
        tickAction();

      window.ochoose = window.choose;

      const filterWord = (word) => (sentence = ``) => sentence.toString().toLowerCase().indexOf(word.toLowerCase()) < 0;
      const filterBuildingDeBuffs = (k = ``) => unwantedEffects.some(t => filterWord(t)(k))

      window.ochoose = window.choose;
      window.choose = (arr) => window.ochoose(
        arr
          .filter(options.preventClot ? filterWord(`clot`) : () => true)
          .filter(options.preventRuin ? filterWord(`ruin`) : () => true)
          .filter(options.preventBuildingDeBuff ? filterBuildingDeBuffs : () => true)
      );
    }

    setTimeout(buildUI, 500);
  }, 500)
})();