// ==UserScript== // @name MouseHunt - QoL Utilities // @author Tran Situ (tsitu) // @namespace https://greasyfork.org/en/users/232363-tsitu // @version 1.0 // @description Miscellaneous utilities to turbo-charge your MH experience // @match http://www.mousehuntgame.com/* // @match https://www.mousehuntgame.com/* // @downloadURL none // ==/UserScript== (function () { /** * TODO: Alert when sounding horn after unseen trap check (user set 00, 15, 30, 45) to avoid wasted hunt if TC'd something * TODO: Track outbound supply transfers */ // TODO: Claim-time map participants/duster tracker (move to mapping helper?) (function mapTracker() { const map = temp1; if (map.can_claim_reward && map.is_complete) { // } const data = {}; map.hunters.forEach(hunter => { if (hunter.is_active) { data[hunter.user_id] = { name: hunter.name }; const completedItems = hunter.completed_goal_ids.item; const completedMice = hunter.completed_goal_ids.mouse; if (completedItems.length > 0) { data[hunter.user_id].i = completedItems.length; } if (completedMice.length > 0) { data[hunter.user_id].m = completedMice.length; } if (hunter.upgrader) { data[hunter.user_id].d = true; } } }); console.log(data); }); (function lockConvertibleButtons() { // Observe for 'Special' tab of Inventory const observerTarget = document.querySelector(".mousehuntPage-content"); if (observerTarget) { MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; const observer = new MutationObserver(function () { const isSpecial = observerTarget.querySelector( ".mousehuntHud-page-tabContent.special.active" ); if (isSpecial) { // Disconnect and reconnect later to prevent infinite mutation loop observer.disconnect(); render(); observer.observe(observerTarget, { childList: true, subtree: true }); } }); observer.observe(observerTarget, { childList: true, subtree: true }); } function render() { document .querySelectorAll(".tsitu-lock-convertible") .forEach(el => el.remove()); const convertibles = document.querySelectorAll( ".inventoryPage-item.full.convertible" ); if (convertibles.length > 0) { // Apply cached locks on page load const cacheRaw = localStorage.getItem("tsitu-convertible-locks"); if (cacheRaw) { const cache = JSON.parse(cacheRaw); convertibles.forEach(el => { const id = el.getAttribute("data-item-id"); if (cache.indexOf(id) >= 0) { el.querySelectorAll( ".inventoryPage-item-content-action .button" ).forEach(button => { if (!button.classList.contains("disabled")) { button.classList.toggle("disabled"); } }); } }); } // Generate individual item lock buttons convertibles.forEach(el => { const a = document.createElement("a"); a.href = "#"; a.className = "inventoryPage-item-larryLexicon tsitu-lock-convertible"; a.style.right = "22px"; a.style.height = "15px"; a.innerText = "🔒"; a.onclick = function () { el.querySelectorAll( ".inventoryPage-item-content-action .button" ).forEach(button => { button.classList.toggle("disabled"); }); updateLockCache(); return false; }; const target = el.querySelector(".inventoryPage-item-name"); if (target) target.insertAdjacentElement("afterend", a); }); function updateLockCache() { const cacheArr = []; convertibles.forEach(el => { const button = el.querySelector( ".inventoryPage-item-content-action .button" ); if (button.classList.contains("disabled")) { cacheArr.push(el.getAttribute("data-item-id")); } }); localStorage.setItem( "tsitu-convertible-locks", JSON.stringify(cacheArr) ); } // Add buttons for [un]locking entire tabs const lockableTabs = [ "Baskets & Kits", "Scrolls, Posters, Assignments", "Spring Egg Hunt", "Treasure Chests" ]; observerTarget .querySelectorAll(".inventoryPage-tagContent-tagGroup.clear-block") .forEach(tab => { const tabType = tab.getAttribute("data-name"); if (lockableTabs.indexOf(tabType) >= 0) { const span = document.createElement("span"); span.className = "inventoryPage-tagContent-tagTitle tsitu-lock-convertible"; span.style.margin = "5px 0 5px 0"; const lockAll = document.createElement("button"); lockAll.innerText = "Lock Tab"; lockAll.onclick = function () { if ( confirm( `Are you sure you'd like to lock all convertibles on this tab?\n\n- ${tabType}` ) ) { tab .querySelectorAll( ".inventoryPage-item-content-action .button" ) .forEach(button => { if (!button.classList.contains("disabled")) { button.classList.toggle("disabled"); } }); updateLockCache(); } }; const unlockAll = document.createElement("button"); unlockAll.innerText = "Unlock Tab"; unlockAll.onclick = function () { if ( confirm( `Are you sure you'd like to unlock all convertibles on this tab?\n\n- ${tabType}` ) ) { tab .querySelectorAll( ".inventoryPage-item-content-action .button" ) .forEach(button => { if (button.classList.contains("disabled")) { button.classList.toggle("disabled"); } }); updateLockCache(); } }; span.appendChild(lockAll); span.appendChild(document.createTextNode("\u00A0\u00A0")); span.appendChild(unlockAll); const target = tab.querySelector( ".inventoryPage-tagContent-tagTitle" ); if (target) target.appendChild(span); } }); } } })(); (function relicHunterHintTravel() { const hintMap = { "Standing on the other side of a green and purple portal.": "Acolyte Realm", "Inside an elaborate one-way trap designed by Plankrun.": "Acolyte Realm", "Outside a smoky purple tower.": "Acolyte Realm", "Roaming amongst the most powerful of Lich mice.": "Balack's Cove", "Lurking in a damp and darkened grotto.": "Balack's Cove", "Searching for the best deals in the Burroughs.": "Bazaar", "Ducking between stalls and tents and loud merchants.": "Bazaar", "Under the pointiest tent in all the Kingdom!": "Bazaar", "Taking a relaxing hike through a forested area.": "Calm Clearing", "By a peaceful rock in a grassy clearing.": "Calm Clearing", "Tucked behind dense trees where it's quiet and peaceful.": "Calm Clearing", "Watching the peaceful gathering of tribal mice.": "Cape Clawed", "On a small bit of land near a volcano.": "Cape Clawed", "Listening for sinister secrets deep underground.": "Catacombs", "Walking through dark hallways in search of a Keeper's Candle.": "Catacombs", "Keeping an eye on the long-arm of the law.": "Claw Shot City", "Spitting in a spittoon! Yuck!": "Claw Shot City", "Leafing through ancient tomes of knowledge.": "Crystal Library", "Expanding knowledge and climbing endless ladders.": "Crystal Library", "Ankle deep in rocky, tropical sand.": "Derr Dunes", "Tumbling down hills of rreD sand.": "Derr Dunes", "Practicing an ancient art with fledgling warriors.": "Dojo", "Safely inside the bottom floor of a bamboo building.": "Dojo", "Carefully watching the training activities of advanced students.": "Dojo", "Near the bluE waters of the island.": "Elub Shore", "Watching the calm waters of Rodentia while remaining safely ashore.": "Elub Shore", "Marching through the Sandtail Desert.": "Fiery Warpath", "Dodging arrows, spears, swords, and spells!": "Fiery Warpath", "Trapped between two planes of existence.": "Forbidden Grove", "Behind heavy stone gates.": "Forbidden Grove", "Carefully navigating a subterranean and humid environment.": "Fungal Cavern", "Deep inside of an infested, glowing, twisting, unending cave of untold riches...": "Fungal Cavern", "Tracing the deep patterns of bark growing on ancient towers.": "Great Gnarled Tree", "By a tree older than Gnawnia itself.": "Great Gnarled Tree", "Finding shade in the largest tree in the Kingdom.": "Great Gnarled Tree", "Near the loud and low horns and the dinging of bells.": "Harbour", "Visiting where many new hunters seek out seafaring mice.": "Harbour", "By the sea where there's plenty of fresh air and sunshine.": "Harbour", "Where royal strength rewards hunting prowess.": "King's Arms", "Under a circular roof atop arm-shared paths.": "King's Arms", "Browsing wares available with a most royal currency.": "King's Arms", "Climbing up spiralling, menacing stairs.": "King's Gauntlet", "Trekking up a massive tower in Valour.": "King's Gauntlet", "Atop a tall tower with the perfect view of an Eclipse.": "King's Gauntlet", "Performing bizarre experiments and chemical reactions.": "Laboratory", "Where the powerful and strange breeds of mice first arose.": "Laboratory", "Amongst brightly glowing potions.": "Laboratory", "Waist-deep in a shallow, sparkling pond.": "Lagoon", "Amongst sparkling, still water.": "Lagoon", "Climbing jagged rocks and slick moss.": "Lagoon", "Tending to a most troublesome and dangerous garden.": "Living Garden", "Enjoying a drink on the overgrown rooftop patio.": "Living Garden", "Looking across vast landscapes and the many horizons of the land.": "Mountain", "Cutting through the pass to reach the town on the other side.": "Mountain", "In a treacherous environment where only the toughest of mice survive.": "Mountain", "Investigating the spirits of slain mice.": "Mousoleum", "Surveying where scientists harvest 'spare parts'.": "Mousoleum", "Studying the spooky remains of Zombie Mice.": "Mousoleum", "Climbing and exploring some long lost ruins.": "Moussu Picchu", "Up high upon a weather changing plateau.": "Moussu Picchu", "Visiting a walled city that is no stranger to sieges.": "Muridae Market", "Keeping a close eye on would-be thieves...": "Muridae Market", "Investigating a well-seasoned Gumbo Cheese.": "Nerg Plains", "Running through flat fields of greeN.": "Nerg Plains", "Enjoying a quick dip in a cheesy bath.": "Queso River", "Sipping delicious liquid cheese from a river.": "Queso River", "Protecting her ears from the sound of loud pumps.": "Queso River", "Testing out balance on the high seas.": "S.S. Huntington IV", "Looking a bit queasy...": "S.S. Huntington IV", "Watching the sky and wondering what the weather will bring.": "Seasonal Garden", "Braving the ever-changing elements.": "Seasonal Garden", "Walking along the coldest waters in Gnawnia.": "Slushy Shoreline", "At the beachside site of an invasion force!": "Slushy Shoreline", "Shivering near the edges of the mainland.": "Slushy Shoreline", "Walking along the bottom of the Rodentia Ocean.": "Sunken City", "Investigating powerful diving equipment.": "Sunken City", "Amongst the triumphant trumpets of master hunters of old.": "Tournament Hall", "Browsing the rewards of competitive champions.": "Tournament Hall", "Competing for the limelight amongst the finest champions.": "Tournament Hall", "Exploring the deep and winding caverns near a technologically-advanced underground city.": "Town of Digby", "Amongst powerful drills and excavation equipment.": "Town of Digby", "Hiding in the shadows while standing in the limelight.": "Town of Digby", "Hiding within the hustle and bustle in the city of the crown.": "Town of Gnawnia", "Trying to spot the King himself.": "Town of Gnawnia", "In a town with a dense population.": "Town of Gnawnia", "Standing among the ranks of new students out in the field.": "Training Grounds", "Watching the careful training of artful students.": "Training Grounds", "Relaxing in the shade of tall engraved rock.": "Training Grounds", "Observing the churning and grinding of the new harvest.": "Windmill", "By an agricultural structure once owned by one of Gnawnia's most prosperous farmers.": "Windmill", "Grinding up hundreds of tiny seeds from a stalky, golden plant.": "Windmill" }; // MutationObserver logic for map UI // Observers are attached to a *specific* element (will DC if removed from DOM) const observerTarget = document.getElementById("overlayPopup"); if (observerTarget) { MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; const observer = new MutationObserver(function () { // Render if Relic Hunter hint is available const rhHint = observerTarget.querySelector( ".treasureMapInventoryView-relicHunter-hint" ); // Prevent conflict with 'Mapping Helper' const mapTab = observerTarget.querySelector( ".treasureMapManagerView-header-navigation-item.tasks.active" ); // Prevent conflict with 'Bulk Map Invites' const inviteHeader = document.querySelector( // ".treasureMapPopup-inviteFriend-header" ".treasureMapManagerDialogView-userSelector" ); if (rhHint && !mapTab && !inviteHeader) { // Disconnect and reconnect later to prevent infinite mutation loop observer.disconnect(); render(); observer.observe(observerTarget, { childList: true, subtree: true }); } }); observer.observe(observerTarget, { childList: true, subtree: true }); } function render() { document.querySelectorAll(".tsitu-rh-helper").forEach(el => el.remove()); const div = document.createElement("div"); div.style.textAlign = "center"; div.className = "tsitu-rh-helper"; const button = document.createElement("a"); button.href = "#"; button.className = "mousehuntActionButton small"; const locSpan = document.createElement("span"); locSpan.style.fontSize = "12px"; locSpan.innerText = "N/A"; const rhHint = observerTarget.querySelector( ".treasureMapInventoryView-relicHunter-hint" ); const hint = rhHint.textContent; Object.keys(hintMap).forEach(key => { const loc = hintMap[key]; if (hint == key) { locSpan.innerText = `Location: ${loc}`; button.onclick = function () { const newWindow = window.open( "https://www.mousehuntgame.com/travel.php?tab=map" ); newWindow.addEventListener("load", function () { const hud = newWindow.document.querySelector( ".mousehuntHud-page-tabContent[data-tab='map']" ); if (hud && hud.classList.contains("full")) { newWindow.document .querySelectorAll( ".travelPage-map-region-environment-link-name" ) .forEach(el => { if (el.textContent == loc) { el.click(); } }); const scrollTo = newWindow.document.querySelector( ".travelPage-map-simpleToggle.full" ); if (scrollTo) { scrollTo.scrollIntoView({ behavior: "auto", block: "nearest", inline: "nearest" }); } } }); return false; }; } }); const buttonText = document.createElement("span"); buttonText.innerText = "Travel"; button.appendChild(buttonText); div.appendChild(button); div.appendChild(locSpan); rhHint.insertAdjacentElement("afterend", div); } })(); })();