🐭️ MouseHunt - Better Travel / Travel Tweaks

Makes the travel page better.

  1. // ==UserScript==
  2. // @name 🐭️ MouseHunt - Better Travel / Travel Tweaks
  3. // @description Makes the travel page better.
  4. // @version 3.1.0
  5. // @license MIT
  6. // @author bradp
  7. // @namespace bradp
  8. // @match https://www.mousehuntgame.com/*
  9. // @icon https://i.mouse.rip/mh-improved/icon-64.png
  10. // @run-at document-end
  11. // @grant none
  12. // @require https://cdn.jsdelivr.net/npm/script-migration@1.1.1
  13. // ==/UserScript==
  14.  
  15. var mhui = (() => {
  16. var __defProp = Object.defineProperty;
  17. var __defProps = Object.defineProperties;
  18. var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
  19. var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
  20. var __getOwnPropNames = Object.getOwnPropertyNames;
  21. var __getOwnPropSymbols = Object.getOwnPropertySymbols;
  22. var __hasOwnProp = Object.prototype.hasOwnProperty;
  23. var __propIsEnum = Object.prototype.propertyIsEnumerable;
  24. var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
  25. var __spreadValues = (a, b) => {
  26. for (var prop in b || (b = {}))
  27. if (__hasOwnProp.call(b, prop))
  28. __defNormalProp(a, prop, b[prop]);
  29. if (__getOwnPropSymbols)
  30. for (var prop of __getOwnPropSymbols(b)) {
  31. if (__propIsEnum.call(b, prop))
  32. __defNormalProp(a, prop, b[prop]);
  33. }
  34. return a;
  35. };
  36. var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
  37. var __export = (target, all) => {
  38. for (var name in all)
  39. __defProp(target, name, { get: all[name], enumerable: true });
  40. };
  41. var __copyProps = (to, from, except, desc) => {
  42. if (from && typeof from === "object" || typeof from === "function") {
  43. for (let key of __getOwnPropNames(from))
  44. if (!__hasOwnProp.call(to, key) && key !== except)
  45. __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  46. }
  47. return to;
  48. };
  49. var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
  50. var __async = (__this, __arguments, generator) => {
  51. return new Promise((resolve, reject) => {
  52. var fulfilled = (value) => {
  53. try {
  54. step(generator.next(value));
  55. } catch (e) {
  56. reject(e);
  57. }
  58. };
  59. var rejected = (value) => {
  60. try {
  61. step(generator.throw(value));
  62. } catch (e) {
  63. reject(e);
  64. }
  65. };
  66. var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
  67. step((generator = generator.apply(__this, __arguments)).next());
  68. });
  69. };
  70.  
  71. // src/modules/better-travel/index.js
  72. var better_travel_exports = {};
  73. __export(better_travel_exports, {
  74. default: () => better_travel_default
  75. });
  76.  
  77. // src/utils/event-registry.js
  78. var eventsAdded = {};
  79. var onEvent = (event, callback, remove = false) => {
  80. if (!eventRegistry) {
  81. return;
  82. }
  83. const id = `${event}-${remove.toString()}-${callback.toString()}`;
  84. if (eventsAdded[id]) {
  85. return;
  86. }
  87. eventsAdded[id] = true;
  88. eventRegistry.addEventListener(event, callback, null, remove);
  89. };
  90.  
  91. // src/utils/styles.js
  92. var addStylesDirect = (styles, identifier = "mh-utils-custom-styles", once = false) => {
  93. identifier = `mh-utils-${identifier}`;
  94. const existingStyles = document.querySelector(`#${identifier}`);
  95. if (existingStyles) {
  96. if (once) {
  97. return existingStyles;
  98. }
  99. existingStyles.innerHTML += styles;
  100. return existingStyles;
  101. }
  102. const style = document.createElement("style");
  103. style.id = identifier;
  104. style.innerHTML = styles;
  105. document.head.append(style);
  106. return style;
  107. };
  108. var addModuleStyles = (styles, identifier = "mh-improved-styles", replace = false) => {
  109. const existingStyles = document.querySelector(`#${identifier}`);
  110. styles = Array.isArray(styles) ? styles.join("\n") : styles;
  111. if (existingStyles) {
  112. if (replace) {
  113. existingStyles.innerHTML = styles;
  114. } else {
  115. existingStyles.innerHTML += styles;
  116. }
  117. return existingStyles;
  118. }
  119. const style = document.createElement("style");
  120. style.id = identifier;
  121. style.innerHTML = styles;
  122. document.head.append(style);
  123. return style;
  124. };
  125. var addStyles = (styles, module = false, identifier = "mh-improved-styles") => {
  126. if (!module) {
  127. throw new Error("Module ID is required for adding module styles.", module);
  128. }
  129. const key = `${identifier}-${module}`;
  130. let stylesEl = addModuleStyles(styles, key, true);
  131. onEvent(`mh-improved-settings-changed-${module}`, (enabled) => {
  132. if (enabled) {
  133. stylesEl = addModuleStyles(styles, key, true);
  134. } else if (stylesEl) {
  135. stylesEl.remove();
  136. }
  137. });
  138. };
  139.  
  140. // src/utils/settings.js
  141. var getSettingDirect = (key = null, defaultValue = null, identifier = "mousehunt-improved-settings") => {
  142. const settings = JSON.parse(localStorage.getItem(identifier)) || {};
  143. if (!key) {
  144. return settings;
  145. }
  146. if (!key.includes(".")) {
  147. if (settings[key] === void 0) {
  148. return defaultValue;
  149. }
  150. return settings[key];
  151. }
  152. const groupAndKey = getGroupAndKey(key);
  153. if (!groupAndKey.group) {
  154. if (settings[groupAndKey.key] === void 0) {
  155. return defaultValue;
  156. }
  157. return settings[groupAndKey.key];
  158. }
  159. const groupSettings = settings[groupAndKey.group] || {};
  160. if (groupSettings[groupAndKey.key] === void 0) {
  161. return defaultValue;
  162. }
  163. return groupSettings[groupAndKey.key];
  164. };
  165. var saveSettingDirect = (key, value, identifier = "mousehunt-improved-settings") => {
  166. const settings = getSettingDirect(null, {}, identifier);
  167. const groupAndKey = getGroupAndKey(key);
  168. if (groupAndKey.group) {
  169. if (!settings[groupAndKey.group]) {
  170. settings[groupAndKey.group] = {};
  171. }
  172. settings[groupAndKey.group][groupAndKey.key] = value;
  173. } else {
  174. settings[key] = value;
  175. }
  176. localStorage.setItem(identifier, JSON.stringify(settings));
  177. };
  178. var getGroupAndKey = (key) => {
  179. const split = key.split(".");
  180. if (split.length === 1) {
  181. return {
  182. group: null,
  183. key: split[0]
  184. };
  185. }
  186. if (split[0] === "location-huds-enabled") {
  187. return {
  188. group: "location-huds-enabled",
  189. key: split[1]
  190. };
  191. }
  192. return {
  193. group: `${split[0]}-settings`,
  194. key: split[1]
  195. };
  196. };
  197. var getSetting = (key, defaultValue = false) => {
  198. return getSettingDirect(key, defaultValue, "mousehunt-improved-settings");
  199. };
  200. var saveSetting = (key, value) => {
  201. saveSettingDirect(key, value, "mousehunt-improved-settings");
  202. return value;
  203. };
  204.  
  205. // src/utils/styles/favorite-button.css
  206. var favorite_button_default = ".custom-favorite-button{top:0;right:0;display:inline-block;width:35px;height:35px;vertical-align:middle;background:url(https://www.mousehuntgame.com/images/ui/camp/trap/star_empty.png?asset_cache_version=2) 50% 50% no-repeat;background-size:90%;border-radius:50%}.custom-favorite-button-small{width:20px;height:20px}.custom-favorite-button:hover{background-color:#fff;background-image:url(https://www.mousehuntgame.com/images/ui/camp/trap/star_favorite.png?asset_cache_version=2);outline:2px solid #ccc}.custom-favorite-button.active{background-image:url(https://www.mousehuntgame.com/images/ui/camp/trap/star_favorite.png?asset_cache_version=2)}.custom-favorite-button.busy{background-image:url(https://www.mousehuntgame.com/images/ui/loaders/small_spinner.gif?asset_cache_version=2)}\n";
  207.  
  208. // src/utils/elements.js
  209. var makeElement = (tag, classes = "", text = "", appendTo = null) => {
  210. const element = document.createElement(tag);
  211. if (Array.isArray(classes)) {
  212. classes = classes.join(" ");
  213. }
  214. if (classes && classes.length) {
  215. element.className = classes;
  216. }
  217. element.innerHTML = text;
  218. if (appendTo) {
  219. appendTo.append(element);
  220. return appendTo;
  221. }
  222. return element;
  223. };
  224. var makeFavoriteButton = (options) => __async(void 0, null, function* () {
  225. addStylesDirect(favorite_button_default, "mh-improved-styles-favorite-button", true);
  226. const {
  227. id = null,
  228. target = null,
  229. size = "small",
  230. state = false,
  231. isSetting = true,
  232. defaultState = false,
  233. onChange = null,
  234. onActivate = null,
  235. onDeactivate = null
  236. } = options;
  237. const existing = document.querySelector(`#${id}`);
  238. if (existing) {
  239. existing.remove();
  240. }
  241. const star = document.createElement("a");
  242. star.classList.add("custom-favorite-button");
  243. if (size === "small") {
  244. star.classList.add("custom-favorite-button-small");
  245. }
  246. star.id = id;
  247. star.setAttribute("data-item-id", id);
  248. star.setAttribute("href", "#");
  249. star.style.display = "inline-block";
  250. let currentSetting = false;
  251. currentSetting = isSetting ? getSetting(id, defaultState) : state;
  252. if (currentSetting) {
  253. star.classList.add("active");
  254. } else {
  255. star.classList.add("inactive");
  256. }
  257. star.addEventListener("click", (e) => __async(void 0, null, function* () {
  258. star.classList.add("busy");
  259. e.preventDefault();
  260. e.stopPropagation();
  261. const currentStar = e.target;
  262. const currentState = !currentStar.classList.contains("active");
  263. if (onChange !== null) {
  264. yield onChange(currentState);
  265. } else if (isSetting) {
  266. saveSetting(id, currentState);
  267. }
  268. currentStar.classList.remove("inactive");
  269. currentStar.classList.remove("active");
  270. if (currentState) {
  271. currentStar.classList.add("active");
  272. if (onActivate !== null) {
  273. yield onActivate(currentState);
  274. }
  275. } else {
  276. currentStar.classList.add("inactive");
  277. if (onDeactivate !== null) {
  278. yield onDeactivate(currentState);
  279. }
  280. }
  281. setTimeout(() => {
  282. currentStar.classList.remove("busy");
  283. }, 300);
  284. }));
  285. if (target) {
  286. target.append(star);
  287. }
  288. return star;
  289. });
  290. var createPopup = (options) => {
  291. if ("undefined" === typeof jsDialog || !jsDialog) {
  292. return false;
  293. }
  294. const settings = Object.assign({}, {
  295. title: "",
  296. content: "",
  297. hasCloseButton: true,
  298. template: "default",
  299. show: true,
  300. className: ""
  301. }, options);
  302. const popup = new jsDialog();
  303. popup.setIsModal(!settings.hasCloseButton);
  304. popup.setTemplate(settings.template);
  305. popup.addToken("{*title*}", settings.title);
  306. popup.addToken("{*content*}", settings.content);
  307. popup.setAttributes({
  308. className: settings.className
  309. });
  310. if (settings.show) {
  311. popup.show();
  312. }
  313. return popup;
  314. };
  315.  
  316. // src/utils/db.js
  317. var database = (databaseName) => __async(void 0, null, function* () {
  318. return new Promise((resolve, reject) => {
  319. const request = indexedDB.open(`mh-improved-${databaseName}`, 6);
  320. request.onerror = (event) => {
  321. reject(event.target.error);
  322. };
  323. request.onsuccess = (event) => {
  324. resolve(event.target.result);
  325. };
  326. request.onupgradeneeded = (event) => {
  327. const db = event.target.result;
  328. if (!db.objectStoreNames.contains(databaseName)) {
  329. db.createObjectStore(databaseName, { keyPath: "id" });
  330. }
  331. };
  332. });
  333. });
  334. var dbGet = (databaseName, id) => __async(void 0, null, function* () {
  335. const db = yield database(databaseName);
  336. const transaction = db.transaction(databaseName, "readonly");
  337. transaction.onerror = (event) => {
  338. throw new Error(event.target.error);
  339. };
  340. const objectStore = transaction.objectStore(databaseName);
  341. const request = objectStore.get(id);
  342. return new Promise((resolve, reject) => {
  343. request.onsuccess = () => {
  344. resolve(request.result);
  345. };
  346. request.onerror = () => {
  347. reject(request.error);
  348. };
  349. transaction.oncomplete = () => {
  350. db.close();
  351. };
  352. });
  353. });
  354. var dbSet = (databaseName, data) => __async(void 0, null, function* () {
  355. const db = yield database(databaseName);
  356. const transaction = db.transaction(databaseName, "readwrite");
  357. const objectStore = transaction.objectStore(databaseName);
  358. data = {
  359. data,
  360. id: data.id || Date.now()
  361. };
  362. const request = objectStore.put(data);
  363. return new Promise((resolve, reject) => {
  364. request.onsuccess = () => {
  365. resolve(request.result);
  366. };
  367. request.onerror = () => {
  368. reject(request.error);
  369. };
  370. transaction.oncomplete = () => {
  371. db.close();
  372. };
  373. });
  374. });
  375. var dbDelete = (databaseName, id) => __async(void 0, null, function* () {
  376. const db = yield database(databaseName);
  377. const transaction = db.transaction(databaseName, "readwrite");
  378. const objectStore = transaction.objectStore(databaseName);
  379. const request = objectStore.delete(id);
  380. return new Promise((resolve, reject) => {
  381. request.onsuccess = () => {
  382. resolve(request.result);
  383. };
  384. request.onerror = () => {
  385. reject(request.error);
  386. };
  387. transaction.oncomplete = () => {
  388. db.close();
  389. };
  390. });
  391. });
  392. var dbDeleteAll = (databaseName) => __async(void 0, null, function* () {
  393. const db = yield database(databaseName);
  394. const transaction = db.transaction(databaseName, "readwrite");
  395. const objectStore = transaction.objectStore(databaseName);
  396. const request = objectStore.clear();
  397. return new Promise((resolve, reject) => {
  398. request.onsuccess = () => {
  399. resolve(request.result);
  400. };
  401. request.onerror = () => {
  402. reject(request.error);
  403. };
  404. transaction.oncomplete = () => {
  405. db.close();
  406. };
  407. });
  408. });
  409.  
  410. // src/utils/global.js
  411. var getGlobal = (key) => {
  412. if (window && window.mhui) {
  413. return window.mhui[key] || false;
  414. }
  415. if ("undefined" !== typeof app && app && app.mhui) {
  416. return app.mhui[key] || false;
  417. }
  418. return false;
  419. };
  420.  
  421. // src/utils/debug.js
  422. var debug = (message, ...args) => {
  423. if (getSetting("debug.module", false) || getGlobal("mh-improved-updating") || getGlobal("mh-improved-debug")) {
  424. console.log(
  425. `%cMH Improved%c: ${message}`,
  426. "color: #90588c; font-weight: 900",
  427. "color: inherit; font-weight: inherit",
  428. ...args
  429. );
  430. }
  431. };
  432. var debuglog = (module, message, ...args) => {
  433. if (getSetting("debug.all", false) || getSetting(`debug.${module}`, false) || getGlobal("mh-improved-updating")) {
  434. console.log(
  435. `%cMH Improved %c${module}%c ${message}`,
  436. "color: #90588c; font-weight: 900",
  437. "color: #90588c; font-weight: 400",
  438. "color: inherit; font-weight: inherit",
  439. ...args
  440. );
  441. }
  442. };
  443.  
  444. // src/utils/data.js
  445. var validDataFiles = /* @__PURE__ */ new Set([
  446. "effs",
  447. "environments-events",
  448. "environments",
  449. "item-thumbnails",
  450. "items-tradable",
  451. "m400-locations",
  452. "marketplace-hidden-items",
  453. "mice-groups",
  454. "mice-regions",
  455. "mice-thumbnails",
  456. "minlucks",
  457. "relic-hunter-hints",
  458. "scoreboards",
  459. "ultimate-checkmark",
  460. "upscaled-images",
  461. "wisdom"
  462. ]);
  463. var isValidDataFile = (file) => {
  464. return validDataFiles.has(file);
  465. };
  466. var getCacheExpiration = (key = null) => __async(void 0, null, function* () {
  467. return yield cacheGet(`expiration-${key}`, false);
  468. });
  469. var setCacheExpiration = (key) => __async(void 0, null, function* () {
  470. debuglog("utils-data", `Setting cache expiration for ${key}`);
  471. cacheSet(`expiration-${key}`, Date.now() + (Math.floor(Math.random() * 7) + 7) * 24 * 60 * 60 * 1e3);
  472. });
  473. var isCacheExpired = (key) => __async(void 0, null, function* () {
  474. const expiration = yield getCacheExpiration(key);
  475. if (!expiration) {
  476. return true;
  477. }
  478. return expiration.date < Date.now();
  479. });
  480. var fetchData = (key, retries = 0) => __async(void 0, null, function* () {
  481. try {
  482. const data = yield fetch(`https://api.mouse.rip/${key}`, {
  483. method: "GET",
  484. headers: getHeaders()
  485. });
  486. return yield data.json();
  487. } catch (error) {
  488. console.error(`Error fetching data for ${key}:`, error);
  489. if (retries >= 3) {
  490. return false;
  491. }
  492. yield new Promise((resolve) => setTimeout(resolve, 500 * retries));
  493. return fetchData(key, retries + 1);
  494. }
  495. });
  496. var getData = (key) => __async(void 0, null, function* () {
  497. if (!isValidDataFile(key)) {
  498. debuglog("utils-data", `Cannot get data for ${key}, invalid key`);
  499. return false;
  500. }
  501. const isExpired = yield isCacheExpired(key);
  502. if (!isExpired) {
  503. const cachedData = yield dataCacheGet(key, false);
  504. if (cachedData) {
  505. return cachedData;
  506. }
  507. }
  508. debuglog("utils-data", `Fetching data for ${key}\u2026`);
  509. const data = yield fetchData(key);
  510. debuglog("utils-data", `Fetched data for ${key}`, data);
  511. if (data) {
  512. dataCacheSet(key, data);
  513. setCacheExpiration(key);
  514. }
  515. return data;
  516. });
  517. var clearCaches = () => __async(void 0, null, function* () {
  518. validDataFiles.forEach((file) => {
  519. dbDelete("data", file);
  520. });
  521. dbDeleteAll("ar-cache");
  522. for (const key of Object.keys(localStorage)) {
  523. if (key.startsWith("mh-improved-cache")) {
  524. localStorage.removeItem(key);
  525. }
  526. }
  527. for (const key of Object.keys(sessionStorage)) {
  528. if (key.startsWith("mh-improved")) {
  529. sessionStorage.removeItem(key);
  530. }
  531. }
  532. yield dbDelete("cache", "expirations");
  533. });
  534. var getHeaders = () => {
  535. return {
  536. "Content-Type": "application/json",
  537. "X-MH-Improved": "true",
  538. "X-MH-Improved-Version": mhImprovedVersion || "unknown",
  539. "X-MH-Improved-Platform": mhImprovedPlatform || "unknown"
  540. };
  541. };
  542. var sessionSet = (key, value, retry = false) => {
  543. if (getSetting("debug.no-cache")) {
  544. return;
  545. }
  546. key = `mh-improved-${key}`;
  547. const stringified = JSON.stringify(value);
  548. try {
  549. sessionStorage.setItem(key, stringified);
  550. } catch (error) {
  551. if ("QuotaExceededError" === error.name && !retry) {
  552. clearCaches();
  553. sessionSet(key, value, true);
  554. }
  555. }
  556. };
  557. var sessionGet = (key, defaultValue = false) => {
  558. if (getSetting("debug.no-cache")) {
  559. return defaultValue;
  560. }
  561. key = `mh-improved-${key}`;
  562. const value = sessionStorage.getItem(key);
  563. if (!value) {
  564. return defaultValue;
  565. }
  566. return JSON.parse(value);
  567. };
  568. var cacheSet = (key, value) => {
  569. dbSet("cache", { id: key, value });
  570. };
  571. var dataCacheSet = (key, value) => {
  572. dbSet("data", { id: key, value });
  573. };
  574. var cacheGetHelper = (key, defaultValue = false, db = "cache") => __async(void 0, null, function* () {
  575. var _a;
  576. const cached = yield dbGet(db, key);
  577. if (!((_a = cached == null ? void 0 : cached.data) == null ? void 0 : _a.value)) {
  578. return defaultValue;
  579. }
  580. return cached.data.value;
  581. });
  582. var cacheGet = (key, defaultValue = false) => __async(void 0, null, function* () {
  583. return yield cacheGetHelper(key, defaultValue, "cache");
  584. });
  585. var dataCacheGet = (key, defaultValue = false) => __async(void 0, null, function* () {
  586. return yield cacheGetHelper(key, defaultValue, "data");
  587. });
  588.  
  589. // src/utils/page.js
  590. var getCurrentPage = () => {
  591. var _a, _b, _c, _d;
  592. if (!((_b = (_a = hg == null ? void 0 : hg.utils) == null ? void 0 : _a.PageUtil) == null ? void 0 : _b.getCurrentPage)) {
  593. return null;
  594. }
  595. const page = hg.utils.PageUtil.getCurrentPage();
  596. if (!page) {
  597. const query = ((_d = (_c = hg == null ? void 0 : hg.utils) == null ? void 0 : _c.PageUtil) == null ? void 0 : _d.getQueryParams()) || {};
  598. if ((query == null ? void 0 : query.switch_to) && "mobile" === query.switch_to) {
  599. return "camp";
  600. }
  601. return null;
  602. }
  603. return page.toLowerCase();
  604. };
  605. var setPage = (page, ...args) => {
  606. var _a, _b;
  607. if ("wiki" === page.toLowerCase()) {
  608. doEvent("mh-improved-open-wiki");
  609. return;
  610. }
  611. page = page.charAt(0).toUpperCase() + page.slice(1);
  612. if ((_b = (_a = hg == null ? void 0 : hg.utils) == null ? void 0 : _a.PageUtil) == null ? void 0 : _b.setPage) {
  613. hg.utils.PageUtil.setPage(page, ...args);
  614. }
  615. };
  616. var setTab = (tab, ...args) => {
  617. var _a, _b;
  618. if ((_b = (_a = hg == null ? void 0 : hg.utils) == null ? void 0 : _a.PageUtil) == null ? void 0 : _b.setPageTab) {
  619. hg.utils.PageUtil.setPageTab(tab, ...args);
  620. }
  621. };
  622. var getCurrentTab = () => {
  623. var _a, _b;
  624. if (!((_b = (_a = hg == null ? void 0 : hg.utils) == null ? void 0 : _a.PageUtil) == null ? void 0 : _b.getCurrentPageTab)) {
  625. return getCurrentPage();
  626. }
  627. const tab = hg.utils.PageUtil.getCurrentPageTab() || "";
  628. if (tab.length <= 0) {
  629. return getCurrentPage();
  630. }
  631. return tab.toLowerCase();
  632. };
  633. var getCurrentSubtab = () => {
  634. const subtab = hg.utils.PageUtil.getCurrentPageSubTab();
  635. if (!subtab || subtab.length <= 0) {
  636. return getCurrentTab();
  637. }
  638. return subtab.toLowerCase();
  639. };
  640. var isCurrentPage = (targetPage = null, targetTab = null, targetSubtab = null, forceCurrentPage = null, forceCurrentTab = null, forceCurrentSubtab = null) => {
  641. if (!targetPage) {
  642. return false;
  643. }
  644. const currentPage = forceCurrentPage || getCurrentPage();
  645. if (!targetTab) {
  646. return currentPage === targetPage;
  647. }
  648. const currentTab = forceCurrentTab || getCurrentTab();
  649. if (!targetSubtab) {
  650. return currentPage === targetPage && currentTab === targetTab;
  651. }
  652. const currentSubtab = forceCurrentSubtab || getCurrentSubtab();
  653. if (currentSubtab === currentTab) {
  654. return currentPage === targetPage && currentTab === targetTab;
  655. }
  656. return currentPage === targetPage && currentTab === targetTab && currentSubtab === targetSubtab;
  657. };
  658.  
  659. // src/utils/location.js
  660. var getCurrentLocation = () => {
  661. const location = (user == null ? void 0 : user.environment_type) || "";
  662. return location.toLowerCase();
  663. };
  664. var getRelicHunterLocation = () => {
  665. const cacheExpiry = 5 * 60 * 1e3;
  666. const cacheKey = "mh-improved-relic-hunter-location";
  667. let cached = sessionGet(cacheKey);
  668. if (cached) {
  669. cached = JSON.parse(cached);
  670. }
  671. if (cached && cached.expiry > Date.now()) {
  672. return cached.data;
  673. }
  674. return fetch("https://rh-api.mouse.rip/", { headers: getHeaders() }).then((response) => response.json()).then((data) => {
  675. const expiry = Date.now() + cacheExpiry;
  676. sessionSet(cacheKey, JSON.stringify({ expiry, data }));
  677. return data;
  678. }).catch((error) => {
  679. console.error(error);
  680. });
  681. };
  682.  
  683. // src/utils/horn.js
  684. var showHornMessage = (options) => {
  685. const huntersHornView = document.querySelector(".huntersHornView__messageContainer");
  686. if (!huntersHornView) {
  687. return;
  688. }
  689. const settings = {
  690. title: options.title || "Hunters Horn",
  691. text: options.text || "This is a message from the Hunters Horn",
  692. button: options.button || "OK",
  693. action: options.action || (() => {
  694. }),
  695. dismiss: options.dismiss || null,
  696. type: options.type || "recent_linked_turn",
  697. classname: options.classname || "",
  698. image: options.image || null,
  699. imageLink: options.imageLink || null,
  700. imageCallback: options.imageCallback || null
  701. };
  702. const backdrop = document.querySelector(".huntersHornView__backdrop");
  703. if (backdrop) {
  704. backdrop.classList.add("huntersHornView__backdrop--active");
  705. }
  706. const gameInfo = document.querySelector(".mousehuntHud-gameInfo");
  707. if (gameInfo) {
  708. gameInfo.classList.add("blur");
  709. }
  710. const messageWrapper = makeElement("div", ["huntersHornView__message huntersHornView__message--active", settings.classname]);
  711. const message = makeElement("div", ["huntersHornMessageView", `huntersHornMessageView--${settings.type}`]);
  712. makeElement("div", "huntersHornMessageView__title", settings.title, message);
  713. const content = makeElement("div", "huntersHornMessageView__content");
  714. if (settings.image) {
  715. const imgWrapper = makeElement("div", "huntersHornMessageView__friend");
  716. const img = makeElement("a", "huntersHornMessageView__friendProfilePic");
  717. if (settings.imageLink) {
  718. img.href = settings.imageLink;
  719. } else if (settings.imageCallback) {
  720. img.addEventListener("click", settings.imageCallback);
  721. } else {
  722. img.href = "#";
  723. }
  724. img.style.backgroundImage = `url(${settings.image})`;
  725. imgWrapper.append(img);
  726. content.append(imgWrapper);
  727. }
  728. makeElement("div", "huntersHornMessageView__text", settings.text, content);
  729. const buttonSpacer = makeElement("div", "huntersHornMessageView__buttonSpacer");
  730. const button = makeElement("button", "huntersHornMessageView__action");
  731. const buttonLabel = makeElement("div", "huntersHornMessageView__actionLabel");
  732. makeElement("span", "huntersHornMessageView__actionText", settings.button, buttonLabel);
  733. button.append(buttonLabel);
  734. button.addEventListener("click", () => {
  735. if (settings.action) {
  736. settings.action();
  737. }
  738. messageWrapper.innerHTML = "";
  739. backdrop.classList.remove("huntersHornView__backdrop--active");
  740. gameInfo.classList.remove("blur");
  741. });
  742. buttonSpacer.append(button);
  743. content.append(buttonSpacer);
  744. message.append(content);
  745. if (settings.dismiss) {
  746. const countdown = makeElement("button", ["huntersHornMessageView__countdown"]);
  747. makeElement("div", "huntersHornMessageView__countdownButtonImage", "", countdown);
  748. const svgMarkup = `<svg class="huntersHornMessageView__countdownSVG">
  749. <circle r="46%" cx="50%" cy="50%" class="huntersHornMessageView__countdownCircleTrack"></circle>
  750. <circle r="46%" cx="50%" cy="50%" class="huntersHornMessageView__countdownCircle" style="animation-duration: ${settings.dismiss}ms;"></circle>
  751. </svg>`;
  752. countdown.innerHTML += svgMarkup;
  753. countdown.addEventListener("click", () => {
  754. countdown.classList.add("huntersHornMessageView__countdown--complete");
  755. messageWrapper.innerHTML = "";
  756. backdrop.classList.remove("huntersHornView__backdrop--active");
  757. gameInfo.classList.remove("blur");
  758. });
  759. message.append(countdown);
  760. }
  761. messageWrapper.append(message);
  762. const existingMessages = huntersHornView.querySelector(".huntersHornView__message");
  763. if (existingMessages) {
  764. existingMessages.remove();
  765. }
  766. huntersHornView.append(messageWrapper);
  767. if (settings.dismiss) {
  768. setTimeout(() => {
  769. const countdown = messageWrapper.querySelector(".huntersHornMessageView__countdown");
  770. if (countdown) {
  771. countdown.classList.add("huntersHornMessageView__countdown--complete");
  772. }
  773. messageWrapper.innerHTML = "";
  774. backdrop.classList.remove("huntersHornView__backdrop--active");
  775. gameInfo.classList.remove("blur");
  776. }, settings.dismiss);
  777. }
  778. };
  779.  
  780. // src/utils/events.js
  781. var getDialogMapping = () => {
  782. return {
  783. treasureMapPopup: "map",
  784. itemViewPopup: "item",
  785. mouseViewPopup: "mouse",
  786. largerImage: "image",
  787. convertibleOpenViewPopup: "convertible",
  788. adventureBookPopup: "adventureBook",
  789. marketplaceViewPopup: "marketplace",
  790. giftSelectorViewPopup: "gifts",
  791. supportPageContactUsForm: "support",
  792. MHCheckout: "premiumShop"
  793. };
  794. };
  795. var onDialogHide = (callback, overlay = null, once = false) => {
  796. eventRegistry.addEventListener("js_dialog_hide", () => {
  797. var _a, _b;
  798. const dialogType = ((_b = (_a = window == null ? void 0 : window.mhutils) == null ? void 0 : _a.lastDialog) == null ? void 0 : _b.overlay) || null;
  799. window.mhutils = window.mhutils ? __spreadProps(__spreadValues({}, window.mhutils), { lastDialog: null }) : null;
  800. if (!overlay) {
  801. return callback();
  802. }
  803. const dialogMapping = getDialogMapping();
  804. if (overlay === dialogType || overlay === dialogMapping[dialogType]) {
  805. return callback();
  806. }
  807. }, null, once);
  808. };
  809. var callbacks = [];
  810. var hasAddedNavigationListener = false;
  811. var onNavigation = (callback, options = {}) => {
  812. const defaults = {
  813. page: false,
  814. tab: false,
  815. subtab: false,
  816. onLoad: true,
  817. anyTab: false,
  818. anySubtab: false
  819. };
  820. const { page, tab, subtab, onLoad, anyTab, anySubtab } = Object.assign(defaults, options);
  821. const bypassMatch = !page;
  822. if (onLoad && (bypassMatch || isCurrentPage(
  823. page,
  824. anyTab ? getCurrentTab() : tab,
  825. anySubtab ? getCurrentSubtab() : subtab
  826. ))) {
  827. callback();
  828. }
  829. callbacks.push({ callback, page, tab, subtab, bypassMatch });
  830. if (!hasAddedNavigationListener) {
  831. addNavigationListeners();
  832. hasAddedNavigationListener = true;
  833. }
  834. };
  835. var addNavigationListeners = () => {
  836. eventRegistry.addEventListener("set_page", (e) => {
  837. var _a;
  838. const tabs = ((_a = e == null ? void 0 : e.data) == null ? void 0 : _a.tabs) || {};
  839. const currentTab = Object.keys(tabs).find((key) => tabs[key].is_active_tab);
  840. const forceCurrentTab = currentTab == null ? void 0 : currentTab.type;
  841. callbacks.forEach(({ callback, page, tab, subtab, bypassMatch }) => {
  842. if (bypassMatch) {
  843. callback();
  844. return;
  845. }
  846. if (!subtab) {
  847. if (isCurrentPage(page, tab, false, getCurrentPage(), forceCurrentTab)) {
  848. callback();
  849. }
  850. return;
  851. }
  852. if ((currentTab == null ? void 0 : currentTab.subtabs) && (currentTab == null ? void 0 : currentTab.subtabs.length) > 0) {
  853. const forceSubtab = currentTab.subtabs.find((searchTab) => searchTab.is_active_subtab).subtab_type;
  854. if (isCurrentPage(page, tab, subtab, getCurrentPage(), forceCurrentTab, forceSubtab)) {
  855. callback();
  856. }
  857. }
  858. });
  859. });
  860. eventRegistry.addEventListener("set_tab", (e) => {
  861. callbacks.forEach(({ callback, page, tab, subtab, bypassMatch }) => {
  862. if (bypassMatch) {
  863. callback();
  864. return;
  865. }
  866. if (isCurrentPage(page, tab, subtab, getCurrentPage(), e.page_arguments.tab, e.page_arguments.sub_tab)) {
  867. callback();
  868. }
  869. });
  870. });
  871. };
  872.  
  873. // src/utils/flags.js
  874. var getFlag = (flag) => {
  875. return getSetting(`experiments.${flag}`, getFlags().includes(flag));
  876. };
  877. var getFlags = () => {
  878. return getSetting("override-flags", "").toLowerCase().replaceAll(" ", "").split(",");
  879. };
  880.  
  881. // src/utils/links.js
  882. var getCleanSubmenuLabel = (label) => {
  883. return label.toLowerCase().replaceAll(/[^\da-z]/g, "-");
  884. };
  885. var addSubmenuItem = (options) => {
  886. const settings = Object.assign({}, {
  887. id: null,
  888. menu: "kingdom",
  889. label: "",
  890. icon: "https://www.mousehuntgame.com/images/ui/hud/menu/special.png",
  891. href: "",
  892. class: "",
  893. callback: null,
  894. external: false
  895. }, options);
  896. const menuTarget = document.querySelector(`.mousehuntHud-menu .${settings.menu}`);
  897. if (!menuTarget) {
  898. return;
  899. }
  900. if (!menuTarget.classList.contains("hasChildren")) {
  901. menuTarget.classList.add("hasChildren");
  902. }
  903. let hasSubmenu = true;
  904. let submenu = menuTarget.querySelector("ul");
  905. if (!submenu) {
  906. hasSubmenu = false;
  907. submenu = document.createElement("ul");
  908. }
  909. const item = document.createElement("li");
  910. item.classList.add("custom-submenu-item");
  911. const label = settings.label.length > 0 ? settings.label : settings.id;
  912. const cleanLabel = getCleanSubmenuLabel(label);
  913. const exists = document.querySelector(`#custom-submenu-item-${cleanLabel}`);
  914. if (exists) {
  915. exists.remove();
  916. }
  917. item.id = settings.id ? `custom-submenu-item-${settings.id}` : `custom-submenu-item-${cleanLabel}`;
  918. if (settings.class) {
  919. const classes = settings.class.split(" ");
  920. item.classList.add(...classes);
  921. }
  922. const link = document.createElement("a");
  923. link.href = settings.href || "#";
  924. if (settings.callback) {
  925. link.addEventListener("click", (e) => {
  926. e.preventDefault();
  927. settings.callback();
  928. });
  929. }
  930. const icon = document.createElement("div");
  931. icon.classList.add("icon");
  932. icon.style = `background-image: url(${settings.icon});`;
  933. const name = document.createElement("div");
  934. name.classList.add("name");
  935. name.innerHTML = settings.label;
  936. link.append(icon);
  937. link.append(name);
  938. if (settings.external) {
  939. const externalLinkIcon = document.createElement("div");
  940. externalLinkIcon.classList.add("external_icon");
  941. link.append(externalLinkIcon);
  942. link.target = "_blank";
  943. link.rel = "noopener noreferrer";
  944. }
  945. item.append(link);
  946. submenu.append(item);
  947. if (!hasSubmenu) {
  948. menuTarget.append(submenu);
  949. }
  950. };
  951. var removeSubmenuItem = (id) => {
  952. id = getCleanSubmenuLabel(id);
  953. const item = document.querySelector(`#custom-submenu-item-${id}`);
  954. if (item) {
  955. item.remove();
  956. }
  957. };
  958. var addSubmenuDivider = (menu, className = "") => {
  959. addSubmenuItem({
  960. menu,
  961. id: `mh-improved-submenu-divider-${className}`,
  962. label: "",
  963. icon: "",
  964. href: "",
  965. class: `mh-improved-submenu-divider ${className}`
  966. });
  967. };
  968.  
  969. // src/utils/messages.js
  970. hadAddedErrorStyles = false;
  971.  
  972. // src/utils/user.js
  973. var normalizeTitle = (title = "") => {
  974. if (!title) {
  975. return "";
  976. }
  977. const normalizedTitle = title.toLowerCase().replaceAll(" ", "").replaceAll("/", "_").replaceAll("journeyman_journeywoman", "journeyman").replaceAll("journeywoman", "journeyman").replaceAll("lord_lady", "lord").replaceAll("lady", "lord").replaceAll("baron_baroness", "baron").replaceAll("baroness", "baron").replaceAll("count_countess", "count").replaceAll("countess", "count").replaceAll("grand_duke_grand_duchess", "grand_duke").replaceAll("grand_duchess", "grand_duke").replaceAll("archduke_archduchess", "archduke").replaceAll("archduchess", "archduke").replaceAll("duke_duchess", "duke").replaceAll("duke_dutchess", "duke").replaceAll("duchess", "duke").replaceAll("grand_duke", "grandduke").replaceAll("/", "").replaceAll(" ", "").toLowerCase();
  978. return normalizedTitle;
  979. };
  980. var isUserTitleAtLeast = (title) => {
  981. const titles = [
  982. "novice",
  983. "recruit",
  984. "apprentice",
  985. "initiate",
  986. "journeyman",
  987. "master",
  988. "grandmaster",
  989. "legendary",
  990. "hero",
  991. "knight",
  992. "lord",
  993. "baron",
  994. "count",
  995. "duke",
  996. "grandduke",
  997. "archduke",
  998. "viceroy",
  999. "elder",
  1000. "sage",
  1001. "fable"
  1002. ];
  1003. const titleIndex = titles.indexOf(normalizeTitle(user.title_name));
  1004. const checkIndex = titles.indexOf(normalizeTitle(title));
  1005. return titleIndex >= checkIndex;
  1006. };
  1007.  
  1008. // src/modules/better-travel/travel-utils.js
  1009. var getTravelSetting = (settingName, defaultValue) => {
  1010. return getSetting(`better-travel.${settingName}`, defaultValue);
  1011. };
  1012. var saveTravelSetting = (settingName, value) => {
  1013. saveSetting(`better-travel.${settingName}`, value);
  1014. };
  1015. var travelTo = (location) => {
  1016. const header = document.querySelector(".mousehuntHeaderView");
  1017. if (header) {
  1018. const existing = header.querySelector(".mh-improved-travel-message");
  1019. if (existing) {
  1020. existing.remove();
  1021. }
  1022. makeElement("div", ["mh-improved-travel-message", "travelPage-map-message"], "Traveling...", header);
  1023. }
  1024. app.pages.TravelPage.travel(location);
  1025. };
  1026.  
  1027. // src/modules/better-travel/reminders.js
  1028. var addReminders = () => {
  1029. var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E;
  1030. const reminderOpts = {
  1031. title: "Travel Reminder",
  1032. dismiss: 4e3
  1033. };
  1034. switch (getCurrentLocation()) {
  1035. case "rift_valour":
  1036. if ((_b = (_a = user.quests) == null ? void 0 : _a.QuestRiftValour) == null ? void 0 : _b.is_fuel_enabled) {
  1037. reminderOpts.text = "Champion's Fire is active.";
  1038. reminderOpts.image = "https://www.mousehuntgame.com/images/items/stats/transparent_thumb/6622efd1db7028b30f48b15771138720.png?cv=2";
  1039. reminderOpts.button = "Deactivate";
  1040. reminderOpts.action = () => {
  1041. const button = document.querySelector(".valourRiftHUD-fuelContainer-armButton");
  1042. if (button) {
  1043. button.click();
  1044. }
  1045. };
  1046. }
  1047. break;
  1048. case "queso_river":
  1049. case "queso_plains":
  1050. case "queso_quarry":
  1051. case "queso_geyser":
  1052. if (((_d = (_c = user.quests) == null ? void 0 : _c.QuestQuesoCanyon) == null ? void 0 : _d.is_wild_tonic_active) || ((_f = (_e = user.quests) == null ? void 0 : _e.QuestQuesoGeyser) == null ? void 0 : _f.is_wild_tonic_enabled)) {
  1053. reminderOpts.text = "Wild Tonic is active.";
  1054. reminderOpts.image = "https://www.mousehuntgame.com/images/items/stats/transparent_thumb/b6b9f97a1ee3692fdff0b5a206adf7e1.png?cv=2";
  1055. reminderOpts.button = "Deactivate";
  1056. reminderOpts.action = () => {
  1057. const button = document.querySelector(".quesoHUD-wildTonic-button");
  1058. if (button) {
  1059. button.click();
  1060. }
  1061. };
  1062. }
  1063. break;
  1064. case "floating_islands":
  1065. if ("launch_pad_island" === ((_i = (_h = (_g = user.quests) == null ? void 0 : _g.QuestFloatingIslands) == null ? void 0 : _h.hunting_site_atts) == null ? void 0 : _i.island_power_type)) {
  1066. break;
  1067. }
  1068. if (!((_l = (_k = (_j = user.quests) == null ? void 0 : _j.QuestFloatingIslands) == null ? void 0 : _k.hunting_site_atts) == null ? void 0 : _l.is_fuel_enabled) && // BW not active.
  1069. !(((_o = (_n = (_m = user.quests) == null ? void 0 : _m.QuestFloatingIslands) == null ? void 0 : _n.hunting_site_atts) == null ? void 0 : _o.is_vault_island) && // is SP.
  1070. ((_s = (_r = (_q = (_p = user.quests) == null ? void 0 : _p.QuestFloatingIslands) == null ? void 0 : _q.hunting_site_atts) == null ? void 0 : _r.island_mod_panels[2]) == null ? void 0 : _s.is_complete))) {
  1071. reminderOpts.text = "Bottled Wind is <strong>not</strong> active.";
  1072. reminderOpts.image = "https://www.mousehuntgame.com/images/ui/hud/floating_islands/items/bottled_wind_stat_item.png?asset_cache_version=2";
  1073. reminderOpts.button = "Activate";
  1074. reminderOpts.action = () => {
  1075. const button = document.querySelector(".floatingIslandsHUD-fuel-button");
  1076. if (button) {
  1077. button.click();
  1078. }
  1079. };
  1080. }
  1081. break;
  1082. case "foreword_farm":
  1083. case "prologue_pond":
  1084. case "table_of_contents":
  1085. if (((_u = (_t = user.quests) == null ? void 0 : _t.QuestProloguePond) == null ? void 0 : _u.is_fuel_enabled) || ((_w = (_v = user.quests) == null ? void 0 : _v.QuestForewordFarm) == null ? void 0 : _w.is_fuel_enabled) || ((_y = (_x = user.quests) == null ? void 0 : _x.QuestTableOfContents) == null ? void 0 : _y.is_fuel_enabled)) {
  1086. reminderOpts.text = "Condensed Creativity is active.";
  1087. reminderOpts.button = "Deactivate";
  1088. } else {
  1089. reminderOpts.text = "Condensed Creativity is <strong>not</strong> active.";
  1090. reminderOpts.button = "Activate";
  1091. }
  1092. reminderOpts.image = "https://www.mousehuntgame.com/images/items/stats/transparent_thumb/4f5d55c1eff77474c7363f0e52d03e49.png?cv=2";
  1093. reminderOpts.action = hg.views.HeadsUpDisplayFolkloreForestRegionView.toggleFuel;
  1094. break;
  1095. case "winter_hunt_grove":
  1096. case "winter_hunt_workshop":
  1097. case "winter_hunt_fortress":
  1098. if (((_A = (_z = user.quests) == null ? void 0 : _z.QuestCinnamonTreeGrove) == null ? void 0 : _A.is_fuel_enabled) || ((_C = (_B = user.quests) == null ? void 0 : _B.QuestGolemWorkshop) == null ? void 0 : _C.is_fuel_enabled) || ((_E = (_D = user.quests) == null ? void 0 : _D.QuestIceFortress) == null ? void 0 : _E.is_fuel_enabled)) {
  1099. reminderOpts.text = "Festive Spirit is active.";
  1100. reminderOpts.button = "Deactivate";
  1101. } else if ("winter_hunt_forest" === getCurrentLocation()) {
  1102. reminderOpts.text = "Festive Spirit is <strong>not</strong> active.";
  1103. reminderOpts.button = "Activate";
  1104. }
  1105. reminderOpts.image = "https://www.mousehuntgame.com/images/items/stats/large/cda292833fce3b65b7a6a38c000e8620.png?cv=2";
  1106. reminderOpts.action = () => {
  1107. const toggle = document.querySelector(".headsUpDisplayWinterHuntRegionView__fuelButton");
  1108. if (toggle) {
  1109. toggle.click();
  1110. }
  1111. };
  1112. }
  1113. if (reminderOpts.text) {
  1114. showHornMessage(reminderOpts);
  1115. }
  1116. };
  1117. var reminders_default = addReminders;
  1118.  
  1119. // src/modules/better-travel/travel-menu.css
  1120. var travel_menu_default = ".mh-improved-travel-window.greatWinterHuntGolemDestinationView{padding:10px 0}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__content{align-items:flex-start;margin-right:5px;background-color:transparent}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__environmentsScroller{height:auto;min-height:425px;max-height:650px;padding:0 0 10px 5px;margin-right:-5px}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__regionEnvironments{gap:15px 6px;justify-content:space-evenly}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__regionsContainer{display:none}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__regionName{margin:10px 0;font-size:16px;text-align:center;border:none}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__environment{width:150px;overflow:hidden;border:1px solid #b4a481;box-shadow:0 2px 2px #7e7e7e}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__regionGroup{margin:0}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__environmentName{position:absolute;right:0;left:0;z-index:2;height:20px;background-color:#ffffffe5;border-radius:0;transition:all .2s ease-in-out}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__environmentName span{padding:5px;text-align:center}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__environmentImage{border-radius:0;transition:all .2s ease-in-out}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__environment:hover .greatWinterHuntGolemDestinationView__environmentImage,.mh-improved-travel-window .greatWinterHuntGolemDestinationView__environment:focus .greatWinterHuntGolemDestinationView__environmentImage{background-position-y:30%}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__environment:hover .greatWinterHuntGolemDestinationView__environmentName,.mh-improved-travel-window .greatWinterHuntGolemDestinationView__environment:focus .greatWinterHuntGolemDestinationView__environmentName{background-color:#fff}.mh-improved-travel-window .greatWinterHuntGolemDestinationView__environment[data-environment-type=train_station] .greatWinterHuntGolemDestinationView__environmentName span{font-size:10px}.mh-improved-travel-window-footer{position:absolute;bottom:20px;display:flex;gap:10px;align-items:center;width:330px}.mh-improved-travel-window-edit{padding:0 15px;font-weight:400;line-height:24px}.mh-improved-travel-window--editing{border-radius:5px;outline:3px solid #f37c7c}.mh-improved-travel-window-description,.mh-improved-travel-window-hidden{display:none}.mh-improved-travel-window--editing .mh-improved-travel-window-hidden{display:block;filter:grayscale(1);opacity:.4}.mh-improved-travel-window--editing .mh-improved-travel-window-description{display:inline-block}.mh-improved-travel-window-environment-icon{cursor:pointer}\n";
  1121.  
  1122. // src/modules/better-travel/travel-window.js
  1123. var getHiddenLocations = () => {
  1124. return getTravelSetting("travel-window-hidden-locations", []);
  1125. };
  1126. var toggleLocation = (location) => {
  1127. if (isLocationHidden(location)) {
  1128. unhideLocation(location);
  1129. } else {
  1130. hideLocation(location);
  1131. }
  1132. };
  1133. var hideLocation = (location) => {
  1134. const hiddenLocations = getHiddenLocations();
  1135. if (hiddenLocations.includes(location)) {
  1136. return;
  1137. }
  1138. hiddenLocations.push(location);
  1139. saveTravelSetting("travel-window-hidden-locations", hiddenLocations);
  1140. };
  1141. var unhideLocation = (location) => {
  1142. const hiddenLocations = getHiddenLocations();
  1143. if (!hiddenLocations.includes(location)) {
  1144. return;
  1145. }
  1146. hiddenLocations.splice(hiddenLocations.indexOf(location), 1);
  1147. saveTravelSetting("travel-window-hidden-locations", hiddenLocations);
  1148. };
  1149. var isLocationHidden = (location) => {
  1150. const hiddenLocations = getHiddenLocations();
  1151. return hiddenLocations.includes(location);
  1152. };
  1153. var openTravelWindow = () => __async(void 0, null, function* () {
  1154. debug("Opening travel window");
  1155. const regions = [
  1156. { type: "gnawnia", name: "Gnawnia" },
  1157. { type: "valour", name: "Valour" },
  1158. { type: "whisker_woods", name: "Whisker Woods" },
  1159. { type: "burroughs", name: "Burroughs" },
  1160. { type: "furoma", name: "Furoma" },
  1161. { type: "bristle_woods", name: "Bristle Woods" },
  1162. { type: "tribal_isles", name: "Tribal Isles" },
  1163. { type: "varmint_valley", name: "Varmint Valley" },
  1164. { type: "desert", name: "Sandtail Desert" },
  1165. { type: "rodentia", name: "Rodentia" },
  1166. { type: "queso_canyon", name: "Queso Canyon" },
  1167. { type: "zokor_zone", name: "Hollow Heights" },
  1168. { type: "folklore_forest", name: "Folklore Forest" },
  1169. { type: "riftopia", name: "Rift Plane" }
  1170. ];
  1171. environments = yield getData("environments");
  1172. const eventEnvironments = yield getData("environments-events");
  1173. environments = [...environments, ...eventEnvironments];
  1174. const currentEnvironment = environments.find((e) => e.id === getCurrentLocation());
  1175. const locationsToRemove = ["forbidden_grove"];
  1176. environments = environments.map((env) => {
  1177. if (!isUserTitleAtLeast(env.title)) {
  1178. locationsToRemove.push(env.id);
  1179. }
  1180. return env;
  1181. });
  1182. environments = environments.filter((env) => !locationsToRemove.includes(env.id));
  1183. let content = '<div class="mh-improved-travel-window greatWinterHuntGolemDestinationView"><div class="greatWinterHuntGolemDestinationView__content">';
  1184. content += '<div class="greatWinterHuntGolemDestinationView__regionsContainer">';
  1185. for (const region of regions) {
  1186. let buttonClass = "greatWinterHuntGolemDestinationView__regionButton";
  1187. if ((currentEnvironment == null ? void 0 : currentEnvironment.region) === (region == null ? void 0 : region.type)) {
  1188. buttonClass += " greatWinterHuntGolemDestinationView__regionButton--active";
  1189. }
  1190. content += `<button class="${buttonClass}" data-region-type="${region.type}">${region.name}</button>`;
  1191. }
  1192. content += "</div>";
  1193. const hasTitles = false;
  1194. content += '<div class="greatWinterHuntGolemDestinationView__environmentsContainer"><div class="greatWinterHuntGolemDestinationView__environmentsScroller"><div class="greatWinterHuntGolemDestinationView__regionList">';
  1195. if (!hasTitles) {
  1196. content += `<div class="greatWinterHuntGolemDestinationView__regionGroup" data-region-type="all">
  1197. <div class="greatWinterHuntGolemDestinationView__regionEnvironments">`;
  1198. }
  1199. for (const region of regions) {
  1200. if (hasTitles) {
  1201. content += `<div class="greatWinterHuntGolemDestinationView__regionGroup" data-region-type="${region.type}">
  1202. <div class="greatWinterHuntGolemDestinationView__regionName">${region.name}</div>
  1203. <div class="greatWinterHuntGolemDestinationView__regionEnvironments">`;
  1204. }
  1205. const regionEnvironments = environments.filter((e) => e.region === region.type);
  1206. regionEnvironments.forEach((environment) => {
  1207. let envButtonClass = "greatWinterHuntGolemDestinationView__environment";
  1208. if (currentEnvironment.id === environment.id) {
  1209. envButtonClass += " greatWinterHuntGolemDestinationView__environment--active";
  1210. }
  1211. if (isLocationHidden(environment.id)) {
  1212. envButtonClass += " mh-improved-travel-window-hidden";
  1213. }
  1214. content += `<button class="${envButtonClass}" data-environment-type="${environment.id}">
  1215. <div class="greatWinterHuntGolemDestinationView__environmentName">
  1216. <span>${environment.name}</span>
  1217. </div>
  1218. <div class="greatWinterHuntGolemDestinationView__environmentImage" style="background-image:url(${environment.headerImage});" data-environment-type="${environment.id}"></div>
  1219. </button>`;
  1220. });
  1221. if (hasTitles) {
  1222. content += "</div></div>";
  1223. }
  1224. }
  1225. if (!hasTitles) {
  1226. content += "</div></div>";
  1227. }
  1228. content += "</div></div></div>";
  1229. content += "</div>";
  1230. content += `<div class="mh-improved-travel-window-footer">
  1231. <div class="mh-improved-travel-window-edit mousehuntActionButton"><span>Edit</span></div>
  1232. <div class="mh-improved-travel-window-description">Click on a location to toggle the visibility.</div>
  1233. </div>`;
  1234. content += "</div>";
  1235. const popup = createPopup({
  1236. id: "mh-improved-travel-window",
  1237. title: "",
  1238. content,
  1239. className: "mh-improved-travel-window-popup jsDialogFixed",
  1240. show: false
  1241. });
  1242. popup.setOffsetHeight(0);
  1243. popup.setPersistentOffsetHeight(0);
  1244. popup.setIsModal(false);
  1245. popup.show();
  1246. const travelWindow = document.querySelector(".mh-improved-travel-window");
  1247. if (!travelWindow) {
  1248. return;
  1249. }
  1250. const editButton = document.querySelector(".mh-improved-travel-window-edit");
  1251. if (!editButton) {
  1252. return;
  1253. }
  1254. const editButtonSpan = editButton.querySelector("span");
  1255. if (!editButtonSpan) {
  1256. return;
  1257. }
  1258. const environmentButtons = document.querySelectorAll(".greatWinterHuntGolemDestinationView__environment");
  1259. if (!environmentButtons) {
  1260. return;
  1261. }
  1262. editButton.addEventListener("click", () => {
  1263. isEditing = !isEditing;
  1264. if (isEditing) {
  1265. travelWindow.classList.add("mh-improved-travel-window--editing");
  1266. editButtonSpan.textContent = "Save";
  1267. editButton.classList.add("active");
  1268. } else {
  1269. travelWindow.classList.remove("mh-improved-travel-window--editing");
  1270. editButtonSpan.textContent = "Edit";
  1271. editButton.classList.remove("active");
  1272. }
  1273. });
  1274. environmentButtons.forEach((button) => {
  1275. const environmentType = button.getAttribute("data-environment-type");
  1276. button.addEventListener("click", () => {
  1277. if (isEditing) {
  1278. toggleLocation(environmentType);
  1279. button.classList.toggle("mh-improved-travel-window-hidden");
  1280. } else {
  1281. debug(`Traveling to ${environmentType}`);
  1282. travelTo(environmentType);
  1283. setPage("Camp");
  1284. popup.hide();
  1285. }
  1286. });
  1287. });
  1288. onDialogHide(() => {
  1289. isEditing = false;
  1290. });
  1291. });
  1292. var isEditing = false;
  1293. var environments = [];
  1294. var makeMenuItem = () => {
  1295. addSubmenuItem({
  1296. id: "mh-improved-travel-window",
  1297. menu: "travel",
  1298. label: "Travel Window",
  1299. icon: "https://www.mousehuntgame.com/images/ui/hud/menu/special.png?asset_cache_version=2",
  1300. callback: () => {
  1301. openTravelWindow();
  1302. }
  1303. });
  1304. };
  1305. var addEnvironmentIconListener = () => {
  1306. const environmentIcon = document.querySelector(".mousehuntHud-environmentIcon");
  1307. if (!environmentIcon) {
  1308. return;
  1309. }
  1310. environmentIcon.classList.add("mh-improved-travel-window-environment-icon");
  1311. environmentIcon.title = "Open Travel Window";
  1312. environmentIcon.addEventListener("click", () => {
  1313. openTravelWindow();
  1314. });
  1315. };
  1316. var travel_window_default = () => __async(void 0, null, function* () {
  1317. addStyles(travel_menu_default, "better-travel-travel-window");
  1318. makeMenuItem();
  1319. if (getSetting("better-travel.travel-window-environment-icon", true)) {
  1320. addEnvironmentIconListener();
  1321. }
  1322. onEvent("mh-improved-open-travel-window", openTravelWindow);
  1323. environments = yield getData("environments");
  1324. });
  1325.  
  1326. // src/modules/better-travel/settings/index.js
  1327. var settings_default = () => __async(void 0, null, function* () {
  1328. return [
  1329. {
  1330. id: "better-travel.default-to-simple-travel",
  1331. title: "Show Simple Travel tab by default",
  1332. default: false,
  1333. description: ""
  1334. },
  1335. {
  1336. id: "better-travel.show-alphabetized-list",
  1337. title: "Show alphabetized list on Simple Travel",
  1338. default: false,
  1339. description: ""
  1340. },
  1341. {
  1342. id: "better-travel.show-reminders",
  1343. title: "Show Travel Reminders",
  1344. default: true,
  1345. description: ""
  1346. },
  1347. {
  1348. id: "better-travel.travel-window",
  1349. title: "Travel Window",
  1350. default: true,
  1351. description: ""
  1352. },
  1353. {
  1354. id: "better-travel.travel-window-environment-icon",
  1355. title: "Environment icon opens Travel Window",
  1356. default: true,
  1357. description: ""
  1358. }
  1359. ];
  1360. });
  1361.  
  1362. // src/modules/better-travel/styles.css
  1363. var styles_default = '.travelPage-map-spacer,.travelPage-map-simpleToggle,.mousehuntHud-page-tabContent.map.full .travelPage-map-simpleToggle.full,.mousehuntHud-page-tabContent.map.full .travelPage-map-prefix.full{display:none}.travelPage-regionMenu{width:22%;overflow:scroll}.travelPage-map-environment-detailContainer{left:22%;width:78%}.travelPage-regionMenu-environmentLink.active{color:#000;background:#a4cafc}.travelPage-regionMenu-stats{color:#4d4d4d;background-color:#d8d8d8}.travelPage-regionMenu-numFriends{padding:0;background:none}.travelPage-mapContainer.full{height:auto;min-height:800px;max-height:900px;border:none}.travelPage-map-imageContainer{width:78%}.travelPage-map-zoomContainer{bottom:300px;transform:scale(1.5)}.travelPage-map-image-environment-name{top:70px;z-index:15;font-size:22px;font-variant:none;text-shadow:1px 1px #000,0 0 10px #000,8px 12px 9px #000}.travelPage-map-image-environment.locked .travelPage-map-image-environment-status{z-index:1;opacity:.5}.travelPage-map-image-environment-star{z-index:10}.travelPage-map-image-environment-button{top:100px;transform:scale(1.2)}.travelPage-regionMenu-environmentLink.mystery{display:inline-block;color:#9e9e9e;pointer-events:none}.travelPage-regionMenu-item[data-region=riftopia],.travelPage-regionMenu-item[data-region=riftopia] .travelPage-regionMenu-item-contents{display:block!important}.travelPage-regionMenu-regionLink:hover,.travelPage-regionMenu-regionLink:focus{cursor:unset}#mh-simple-travel-page .travelPage-map-prefix{display:block}#mh-simple-travel-page .travelPage-regionMenu{display:grid;grid-template-columns:repeat(5,1fr);width:100%;margin-bottom:10px;overflow:visible;background-color:transparent}#mh-simple-travel-page .travelPage-regionMenu-item{box-sizing:border-box;margin:1px;background-color:#e2e2e2;border:1px solid #4c71b4}#mh-simple-travel-page .travelPage-regionMenu-item[data-region=gnawnia],#mh-simple-travel-page .travelPage-regionMenu-item[data-region=valour],#mh-simple-travel-page .travelPage-regionMenu-item[data-region=whisker_woods],#mh-simple-travel-page .travelPage-regionMenu-item[data-region=burroughs],#mh-simple-travel-page .travelPage-regionMenu-item[data-region=furoma]{min-height:215px}#mh-simple-travel-page .travelPage-regionMenu-item[data-region=riftopia]{min-height:250px}#mh-simple-travel-page .travelPage-regionMenu-environments{width:145px;padding-left:2px;box-shadow:none}#mh-simple-travel-page .travelPage-regionMenu-item-contents{overflow:visible!important}#mh-simple-travel-page .travelPage-regionMenu-environmentLink.active{color:#4e6081}#mh-simple-travel-page .travelPage-regionMenu-environmentLink:hover,#mh-simple-travel-page .travelPage-regionMenu-environmentLink:focus{color:#fff;background-color:#6383bf}.huntersHornView__messageContent strong{font-weight:900}#mh-simple-travel-page .travelPage-alpha-wrapper .travelPage-regionMenu{display:block;width:100%}#mh-simple-travel-page .travelPage-alpha-wrapper .travelPage-regionMenu-environments{display:flex;flex-flow:column wrap;align-items:stretch;justify-content:flex-start;width:754px;height:425px;padding:4px 1px}#mh-simple-travel-page .travelPage-alpha-wrapper a.travelPage-regionMenu-environmentLink{width:112px;margin-left:1px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mhui-region-travel-item .icon{border-radius:5px}.mousehuntHud-menu ul li ul li.mhui-region-travel-item a .icon{top:6px;left:3px;width:22px;height:22px}#mh-simple-travel-page .travelPage-regionMenu .travelPage-regionMenu-environmentLink.active.highlight{margin-right:-3px;border-right:1px solid #4c71b4}#mh-simple-travel-page .travelPage-alpha-wrapper .travelPage-regionMenu-environmentLink.active.highlight{margin-right:0;border-right:none;border-radius:3px}.travelPage-regionMenu-environmentLink.relic-hunter-is-here:after{position:absolute;top:5px;right:5px;display:none;width:20px;height:20px;content:"";background-image:url(https://www.mousehuntgame.com/images/mice/thumb/d6980f1b00ff8ec688804706cba9370c.gif?cv=2);background-repeat:no-repeat;background-size:contain;border-radius:5px}.travelPage-regionMenu-environments:hover .travelPage-regionMenu-environmentLink.relic-hunter-is-here:after,.travelPage-regionMenu-environments:focus .travelPage-regionMenu-environmentLink.relic-hunter-is-here:after,.travelPage-regionMenu-environmentLink.relic-hunter-is-here:hover:after,.travelPage-regionMenu-environmentLink.relic-hunter-is-here:focus:after{display:block}.travelPage-regionMenu-environmentLink.relic-hunter-is-here{background-color:#e0f2d5}.mousehuntHud-page-tabContent.simple-travel .travelPage-regionMenu-environmentLink.relic-hunter-is-here{margin:0;border:none;border-radius:6px;outline:1px solid #ccc}.travelPage-alpha-wrapper .relic-hunter-is-here .travelPage-regionMenu-environmentLink-image{margin-left:0}.travelPage-map-image-environment .map-relic-hunter-is-here-image{position:absolute;top:5px;left:5px;width:60px;height:60px;overflow:hidden;background:url(https://www.mousehuntgame.com/images/mice/thumb/d6980f1b00ff8ec688804706cba9370c.gif?cv=2);filter:hue-rotate(-326deg);background-repeat:no-repeat;background-size:contain;border-radius:50%;transform:rotate(-70deg)}.map-relic-hunter-is-here.travelPage-map-image-environment-pointer{top:41px;left:86px;z-index:9;filter:hue-rotate(326deg);transform:rotate(70deg)}#mh-simple-travel-page .first-letter:first-letter{font-size:12px;font-weight:900}#mh-simple-travel-page .travelPage-alpha-wrapper:hover .first-letter:first-letter{border-bottom:1px solid #4e6081}#mh-simple-travel-page .travelPage-regionMenu .travelPage-regionMenu-environmentLink.active.highlight.event-location,#mh-simple-travel-page .travelPage-regionMenu .travelPage-regionMenu-environmentLink.event-location{color:#c01dff}#mh-simple-travel-page .travelPage-regionMenu .travelPage-regionMenu-environmentLink.active.highlight.event-location:after,#mh-simple-travel-page .travelPage-regionMenu .travelPage-regionMenu-environmentLink.event-location:after{position:absolute;top:1px;left:4px;width:15px;height:15px;content:"";background-image:url(https://www.mousehuntgame.com/images/ui/camp/trap/star_favorite.png?asset_cache_version=2);filter:drop-shadow(0 0 1px #fff);background-repeat:no-repeat;background-size:contain}.travelPage-map-environment-detail-title .custom-favorite-button{margin-top:-1px;margin-left:10px}.mousehuntHud-menu ul li ul li.mh-improved-better-travel-favorites-divider{height:1px;pointer-events:none;background-color:#6c3d0e7f}.mh-improved-better-travel-favorite-location:after{position:absolute;top:6px;right:4px;bottom:0;display:block;width:20px;height:20px;content:"";background:url(https://www.mousehuntgame.com/images/ui/map/star_gold_320.png?asset_cache_version=2);background-size:contain;opacity:.3}.mh-improved-better-travel-favorite-location:hover:after,.mh-improved-better-travel-favorite-location:focus:after{opacity:.1}.mh-improved-better-travel-menu-item .name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mousehuntHud-environmentName{padding-top:0;margin-top:29px}.mh-improved-better-travel-region-location .icon{border:1px solid #9f9171;border-radius:3px}.mh-improved-travel-message.travelPage-map-message.active{top:46px;box-shadow:0 3px 6px -3px #333}.mh-improved-travel-message.travelPage-map-message .mousehuntActionButton{padding:3px 10px;font-size:11px}\n';
  1364.  
  1365. // src/modules/better-travel/travel-menu-hiding.css
  1366. var travel_menu_hiding_default = "ul.fast-travel-list>li:not(.custom-submenu-item){display:none}\n";
  1367.  
  1368. // src/modules/better-travel/index.js
  1369. var expandTravelRegions = () => {
  1370. var _a, _b;
  1371. if ("travel" !== getCurrentPage()) {
  1372. return;
  1373. }
  1374. const hud = document.querySelector("#mousehuntHud");
  1375. if (hud) {
  1376. const hudHeight = hud.offsetHeight + 30;
  1377. const map = document.querySelector(".travelPage-mapContainer.full");
  1378. if (map) {
  1379. map.style.height = `calc(100vh - ${hudHeight}px)`;
  1380. }
  1381. }
  1382. const regionHeaders = document.querySelectorAll(".travelPage-regionMenu-regionLink");
  1383. if (regionHeaders) {
  1384. regionHeaders.forEach((regionHeader) => {
  1385. regionHeader.setAttribute("onclick", "return false;");
  1386. });
  1387. }
  1388. const travelAreas = document.querySelectorAll(".travelPage-regionMenu-item");
  1389. if (travelAreas && travelAreas.length > 0) {
  1390. travelAreas.forEach((area) => {
  1391. area.classList.add("active");
  1392. area.classList.remove("contracted");
  1393. });
  1394. }
  1395. const locations = document.querySelectorAll(".travelPage-map-image-environment.active");
  1396. if (locations && locations.length > 0) {
  1397. locations.forEach((location) => {
  1398. location.addEventListener("mouseover", () => {
  1399. location.classList.add("highlight");
  1400. });
  1401. location.addEventListener("mouseout", () => {
  1402. setTimeout(() => {
  1403. location.classList.remove("highlight");
  1404. }, 1e3);
  1405. });
  1406. });
  1407. }
  1408. if ((_b = (_a = app == null ? void 0 : app.pages) == null ? void 0 : _a.TravelPage) == null ? void 0 : _b.zoomOut) {
  1409. setTimeout(() => {
  1410. app.pages.TravelPage.zoomOut();
  1411. }, 500);
  1412. }
  1413. };
  1414. var travelClickHandler = (event) => {
  1415. var _a, _b;
  1416. if ((_b = (_a = app == null ? void 0 : app.pages) == null ? void 0 : _a.TravelPage) == null ? void 0 : _b.travel) {
  1417. travelTo(event.target.getAttribute("data-environment"));
  1418. setPage("Camp");
  1419. }
  1420. };
  1421. var cloneRegionMenu = () => {
  1422. const regionMenu = document.querySelector(".travelPage-regionMenu");
  1423. if (!regionMenu) {
  1424. return;
  1425. }
  1426. const regionMenuClone = regionMenu.cloneNode(true);
  1427. const travelLinks = regionMenuClone.querySelectorAll(".travelPage-regionMenu-environmentLink");
  1428. if (travelLinks && travelLinks.length > 0) {
  1429. travelLinks.forEach((link) => {
  1430. link.setAttribute("onclick", "return false;");
  1431. link.addEventListener("click", travelClickHandler);
  1432. });
  1433. }
  1434. return regionMenuClone;
  1435. };
  1436. var addTab = (id, label) => {
  1437. if ("travel" !== getCurrentPage()) {
  1438. return;
  1439. }
  1440. const exists = document.querySelector(`#mh-${id}-tab`);
  1441. if (exists) {
  1442. return;
  1443. }
  1444. const tabContainer = document.querySelector(".mousehuntHud-page-tabHeader-container");
  1445. if (!tabContainer) {
  1446. return;
  1447. }
  1448. const tab = makeElement("a", "mousehuntHud-page-tabHeader");
  1449. tab.id = `mh-${id}-tab`;
  1450. tab.setAttribute("data-tab", id);
  1451. tab.setAttribute("onclick", "hg.utils.PageUtil.onclickPageTabHandler(this); return false;");
  1452. makeElement("span", "", label, tab);
  1453. tabContainer.append(tab);
  1454. };
  1455. var addPage = (id, content) => {
  1456. if ("travel" !== getCurrentPage()) {
  1457. return;
  1458. }
  1459. const exists = document.querySelector(`#mh-${id}-page`);
  1460. if (exists) {
  1461. return;
  1462. }
  1463. const pageContainer = document.querySelector(".mousehuntHud-page-tabContentContainer");
  1464. if (!pageContainer) {
  1465. return;
  1466. }
  1467. const page = makeElement("div", ["mousehuntHud-page-tabContent", id]);
  1468. page.id = `mh-${id}-page`;
  1469. page.setAttribute("data-tab", id);
  1470. if (content) {
  1471. page.append(content);
  1472. } else {
  1473. const blank = makeElement("div");
  1474. page.append(blank);
  1475. }
  1476. pageContainer.append(page);
  1477. };
  1478. var addAlphabetizedList = (regionMenu) => {
  1479. const alphaWrapper = makeElement("div", "travelPage-alpha-wrapper");
  1480. const alphaContent = makeElement("div", "travelPage-regionMenu");
  1481. const alphaHeader = makeElement("div", ["travelPage-regionMenu-item", "active"]);
  1482. const alphaList = makeElement("div", "travelPage-regionMenu-item-contents");
  1483. const alphaListContent = makeElement("div", "travelPage-regionMenu-environments");
  1484. const links = regionMenu.querySelectorAll(".travelPage-regionMenu-environmentLink");
  1485. const sortedLinks = [...links].sort((a, b) => {
  1486. const aName = a.innerText;
  1487. const bName = b.innerText;
  1488. if (aName < bName) {
  1489. return -1;
  1490. }
  1491. if (aName > bName) {
  1492. return 1;
  1493. }
  1494. return 0;
  1495. });
  1496. let lastLetter = "";
  1497. sortedLinks.forEach((link) => {
  1498. const linkClone = link.cloneNode(true);
  1499. alphaListContent.append(linkClone);
  1500. linkClone.addEventListener("click", travelClickHandler);
  1501. const firstLetter = linkClone.innerText.charAt(0).toLowerCase();
  1502. if (firstLetter !== lastLetter) {
  1503. linkClone.classList.add("first-letter");
  1504. }
  1505. lastLetter = firstLetter;
  1506. const environment = environments2.find((env) => {
  1507. return env.id === link.getAttribute("data-environment");
  1508. });
  1509. if (!environment) {
  1510. linkClone.classList.add("event-location");
  1511. }
  1512. });
  1513. alphaList.append(alphaListContent);
  1514. alphaHeader.append(alphaList);
  1515. alphaContent.append(alphaHeader);
  1516. alphaWrapper.append(alphaContent);
  1517. return alphaWrapper;
  1518. };
  1519. var addSimpleTravelPage = () => {
  1520. expandTravelRegions();
  1521. const wrapper = makeElement("div", "travelPage-wrapper");
  1522. if ("not-set" === getSetting("better-travel.default-to-simple-travel", "not-set")) {
  1523. const settingTip = makeElement("div", ["travelPage-map-prefix", "simple-travel-tip"], 'You can set this as the default travel tab in the <a href="https://www.mousehuntgame.com/preferences.php?tab=mousehunt-improved-settings">MouseHunt Improved settings</a>.');
  1524. wrapper.append(settingTip);
  1525. }
  1526. const regionMenu = cloneRegionMenu();
  1527. if (getSetting("better-travel.show-alphabetized-list", false)) {
  1528. wrapper.append(addAlphabetizedList(regionMenu));
  1529. }
  1530. wrapper.append(regionMenu);
  1531. addPage("simple-travel", wrapper);
  1532. };
  1533. var addSimpleTravel = () => {
  1534. if ("travel" !== getCurrentPage()) {
  1535. return;
  1536. }
  1537. addTab("simple-travel", "Simple Travel");
  1538. addSimpleTravelPage();
  1539. };
  1540. var getPreviousLocation = () => {
  1541. const previousLocation = getSetting("better-travel.previous-location", false);
  1542. if (previousLocation && previousLocation !== getCurrentLocation()) {
  1543. return environments2.find((environment) => {
  1544. return environment.id === previousLocation;
  1545. });
  1546. }
  1547. return false;
  1548. };
  1549. var goToPreviousLocation = () => {
  1550. const previousLocation = getPreviousLocation();
  1551. if (previousLocation) {
  1552. travelTo(previousLocation.id);
  1553. }
  1554. };
  1555. var addToTravelDropdown = () => __async(void 0, null, function* () {
  1556. const currentLocation = getCurrentLocation();
  1557. const eventEnvironments = yield getData("environments-events");
  1558. environments2.push(...eventEnvironments);
  1559. let currentRegion = environments2.find((environment) => {
  1560. return environment.id === currentLocation;
  1561. });
  1562. if (!currentRegion) {
  1563. currentRegion = eventEnvironments.find((environment) => {
  1564. return environment.id === currentLocation;
  1565. });
  1566. if (!currentRegion) {
  1567. return;
  1568. }
  1569. }
  1570. const otherRegions = environments2.filter((environment) => {
  1571. if (!(environment == null ? void 0 : environment.region) || !(currentRegion == null ? void 0 : currentRegion.region)) {
  1572. return false;
  1573. }
  1574. return environment.region === currentRegion.region;
  1575. });
  1576. otherRegions.splice(otherRegions.findIndex((environment) => {
  1577. return environment.id === currentLocation;
  1578. }), 1);
  1579. const existingCustomSubmenuItems = document.querySelectorAll(".mh-improved-better-travel-menu-item");
  1580. if (existingCustomSubmenuItems) {
  1581. existingCustomSubmenuItems.forEach((item) => {
  1582. item.remove();
  1583. });
  1584. }
  1585. const previousLocation = getPreviousLocation();
  1586. if (previousLocation) {
  1587. addSubmenuItem({
  1588. menu: "travel",
  1589. label: `Back to ${previousLocation.name}`,
  1590. icon: "https://www.mousehuntgame.com/images/ui/puzzle/refresh.png",
  1591. callback: goToPreviousLocation,
  1592. class: "mh-improved-better-travel-menu-item mh-improved-better-travel-previous-location"
  1593. });
  1594. }
  1595. otherRegions.forEach((region) => {
  1596. if (region.id === currentLocation) {
  1597. return;
  1598. }
  1599. addSubmenuItem({
  1600. menu: "travel",
  1601. label: region.name,
  1602. icon: region.image,
  1603. callback: () => {
  1604. travelTo(region.id);
  1605. },
  1606. class: "mh-improved-better-travel-menu-item mh-improved-better-travel-region-location"
  1607. });
  1608. });
  1609. const favorites = getLocationFavorites();
  1610. if (favorites && favorites.length > 0) {
  1611. addSubmenuDivider("travel", "mh-improved-better-travel-favorites-divider");
  1612. favorites.forEach((favorite) => {
  1613. const favoriteRegion = environments2.find((environment) => {
  1614. return environment.id === favorite;
  1615. });
  1616. if (favoriteRegion) {
  1617. addSubmenuItem({
  1618. menu: "travel",
  1619. label: favoriteRegion.name,
  1620. icon: favoriteRegion.image,
  1621. callback: () => {
  1622. travelTo(favoriteRegion.id);
  1623. },
  1624. class: "mh-improved-better-travel-menu-item mh-improved-better-travel-favorite-location"
  1625. });
  1626. }
  1627. });
  1628. }
  1629. });
  1630. var onTravelComplete = () => {
  1631. onEvent("travel_complete", () => {
  1632. saveTravelLocation();
  1633. setTimeout(() => {
  1634. if (getSetting("better-travel.show-reminders", true)) {
  1635. reminders_default();
  1636. }
  1637. addToTravelDropdown();
  1638. }, 250);
  1639. });
  1640. };
  1641. var initSimpleTab = () => {
  1642. if ("simple-travel" === getCurrentTab()) {
  1643. const isActive = document.querySelector(".mousehuntHud-page-tabContent.simple-travel");
  1644. if (!isActive || isActive && isActive.classList.contains("active")) {
  1645. return;
  1646. }
  1647. setTab("simple-travel");
  1648. }
  1649. };
  1650. var maybeSetTab = () => {
  1651. if ("travel" !== getCurrentPage()) {
  1652. return;
  1653. }
  1654. initSimpleTab();
  1655. if ("map" !== getCurrentTab()) {
  1656. return;
  1657. }
  1658. if (!getSetting("better-travel.default-to-simple-travel", false)) {
  1659. return;
  1660. }
  1661. setTab("simple-travel");
  1662. };
  1663. var addRhToSimpleTravel = () => __async(void 0, null, function* () {
  1664. const location = yield getRelicHunterLocation();
  1665. if (!location) {
  1666. return;
  1667. }
  1668. const travelLink = document.querySelectorAll(`.travelPage-regionMenu-environmentLink[data-environment="${location.id}"]`);
  1669. if (!travelLink.length) {
  1670. return;
  1671. }
  1672. travelLink.forEach((link) => {
  1673. link.classList.add("relic-hunter-is-here");
  1674. });
  1675. });
  1676. var addRhToMap = () => __async(void 0, null, function* () {
  1677. const location = yield getRelicHunterLocation();
  1678. if (!location) {
  1679. return;
  1680. }
  1681. const mapLocation = document.querySelector(`.travelPage-map-image-environment[data-environment-type="${location.id}"]`);
  1682. if (!mapLocation) {
  1683. return;
  1684. }
  1685. const rh = makeElement("div", ["map-relic-hunter-is-here", "travelPage-map-image-environment-pointer"]);
  1686. makeElement("div", ["map-relic-hunter-is-here-image", "travelPage-map-image-environment-pointer-image"], "", rh);
  1687. mapLocation.append(rh);
  1688. });
  1689. var maybeDoMapView = () => {
  1690. if ("travel" !== getCurrentPage()) {
  1691. return;
  1692. }
  1693. if ("map" !== getCurrentTab()) {
  1694. return;
  1695. }
  1696. expandTravelRegions();
  1697. addRhToMap();
  1698. };
  1699. var _tabHandler = null;
  1700. var listenTabChange = () => {
  1701. var _a, _b;
  1702. if (_tabHandler) {
  1703. return;
  1704. }
  1705. if (!((_b = (_a = hg == null ? void 0 : hg.utils) == null ? void 0 : _a.PageUtil) == null ? void 0 : _b.onclickPageTabHandler)) {
  1706. return;
  1707. }
  1708. _tabHandler = hg.utils.PageUtil.onclickPageTabHandler;
  1709. hg.utils.PageUtil.onclickPageTabHandler = (tab) => {
  1710. _tabHandler(tab);
  1711. maybeDoMapView();
  1712. };
  1713. };
  1714. var saveTravelLocation = () => {
  1715. const isLocationDashboardRefreshing = sessionGet("doing-location-refresh", false);
  1716. if (isLocationDashboardRefreshing) {
  1717. return;
  1718. }
  1719. const previousLocation = getTravelSetting("current-location", "not-set");
  1720. const currentLocation = getCurrentLocation();
  1721. if (currentLocation === previousLocation) {
  1722. return;
  1723. }
  1724. saveTravelSetting("previous-location", previousLocation);
  1725. saveTravelSetting("current-location", currentLocation);
  1726. };
  1727. var getLocationFavorites = () => {
  1728. const faves = getSetting("better-travel.favorites", []);
  1729. return faves;
  1730. };
  1731. var isLocationFavorite = (type) => {
  1732. return getLocationFavorites().includes(type);
  1733. };
  1734. var saveLocationFavorites = (favorites) => {
  1735. saveTravelSetting("favorites", favorites);
  1736. };
  1737. var addToLocationFavorites = (type) => {
  1738. if (!isLocationFavorite(type)) {
  1739. const faves = getLocationFavorites();
  1740. faves.push(type);
  1741. saveLocationFavorites(faves);
  1742. }
  1743. };
  1744. var removeFromLocationFavorites = (type) => {
  1745. if (getLocationFavorites()) {
  1746. const faves = getLocationFavorites();
  1747. faves.splice(faves.indexOf(type), 1);
  1748. saveLocationFavorites(faves);
  1749. }
  1750. };
  1751. var addFavoriteButtonsToTravelPage = () => __async(void 0, null, function* () {
  1752. const locations = document.querySelectorAll(".travelPage-map-environment-detailContainer .travelPage-map-environment-detail");
  1753. if (!locations) {
  1754. return;
  1755. }
  1756. const locationFavorites = getLocationFavorites();
  1757. locations.forEach((location) => {
  1758. const type = location.getAttribute("data-environment-type");
  1759. if (!type) {
  1760. return;
  1761. }
  1762. const isEventLocation = environments2.find((environment) => {
  1763. return environment.id === type;
  1764. });
  1765. if (isEventLocation) {
  1766. return;
  1767. }
  1768. const isFavorite = locationFavorites.includes(type);
  1769. makeFavoriteButton({
  1770. id: `better-travel-favorite-${type}`,
  1771. target: location.querySelector(".travelPage-map-environment-detail-title"),
  1772. size: "small",
  1773. state: isFavorite,
  1774. isSetting: false,
  1775. defaultState: false,
  1776. onActivate: () => {
  1777. addToLocationFavorites(type);
  1778. addToTravelDropdown();
  1779. },
  1780. onDeactivate: () => {
  1781. removeFromLocationFavorites(type);
  1782. removeSubmenuItem(type);
  1783. }
  1784. });
  1785. });
  1786. });
  1787. var main = () => {
  1788. if (getSetting("better-travel.travel-window", true)) {
  1789. travel_window_default();
  1790. }
  1791. onNavigation(() => {
  1792. addSimpleTravel();
  1793. addRhToSimpleTravel();
  1794. addFavoriteButtonsToTravelPage();
  1795. maybeSetTab();
  1796. }, {
  1797. page: "travel"
  1798. });
  1799. listenTabChange();
  1800. initSimpleTab();
  1801. maybeDoMapView();
  1802. onTravelComplete();
  1803. saveTravelLocation();
  1804. addToTravelDropdown();
  1805. onEvent("mh-improved-goto-previous-location", goToPreviousLocation);
  1806. };
  1807. var environments2 = [];
  1808. var init = () => __async(void 0, null, function* () {
  1809. const stylesJoined = [styles_default];
  1810. if (!getFlag("no-travel-menu-hiding")) {
  1811. stylesJoined.push(travel_menu_hiding_default);
  1812. }
  1813. addStyles(stylesJoined, "better-travel");
  1814. environments2 = yield getData("environments");
  1815. main();
  1816. });
  1817. var better_travel_default = {
  1818. id: "better-travel",
  1819. name: "Better Travel",
  1820. type: "better",
  1821. default: true,
  1822. description: 'Adds locations in the current region to the Travel dropdown menu, a "Simple Travel" tab with a grid of locations, an optional alphabetized list, an indicator for where the Relic Hunter is.',
  1823. load: init,
  1824. settings: settings_default
  1825. };
  1826. return __toCommonJS(better_travel_exports);
  1827. })();
  1828. mhImprovedVersion = "0.0.0-userscript;"
  1829. mhImprovedPlatform = "userscript";
  1830. mhui.default.load();
  1831. migrateUserscript('Better Travel / Travel Tweaks', 'https://greasyfork.org/en/scripts/452232-mousehunt-travel-tweaks');