您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Misc enhancements for kingdom of loathing
当前为
// ==UserScript== // @name KoLE2-alpha // @namespace fnoot/kol/kole2-alpha // @description Misc enhancements for kingdom of loathing // @include http://www.kingdomofloathing.com/* // @version 0.1 // @grant none // ==/UserScript== (function() { var saveSettings = function() { localStorage.kole2Settings = JSON.stringify(top.kole.userSettings); }; // used by getSetting() when called before top.kole is initialised var userSettingsPreload = typeof localStorage.kole2Settings == "undefined" ? {} : JSON.parse(localStorage.kole2Settings); var controlTypes = { input: function(name, spec, parent) { var input = crel("input", {}, parent); input.id = "kole_config_" + name; var setValue = function() { if (spec.onchange) spec.onchange(input.value); top.kole.userSettings[name] = input.value; saveSettings(); }; input.value = getSetting(name); input.onkeyup = setValue; input.onpaste = setValue; }, yesno: function(name, spec, parent) { var select = crel("select", {}, parent); select.id = "kole_config_" + name; with(crel("option", {}, select)) { innerHTML = "Yes"; value = 1; } with(crel("option", {}, select)) { innerHTML = "No"; value = 0; } select.selectedIndex = getSetting(name) ? 0 : 1; select.onchange = function() { top.kole.userSettings[name] = this.selectedIndex == 0; saveSettings(); }; }, check: function(name, spec, parent) { var cbox = crel("input", {}, parent); cbox.checked = getSetting(name); cbox.id = "kole_config_" + name; cbox.type = "checkbox"; cbox.onclick = function() { top.kole.userSettings[name] = this.checked; saveSettings(); if (spec.onchange) spec.onchange(); } }, spin: function(name, spec, parent) { var min = spec.range[0], max = spec.range[1]; var value = getSetting(name); var displayCallback = spec.displayCallback || function(v) { return v; }; var downButton = crel("button", {}, parent); downButton.innerHTML = "<"; var valueSpan = crel("span", { display: "inline-block", "margin": "0 6px", "width": "50px", "text-align": "center" }, parent); var fixPrecision = function() { value = Math.round(value * 100) / 100; } valueSpan.innerHTML = displayCallback(value); var upButton = crel("button", {}, parent); upButton.innerHTML = ">"; downButton.onclick = function() { value -= spec.step; fixPrecision(); if (value < min) value = min; valueSpan.innerHTML = displayCallback(value); top.kole.userSettings[name] = value; if (spec.onchange) spec.onchange(value); saveSettings(); }; upButton.onclick = function() { value += spec.step; fixPrecision(); if (value > max) value = max; valueSpan.innerHTML = displayCallback(value); top.kole.userSettings[name] = value; if (spec.onchange) spec.onchange(value); saveSettings(); }; }, button: function(name, spec, parent) { with(crel("a", {}, parent)) { onclick = function() { spec.onclick(); return false; }; href = "#" + name; innerHTML = spec.buttonCaption; } }, raw: function(name, spec, parent) { parent.innerHTML = spec.html; } }; var getSetting = function(name) { var source = typeof top.kole == "undefined" || top.kole == null || typeof top.kole.userSettings == "undefined" ? userSettingsPreload : top.kole.userSettings; return typeof source[name] == "undefined" ? configOptions[name].default : source[name]; }; var itemLookup = function(fuzzyName) { if (!top.kole) return null; var matches = []; var item = null; for (var name in top.kole.itemIds) { if (name.trim().toUpperCase().indexOf(fuzzyName.toUpperCase()) > -1) { if (name.toLowerCase() == fuzzyName.toLowerCase()) { return { name: name, id: top.kole.itemIds[name] }; } matches.push({ name: name, id: top.kole.itemIds[name] }); } } if (matches.length > 1) { return { error: "Multiple matches for \"" + fuzzyName + "\". Please be more specific." }; } else if (matches.length == 1) { return matches[0]; } return null; }; var configOptions = { hoverHints: { default: true, control: "check", caption: "Hover hints", description: "Shows information about an item/effect/icon when the mouse pointer hovers over it" }, hintDelay: { default: 230, caption: "Hint delay (milliseconds)", description: "Specifies how long you need to hover over an item/effect/icon before its description is shown", control: "spin", range: [0, 2000], step: 25 }, darkness: { default: 0.35, caption: "Darkness", description: "Darkens the whole game; great for headaches and photosensitives!", control: "spin", range: [0, 0.8], step: 0.1, onchange: function(value) { top.kole.setDarkness(value); }, displayCallback: function(value) { return ((value / 0.8) * 100).toFixed(1).replace(/(\d+)\.0+$/, '$1') + "%"; } }, stayLoggedIn: { default: true, caption: "Stay logged in", description: "Defeats the timeout that logs you out after an idle period by sending a dummy request every two minutes", control: "check", onchange: function(value) { if (value) xhr("main.php", function() {}, false); } }, nullifySword: { default: true, caption: "Fix prepositions", description: "Undoes the effect of the Sword", control: "check" }, autoFight: { default: false, caption: "Automatic fighting", description: "Always clicks the last item in the combat bar or \"Adventure again\" when available; requires combat bar enabled in KoL options", control: "check" }, autoFightDelay: { default: 4000, caption: "Automatic fighting delay", description: "Defines how long to wait before taking an automatic action in a fight", control: "spin", range: [1000, 10000], step: 500, displayCallback: function(v) { return (v / 1000) + "sec"; } }, chatHelp: { caption: "Chat commands", buttonCaption: "Show", "description": "Shows a list of chat commands added by KoLE", "control": "button", onclick: function() { var pop = crel("div", { padding: "12px" }); crel("h1", { margin: "0 0 12px 0", "font-weight": "100" }, pop).innerHTML = "KoLE Chat Commands"; crel("p", { "font-size": "small" }, pop).innerHTML = "These commands require <i>Modern</i> chat version selected in <a href='account.php?tab=chat'>KoL options</a>"; pop.appendChild(tabulate([ ["<code>/wiki <searchterm></code>", "Search Coldfront KoL wiki"], ["<code>/qs [amount] <itemname></code>", "Quicksell item"] ], "rgba(0,0,0,0.06")); poop(pop); } }, donate: { caption: "Appreciation", control: "raw", description: "I am poorly and well below the poverty line. Has this been useful?", html: '<form target="_blank" action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top" style="margin:none;padding:none;display:inline">' + '<input type="hidden" name="cmd" value="_s-xclick">' + '<input type="hidden" name="hosted_button_id" value="G33Q3HVDX4G3Y">' + '<input type="submit" value="Show via PayPal" src="https://www.paypalobjects.com/en_GB/i/btn/btn_donate_SM.gif" border="0" name="submit">' + '<img alt="" border="0" src="https://www.paypalobjects.com/en_GB/i/scr/pixel.gif" width="1" height="1">' + '</form>' } }; var prepositions = ["about", "above", "across", "after", "against", "along", "among", "around", "at", "before", "behind", "below", "beneath", "beside", "between", "beyond", "by", "down", "during", "except", "for", "from", "in", "inside", "into", "like", "near", "of", "off", "on", "onto", "out", "outside", "over", "past", "through", "throughout", "to", "under", "up", "upon", "with", "within", "without" ]; var nullifySword = function(s) { for (var i = 0; i < prepositions.length; i++) { var prep = prepositions[i]; var search = new RegExp(" " + prep, "g"); s = s.replace(search, "\x09" + prep); var search = new RegExp(prep + " ", "g"); s = s.replace(search, prep + "\x09"); } return s; }; var tabulate = function(data, altColour) { var table = crel("table", { width: "100%", "font-size": "small" }); table.setAttribute("cellspacing", 0); table.setAttribute("cellpadding", 4); var tb = crel("tbody", {}, table); if (data.length == 0) return table; var alt = false; for (var i = 0; i < data.length; i++) { var row = data[i]; var tr = crel("tr", {}, tb); if (alt) tr.style.background = altColour; alt = !alt; for (var x = 0; x < row.length; x++) { var td = crel("td", {}, tr); td.innerHTML = row[x]; } } return table; }; var applyStyles = function(el, styles) { for (var k in styles) { el.style.setProperty(k, styles[k]); //lazily prepend browser-specific prefixes el.style.setProperty("-moz-" + k, styles[k]); el.style.setProperty("-webkit-" + k, styles[k]); } }; // document.createElement > applyStyles > parent.append shortcut var crel = function(tag, styles, parent) { var el = document.createElement(tag); if (typeof styles != "undefined") applyStyles(el, styles); if (typeof parent != "undefined") parent.appendChild(el); return el; }; var elX = function(el) { return el.offsetParent ? elX(el.offsetParent) + el.offsetLeft : el.offsetLeft; }; var elY = function(el) { return el.offsetParent ? elY(el.offsetParent) + el.offsetTop : el.offsetTop; }; var darkCover = crel("div", { "position": "fixed", "top": "0", "left": "0", "right": "0", "bottom": "0", "background": "#000", "opacity": 0, "pointer-events": "none", "z-index": 999999, }, document.body); var hintBox = crel("div", { "position": "absolute", "width": "260px", "padding": "12px 0px", "border": "1px #bbb solid", "border-radius": "5px", "box-shadow": "2px 2px 3px rgba(0,0,0,0.4)", "pointer-events": "none", "background": "#fff", "opacity": 0, "transform": "scale(0.1,0.1)", "transition": "100ms opacity ease-out, 100ms transform ease-out, 100ms -moz-transform ease-out, 100ms -webkit-transform ease-out", "z-index": 999998, "font-size": "small" }, document.body); setTimeout(function() { darkCover.style.transition = "600ms opacity"; }); var initialHintWidth = hintBox.clientWidth; var showHint = function(forEl, html) { forX = elX(forEl); forY = elY(forEl); hintBox.innerHTML = html; hintBox.style.width = initialHintWidth + "px"; hintBox.style.left = forX + forEl.clientWidth + 12 + "px"; if ((elX(hintBox) + hintBox.clientWidth) > document.body.clientWidth) { hintBox.style.width = document.body.clientWidth - elX(hintBox) + "px"; } // hintBox.style.left = (forX+forEl.clientWidth+12+hintBox.clientWidth) > document.body.clientWidth // ? forX - (hintBox.clientWidth +12)+"px" // : forX +forEl.clientWidth +12+"px"; hintBox.style.top = (forY + (hintBox.clientHeight * 1.5)) > document.body.scrollHeight ? document.body.scrollHeight - (hintBox.clientHeight * 1.5) + "px" : forY + "px"; crel("div", { background: "rgba(100, 150, 255,0.04)", "position": "absolute", "box-shadow": "0 0 22px rgba(100, 150, 255,0.09)", "top": "42px", "left": "0", "right": "0", "bottom": "0" }, hintBox); applyStyles(hintBox, { opacity: 1, transform: "scale(1,1)" }); hintElement = forEl; }; var hintTimer = null; var hintElement = null; var xhr = function(url, callback, cached) { if (cached && typeof top.kole.xhrCache[url] != "undefined") { setTimeout(function() { callback(top.kole.xhrCache[url]); }, 0); return { cancel: function() {} }; }; var canceled = false; var req = new XMLHttpRequest(); var stateChange = function() { if (this.readyState == 4) { top.kole.xhrCache[url] = this.responseText; if (!canceled) callback(this.responseText); req.removeEventListener("readystatechange", stateChange); } }; req.addEventListener("readystatechange", stateChange, false); req.open("GET", url, true); req.send(); return { cancel: function() { canceled = true; } } }; var extractDescription = function(url, callback, cached) { return xhr(url, function(response) { var tempEl = crel("div"); tempEl.innerHTML = response; var scripts = tempEl.querySelectorAll("script"); for (var i = scripts.length - 1; i >= 0; i--) scripts[i].parentNode.removeChild(scripts[i]); callback(tempEl.querySelectorAll("#description")[0].innerHTML); }, cached); }; var cancelLastHintCallback = function() {}; var cancelHint = function() { cancelLastHintCallback(); if (hintTimer !== null) clearTimeout(hintTimer); applyStyles(hintBox, { opacity: 0, transform: "scale(0.9,0.9)" }); }; // htmlCallback(done(html)) should return {cancel:function(){...}} var setHintTimer = function(el, htmlCallback, ___args) { cancelHint(); // show when both timer AND callback async complete var asyncRemaining = 2; var hintHtml = ""; var asyncDone = function() { asyncRemaining--; if (asyncRemaining == 0) { showHint(el, hintHtml); } }; hintTimer = setTimeout(asyncDone, getSetting("hintDelay")); var cancelLastHintCallback = htmlCallback(function(html) { hintHtml = html; asyncDone(); }).cancel; }; if (window == top) { var whenReady = function(cb) { for (var i = 0; i < frames.length; i++) if (typeof frames[i].kole == "undefined") { setTimeout(function() { whenReady(cb); }, 200); return; } cb(); } if (typeof this.kole != "undefined") { alert("A browser plugin or KoL update is conflicting with KoLE"); return; } window.kole = null; whenReady(function() { window.kole = { setDarkness: function(darkness) { for (var i = 0; i < frames.length; i++) { frames[i].window.kole.setDarkness(darkness); } }, itemIds: typeof localStorage.itemIds == "undefined" ? {} : JSON.parse(localStorage.itemIds), xhrCache: {}, userSettings: userSettingsPreload }; }); } else { window.kole = { setDarkness: function(darkness) { darkCover.style.opacity = darkness + 0.00001; // fixes gre render bug }, top: top.kole }; kole.setDarkness(getSetting("darkness")); } var timedClick = function(el, delay, cancelCaption, oncancel) { var cancelButton = crel("button", { background: "#fff", border: "2px #000 solid", transition: delay + "ms box-shadow linear", "box-shadow": "inset 0 0 0 rgba(255,0,0,0.9)", position: "fixed", bottom: 0, right: 0, padding: "4px", width: "200px" }, document.body); applyStyles(el, { transition: delay + "ms box-shadow linear, " + delay + "ms border-color linear", "box-shadow": "inset 0 0 0 rgba(0,255,0,0.5)", "border-color": "rgba(0,255,0,0)" }); cancelButton.innerHTML = cancelCaption; var timer = setTimeout(function() { el.click(); }, delay + 100); setTimeout(function() { cancelButton.style.boxShadow = "inset 208px 0 0 rgba(255,0,0,1)"; el.style.boxShadow = "inset " + el.scrollWidth + "px 0 0 rgba(0,255,0,0.3)"; el.style.borderColor = "rgba(0,255,0,1)"; }, 100); window.CLICKEL = el; cancelButton.onclick = function() { if (oncancel) oncancel(); clearTimeout(timer); document.body.removeChild(cancelButton); }; }; if (window.name == "mainpane") { var openPanel = function() { koleButton.disabled = true; var panel = crel("div", { "position": "fixed", "top": "0", "left": "0", "right": "0", "max-height": "100%", "box-shadow": "0 0 8px rgba(0,0,0,0.6)", "border-bottom": "1px #888 solid", "transform": "scale(0.1,0.1)", "transform-origin": "100% 0", "padding": "12px", "overflow": "auto", "opacity": 0, "z-index": 9001, background: "#eef", "transition": "220ms all ease-in" }, document.body); crel("h1", { "font-weight": "100" }, panel).innerHTML = "KoLE Settings"; var settingsTable = crel("table", { "font-size": "small", "width": "100%", }, panel); settingsTable.setAttribute("cellpadding", 4); settingsTable.setAttribute("cellspacing", 0); var tbody = crel("tbody", {}, settingsTable); var alt = false; for (var name in configOptions) { alt = !alt; var spec = configOptions[name]; var tr = crel("tr", { background: alt ? "rgba(255,255,255,0.5)" : "transparent" }, tbody); var labelCell = crel("td", { height: "2em", "width": "200px", "vertical-align": "middle" }, tr); var label = crel("label", {}, labelCell); label.innerHTML = spec.caption; label.setAttribute("for", "kole_config_" + name); var editCell = crel("td", { "vertical-align": "middle" }, tr); controlTypes[spec.control](name, spec, editCell); if (spec.description) { var descTr = crel("tr", { "font-size": "0.8em", "color": "#666", background: alt ? "rgba(255,255,255,0.5)" : "transparent" }, tbody); var descTd = crel("td", {}, descTr); descTd.innerHTML = spec.description; descTd.setAttribute("colspan", 2); } } with(crel("p", { "font-size": "small" }, panel)) { innerHTML = "Kingdom of Loathing Enhancement <b>alpha</b> by <a href='showplayer.php?who=2362564'>fnoot</a><br>This is an <b>alpha testing</b> version; please report any problems by kmail."; } var closeButton = crel("button", { position: "absolute", top: 0, right: 0 }, panel); closeButton.innerHTML = "X"; closeButton.onclick = function() { koleButton.disabled = false; applyStyles(panel, { opacity: 0, "pointer-events": "none", transform: "scale(0.2,0.2)" }); setTimeout(function() { document.body.removeChild(panel); panel = null; }, 2000); }; setTimeout(function() { applyStyles(panel, { opacity: 1, transform: "scale(1,1)" }); }, 100) }; var koleButton = crel("button", { "position": "fixed", "top": "0", "right": "0", "z-index": 9000 }, document.body); with(koleButton) { innerHTML = "KoLE"; onclick = openPanel; } if (getSetting("autoFight")) { (function() { // auto fighting var links = document.querySelectorAll("a"); var adventureAgainRegex = /Adventure Again \(/; for (var i = 0; i < links.length; i++) { if (adventureAgainRegex.test(links[i].innerHTML)) { timedClick(links[i], getSetting("autoFightDelay"), "Cancel automatic fighting", function() { top.kole.userSettings.autoFight = false; saveSettings(); }); return; } } var button12 = document.getElementById("button12"); if (button12 != null) { timedClick(button12, getSetting("autoFightDelay"), "Cancel automatic fighting", function() { top.kole.userSettings.autoFight = false; saveSettings(); }); } })(); } setInterval(function() { if (getSetting("stayLoggedIn")) { xhr("main.php", function() {}, false); } }, 1000 * 60 * 2); var scanItems = function() { if (top.kole == null) return; var itemIds = top.kole.itemIds; var learnedItems = false; var itemCells = document.querySelectorAll(".stuffbox table.item .ircm"); for (var i = 0; i < itemCells.length; i++) { var cell = itemCells[i]; var itemName = cell.innerHTML; if (typeof itemIds[itemName] == "undefined") { learnedItems = true; itemIds[itemName] = cell.parentNode.id.replace(/i/, ''); // console.log("Learned item '"+itemName +"' id: "+itemIds[itemName]); } } if (learnedItems) localStorage.itemIds = JSON.stringify(itemIds); }; setInterval(scanItems, 3500); } // /mainpane if (window.name == "chatpane") { var chatLog = function(s) { handleMessage({ type: 'event', msg: "<span style='color:#08c'><span style='opacity:0.5'>[</span>kole<span style='opacity:0.5'>]</span></span> " + s }); }; var chatCommands = { wiki: function(args) { window.open("http://kol.coldfront.net/thekolwiki/index.php/Special:Search?search=" + encodeURIComponent(args.trim()) + "&go=Go"); }, qs: function(args) { args = args.trim(); var amountMatches = args.match(/(\d+|\*)\s+([\w\s]+)/); if (amountMatches && amountMatches.length > 1) { var amount = amountMatches[1]; args = amountMatches[2]; } else { var amount = 1; } var item = itemLookup(args); if (item === null) { chatLog("KoLE doesn't know that item! Teach it by opening your inventory."); } else if (item.error) { chatLog("" + item.error); } else { chatLog("Quickselling " + amount + " x " + item.name); dojax("sellstuff.php?action=sell&ajax=1&type=quant&whichitem%5B%5D=" + item.id + "&howmany=" + amount + "&pwd=" + pwdhash); } } } var previousOnload = window.onload; window.onload = function() { if (previousOnload) previousOnload.apply(this, arguments); var oldForm = document.getElementById('InputForm'); if (oldForm == null) return; oldForm = oldForm.parentNode; newForm = oldForm.cloneNode(true); newForm.style.background = "red"; oldForm.parentNode.replaceChild(newForm, oldForm); var old$inp = $inp; $inp = $$("#graf"); newForm.onsubmit = function(ev) { ev.preventDefault(); var inp = $inp.val(); var matches = inp.match(/^\/(\w+)(\s+(.*))?/); if (matches && matches.length > 0) { var cmd = matches[1]; if (typeof chatCommands[cmd] != "undefined") { $inp.val(""); chatCommands[cmd].call(this, matches.length > 1 ? matches[2] : undefined); return; } } old$inp.val(getSetting("nullifySword") ? nullifySword($inp.val()) : $inp.val()); $inp.val(""); submitchat(ev); }; }; }; var poop = function(htmlOrElement) { var cover = crel("div", { position: "fixed", top: 0, left: 0, right: 0, bottom: 0, background: "rgba(0,0,0,0.2)", opacity: 0, transition: "200ms all", "z-index": 9002 }); var win = crel("div", { width: "420px", margin: "9% auto 0 auto", background: "#fff", position: "relative", transform: "scale(3,3)", opacity: 0, transition: "300ms all", "box-shadow": "1px 1px 6px rgba(0,0,0,0.4)" }, cover); var winner = crel("div", { padding: "12px" }, win); if (typeof htmlOrElement == "string") { winner.innerHTML = htmlOrElement; } else { winner.appendChild(htmlOrElement) } with(crel("button", { position: "absolute", top: 0, right: 0 }, win)) { onclick = function() { cover.style.opacity = 0; applyStyles(win, { "transform": "scale(3,3)", opacity: 0 }); setTimeout(function() { document.body.removeChild(cover); }, 600); }; innerHTML = "X"; } document.body.appendChild(cover); setTimeout(function() { cover.style.opacity = 1; applyStyles(win, { "transform": "scale(1,1)", opacity: 1 }); }, 100); }; var applyHoverHints = function() { var els = document.querySelectorAll("a,img"); var onclickRegex = /\b(descitem|eff|javascript:poop)\("?([\w\.\?\=]+)"?\b(\s*,\s*(\w+)\b\))?/; for (var i = 0; i < els.length; i++) { var funcUrls = { descitem: "desc_item.php?whichitem=", eff: "desc_effect.php?whicheffect=", "javascript:poop": "" }; var onclick = els[i].getAttribute("onclick") + ""; var matches = onclick.match(onclickRegex); if (onclick && matches && (matches.length > 0)) { if (typeof els[i]['@kole2_hoverhint_init'] == "undefined") { els[i]['@kole2_hoverhint_init'] = true; els[i].style.cursor = "help"; els[i].title = ""; with({ func: matches[1], itemId: matches[2], otherPlayer: matches[4] }) { els[i].addEventListener("mouseenter", function() { cancelHint(); if (!getSetting("hoverHints")) return; hintElement = this; var query = typeof otherPlayer == "undefined" ? itemId : itemId + "&otherplayer=" + otherPlayer; setHintTimer(this, function(callback) { return extractDescription(funcUrls[func] + query, callback, true); }); }, false); els[i].addEventListener("mouseout", function() { if (this == hintElement) cancelHint(); }, false); } // with } // if not init } // if onclick match } // for i in els }; // applyHoverHints() applyHoverHints(); setInterval(applyHoverHints, 2500); })();