NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Avabur Improved // @namespace org.alorel.avaburimproved // @author Alorel <a.molcanovas@gmail.com> // @homepage https://github.com/Alorel/avabur-improved // @supportURL https://github.com/Alorel/avabur-improved/issues // @description Some welcome additions to Avabur's UI choices // @include https://avabur.com/game.php // @include http://avabur.com/game.php // @include https://www.avabur.com/game.php // @include http://www.avabur.com/game.php // @version 0.6.7 // @icon https://cdn.rawgit.com/Alorel/avabur-improved/0.6.3/res/img/logo-16.png // @icon64 https://cdn.rawgit.com/Alorel/avabur-improved/0.6.3/res/img/logo-64.png // @downloadURL https://github.com/Alorel/avabur-improved/raw/master/avabur-improved.user.js // @updateURL https://github.com/Alorel/avabur-improved/raw/master/avabur-improved.user.js // @run-at document-end // @grant GM_getValue // @grant GM_setValue // @grant GM_deleteValue // @grant GM_notification // @grant GM_listValues // @grant GM_xmlhttpRequest // @connect githubusercontent.com // @connect github.com // @connect self // @require https://cdn.rawgit.com/Alorel/avabur-improved/0.6.7/lib/toastmessage/jquery.toastmessage.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/buzz/1.1.10/buzz.min.js // @require https://cdn.rawgit.com/Alorel/avabur-improved/0.6.7/lib/jalc-1.0.1.min.js // @require https://cdn.rawgit.com/Alorel/alo-timer/master/src/alotimer.min.js // @license LGPL-2.1 // @noframes // ==/UserScript== const is_dev = false, dev_hash = "604495cad98e0431e4d8e8ef4f0782b05ca19416"; /** Create toast messages */ const Toast = { //Tampermonkey's scoping won't let this constant be globally visible error: function (msg) { console.error(msg); $().toastmessage('showErrorToast', msg); }, notice: function (msg) { $().toastmessage('showNoticeToast', msg); }, success: function (msg) { $().toastmessage('showSuccessToast', msg); }, warn: function (msg) { console.warn(msg); $().toastmessage('showWarningToast', msg); }, incompatibility: function (what) { $().toastmessage('showToast', { text: "Your browser does not support " + what + ". Please <a href='https://www.google.co.uk/chrome/browser/desktop/' target='_blank'>" + "Download the latest version of Google Chrome</a>", sticky: true, position: 'top-center', type: 'error' }); } }; //Check if the user can even support the bot if (typeof(window.sessionStorage) === "undefined") { Toast.incompatibility("Session storage"); } else if (typeof(MutationObserver) === "undefined") { Toast.incompatibility("MutationObserver"); } else { (function ($, CACHE_STORAGE, MutationObserver, buzz, AloTimer) { 'use strict'; /** * Creates a GitHub CDN URL * @param {String} path Path to the file without leading slashes * @param {String} [author] The author. Defaults to Alorel * @param {String} [repo] The repository. Defaults to avabur-improved * @returns {String} The URL */ const gh_url = function (path, author, repo) { author = author || "Alorel"; repo = repo || "avabur-improved"; return "https://cdn.rawgit.com/" + author + "/" + repo + "/" + (is_dev ? dev_hash : GM_info.script.version) + "/" + path; }; const URLS = { sfx: { circ_saw: gh_url("res/sfx/circ_saw.wav"), message_ding: gh_url("res/sfx/message_ding.wav") }, css: { toast: gh_url("lib/toastmessage/jquery.toastmessage.min.css"), script: gh_url("res/css/avabur-improved.min.css") }, img: { ajax_loader: gh_url("res/img/ajax-loader.gif") }, svg: { sword_clash: gh_url("res/svg/sword-clash.svg"), log: gh_url("res/svg/log.svg"), metal_bar: gh_url("res/svg/metal-bar.svg"), stone_block: gh_url("res/svg/stone-block.svg"), fishing: gh_url("res/svg/fishing.svg") }, html: { house_timers: gh_url("res/html/house-timers.html"), settings_modal: gh_url("res/html/script-settings.html"), market_tooltip: gh_url("res/html/market-tooltip.html") } }; //////////////////////////////////////////////////////////////////////// // These are the settings - you can safely change them, but they will // // be overwritten during script updates // //////////////////////////////////////////////////////////////////////// /** How long our AJAX cache is meant to last */ const CACHE_TTL = { /** Resource tooltip market price lookups */ market: 1 / 3600 * 60, //30 sec, /** Tradeskill material ID mapping */ tradeskill_mats: 1 }; /** * The URL where we check for updates. This is different from @updateURL because we want it to come through * as a regular page load, not a request to the raw file */ const UPDATE_URL = "https://github.com/Alorel/avabur-improved/blob/master/avabur-improved.user.js"; ///////////////////////////////////////////////////// // This is the script code. Don't change it unless // // you know what you're doing ;) // ///////////////////////////////////////////////////// const SettingsHandler = function () { /** @type SettingsHandler.defaults */ this.settings = this.defaults; this.load(); }; SettingsHandler.prototype = { /** Default settings */ defaults: { /** * Notification settings. * sound: [bool] Whether to play a sound * gm: [bool] Whether to show the Greasemonkey notification */ notifications: { /** Global overrides */ all: { sound: false, gm: false }, /** Whisper notifcations */ whisper: { sound: true, gm: true }, construction: { sound: true, gm: true } }, features: { house_timer: true } }, save: function () { GM_setValue("settings", JSON.stringify(this.settings)); }, load: function () { this.settings = $.extend(true, this.defaults, JSON.parse(GM_getValue("settings") || "{}")); } }; const Settings = new SettingsHandler(); /* /(([0-9])+\s(minutes|seconds|hours))/g ^ tmp - will be used for future update */ /** Our persistent DOM stuff */ const $DOM = { currency_tooltip: { the_tooltip: $("#currencyTooltip"), /** The HTML element which will be used for currency tooltip colour references */ colour_reference: $("#currencyTooltipMarketable"), /** Thr row we will be colouring */ table_row: null, /** The 1st page low price */ market_low: null, /** The 1st page avg price */ market_avg: null, /** The 1st page high price */ market_high: null }, /** Game modals */ modal: { /** The outer wrapper */ modal_wrapper: $("#modalWrapper"), /** The faded background for modals */ modal_background: $("#modalBackground"), /** The title for modal windows */ modal_title: $("#modalTitle"), /** The script settings modal */ script_settings: null }, /** Navigation items */ nav: { market: $("#viewMarket") }, house_monitor: { status: null }, market: { navlinks: $("#marketTypeSelector").find("a"), market_tooltip: null } }; const SFX = { circ_saw: new buzz.sound(URLS.sfx.circ_saw), msg_ding: new buzz.sound(URLS.sfx.message_ding) }; /** AJAX spinners throughout the page */ const $AJAX_SPINNERS = { /** The spinner @ the currency tooltip */ currency_tooltip: $('<img src="' + URLS.img.ajax_loader + '"/>') }; const FUNCTION_PERSISTENT_VARS = { house_update_last_msg: null, }; /** * Interval manager * @param {String} name Interval name/ID * @constructor */ const Interval = function (name) { this.name = name; }; Interval.prototype = { _intervals: {}, isRunning: function () { return typeof(this._intervals[this.name]) !== "undefined" }, clear: function () { if (this.isRunning()) { clearInterval(this._intervals[this.name]); delete this._intervals[this.name]; return true; } return false; }, set: function (callback, frequency) { this.clear(); this._intervals[this.name] = setInterval(callback, frequency); return this._intervals[this.name]; } }; /** Misc function container */ const fn = { parseTimeStringLong: function (str) { var time = 0; const match = str.match(/([0-9]+\s+(hours?|minutes?|seconds?))/g); for (var i = 0; i < match.length; i++) { const currentMatch = match[i].toLowerCase(); const number = currentMatch.match(/[0-9]+/); var multiplier; if (currentMatch.indexOf("hour") !== -1) { multiplier = 3600000; } else if (currentMatch.indexOf("minute") !== -1) { multiplier = 60000; } else { multiplier = 1000; } time += parseInt(number) * multiplier; } return time; }, check_github_for_updates: function () { GM_xmlhttpRequest({ method: "GET", url: UPDATE_URL, onload: function (r) { const theirVersion = r.responseText.match(/\/\/\s+@version\s+([^\n<>]+)/)[1]; if (fn.versionCompare(GM_info.script.version, theirVersion) < 0) { $().toastmessage('showToast', { text: 'A new version of ' + GM_info.script.name + ' is available! Click your ' + 'Greasemonkey/Tampermonkey icon, select "Check for updates" and reload the page in a few seconds.', sticky: true, position: 'top-center', type: 'notice' }); } } }); }, svg: function ($this, url) { $this.html('<img src="' + URLS.img.ajax_loader + '" alt="Loading"/>'); $.get(url).done(function (r) { $this.html($(r).find("svg")); }); return $this; }, /** @param {Interval} interval */ house_status_update_end: function (interval) { interval.clear(); $DOM.house_monitor.status.addClass("avi-highlight").html( $('<span data-delegate-click="#header_house" style="cursor:pointer;text-decoration:underline;padding-right:5px">Ready!</span>') .click($HANDLERS.click.delegate_click) ) .append( $("<a href='javascript:;'>(refresh)</a>").click($HANDLERS.click.house_state_refresh) ); if (Settings.settings.notifications.construction.gm && Settings.settings.notifications.all.gm) { fn.notification(Demo.prototype.gm_texts.construction); } if (Settings.settings.notifications.construction.sound && Settings.settings.notifications.all.sound) { SFX.circ_saw.play(); } }, handle_house_status_update: function (text) { if (text !== FUNCTION_PERSISTENT_VARS.house_update_last_msg) { FUNCTION_PERSISTENT_VARS.house_update_last_msg = text; const interval = new Interval("house_status"); interval.clear(); if (text.indexOf("available again") !== -1) { // Working const timer = new AloTimer(fn.parseTimeStringLong(text)); interval.set(function () { if (timer.isFinished()) { fn.house_status_update_end(interval); } else { $DOM.house_monitor.status.removeClass("avi-highlight").text(timer.toString()); } }, 1000); } else if (text.indexOf("are available")) { fn.house_status_update_end(interval); } else { setTimeout(function () { $.get("/house.php") }, 3000); } } }, /** * Creates a floaty notification * @param {String} text Text to display * @param {Object} [options] Overrides as shown here: https://tampermonkey.net/documentation.php#GM_notification */ notification: function (text, options) { GM_notification($.extend({ text: text, title: GM_info.script.name, highlight: true, timeout: 5 }, options || {})); }, /** * Opens the market * @param {String} type The top category name */ openMarket: function (type) { const $document = $(document); const $openCategory = function (evt, xhr, opts) { if (opts.url === "market.php") { $document.unbind("ajaxComplete", $openCategory); $DOM.market.navlinks.removeClass("active") .filter("a:contains('" + type + "')").addClass("active").click(); } }; $document.ajaxComplete($openCategory); $DOM.nav.market.click(); }, analysePrice: function (arr) { const ret = { low: arr[0].price, high: arr[arr.length - 1].price }; ret.avg = Math.round((parseFloat(ret.low) + parseFloat(ret.high)) / 2); return ret; }, /** * Tabifies the div * @param {jQuery|$|HTMLElement|*} $container The div to tabify */ tabify: function ($container) { const $nav = $container.find(">nav>*"), $tabs = $container.find(">div>*"), $activeNav = $nav.filter(".active"); $nav.click(function () { const $this = $(this); $tabs.filter("[data-menu='" + $this.attr("data-menu") + "']").show().siblings().hide(); $this.addClass("active").siblings().removeClass("active"); }); ($activeNav.length ? $activeNav : $nav).first().click(); }, /** Puts commas in large numbers */ numberWithCommas: function (x) { return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); }, /** Toggles the visibility attribute of the element */ toggleVisibility: function ($el, shouldBeVisible) { $el.css("visibility", shouldBeVisible ? "visible" : "hidden"); }, openStdModal: function (item) { var $el; if (item instanceof $) { $el = item; } else if (item instanceof HTMLElement || typeof(item) === "string") { $el = $(item); } else { console.error("Failed to open modal: Invalid selector as shown below"); console.error(item); return false; } $el.show().siblings().hide(); $DOM.modal.modal_background.fadeIn(); $DOM.modal.modal_wrapper.fadeIn(); }, /** * @return * 0 if the versions are equal * a negative integer iff v1 < v2 * a positive integer iff v1 > v2 * NaN if either version string is in the wrong format */ versionCompare: function (v1, v2, options) { var lexicographical = options && options.lexicographical, zeroExtend = options && options.zeroExtend, v1parts = v1.split('.'), v2parts = v2.split('.'); function isValidPart(x) { return (lexicographical ? /^\d+[A-Za-z]*$/ : /^\d+$/).test(x); } if (!v1parts.every(isValidPart) || !v2parts.every(isValidPart)) { return NaN; } if (zeroExtend) { while (v1parts.length < v2parts.length) v1parts.push("0"); while (v2parts.length < v1parts.length) v2parts.push("0"); } if (!lexicographical) { v1parts = v1parts.map(Number); v2parts = v2parts.map(Number); } for (var i = 0; i < v1parts.length; ++i) { if (v2parts.length == i) { return 1; } if (v1parts[i] == v2parts[i]) { } else if (v1parts[i] > v2parts[i]) { return 1; } else { return -1; } } if (v1parts.length != v2parts.length) { return -1; } return 0; } }; /** * Represents an AJAX request to be used with cache * @param {String} url The URL we're calling * @param {Boolean|Number} cacheTime Cache time in hours or false if the request should not be cached * @param {Function} [errorCallback] A custom error callback * @constructor */ const Request = function (url, cacheTime, errorCallback) { /** The URL we're calling */ this.url = url; /** OnError callback */ this.errorCallback = errorCallback || Request.prototype.callbacks.error.generic; /** * How long the request should be cached for * @type {Boolean|Number} */ this.cacheTime = cacheTime || false; }; Request.prototype = { /** Ajax callbacks container */ callbacks: { /** Successful AJAX callbacks */ success: { /** Successful callback for the currency tooltip market info lookup */ currency_tooltip: function (r) { const analysis = fn.analysePrice(r.l); fn.toggleVisibility($AJAX_SPINNERS.currency_tooltip, false); $DOM.currency_tooltip.market_low.text(fn.numberWithCommas(analysis.low)); $DOM.currency_tooltip.market_avg.text(fn.numberWithCommas(analysis.avg)); $DOM.currency_tooltip.market_high.text(fn.numberWithCommas(analysis.high)); }, house_requery: function (evt, r, opts) { if (opts.url.indexOf("house") !== -1 && typeof(r.responseJSON) !== "undefined" && typeof(r.responseJSON.m) !== "undefined") { fn.handle_house_status_update(r.responseJSON.m); } }, house_state_refresh: function (r) { fn.handle_house_status_update(r.m); } }, /** Error callbacks */ error: { /** Generic error callback */ generic: function (xhr, textStatus, errorThrown) { Toast.error("[" + textStatus + "] " + xhr.responseText); console.error({ xhr: xhr, textStatus: textStatus, errorThrown: errorThrown }); } } }, /** * Make a GET request * @returns {*|jqXHR|XMLHTTPRequest|jQuery|$} */ get: function () { return this._generic({ method: "GET" }); }, /** * To be called internally to start the request * @param {Object} generated params generated by the get/post methods * @returns {jqXHR|XMLHTTPRequest|jQuery|$} * @private */ _generic: function (generated) { const methodArgs = $.extend({ url: this.url, error: this.errorCallback }, generated || {}); if (this.cacheTime !== false && !isNaN(this.cacheTime)) { methodArgs.cacheTTL = this.cacheTime; methodArgs.localCache = CACHE_STORAGE; } return $.ajax(this.url, methodArgs); }, /** * Make a POST request * @param {Object} data Post params * @returns {*|jqXHR|XMLHTTPRequest|jQuery|$} */ post: function (data) { return this._generic({ method: "POST", data: data }); } }; /** Collection of mutation observers the script uses */ const OBSERVERS = { /** Mutation observer for the currency page tooltip */ currency_tooltips: new MutationObserver( /** @param {MutationRecord[]} records */ function (records) { if (records.length && $DOM.currency_tooltip.colour_reference.is(":visible")) { const cssClass = $DOM.currency_tooltip.colour_reference.attr("class"), marketID = cssClass.replace("crystals", "premium") .replace("materials", "weapon_scraps") .replace("fragments", "gem_fragments"), $allTDs = $DOM.currency_tooltip.table_row.find(">td"); $DOM.currency_tooltip.table_row.attr("class", cssClass); if (cssClass === "gold") { $allTDs.text("N/A"); fn.toggleVisibility($AJAX_SPINNERS.currency_tooltip, false); } else { $allTDs.text(" "); fn.toggleVisibility($AJAX_SPINNERS.currency_tooltip, true); (new Request("/market.php", CACHE_TTL.market)).post({ type: "currency", page: 0, st: marketID }).done(Request.prototype.callbacks.success.currency_tooltip); } } }), /** Makes sure the script settings modal doesn't get nasty with the other game modals */ script_settings: new MutationObserver(function () { if (!$DOM.modal.script_settings.is(":visible")) { $DOM.modal.script_settings.hide(); } } ), house_status: new MutationObserver(function (records) { for (var i = 0; i < records.length; i++) { if (records[i].addedNodes.length) { fn.handle_house_status_update(records[i].target.innerText.trim()); break; } } }), chat_whispers: new MutationObserver( /** @param {MutationRecord[]} records */ function (records) { const sound_on = Settings.settings.notifications.all.sound && Settings.settings.notifications.whisper.sound; const gm_on = Settings.settings.notifications.all.gm && Settings.settings.notifications.whisper.gm; if (sound_on || gm_on) { for (var i = 0; i < records.length; i++) { const addedNodes = records[i].addedNodes; if (addedNodes.length) { for (var j = 0; j < addedNodes.length; j++) { const text = $(addedNodes[j]).text(); if (text.match(/^\[[0-9]+:[0-9]+:[0-9]+]\s*Whisper from/)) { if (gm_on) { fn.notification(text); } if (sound_on) { SFX.msg_ding.play(); } } } } } } } ), inventory_table: new MutationObserver( /** @param {MutationRecord[]} records */ function (records) { for (var i = 0; i < records.length; i++) { if (records[i].addedNodes.length) { for (var n = 0; n < records[i].addedNodes.length; n++) { if (records[i].addedNodes[n] instanceof HTMLTableSectionElement) { const $tbody = $(records[i].addedNodes[n]); if ($tbody.find("th:contains(Ingredient)").length) { //Bingo! $tbody.find(">tr>[data-th=Item]").each($HANDLERS.each.inventory_table_ingredients); } break; } } break; } } } ) }; var TRADESKILL_MATS = {}; const Demo = function (kind) { this.kind = kind; }; Demo.prototype.kinds = { SOUND: 1, GM_NOTIFICATION: 2 }; Demo.prototype.gm_texts = { whisper: "[00:00:00] Whisper from Alorel: send me all of your crystals.", construction: "Construction finished!" }; Demo.prototype.scenarios = { "whisper-sound": { kind: Demo.prototype.kinds.SOUND, src: SFX.msg_ding }, "whisper-gm": { kind: Demo.prototype.kinds.GM_NOTIFICATION, src: Demo.prototype.gm_texts.whisper }, "construction-sound": { kind: Demo.prototype.kinds.SOUND, src: SFX.circ_saw }, "construction-gm": { kind: Demo.prototype.kinds.GM_NOTIFICATION, src: Demo.prototype.gm_texts.construction } }; Demo.prototype.play = function () { if (typeof(this.scenarios[this.kind]) !== "undefined") { const scenario = this.scenarios[this.kind]; switch (scenario.kind) { case Demo.prototype.kinds.SOUND: if (!buzz.isWAVSupported()) { Toast.incompatibility("WAV sounds"); } else { scenario.src.play(); } break; case Demo.prototype.kinds.GM_NOTIFICATION: fn.notification(scenario.src); break; default: Toast.error("Misconfigured demo scenario: " + this.kind); } } else { Toast.error("Invalid demo scenario picked: " + this.kind); } }; const $HANDLERS = { click: { demo: function () { (new Demo($(this).attr("data-demo"))).play(); }, house_state_refresh: function () { $.post("/house.php", {}, Request.prototype.callbacks.success.house_state_refresh); }, topbar_currency: function () { const type = $(this).find(">td:first").text().trim(); fn.openMarket(type.substring(0, type.length - 1)); }, ingredient: function () { $DOM.modal.modal_background.click(); fn.openMarket("Ingredients"); }, script_menu: function () { $DOM.modal.modal_title.text(GM_info.script.name + " " + GM_info.script.version); fn.openStdModal($DOM.modal.script_settings); }, delegate_click: function () { $($(this).data("delegate-click")).click(); } }, change: { settings_notification: function () { const $this = $(this); Settings.settings.notifications[$this.data("notification")][$this.data("type")] = $this.is(":checked"); Settings.save(); }, settings_feature: function () { const $this = $(this); Settings.settings.features[$this.data("feature")] = $this.is(":checked"); Settings.save(); } }, mouseenter: { inventory_table_ingredient: function () { const $this = $(this), ingredient = $this.text().trim(); if (typeof(TRADESKILL_MATS[ingredient]) === "undefined") { Toast.error("Failed to lookup " + ingredient + ": ID not found"); } else { (new Request("/market.php", CACHE_TTL.market)) .post({ type: "ingredient", page: 0, q: 0, ll: 0, hl: 0, st: TRADESKILL_MATS[ingredient] }).done(function (r) { const describedBy = $this.attr("aria-describedby"), $describedBy = $("#" + describedBy); if (describedBy && $describedBy.length) { const analysis = fn.analysePrice(r.l), $tds = $describedBy.find("tr[data-id=prices]>td"); $tds.first().text(fn.numberWithCommas(analysis.low)) .next().text(fn.numberWithCommas(analysis.avg)) .next().text(fn.numberWithCommas(analysis.high)); } }); } } }, each: { settings_notification: function () { const $this = $(this); $this.prop("checked", Settings.settings.notifications[$this.data("notification")][$this.data("type")]); }, settings_features: function () { const $this = $(this); $this.prop("checked", Settings.settings.features[$this.data("feature")]); }, inventory_table_ingredients: function () { const $this = $(this), ingredient = $this.text().trim(), $span = $('<span>' + ingredient + '</span>'); $this.html($span); $span.popover({ title: ingredient, html: true, trigger: "hover", container: "body", viewport: {"selector": "body", "padding": 0}, placement: "auto right", content: $DOM.market.market_tooltip }); $span.mouseenter($HANDLERS.mouseenter.inventory_table_ingredient) .css("cursor", "pointer") .click($HANDLERS.click.ingredient); } } }; (function () { const ON_LOAD = { "Registering market tooltip users": function () { $.get(URLS.html.market_tooltip).done(function (r) { $DOM.market.market_tooltip = r; const $tooltipTable = $(r); $tooltipTable.find("th[colspan]").append($AJAX_SPINNERS.currency_tooltip); $DOM.currency_tooltip.table_row = $tooltipTable.find("tr[data-id=prices]"); $DOM.currency_tooltip.market_low = $DOM.currency_tooltip.table_row.find(">td").first(); $DOM.currency_tooltip.market_avg = $DOM.currency_tooltip.market_low.next(); $DOM.currency_tooltip.market_high = $DOM.currency_tooltip.market_avg.next(); //Add our stuff to the currency tooltips $DOM.currency_tooltip.the_tooltip.append($tooltipTable); OBSERVERS.currency_tooltips.observe($DOM.currency_tooltip.the_tooltip[0], { attributes: true }); OBSERVERS.inventory_table.observe(document.querySelector("#inventoryTable"), { childList: true, characterData: true }); }); }, "Fixing some game CSS": function () { $("head").append('<style>.materials{color:' + $("#crafting_materials").css("color") + '}.fragments{color:' + $("#gem_fragments").css("color") + '}</style>'); }, "Applying house monitor": function () { if (Settings.settings.features.house_timer) { $.get(URLS.html.house_timers).done(function (r) { const $timer = $(r), $body = $("body"); $("#houseTimerInfo").addClass("avi-force-block"); $body.append("<style>#constructionNotifier,#houseTimerTable [data-typeid='Construction']{display:none!important}</style>"); $("#houseTimerTable").prepend($timer); $DOM.house_monitor.status = $("#avi-house-construction").click($HANDLERS.click.house_state_refresh); OBSERVERS.house_status.observe(document.querySelector("#house_notification"), { childList: true, characterData: true }); $(document).ajaxComplete(Request.prototype.callbacks.success.house_requery); $.get("/house.php") }); } else { console.log("(skipped due to user settings)"); } }, "Checking if the script has been updated": function () { if (fn.versionCompare(GM_getValue("last_ver") || "999999", GM_info.script.version) < 0) { $().toastmessage('showToast', { text: GM_info.script.name + " has been updated! See the changelog " + "<a href='https://github.com/Alorel/avabur-improved/releases' target='_blank'>here</a>", sticky: true, position: 'top-left', type: 'success' }); } GM_setValue("last_ver", GM_info.script.version); }, "Loading script CSS": function () { const $head = $("head"), keys = Object.keys(URLS.css); for (var i = 0; i < keys.length; i++) { $head.append("<link type='text/css' rel='stylesheet' href='" + URLS.css[keys[i]] + "'/>"); } }, "Configuring script modal": function () { $.get(URLS.html.settings_modal).done(function (r) { $DOM.modal.script_settings = $(r); $("#modalContent").append($DOM.modal.script_settings); fn.tabify($DOM.modal.script_settings); $DOM.modal.script_settings.find("[data-demo]").click($HANDLERS.click.demo); $DOM.modal.script_settings.find('[data-setting="notifications"]') .each($HANDLERS.each.settings_notification) .change($HANDLERS.change.settings_notification); $DOM.modal.script_settings.find('[data-setting="features"]') .each($HANDLERS.each.settings_features) .change($HANDLERS.change.settings_feature); OBSERVERS.script_settings.observe($DOM.modal.modal_wrapper[0], {attributes: true}); }); }, "Registering side menu entry": function () { const $helpSection = $("#helpSection"), $menuLink = $('<a href="javascript:;"/>') .html('<li class="active">' + GM_info.script.name + " " + GM_info.script.version + '</li>') .click($HANDLERS.click.script_menu), $appends = { battle: $("<a href='javascript:;' data-delegate-click='#loadMobList' class='avi-tip avi-menu-shortcut' title='Open Battles'/>"), fishing: $("<a href='javascript:;' data-delegate-click='#loadFishing' class='avi-tip avi-menu-shortcut' title='Open Fishing'/>"), wc: $("<a href='javascript:;' data-delegate-click='#loadWoodcutting' class='avi-tip avi-menu-shortcut' title='Open Woodcutting'/>"), mine: $("<a href='javascript:;' data-delegate-click='#loadMining' class='avi-tip avi-menu-shortcut' title='Open Ironing (lol)'/>"), quarry: $("<a href='javascript:;' data-delegate-click='#loadStonecutting' class='avi-tip avi-menu-shortcut' title='Open Stoners'/>") }; $helpSection.append($menuLink); $("#navWrapper").css("padding-top", $menuLink.height()).find("ul") .append( $('<li class="avi-menu"/>') .append($appends.battle) .append($appends.fishing) .append($appends.wc) .append($appends.mine) .append($appends.quarry) ); fn.svg($appends.battle, URLS.svg.sword_clash); fn.svg($appends.fishing, URLS.svg.fishing); fn.svg($appends.wc, URLS.svg.log); fn.svg($appends.mine, URLS.svg.metal_bar); fn.svg($appends.quarry, URLS.svg.stone_block); }, "Registering market shortcuts": function () { $("#allThemTables").find(".currencyWithTooltip:not(:contains(Gold))").css("cursor", "pointer") .click($HANDLERS.click.topbar_currency); }, "Staring whisper monitor": function () { OBSERVERS.chat_whispers.observe(document.querySelector("#chatMessageList"), { childList: true }); }, "Collecting tradeskill material IDs": function () { const cached_ids = window.sessionStorage.getItem("TRADESKILL_MATERIAL_IDS"); if (cached_ids) { TRADESKILL_MATS = JSON.parse(cached_ids); } else { $.post("/market.php", { type: "ingredient", page: 0, st: "all" }, function (r) { const select = $("<select/>"), mats = {}; select.html(r.filter); select.find(">option:not([value=all])").each(function () { const $this = $(this); mats[$this.text().trim()] = parseInt($this.val()); }); window.sessionStorage.setItem("TRADESKILL_MATERIAL_IDS", JSON.stringify(mats)); TRADESKILL_MATS = mats; }); } }, "Applying extra event listeners tooltips": function () { $(".avi-tip").tooltip({ container: "body", viewport: {"selector": "body", "padding": 0} }); $("[data-delegate-click]").click($HANDLERS.click.delegate_click); } }; const keys = Object.keys(ON_LOAD); for (var i = 0; i < keys.length; i++) { console.log("[" + GM_info.script.name + "] " + keys[i]); ON_LOAD[keys[i]](); delete ON_LOAD[keys[i]]; } fn.check_github_for_updates(); (new Interval("gh_update")).set(fn.check_github_for_updates, 60000); })(); })(jQuery, window.sessionStorage, MutationObserver, buzz, AloTimer); }