🐭️ MouseHunt - Minluck & Catch Rate Estimate

View the minluck and catch rate estimate, right on the camp page.

目前為 2024-03-26 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        🐭️ MouseHunt - Minluck & Catch Rate Estimate
// @description View the minluck and catch rate estimate, right on the camp page.
// @version     2.0.1
// @license     MIT
// @author      bradp
// @namespace   bradp
// @match       https://www.mousehuntgame.com/*
// @icon        https://i.mouse.rip/mh-improved/icon-64.png
// @run-at      document-end
// @grant       none
// @require     https://cdn.jsdelivr.net/npm/[email protected]
// ==/UserScript==

var mhui = (() => {
  var __defProp = Object.defineProperty;
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  var __getOwnPropNames = Object.getOwnPropertyNames;
  var __hasOwnProp = Object.prototype.hasOwnProperty;
  var __export = (target, all) => {
    for (var name in all)
      __defProp(target, name, { get: all[name], enumerable: true });
  };
  var __copyProps = (to, from, except, desc) => {
    if (from && typeof from === "object" || typeof from === "function") {
      for (let key of __getOwnPropNames(from))
        if (!__hasOwnProp.call(to, key) && key !== except)
          __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
    }
    return to;
  };
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  var __async = (__this, __arguments, generator) => {
    return new Promise((resolve, reject) => {
      var fulfilled = (value) => {
        try {
          step(generator.next(value));
        } catch (e) {
          reject(e);
        }
      };
      var rejected = (value) => {
        try {
          step(generator.throw(value));
        } catch (e) {
          reject(e);
        }
      };
      var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
      step((generator = generator.apply(__this, __arguments)).next());
    });
  };

  // src/modules/catch-rate-estimate/index.js
  var catch_rate_estimate_exports = {};
  __export(catch_rate_estimate_exports, {
    default: () => catch_rate_estimate_default
  });

  // src/utils/event-registry.js
  var doEvent2 = (eventName, params) => {
    if (!eventRegistry) {
      return;
    }
    eventRegistry.doEvent(eventName, params);
  };
  var onEvent = (event, callback, remove = false) => {
    if (!eventRegistry) {
      return;
    }
    eventRegistry.addEventListener(event, callback, null, remove);
  };

  // src/utils/styles.js
  var addModuleStyles = (styles, identifier = "mh-improved-styles", replace = false) => {
    const existingStyles = document.querySelector(`#${identifier}`);
    styles = Array.isArray(styles) ? styles.join("\n") : styles;
    if (existingStyles) {
      if (replace) {
        existingStyles.innerHTML = styles;
      } else {
        existingStyles.innerHTML += styles;
      }
      return existingStyles;
    }
    const style = document.createElement("style");
    style.id = identifier;
    style.innerHTML = styles;
    document.head.append(style);
    return style;
  };
  var addStyles = (styles, module = false, identifier = "mh-improved-styles") => {
    if (!module) {
      throw new Error("Module ID is required for adding module styles.", module);
    }
    const key = `${identifier}-${module}`;
    let stylesEl = addModuleStyles(styles, key, true);
    onEvent(`mh-improved-settings-changed-${module}`, (enabled) => {
      if (enabled) {
        stylesEl = addModuleStyles(styles, key, true);
      } else if (stylesEl) {
        stylesEl.remove();
      }
    });
  };

  // src/utils/settings.js
  var getSettingDirect = (key = null, defaultValue = null, identifier = "mousehunt-improved-settings") => {
    const settings = JSON.parse(localStorage.getItem(identifier)) || {};
    if (!key) {
      return settings;
    }
    if (!key.includes(".")) {
      if (settings[key] === void 0) {
        return defaultValue;
      }
      return settings[key];
    }
    const groupAndKey = getGroupAndKey(key);
    if (!groupAndKey.group) {
      if (settings[groupAndKey.key] === void 0) {
        return defaultValue;
      }
      return settings[groupAndKey.key];
    }
    const groupSettings = settings[groupAndKey.group] || {};
    if (groupSettings[groupAndKey.key] === void 0) {
      return defaultValue;
    }
    return groupSettings[groupAndKey.key];
  };
  var getGroupAndKey = (key) => {
    const split = key.split(".");
    if (split.length === 1) {
      return {
        group: null,
        key: split[0]
      };
    }
    if (split[0] === "location-huds-enabled") {
      return {
        group: "location-huds-enabled",
        key: split[1]
      };
    }
    return {
      group: `${split[0]}-settings`,
      key: split[1]
    };
  };
  var getSetting = (key, defaultValue = false) => {
    return getSettingDirect(key, defaultValue, "mousehunt-improved-settings");
  };

  // src/utils/elements.js
  var makeElement = (tag, classes = "", text = "", appendTo = null) => {
    const element = document.createElement(tag);
    if (Array.isArray(classes)) {
      classes = classes.join(" ");
    }
    if (classes && classes.length) {
      element.className = classes;
    }
    element.innerHTML = text;
    if (appendTo) {
      appendTo.append(element);
      return appendTo;
    }
    return element;
  };

  // src/utils/db.js
  var database = (databaseName) => __async(void 0, null, function* () {
    return new Promise((resolve, reject) => {
      const request = indexedDB.open(`mh-improved-${databaseName}`, 6);
      request.onerror = (event) => {
        reject(event.target.error);
      };
      request.onsuccess = (event) => {
        resolve(event.target.result);
      };
      request.onupgradeneeded = (event) => {
        const db = event.target.result;
        if (!db.objectStoreNames.contains(databaseName)) {
          db.createObjectStore(databaseName, { keyPath: "id" });
        }
      };
    });
  });
  var dbGet = (databaseName, id) => __async(void 0, null, function* () {
    const db = yield database(databaseName);
    const transaction = db.transaction(databaseName, "readonly");
    transaction.onerror = (event) => {
      throw new Error(event.target.error);
    };
    const objectStore = transaction.objectStore(databaseName);
    const request = objectStore.get(id);
    return new Promise((resolve, reject) => {
      request.onsuccess = () => {
        resolve(request.result);
      };
      request.onerror = () => {
        reject(request.error);
      };
      transaction.oncomplete = () => {
        db.close();
      };
    });
  });
  var dbSet = (databaseName, data) => __async(void 0, null, function* () {
    const db = yield database(databaseName);
    const transaction = db.transaction(databaseName, "readwrite");
    const objectStore = transaction.objectStore(databaseName);
    data = {
      data,
      id: data.id || Date.now()
    };
    const request = objectStore.put(data);
    return new Promise((resolve, reject) => {
      request.onsuccess = () => {
        resolve(request.result);
      };
      request.onerror = () => {
        reject(request.error);
      };
      transaction.oncomplete = () => {
        db.close();
      };
    });
  });

  // src/utils/global.js
  var getGlobal = (key) => {
    if (window.mhui) {
      return window.mhui[key] || false;
    }
    if (app.mhui) {
      return app.mhui[key] || false;
    }
    return false;
  };

  // src/utils/debug.js
  var debuglog = (module, message, ...args) => {
    if (getSetting("debug.all", false) || getSetting(`debug.${module}`, false) || getGlobal("mh-improved-updating", false)) {
      console.log(
        `%cMH Improved %c${module}%c ${message}`,
        "color: #90588c; font-weight: 900",
        "color: #90588c; font-weight: 400",
        "color: inherit; font-weight: inherit",
        ...args
      );
    }
  };

  // src/utils/data.js
  var validDataFiles = /* @__PURE__ */ new Set([
    "effs",
    "environments-events",
    "environments",
    "item-thumbnails",
    "items-tradable",
    "m400-locations",
    "marketplace-hidden-items",
    "mice-groups",
    "mice-regions",
    "mice-thumbnails",
    "minlucks",
    "relic-hunter-hints",
    "scoreboards",
    "ultimate-checkmark",
    "upscaled-images",
    "wisdom"
  ]);
  var isValidDataFile = (file) => {
    return validDataFiles.has(file);
  };
  var getCacheExpiration = (key = null) => __async(void 0, null, function* () {
    return yield cacheGet(`expiration-${key}`, false);
  });
  var setCacheExpiration = (key) => __async(void 0, null, function* () {
    debuglog("utils-data", `Setting cache expiration for ${key}`);
    cacheSet(`expiration-${key}`, Date.now() + (Math.floor(Math.random() * 7) + 7) * 24 * 60 * 60 * 1e3);
  });
  var isCacheExpired = (key) => __async(void 0, null, function* () {
    const expiration = yield getCacheExpiration(key);
    if (!expiration) {
      return true;
    }
    return expiration.date < Date.now();
  });
  var fetchData = (key) => __async(void 0, null, function* () {
    const data = yield fetch(`https://api.mouse.rip/${key}`, {
      method: "GET",
      headers: getHeaders()
    });
    return yield data.json();
  });
  var getData = (key) => __async(void 0, null, function* () {
    if (!isValidDataFile(key)) {
      debuglog("utils-data", `Cannot get data for ${key}, invalid key`);
      return false;
    }
    const isExpired = yield isCacheExpired(key);
    if (!isExpired) {
      const cachedData = yield dataCacheGet(key, false);
      if (cachedData) {
        return cachedData;
      }
    }
    debuglog("utils-data", `Fetching data for ${key}\u2026`);
    const data = yield fetchData(key);
    debuglog("utils-data", `Fetched data for ${key}`, data);
    if (data) {
      dataCacheSet(key, data);
      setCacheExpiration(key);
    }
    return data;
  });
  var getHeaders = () => {
    return {
      "Content-Type": "application/json",
      "X-MH-Improved": "true",
      "X-MH-Improved-Version": mhImprovedVersion || "unknown",
      "X-MH-Improved-Platform": mhImprovedPlatform || "unknown"
    };
  };
  var cacheSet = (key, value) => {
    dbSet("cache", { id: key, value });
  };
  var dataCacheSet = (key, value) => {
    dbSet("data", { id: key, value });
  };
  var cacheGetHelper = (key, defaultValue = false, db = "cache") => __async(void 0, null, function* () {
    var _a;
    const cached = yield dbGet(db, key);
    if (!((_a = cached == null ? void 0 : cached.data) == null ? void 0 : _a.value)) {
      return defaultValue;
    }
    return cached.data.value;
  });
  var cacheGet = (key, defaultValue = false) => __async(void 0, null, function* () {
    return yield cacheGetHelper(key, defaultValue, "cache");
  });
  var dataCacheGet = (key, defaultValue = false) => __async(void 0, null, function* () {
    return yield cacheGetHelper(key, defaultValue, "data");
  });

  // src/utils/page.js
  var getCurrentPage = () => {
    var _a, _b;
    if (!((_b = (_a = hg == null ? void 0 : hg.utils) == null ? void 0 : _a.PageUtil) == null ? void 0 : _b.getCurrentPage)) {
      return null;
    }
    const page = hg.utils.PageUtil.getCurrentPage();
    if (!page) {
      return null;
    }
    return page.toLowerCase();
  };

  // src/utils/location.js
  var getCurrentLocation = () => {
    const location = (user == null ? void 0 : user.environment_type) || "";
    return location.toLowerCase();
  };

  // src/utils/horn.js
  var showHornMessage = (options) => {
    const huntersHornView = document.querySelector(".huntersHornView__messageContainer");
    if (!huntersHornView) {
      return;
    }
    const settings = {
      title: options.title || "Hunters Horn",
      text: options.text || "This is a message from the Hunters Horn",
      button: options.button || "OK",
      action: options.action || (() => {
      }),
      dismiss: options.dismiss || null,
      type: options.type || "recent_linked_turn",
      classname: options.classname || "",
      image: options.image || null,
      imageLink: options.imageLink || null,
      imageCallback: options.imageCallback || null
    };
    const backdrop = document.querySelector(".huntersHornView__backdrop");
    if (backdrop) {
      backdrop.classList.add("huntersHornView__backdrop--active");
    }
    const gameInfo = document.querySelector(".mousehuntHud-gameInfo");
    if (gameInfo) {
      gameInfo.classList.add("blur");
    }
    const messageWrapper = makeElement("div", ["huntersHornView__message huntersHornView__message--active", settings.classname]);
    const message = makeElement("div", ["huntersHornMessageView", `huntersHornMessageView--${settings.type}`]);
    makeElement("div", "huntersHornMessageView__title", settings.title, message);
    const content = makeElement("div", "huntersHornMessageView__content");
    if (settings.image) {
      const imgWrapper = makeElement("div", "huntersHornMessageView__friend");
      const img = makeElement("a", "huntersHornMessageView__friendProfilePic");
      if (settings.imageLink) {
        img.href = settings.imageLink;
      } else if (settings.imageCallback) {
        img.addEventListener("click", settings.imageCallback);
      } else {
        img.href = "#";
      }
      img.style.backgroundImage = `url(${settings.image})`;
      imgWrapper.append(img);
      content.append(imgWrapper);
    }
    makeElement("div", "huntersHornMessageView__text", settings.text, content);
    const buttonSpacer = makeElement("div", "huntersHornMessageView__buttonSpacer");
    const button = makeElement("button", "huntersHornMessageView__action");
    const buttonLabel = makeElement("div", "huntersHornMessageView__actionLabel");
    makeElement("span", "huntersHornMessageView__actionText", settings.button, buttonLabel);
    button.append(buttonLabel);
    button.addEventListener("click", () => {
      if (settings.action) {
        settings.action();
      }
      messageWrapper.innerHTML = "";
      backdrop.classList.remove("huntersHornView__backdrop--active");
      gameInfo.classList.remove("blur");
    });
    buttonSpacer.append(button);
    content.append(buttonSpacer);
    message.append(content);
    if (settings.dismiss) {
      const countdown = makeElement("button", ["huntersHornMessageView__countdown"]);
      makeElement("div", "huntersHornMessageView__countdownButtonImage", "", countdown);
      const svgMarkup = `<svg class="huntersHornMessageView__countdownSVG">
        <circle r="46%" cx="50%" cy="50%" class="huntersHornMessageView__countdownCircleTrack"></circle>
        <circle r="46%" cx="50%" cy="50%" class="huntersHornMessageView__countdownCircle" style="animation-duration: ${settings.dismiss}ms;"></circle>
    </svg>`;
      countdown.innerHTML += svgMarkup;
      countdown.addEventListener("click", () => {
        countdown.classList.add("huntersHornMessageView__countdown--complete");
        messageWrapper.innerHTML = "";
        backdrop.classList.remove("huntersHornView__backdrop--active");
        gameInfo.classList.remove("blur");
      });
      message.append(countdown);
    }
    messageWrapper.append(message);
    const existingMessages = huntersHornView.querySelector(".huntersHornView__message");
    if (existingMessages) {
      existingMessages.remove();
    }
    huntersHornView.append(messageWrapper);
    if (settings.dismiss) {
      setTimeout(() => {
        const countdown = messageWrapper.querySelector(".huntersHornMessageView__countdown");
        if (countdown) {
          countdown.classList.add("huntersHornMessageView__countdown--complete");
        }
        messageWrapper.innerHTML = "";
        backdrop.classList.remove("huntersHornView__backdrop--active");
        gameInfo.classList.remove("blur");
      }, settings.dismiss);
    }
  };

  // src/utils/events.js
  var requestCallbacks = {};
  var onRequestHolder = null;
  var onRequest = (url = null, callback = null, skipSuccess = false) => {
    url = "*" === url ? "*" : `managers/ajax/${url}`;
    if (!callback) {
      return;
    }
    if (!requestCallbacks[url]) {
      requestCallbacks[url] = [];
    }
    requestCallbacks[url].push({
      callback,
      skipSuccess
    });
    if (onRequestHolder) {
      return;
    }
    const req = XMLHttpRequest.prototype.open;
    XMLHttpRequest.prototype.open = function() {
      this.addEventListener("load", function() {
        if (this.responseText) {
          let response = {};
          try {
            response = JSON.parse(this.responseText);
          } catch (e) {
            return;
          }
          Object.keys(requestCallbacks).forEach((key) => {
            if ("*" === key || this.responseURL.includes(key)) {
              requestCallbacks[key].forEach((item) => {
                if (item.callback && typeof item.callback === "function" && (item.skipSuccess || (response == null ? void 0 : response.success))) {
                  item.callback(response);
                }
              });
            }
          });
        }
      });
      Reflect.apply(req, this, arguments);
    };
    onRequestHolder = true;
  };
  var runCallbacks = (settings, parentNode, callbacks) => {
    Object.keys(settings).forEach((key) => {
      if (parentNode && parentNode.classList && parentNode.classList.contains(settings[key].selector)) {
        settings[key].isVisible = true;
        if (callbacks[key] && callbacks[key].show) {
          callbacks[key].show();
        }
      } else if (settings[key].isVisible) {
        settings[key].isVisible = false;
        if (callbacks[key] && callbacks[key].hide) {
          callbacks[key].hide();
        }
      }
    });
    return settings;
  };
  var pageChangeCallbacks = [];
  var pageChangeObserver = null;
  var onPageChange = (callbacks) => {
    let tabData = {
      blueprint: { isVisible: null, selector: "showBlueprint" },
      tem: { isVisible: false, selector: "showTrapEffectiveness" },
      trap: { isVisible: false, selector: "editTrap" },
      camp: { isVisible: false, selector: "PageCamp" },
      travel: { isVisible: false, selector: "PageTravel" },
      inventory: { isVisible: false, selector: "PageInventory" },
      shop: { isVisible: false, selector: "PageShops" },
      mice: { isVisible: false, selector: "PageAdversaries" },
      friends: { isVisible: false, selector: "PageFriends" },
      sendSupplies: { isVisible: false, selector: "PageSupplyTransfer" },
      team: { isVisible: false, selector: "PageTeam" },
      tournament: { isVisible: false, selector: "PageTournament" },
      news: { isVisible: false, selector: "PageNews" },
      scoreboards: { isVisible: false, selector: "PageScoreboards" },
      discord: { isVisible: false, selector: "PageJoinDiscord" },
      preferences: { isVisible: false, selector: "PagePreferences" },
      profile: { isVisible: false, selector: "HunterProfile" }
    };
    pageChangeCallbacks.push(callbacks);
    if (pageChangeObserver) {
      return;
    }
    pageChangeObserver = true;
    const observer = new MutationObserver(() => {
      pageChangeCallbacks.forEach((callback) => {
        if (callback.change) {
          callback.change();
        }
        const mhContainer = document.querySelector("#mousehuntContainer");
        if (mhContainer && mhContainer.classList.length > 0) {
          tabData = runCallbacks(tabData, mhContainer, callback);
        }
      });
    });
    const observeTarget = document.querySelector("#mousehuntContainer");
    if (observeTarget) {
      observer.observe(observeTarget, {
        attributes: true,
        attributeFilter: ["class"]
      });
    }
  };
  var onTravel = (location, options) => {
    eventRegistry.addEventListener("travel_complete", () => onTravelCallback(location, options));
  };
  var onTravelCallback = (location, options) => {
    if (location && location !== getCurrentLocation()) {
      return;
    }
    if (options == null ? void 0 : options.shouldAddReminder) {
      showHornMessage({
        title: options.title || "",
        text: options.text || "",
        button: options.button || "Dismiss",
        action: options.action || null
      });
    }
    if (options.callback) {
      options.callback();
    }
  };

  // src/utils/messages.js
  hadAddedErrorStyles = false;

  // src/utils/utils.js
  var doRequest = (_0, ..._1) => __async(void 0, [_0, ..._1], function* (url, formData = {}) {
    var _a;
    if ("undefined" === typeof lastReadJournalEntryId || "undefined" === typeof user) {
      return;
    }
    if (!lastReadJournalEntryId || !user || !(user == null ? void 0 : user.unique_hash)) {
      return;
    }
    const form = new FormData();
    form.append("sn", "Hitgrab");
    form.append("hg_is_ajax", 1);
    form.append("last_read_journal_entry_id", lastReadJournalEntryId != null ? lastReadJournalEntryId : 0);
    form.append("uh", (_a = user == null ? void 0 : user.unique_hash) != null ? _a : "");
    for (const key in formData) {
      form.append(key, formData[key]);
    }
    const requestBody = new URLSearchParams(form).toString();
    const response = yield fetch(
      callbackurl ? callbackurl + url : "https://www.mousehuntgame.com/" + url,
      {
        method: "POST",
        body: requestBody,
        headers: {
          "Content-Type": "application/x-www-form-urlencoded"
        }
      }
    );
    const data = yield response.json();
    return data;
  });

  // src/modules/catch-rate-estimate/data.js
  var miceEffs;
  var hasGottenEffs = false;
  var getMiceEffectiveness = () => __async(void 0, null, function* () {
    if (!hasGottenEffs) {
      miceEffs = yield getData("effs");
      hasGottenEffs = true;
    }
    const response = yield doRequest("managers/ajax/users/getmiceeffectiveness.php");
    return response == null ? void 0 : response.effectiveness;
  });
  var getMouse = (mouseId) => __async(void 0, null, function* () {
    if (!miceEffs || !hasGottenEffs) {
      miceEffs = yield getData("effs");
      hasGottenEffs = true;
    }
    const mouse = miceEffs.find((m) => m.type === mouseId);
    return mouse;
  });
  var getMousePower = (mouseId) => __async(void 0, null, function* () {
    var _a;
    const mouse = yield getMouse(mouseId);
    return (_a = mouse == null ? void 0 : mouse.effectivenesses) == null ? void 0 : _a.power;
  });
  var getMouseEffectiveness = (mouseId) => __async(void 0, null, function* () {
    const mouse = yield getMouse(mouseId);
    return mouse.effectivenesses[user.trap_power_type_name.toLowerCase()];
  });
  var getMinluck = (mousePower, effectiveness) => __async(void 0, null, function* () {
    if (effectiveness === 0) {
      return "\u221E";
    }
    const minluck = Math.ceil(
      Math.ceil(Math.sqrt(mousePower / 2)) / Math.min(effectiveness / 100, 1.4)
    );
    const checkCatchRate = getCatchRate(mousePower, effectiveness, 0, minluck);
    return checkCatchRate.rate === 1 ? minluck : minluck + 1;
  });
  var getPercent = (rate) => {
    if (rate === 1) {
      return "100%";
    }
    const percent = (rate * 100).toFixed(2);
    return `${percent}%`;
  };
  var getCatchRate = (mousePower, effectiveness, power = null, luck = null) => {
    effectiveness = effectiveness / 100;
    if (null === power) {
      power = user.trap_power;
    }
    if (null === luck) {
      luck = user.trap_luck;
    }
    const rate = Math.min(
      1,
      (effectiveness * power + 2 * Math.pow(Math.floor(Math.min(effectiveness, 1.4) * luck), 2)) / (effectiveness * power + mousePower)
    );
    return {
      rate,
      percent: getPercent(rate)
    };
  };

  // src/modules/catch-rate-estimate/styles.css
  var styles_default = '#mh-improved-cre{padding-right:5px;margin:5px 0;cursor:default}#mh-improved-cre table{width:100%}#mh-improved-cre thead{box-shadow:0 -1px #d3cecb inset}.mh-dark-mode #mh-improved-cre thead{box-shadow:0 -1px #5c5c5c inset}#mh-improved-cre table th{font-weight:700;text-align:center}#mh-improved-cre table th.name,#mh-improved-cre table:first-child{text-align:left}.mh-improved-cre-data{min-width:70px;text-align:center}.mh-improved-cre-data-good{color:#138f13}.mh-dark-mode .mh-improved-cre-data-good{color:#4fe54f}.mh-improved-cre-data-bad{color:#bb4646}.mh-dark-mode .mh-improved-cre-data-bad{color:#fb9b9b}.mh-improved-cre-name{padding-left:5px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mh-improved-cre-name a{color:inherit}#mh-improved-cre.cre-loading{display:flex;align-items:flex-end;justify-content:center;height:100%;min-height:50px;padding:20px 0;background-image:url(https://www.mousehuntgame.com/images/ui/loaders/drip_spinner.gif?asset_cache_version=2);background-repeat:no-repeat;background-position:center 10px;background-size:55px}#mh-improved-cre.cre-loading:after{position:absolute;right:0;bottom:-5px;left:0;font-weight:400;color:#926944;text-align:center;content:"Loading Catch Rate Estimator\\2026"}\n';

  // src/modules/catch-rate-estimate/index.js
  var updateMinLucks = () => __async(void 0, null, function* () {
    if ("camp" !== getCurrentPage()) {
      return;
    }
    let minluckList = document.querySelector("#mh-improved-cre");
    if (!minluckList) {
      minluckList = makeElement("div", ["campPage-trap-trapEffectiveness", "cre-loading"]);
      minluckList.id = "mh-improved-cre";
      const statsContainer = document.querySelector(".trapSelectorView__trapStatSummaryContainer");
      if (!statsContainer) {
        return;
      }
      statsContainer.append(minluckList);
    }
    const effectiveness = yield getMiceEffectiveness();
    if (!effectiveness) {
      return;
    }
    const miceIds = Object.values(effectiveness).flatMap(({ mice }) => mice).map((mouse) => {
      return {
        name: mouse.name,
        type: mouse.type
      };
    });
    renderList(miceIds);
  });
  var renderList = (list) => __async(void 0, null, function* () {
    let minluckList = document.querySelector("#mh-improved-cre");
    if (!minluckList) {
      minluckList = makeElement("div", "campPage-trap-trapEffectiveness");
      minluckList.id = "mh-improved-cre";
      const statsContainer = document.querySelector(".trapSelectorView__trapStatSummaryContainer");
      if (!statsContainer) {
        return;
      }
      statsContainer.append(minluckList);
      doEvent2("mh-improved-cre-list-rendered");
    }
    const existing = document.querySelector("#mh-improved-cre-table");
    if (existing) {
      existing.remove();
    }
    minluckList.classList.remove("cre-loading");
    const table = makeElement("table");
    table.id = "mh-improved-cre-table";
    const tableheader = makeElement("thead");
    makeElement("th", "name", "Mouse", tableheader);
    makeElement("th", "", "Minluck", tableheader);
    makeElement("th", "", "Catch Rate", tableheader);
    table.append(tableheader);
    const rows = [];
    for (const mouse of list) {
      const mousePower = yield getMousePower(mouse.type);
      const mouseEffectiveness = yield getMouseEffectiveness(mouse.type);
      const minluck = yield getMinluck(mousePower, mouseEffectiveness);
      const catchRate = yield getCatchRate(mousePower, mouseEffectiveness);
      const crClass = ["mh-improved-cre-data"];
      if (catchRate.rate * 100 >= 100) {
        crClass.push("mh-improved-cre-data-good");
      } else if (catchRate.rate * 100 <= 60) {
        crClass.push("mh-improved-cre-data-bad");
      }
      if (user.trap_luck >= minluck) {
        crClass.push("mh-improved-cre-data-minlucked");
      }
      rows.push({
        mouse: mouse.name,
        type: mouse.type,
        minluck,
        catchRateValue: catchRate.rate,
        catchRate: catchRate.percent,
        crClass
      });
    }
    rows.sort((a, b) => {
      if (a.catchRateValue !== b.catchRateValue) {
        return a.catchRateValue - b.catchRateValue;
      }
      return b.minluck - a.minluck;
    });
    rows.forEach(({ mouse, type, minluck, catchRate, crClass }) => {
      const row = makeElement("tr", "mh-improved-cre-row");
      const name = makeElement("td", "mh-improved-cre-name");
      const nameLink = makeElement("a", "", mouse);
      nameLink.addEventListener("click", (e) => {
        e.preventDefault();
        hg.views.MouseView.show(type);
      });
      name.append(nameLink);
      row.append(name);
      makeElement("td", crClass, minluck, row);
      makeElement("td", crClass, catchRate, row);
      table.append(row);
    });
    minluckList.append(table);
  });
  var main = () => __async(void 0, null, function* () {
    if ("camp" === getCurrentPage()) {
      yield updateMinLucks();
    }
    onPageChange({ camp: { show: updateMinLucks } });
    onRequest("*", updateMinLucks);
    onTravel(null, { callback: updateMinLucks });
  });
  var init = () => __async(void 0, null, function* () {
    addStyles(styles_default, "catch-rate-estimate");
    main();
  });
  var catch_rate_estimate_default = {
    id: "catch-rate-estimate",
    name: "Catch Rate Estimator & Minlucks",
    type: "feature",
    default: true,
    description: "Minluck and catch rate estimates.",
    order: 200,
    load: init
  };
  return __toCommonJS(catch_rate_estimate_exports);
})();
mhui.default.load();
migrateUserscript('Minluck & Catch Rate Estimate', '2.0.1', 'https://greasyfork.org/en/scripts/449334-mousehunt-minluck-catch-rate-estimate');