MouseHunt - QoL Utilities

Miscellaneous utilities to turbo-charge your MH experience

  1. // ==UserScript==
  2. // @name MouseHunt - QoL Utilities
  3. // @author Tran Situ (tsitu)
  4. // @namespace https://gf.qytechs.cn/en/users/232363-tsitu
  5. // @version 1.1.7
  6. // @description Miscellaneous utilities to turbo-charge your MH experience
  7. // @match http://www.mousehuntgame.com/*
  8. // @match https://www.mousehuntgame.com/*
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. /**
  13. * IDEA BANK
  14. * TODO: Alert when sounding horn after unseen trap check (user set 00, 15, 30, 45) to avoid wasted hunt if TC'd something
  15. * TODO: Track outbound supply transfers
  16. */
  17.  
  18. // Adds direct hunter ID / snuid navigation popup via button on 'Friends' dropdown
  19. (function hunterIdNav() {
  20. document
  21. .querySelectorAll(".tsitu-hunter-id-nav")
  22. .forEach(el => el.remove());
  23.  
  24. const target = document.querySelector("li .friend_list");
  25. if (target) {
  26. const li = document.createElement("li");
  27. li.className = "tsitu-hunter-id-nav";
  28. const button = document.createElement("a");
  29. button.href = "#";
  30. button.innerText = "ID Navigation";
  31. button.onclick = function () {
  32. const existing = document.querySelector("#tsitu-hunter-id-nav-ui");
  33. if (existing) existing.remove();
  34. else render();
  35. return false;
  36. };
  37. const icon = document.createElement("div");
  38. icon.className = "icon";
  39. button.appendChild(icon);
  40. li.appendChild(button);
  41. target.insertAdjacentElement("afterend", li);
  42.  
  43. function render() {
  44. document
  45. .querySelectorAll("#tsitu-hunter-id-nav-ui")
  46. .forEach(el => el.remove());
  47.  
  48. const div = document.createElement("div");
  49. div.id = "tsitu-hunter-id-nav-ui";
  50. div.style.backgroundColor = "#F5F5F5";
  51. div.style.position = "fixed";
  52. div.style.zIndex = "9999";
  53. div.style.left = "22.3vw";
  54. div.style.top = "28vh";
  55. div.style.border = "solid 3px #696969";
  56. div.style.borderRadius = "20px";
  57. div.style.padding = "10px";
  58. div.style.textAlign = "center";
  59.  
  60. const closeButton = document.createElement("button", {
  61. id: "close-button"
  62. });
  63. closeButton.textContent = "x";
  64. closeButton.onclick = function () {
  65. document.body.removeChild(div);
  66. };
  67.  
  68. const table = document.createElement("table");
  69. table.style.textAlign = "left";
  70. table.style.borderSpacing = "1em 0";
  71. const rowHid = document.createElement("tr");
  72. const rowSnuid = document.createElement("tr");
  73.  
  74. const hidRadio = document.createElement("input");
  75. hidRadio.type = "radio";
  76. hidRadio.name = "tsitu-hunter-id";
  77. hidRadio.id = "tsitu-radio-hid";
  78. hidRadio.defaultChecked = true;
  79. hidRadio.onchange = function () {
  80. processRadio();
  81. };
  82.  
  83. const hidRadioLabel = document.createElement("label");
  84. hidRadioLabel.innerText = "Hunter ID: ";
  85. hidRadioLabel.htmlFor = "tsitu-radio-hid";
  86.  
  87. const hidInput = document.createElement("input");
  88. hidInput.type = "text";
  89. hidInput.id = "tsitu-input-hid";
  90. hidInput.placeholder = "e.g. 3795351";
  91. hidInput.onkeyup = function (event) {
  92. if (event.keyCode === 13) {
  93. goButton.click();
  94. }
  95. };
  96.  
  97. const colHid = document.createElement("td");
  98. const colHidInput = document.createElement("td");
  99. colHid.appendChild(hidRadio);
  100. colHid.appendChild(document.createTextNode("\u00A0"));
  101. colHid.appendChild(hidRadioLabel);
  102. colHidInput.appendChild(hidInput);
  103. rowHid.appendChild(colHid);
  104. rowHid.appendChild(colHidInput);
  105.  
  106. const snuidRadio = document.createElement("input");
  107. snuidRadio.type = "radio";
  108. snuidRadio.name = "tsitu-hunter-id";
  109. snuidRadio.id = "tsitu-radio-snuid";
  110. snuidRadio.onchange = function () {
  111. processRadio();
  112. };
  113.  
  114. const snuidRadioLabel = document.createElement("label");
  115. snuidRadioLabel.innerText = "SN User ID: ";
  116. snuidRadioLabel.htmlFor = "tsitu-radio-snuid";
  117.  
  118. const snuidInput = document.createElement("input");
  119. snuidInput.type = "text";
  120. snuidInput.id = "tsitu-input-snuid";
  121. snuidInput.placeholder = "e.g. 1062432650";
  122. snuidInput.onkeyup = function (event) {
  123. if (event.keyCode === 13) {
  124. goButton.click();
  125. }
  126. };
  127.  
  128. const colSnuid = document.createElement("td");
  129. const colSnuidInput = document.createElement("td");
  130. colSnuid.appendChild(snuidRadio);
  131. colSnuid.appendChild(document.createTextNode("\u00A0"));
  132. colSnuid.appendChild(snuidRadioLabel);
  133. colSnuidInput.appendChild(snuidInput);
  134. rowSnuid.appendChild(colSnuid);
  135. rowSnuid.appendChild(colSnuidInput);
  136.  
  137. function processRadio() {
  138. if (hidRadio.checked) {
  139. hidInput.disabled = false;
  140. snuidInput.disabled = true;
  141. localStorage.setItem("tsitu-id-radio", "hid");
  142. } else if (snuidRadio.checked) {
  143. hidInput.disabled = true;
  144. snuidInput.disabled = false;
  145. localStorage.setItem("tsitu-id-radio", "snuid");
  146. }
  147. }
  148.  
  149. const goButton = document.createElement("button");
  150. goButton.style.fontWeight = "bold";
  151. goButton.innerText = "Go";
  152. goButton.onclick = function () {
  153. if (hidRadio.checked) {
  154. const val = hidInput.value;
  155. if (
  156. val.length > 0 &&
  157. val.length === parseInt(val).toString().length
  158. ) {
  159. const newWindow = window.open(
  160. `https://www.mousehuntgame.com/profile.php?id=${val}`
  161. );
  162. }
  163. } else if (snuidRadio.checked) {
  164. const val = snuidInput.value;
  165. if (
  166. val.length > 0 &&
  167. val.length === parseInt(val).toString().length
  168. ) {
  169. const newWindow = window.open(
  170. `https://www.mousehuntgame.com/profile.php?snuid=${val}`
  171. );
  172. }
  173. }
  174. };
  175.  
  176. table.appendChild(rowHid);
  177. table.appendChild(rowSnuid);
  178. div.appendChild(closeButton);
  179. div.appendChild(document.createElement("br"));
  180. div.appendChild(document.createElement("br"));
  181. div.appendChild(table);
  182. div.appendChild(document.createElement("br"));
  183. div.appendChild(goButton);
  184. document.body.appendChild(div);
  185.  
  186. // Apply cached radio selection
  187. const radioCache = localStorage.getItem("tsitu-id-radio");
  188. if (radioCache) {
  189. if (radioCache === "hid") {
  190. hidRadio.checked = true;
  191. } else if (radioCache === "snuid") {
  192. snuidRadio.checked = true;
  193. }
  194. }
  195. processRadio();
  196. }
  197. }
  198. })();
  199.  
  200. // TODO: Claim-time map participants/duster tracker (move to mapping helper?)
  201. (function mapTracker() {
  202. const map = temp1;
  203. if (map.can_claim_reward && map.is_complete) {
  204. //
  205. }
  206.  
  207. const data = {};
  208. map.hunters.forEach(hunter => {
  209. if (hunter.is_active) {
  210. data[hunter.user_id] = {
  211. name: hunter.name
  212. };
  213.  
  214. const completedItems = hunter.completed_goal_ids.item;
  215. const completedMice = hunter.completed_goal_ids.mouse;
  216. if (completedItems.length > 0) {
  217. data[hunter.user_id].i = completedItems.length;
  218. }
  219. if (completedMice.length > 0) {
  220. data[hunter.user_id].m = completedMice.length;
  221. }
  222.  
  223. if (hunter.upgrader) {
  224. data[hunter.user_id].d = true;
  225. }
  226. }
  227. });
  228. console.log(data);
  229. });
  230.  
  231. (function lockConvertibleButtons() {
  232. // Observe for 'Special' tab of Inventory
  233. const observerTarget = document.querySelector(".mousehuntPage-content");
  234. if (observerTarget) {
  235. MutationObserver =
  236. window.MutationObserver ||
  237. window.WebKitMutationObserver ||
  238. window.MozMutationObserver;
  239.  
  240. const observer = new MutationObserver(function () {
  241. const isSpecial = observerTarget.querySelector(
  242. ".mousehuntHud-page-tabContent.special.active"
  243. );
  244. if (isSpecial) {
  245. // Disconnect and reconnect later to prevent infinite mutation loop
  246. observer.disconnect();
  247.  
  248. render();
  249.  
  250. observer.observe(observerTarget, {
  251. childList: true,
  252. subtree: true
  253. });
  254. }
  255. });
  256.  
  257. observer.observe(observerTarget, {
  258. childList: true,
  259. subtree: true
  260. });
  261. }
  262.  
  263. function render() {
  264. document
  265. .querySelectorAll(".tsitu-lock-convertible")
  266. .forEach(el => el.remove());
  267.  
  268. const convertibles = document.querySelectorAll(
  269. ".inventoryPage-item.full.convertible"
  270. );
  271. if (convertibles.length > 0) {
  272. // Apply cached locks on page load
  273. const cacheRaw = localStorage.getItem("tsitu-convertible-locks");
  274. if (cacheRaw) {
  275. const cache = JSON.parse(cacheRaw);
  276. convertibles.forEach(el => {
  277. const id = el.getAttribute("data-item-id");
  278. if (cache.indexOf(id) >= 0) {
  279. el.querySelectorAll(
  280. ".inventoryPage-item-content-action .button"
  281. ).forEach(button => {
  282. if (!button.classList.contains("disabled")) {
  283. button.classList.toggle("disabled");
  284. }
  285. });
  286. }
  287. });
  288. }
  289.  
  290. // Generate individual item lock buttons
  291. convertibles.forEach(el => {
  292. const a = document.createElement("a");
  293. a.href = "#";
  294. a.className =
  295. "inventoryPage-item-larryLexicon tsitu-lock-convertible";
  296. a.style.right = "22px";
  297. a.style.height = "15px";
  298. a.innerText = "🔒";
  299. a.onclick = function () {
  300. el.querySelectorAll(
  301. ".inventoryPage-item-content-action .button"
  302. ).forEach(button => {
  303. button.classList.toggle("disabled");
  304. });
  305. updateLockCache();
  306. return false;
  307. };
  308. const target = el.querySelector(".inventoryPage-item-name");
  309. if (target) target.insertAdjacentElement("afterend", a);
  310. });
  311.  
  312. function updateLockCache() {
  313. const cacheArr = [];
  314. convertibles.forEach(el => {
  315. const button = el.querySelector(
  316. ".inventoryPage-item-content-action .button"
  317. );
  318. if (button.classList.contains("disabled")) {
  319. cacheArr.push(el.getAttribute("data-item-id"));
  320. }
  321. });
  322. localStorage.setItem(
  323. "tsitu-convertible-locks",
  324. JSON.stringify(cacheArr)
  325. );
  326. }
  327.  
  328. // Add buttons for [un]locking entire tabs
  329. const lockableTabs = [
  330. "Baskets & Kits",
  331. "Scrolls, Posters, Assignments",
  332. "Spring Egg Hunt",
  333. "Treasure Chests"
  334. ];
  335. observerTarget
  336. .querySelectorAll(".inventoryPage-tagContent-tagGroup.clear-block")
  337. .forEach(tab => {
  338. const tabType = tab.getAttribute("data-name");
  339. if (lockableTabs.indexOf(tabType) >= 0) {
  340. const span = document.createElement("span");
  341. span.className =
  342. "inventoryPage-tagContent-tagTitle tsitu-lock-convertible";
  343. span.style.margin = "5px 0 5px 0";
  344.  
  345. const lockAll = document.createElement("button");
  346. lockAll.innerText = "Lock Tab";
  347. lockAll.onclick = function () {
  348. if (
  349. confirm(
  350. `Are you sure you'd like to lock all convertibles on this tab?\n\n- ${tabType}`
  351. )
  352. ) {
  353. tab
  354. .querySelectorAll(
  355. ".inventoryPage-item-content-action .button"
  356. )
  357. .forEach(button => {
  358. if (!button.classList.contains("disabled")) {
  359. button.classList.toggle("disabled");
  360. }
  361. });
  362. updateLockCache();
  363. }
  364. };
  365.  
  366. const unlockAll = document.createElement("button");
  367. unlockAll.innerText = "Unlock Tab";
  368. unlockAll.onclick = function () {
  369. if (
  370. confirm(
  371. `Are you sure you'd like to unlock all convertibles on this tab?\n\n- ${tabType}`
  372. )
  373. ) {
  374. tab
  375. .querySelectorAll(
  376. ".inventoryPage-item-content-action .button"
  377. )
  378. .forEach(button => {
  379. if (button.classList.contains("disabled")) {
  380. button.classList.toggle("disabled");
  381. }
  382. });
  383. updateLockCache();
  384. }
  385. };
  386.  
  387. span.appendChild(lockAll);
  388. span.appendChild(document.createTextNode("\u00A0\u00A0"));
  389. span.appendChild(unlockAll);
  390. const target = tab.querySelector(
  391. ".inventoryPage-tagContent-tagTitle"
  392. );
  393. if (target) target.appendChild(span);
  394. }
  395. });
  396. }
  397. }
  398. })();
  399.  
  400. // Adds RH location and 'Travel' button directly underneath clue
  401. (function relicHunterHintTravel() {
  402. const hintMap = {
  403. "Standing on the other side of a green and purple portal.":
  404. "Acolyte Realm",
  405. "Inside an elaborate one-way trap designed by Plankrun.": "Acolyte Realm",
  406. "Outside a smoky purple tower.": "Acolyte Realm",
  407. "Roaming amongst the most powerful of Lich mice.": "Balack's Cove",
  408. "Lurking in a damp and darkened grotto.": "Balack's Cove",
  409. "Searching for the best deals in the Burroughs.": "Bazaar",
  410. "Ducking between stalls and tents and loud merchants.": "Bazaar",
  411. "Under the pointiest tent in all the Kingdom!": "Bazaar",
  412. "Hobnobbing with giants.": "Bountiful Beanstalk",
  413. "Infiltrating a lofty castle.": "Bountiful Beanstalk",
  414. "Taking a relaxing hike through a forested area.": "Calm Clearing",
  415. "By a peaceful rock in a grassy clearing.": "Calm Clearing",
  416. "Tucked behind dense trees where it's quiet and peaceful.":
  417. "Calm Clearing",
  418. "Watching the peaceful gathering of tribal mice.": "Cape Clawed",
  419. "On a small bit of land near a volcano.": "Cape Clawed",
  420. "Listening for sinister secrets deep underground.": "Catacombs",
  421. "Walking through dark hallways in search of a Keeper's Candle.":
  422. "Catacombs",
  423. "Keeping an eye on the long-arm of the law.": "Claw Shot City",
  424. "Spitting in a spittoon! Yuck!": "Claw Shot City",
  425. "Leafing through ancient tomes of knowledge.": "Crystal Library",
  426. "Expanding knowledge and climbing endless ladders.": "Crystal Library",
  427. "Ankle deep in rocky, tropical sand.": "Derr Dunes",
  428. "Tumbling down hills of rreD sand.": "Derr Dunes",
  429. "Practicing an ancient art with fledgling warriors.": "Dojo",
  430. "Safely inside the bottom floor of a bamboo building.": "Dojo",
  431. "Carefully watching the training activities of advanced students.":
  432. "Dojo",
  433. "Near the bluE waters of the island.": "Elub Shore",
  434. "Watching the calm waters of Rodentia while remaining safely ashore.":
  435. "Elub Shore",
  436. "Marching through the Sandtail Desert.": "Fiery Warpath",
  437. "Dodging arrows, spears, swords, and spells!": "Fiery Warpath",
  438. "Investigating what can be built in a workshop.": "Floating Islands",
  439. "Searching the skies for treasure.": "Floating Islands",
  440. "Peering through an oculus.": "Floating Islands",
  441. "In the clouds above Hollow Heights.": "Floating Islands",
  442. "Watching hunters' dirigibles fly by.": "Floating Islands",
  443. "Avoiding falling victim to Sky Pirates.": "Floating Islands",
  444. "Trapped between two planes of existence.": "Forbidden Grove",
  445. "Behind heavy stone gates.": "Forbidden Grove",
  446. "Reaping what she sowed...": "Foreword Farm",
  447. "Cultivating a hearty yield...": "Foreword Farm",
  448. "Toiling away in fertile fields...": "Foreword Farm",
  449. "Carefully navigating a subterranean and humid environment.":
  450. "Fungal Cavern",
  451. "Deep inside of an infested, glowing, twisting, unending cave of untold riches...":
  452. "Fungal Cavern",
  453. "Tracing the deep patterns of bark growing on ancient towers.":
  454. "Great Gnarled Tree",
  455. "By a tree older than Gnawnia itself.": "Great Gnarled Tree",
  456. "Finding shade in the largest tree in the Kingdom.": "Great Gnarled Tree",
  457. "Near the loud and low horns and the dinging of bells.": "Harbour",
  458. "Visiting where many new hunters seek out seafaring mice.": "Harbour",
  459. "By the sea where there's plenty of fresh air and sunshine.": "Harbour",
  460. "Where royal strength rewards hunting prowess.": "King's Arms",
  461. "Under a circular roof atop arm-shared paths.": "King's Arms",
  462. "Browsing wares available with a most royal currency.": "King's Arms",
  463. "Climbing up spiralling, menacing stairs.": "King's Gauntlet",
  464. "Trekking up a massive tower in Valour.": "King's Gauntlet",
  465. "Atop a tall tower with the perfect view of an Eclipse.":
  466. "King's Gauntlet",
  467. "Performing bizarre experiments and chemical reactions.": "Laboratory",
  468. "Where the powerful and strange breeds of mice first arose.":
  469. "Laboratory",
  470. "Amongst brightly glowing potions.": "Laboratory",
  471. "Waist-deep in a shallow, sparkling pond.": "Lagoon",
  472. "Amongst sparkling, still water.": "Lagoon",
  473. "Climbing jagged rocks and slick moss.": "Lagoon",
  474. "Tending to a most troublesome and dangerous garden.": "Living Garden",
  475. "Enjoying a drink on the overgrown rooftop patio.": "Living Garden",
  476. "Looking across vast landscapes and the many horizons of the land.":
  477. "Mountain",
  478. "Cutting through the pass to reach the town on the other side.":
  479. "Mountain",
  480. "In a treacherous environment where only the toughest of mice survive.":
  481. "Mountain",
  482. "Investigating the spirits of slain mice.": "Mousoleum",
  483. "Surveying where scientists harvest 'spare parts'.": "Mousoleum",
  484. "Studying the spooky remains of Zombie Mice.": "Mousoleum",
  485. "Climbing and exploring some long lost ruins.": "Moussu Picchu",
  486. "Up high upon a weather changing plateau.": "Moussu Picchu",
  487. "Visiting a walled city that is no stranger to sieges.": "Muridae Market",
  488. "Keeping a close eye on would-be thieves...": "Muridae Market",
  489. "Investigating a well-seasoned Gumbo Cheese.": "Nerg Plains",
  490. "Running through flat fields of greeN.": "Nerg Plains",
  491. "Reeling it in...": "Prologue Pond",
  492. "Choosing the right tackle...": "Prologue Pond",
  493. "Enjoying a quick dip in a cheesy bath.": "Queso River",
  494. "Sipping delicious liquid cheese from a river.": "Queso River",
  495. "Protecting her ears from the sound of loud pumps.": "Queso River",
  496. "Testing out balance on the high seas.": "S.S. Huntington IV",
  497. "Looking a bit queasy...": "S.S. Huntington IV",
  498. "Watching the sky and wondering what the weather will bring.":
  499. "Seasonal Garden",
  500. "Braving the ever-changing elements.": "Seasonal Garden",
  501. "Walking along the coldest waters in Gnawnia.": "Slushy Shoreline",
  502. "At the beachside site of an invasion force!": "Slushy Shoreline",
  503. "Shivering near the edges of the mainland.": "Slushy Shoreline",
  504. "Walking along the bottom of the Rodentia Ocean.": "Sunken City",
  505. "Investigating powerful diving equipment.": "Sunken City",
  506. "Sitting down at a wooden table...": "Table of Contents",
  507. "Creating clever characters...": "Table of Contents",
  508. "Amongst the triumphant trumpets of master hunters of old.":
  509. "Tournament Hall",
  510. "Browsing the rewards of competitive champions.": "Tournament Hall",
  511. "Competing for the limelight amongst the finest champions.":
  512. "Tournament Hall",
  513. "Exploring the deep and winding caverns near a technologically-advanced underground city.":
  514. "Town of Digby",
  515. "Amongst powerful drills and excavation equipment.": "Town of Digby",
  516. "Hiding in the shadows while standing in the limelight.": "Town of Digby",
  517. "Hiding within the hustle and bustle in the city of the crown.":
  518. "Town of Gnawnia",
  519. "Trying to spot the King himself.": "Town of Gnawnia",
  520. "In a town with a dense population.": "Town of Gnawnia",
  521. "Standing among the ranks of new students out in the field.":
  522. "Training Grounds",
  523. "Watching the careful training of artful students.": "Training Grounds",
  524. "Relaxing in the shade of tall engraved rock.": "Training Grounds",
  525. "Observing the churning and grinding of the new harvest.": "Windmill",
  526. "By an agricultural structure once owned by one of Gnawnia's most prosperous farmers.":
  527. "Windmill",
  528. "Grinding up hundreds of tiny seeds from a stalky, golden plant.":
  529. "Windmill"
  530. };
  531.  
  532. // MutationObserver logic for map UI
  533. // Observers are attached to a *specific* element (will DC if removed from DOM)
  534. const observerTarget = document.getElementById("overlayPopup");
  535. if (observerTarget) {
  536. MutationObserver =
  537. window.MutationObserver ||
  538. window.WebKitMutationObserver ||
  539. window.MozMutationObserver;
  540.  
  541. const observer = new MutationObserver(function () {
  542. // Render if Relic Hunter hint is available
  543. const rhHint = observerTarget.querySelector(
  544. ".treasureMapInventoryView-relicHunter-hint"
  545. );
  546.  
  547. // Prevent conflict with 'Mapping Helper'
  548. const mapTab = observerTarget.querySelector(
  549. ".treasureMapManagerView-header-navigation-item.tasks.active"
  550. );
  551.  
  552. // Prevent conflict with 'Bulk Map Invites'
  553. const inviteHeader = document.querySelector(
  554. // ".treasureMapPopup-inviteFriend-header"
  555. ".treasureMapManagerDialogView-userSelector"
  556. );
  557.  
  558. if (rhHint && !mapTab && !inviteHeader) {
  559. // Disconnect and reconnect later to prevent infinite mutation loop
  560. observer.disconnect();
  561.  
  562. render();
  563.  
  564. observer.observe(observerTarget, {
  565. childList: true,
  566. subtree: true
  567. });
  568. }
  569. });
  570.  
  571. observer.observe(observerTarget, {
  572. childList: true,
  573. subtree: true
  574. });
  575. }
  576.  
  577. function render() {
  578. document.querySelectorAll(".tsitu-rh-helper").forEach(el => el.remove());
  579.  
  580. const div = document.createElement("div");
  581. div.style.textAlign = "center";
  582. div.className = "tsitu-rh-helper";
  583. const button = document.createElement("a");
  584. button.href = "#";
  585. button.className = "mousehuntActionButton small";
  586. const locSpan = document.createElement("span");
  587. locSpan.style.fontSize = "12px";
  588. locSpan.innerText = "N/A";
  589.  
  590. const rhHint = observerTarget.querySelector(
  591. ".treasureMapInventoryView-relicHunter-hint"
  592. );
  593. const hint = rhHint.textContent;
  594. Object.keys(hintMap).forEach(key => {
  595. const loc = hintMap[key];
  596. if (hint == key) {
  597. locSpan.innerText = `Location: ${loc}`;
  598. button.onclick = function () {
  599. const newWindow = window.open(
  600. "https://www.mousehuntgame.com/travel.php?tab=map"
  601. );
  602. newWindow.addEventListener("load", function () {
  603. const hud = newWindow.document.querySelector(
  604. ".mousehuntHud-page-tabContent[data-tab='map']"
  605. );
  606. if (hud && hud.classList.contains("full")) {
  607. newWindow.document
  608. .querySelectorAll(
  609. ".travelPage-map-region-environment-link-name"
  610. )
  611. .forEach(el => {
  612. if (el.textContent == loc) {
  613. el.click();
  614. }
  615. });
  616.  
  617. const scrollTo = newWindow.document.querySelector(
  618. ".travelPage-map-simpleToggle.full"
  619. );
  620. if (scrollTo) {
  621. scrollTo.scrollIntoView({
  622. behavior: "auto",
  623. block: "nearest",
  624. inline: "nearest"
  625. });
  626. }
  627. }
  628. });
  629. return false;
  630. };
  631. }
  632. });
  633.  
  634. const buttonText = document.createElement("span");
  635. buttonText.innerText = "Travel";
  636. button.appendChild(buttonText);
  637.  
  638. div.appendChild(button);
  639. div.appendChild(locSpan);
  640. rhHint.insertAdjacentElement("afterend", div);
  641. }
  642. })();
  643. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址