您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Improve Diamond Hunt 2
当前为
// ==UserScript== // @name DH2 Fixed // @namespace FileFace // @description Improve Diamond Hunt 2 // @version 0.140.1 // @author Zorbing // @license ISC; http://opensource.org/licenses/ISC // @grant none // @run-at document-start // @include http://www.diamondhunt.co/game.php // ==/UserScript== /** * ISC License (ISC) * * Copyright (c) 2017, Martin Boekhoff * * Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby * granted, provided that the above copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Source: http://opensource.org/licenses/ISC */ (function () { 'use strict'; var version = '0.140.1'; /** * observer */ var observer; (function (observer) { var observedKeys = new Map(); function add(key, fn) { if (key instanceof Array) { for (var _i = 0, key_1 = key; _i < key_1.length; _i++) { var k = key_1[_i]; add(k, fn); } } else { if (!observedKeys.has(key)) { observedKeys.set(key, new Set()); } observedKeys.get(key).add(fn); } return fn; } observer.add = add; function notify(key, oldValue) { var newValue = getGameValue(key); window[key] = newValue; if (observedKeys.has(key)) { observedKeys.get(key).forEach(function (fn) { return fn(key, oldValue, newValue); }); } } observer.notify = notify; function remove(key, fn) { if (key instanceof Array) { var ret = []; for (var _i = 0, key_2 = key; _i < key_2.length; _i++) { var k = key_2[_i]; ret.push(remove(k, fn)); } return ret; } if (!observedKeys.has(key)) { return false; } return observedKeys.get(key).delete(fn); } observer.remove = remove; })(observer || (observer = {})); /** * global constants */ var TIER_LEVELS = ['empty', 'sapphire', 'emerald', 'ruby', 'diamond']; var TIER_NAMES = ['Standard', 'Sapphire', 'Emerald', 'Ruby', 'Diamond']; var TIER_ITEMS = ['pickaxe', 'shovel', 'hammer', 'axe', 'rake', 'fishingRod', 'chisel']; var FURNACE_LEVELS = ['stone', 'bronze', 'iron', 'silver', 'gold']; var OVEN_LEVELS = ['bronze', 'iron', 'silver', 'gold']; /** / function calcSize(level: number) { if (level == 1) { return 10e3; } const r = 10e3 * Math.exp(0.805 * level); const f = Math.pow(10, Math.floor(Math.log10(r))); return Math.round(r / f) * f; } /**/ /** * next values may be: * - level 6: 1,000,000 * - level 7: 3,000,000 * - level 8: 6,000,000 * - level 9: 10,000,000 * - level 10: 30,000,000 */ var OIL_STORAGE_SIZES = [10e3, 50e3, 100e3, 300e3, 600e3, 1e6, 3e6]; var HIDE_RECIPES = { 'drills': { max: 10 } , 'crushers': { max: 10 } , 'giantDrills': { max: 10 } , 'excavators': { max: 10 } , 'oilPipe': { max: 1 } , 'pumpjacks': { max: 10 } , 'rowBoat': { max: 1 } , 'canoe': { max: 1 } // thanks aguyd , 'bonemealBin': { extraKeys: ['boundFilledBonemealBin'] , max: 1 } , 'oilFactory': { max: 1 } }; var SMELTING_REQUIREMENTS = { 'glass': { sand: 1 , oil: 10 } , 'bronzeBar': { copper: 1 , tin: 1 , oil: 10 } , 'ironBar': { iron: 1 , oil: 100 } , 'silverBar': { silver: 1 , oil: 300 } , 'goldBar': { gold: 1 , oil: 1e3 } }; var SEED_NAME = { '1': 'Dark Mushrooms' , '2': 'Red Mushrooms' , '3': 'Dotted Green Leafs' , '4': 'Green Leafs' , '5': 'Lime Leafs' , '6': 'Gold Leafs' , '7': 'Striped Gold Leafs' , '8': 'Crystal Leafs' , '9': 'Striped Crystal Leafs' , '10': 'Blewit Mushrooms' , '11': 'Snapegrass' , '12': 'Tree' , '13': 'Oak Tree' , '14': 'Wheat' , '15': 'Willow Tree' , '16': 'Grass' , '17': 'Maple Tree' , '18': 'Stardust Tree' }; var SKILL_LIST = ['mining', 'crafting', 'woodcutting', 'farming', 'brewing', 'combat', 'fishing', 'cooking', 'magic']; var AREA_LIST = ['fields', 'forests', 'caves', 'volcano']; var SMELTING_TIME = { 'glass': 1 , 'bronzeBar': 1 , 'ironBar': 5 , 'silverBar': 10 , 'goldBar': 30 }; var FISH_XP = { 'rawShrimp': 50 , 'rawSardine': 500 , 'rawTuna': 3e3 , 'rawSwordfish': 5e3 , 'rawShark': 12e3 }; var BOAT_LIST = ['rowBoat', 'canoe']; var format; (function (format) { var TIME_STEPS = [ { threshold: 1 , name: 'second' , short: 'sec' , padp: 0 } , { threshold: 60 , name: 'minute' , short: 'min' , padp: 0 } , { threshold: 3600 , name: 'hour' , short: 'h' , padp: 1 } , { threshold: 86400 , name: 'day' , short: 'd' , padp: 2 }]; function zeroPadLeft(num) { return (num < 10 ? '0' : '') + num; } function number(num) { return (typeof num === 'number' ? num : Number(num)).toLocaleString('en'); } format.number = number; function numbersInText(text) { return text.replace(/\d(?:[\d',\.]*\d)?/g, function (numStr) { return number(Number(numStr.replace(/\D/g, ''))); }); } format.numbersInText = numbersInText; // use time format established in DHQoL (https://greasyfork.org/scripts/16041-dhqol) function timer(timer, shorten) { if (shorten === void 0) { shorten = true; } if (typeof timer === 'string') { timer = parseInt(timer, 10); } timer = Math.max(timer, 0); var hours = Math.floor(timer / 3600); var minutes = Math.floor((timer % 3600) / 60); var seconds = timer % 60; return (shorten && hours === 0 ? '' : zeroPadLeft(hours) + ':') + zeroPadLeft(minutes) + ':' + zeroPadLeft(seconds); } format.timer = timer; function time2NearestUnit(time, long) { if (long === void 0) { long = false; } var step = TIME_STEPS[0]; for (var i = TIME_STEPS.length - 1; i > 0; i--) { if (time >= TIME_STEPS[i].threshold) { step = TIME_STEPS[i]; break; } } var factor = Math.pow(10, step.padp); var num = Math.round(time / step.threshold * factor) / factor; var unit = long ? step.name + (num === 1 ? '' : 's') : step.short; return num + ' ' + unit; } format.time2NearestUnit = time2NearestUnit; function min2Str(minutes) { if (typeof minutes === 'string') { minutes = parseInt(minutes, 10); } var m = minutes % 60; var h = Math.floor(minutes / 60); return (h > 0 ? h + ' hour' + (h == 1 ? '' : 's') + ' and ' : '') + m + ' minute' + (m == 1 ? '' : 's'); } format.min2Str = min2Str; })(format || (format = {})); /** * general functions */ function addStyle(styleCode, elId) { var id = elId != null ? 'style-' + elId : null; var styleElement = id != null ? document.getElementById(id) : null; if (styleElement == null) { styleElement = document.createElement('style'); if (id != null) { styleElement.id = id; } styleElement.type = 'text/css'; document.head.appendChild(styleElement); } styleElement.innerHTML += styleCode; } function capitalize(str) { return str[0].toUpperCase() + str.substr(1); } function key2Name(key, lowerCase) { if (lowerCase === void 0) { lowerCase = false; } var name = key.replace(/[A-Z]/g, function (c) { return ' ' + (lowerCase ? c.toLowerCase() : c); }); return lowerCase ? name : capitalize(name); } function split2Words(str, char) { if (char === void 0) { char = ' '; } return str.replace(/[A-Z]/g, char + '$&'); } function getBoundKey(key) { return 'bound' + capitalize(key); } function getTierKey(key, tierLevel) { return TIER_LEVELS[tierLevel] + capitalize(key); } function now() { return (new Date()).getTime(); } function ensureTooltip(id, target) { var tooltipId = 'tooltip-' + id; var tooltipEl = document.getElementById(tooltipId); if (!tooltipEl) { tooltipEl = document.createElement('div'); tooltipEl.id = tooltipId; tooltipEl.style.display = 'none'; var tooltipList = document.getElementById('tooltip-list'); tooltipList.appendChild(tooltipEl); } // ensure binded events to show the tooltip if (target.dataset.tooltipId == null) { target.dataset.tooltipId = tooltipId; window.$(target).bind( { mousemove: window.changeTooltipPosition , mouseenter: window.showTooltip , mouseleave: window.hideTooltip }); } return tooltipEl; } var timeStr2Sec = (function () { var unitFactors = { 'd': 24 * 60 * 60 , 'h': 60 * 60 , 'm': 60 , 's': 1 }; return function timeStr2Sec(str) { return str .replace(/(\d+)([hms])/g, function (wholeMatch, num, unit) { return parseInt(num) * (unitFactors[unit] || 1) + '+'; }) .split('+') .map(function (s) { return parseInt(s, 10); }) .filter(function (n) { return !isNaN(n); }) .reduce(function (p, c) { return p + c; }, 0); }; })(); function getGameValue(key) { return window[key]; } function getFurnaceLevel() { for (var i = FURNACE_LEVELS.length - 1; i >= 0; i--) { if (getGameValue(getBoundKey(FURNACE_LEVELS[i] + 'Furnace')) > 0) { return i; } } return -1; } function getFurnaceLevelName() { return FURNACE_LEVELS[getFurnaceLevel()] || ''; } function getPrice(item) { var price = window.getPrice(item); if (typeof price === 'number') { return price; } var match = price.match(/(\d+)([kM])/); if (!match) { return parseInt(price, 10); } var FACTORS = { 'k': 1e3 , 'M': 1e6 }; return parseInt(match[1], 10) * (FACTORS[match[2]] || 1); } /** * persistence store */ var store; (function (store) { var storePrefix = 'dh2-'; function get(key) { var value = localStorage.getItem(storePrefix + key); if (value != null) { try { return JSON.parse(value); } catch (e) {} } return value; } store.get = get; function has(key) { return localStorage.hasOwnProperty(storePrefix + key); } store.has = has; function remove(key) { localStorage.removeItem(storePrefix + key); } store.remove = remove; function set(key, value) { localStorage.setItem(storePrefix + key, JSON.stringify(value)); } store.set = set; })(store || (store = {})); var settings; (function (settings) { settings.name = 'settings'; var KEY; (function (KEY) { KEY[KEY["hideCraftingRecipes"] = 0] = "hideCraftingRecipes"; KEY[KEY["hideUselessItems"] = 1] = "hideUselessItems"; KEY[KEY["useNewChat"] = 2] = "useNewChat"; KEY[KEY["colorizeChat"] = 3] = "colorizeChat"; KEY[KEY["intelligentScrolling"] = 4] = "intelligentScrolling"; KEY[KEY["showTimestamps"] = 5] = "showTimestamps"; KEY[KEY["showIcons"] = 6] = "showIcons"; KEY[KEY["showTags"] = 7] = "showTags"; KEY[KEY["showNotifications"] = 8] = "showNotifications"; })(KEY = settings.KEY || (settings.KEY = {}));; var CFG = (_a = {} , _a[KEY.hideCraftingRecipes] = { name: 'Hide crafting recipes of finished items' , description: "Hides crafting recipes of:\n\t\t\t\t<ul style=\"margin: .5rem 0 0;\">\n\t\t\t\t\t<li>furnace, oil storage and oven recipes if they aren't better than the current level</li>\n\t\t\t\t\t<li>machines if the user has the maximum amount of this type (counts bound and unbound items)</li>\n\t\t\t\t\t<li>non-stackable items which the user already owns (counts bound and unbound items)</li>\n\t\t\t\t</ul>" , defaultValue: true , special: true } , _a[KEY.hideUselessItems] = { name: 'Hide useless items' , description: "Hides <em>unbound</em> items which may has been crafted accidentially and are of no use for the player:\n\t\t\t\t<ul style=\"margin: .5rem 0 0;\">\n\t\t\t\t\t<li>furnace, oil storage and oven recipes if they aren't better than the current level</li>\n\t\t\t\t\t<li>machines if the user has already bound the maximum amount of this type</li>\n\t\t\t\t\t<li>non-stackable items which the user has already bound</li>\n\t\t\t\t</ul>" , defaultValue: false , special: true } , _a[KEY.useNewChat] = { name: 'Use the new chat' , description: "Enables using the completely new chat with pm tabs, clickable links, clickable usernames to send a pm, intelligent scrolling and suggesting commands while typing" , defaultValue: true , special: true } , _a[KEY.colorizeChat] = { name: 'Colorize chat messages' , description: "Colorize chat messages according to a unique color for each user" , defaultValue: false , special: true } , _a[KEY.intelligentScrolling] = { name: 'Intelligent scrolling' , description: "Autoscroll gets disabled when you scroll up and gets enabled again when you scroll all the way down to the bottom of the chat." , defaultValue: true , special: true } , _a[KEY.showTimestamps] = { name: 'Show timestamps' , description: "Enables showing timestamps in chat" , defaultValue: true , special: true } , _a[KEY.showIcons] = { name: 'Show user-icons' , description: "Enables showing icons (formerly sigils) for each user in chat" , defaultValue: true , special: true } , _a[KEY.showTags] = { name: 'Show user-tags' , description: "Enables showing tags (Dev, Mod, Contributor) and colors for messages in chat" , defaultValue: true , special: true } , _a[KEY.showNotifications] = { name: 'Show browser notifications' , description: "Shows browser notifications for the following events:\n\t\t\t<ul style=\"margin: .5rem 0 0;\">\n\t\t\t\t<li>Smelting finished</li>\n\t\t\t\t<li>Tree fully grown</li>\n\t\t\t\t<li>Plant ready for harvest</li>\n\t\t\t\t<li>Potion effect has ended for: (super) stardust, bar and seed potions</li>\n\t\t\t\t<li>Boat returned (either the row boat or the canoe)</li>\n\t\t\t\t<li>Hero fully recoverd and able to fight again</li>\n\t\t\t\t<li>Items sold on the market</li>\n\t\t\t\t<li>Private chat messages (pms)</li>\n\t\t\t\t<li>Server messages (like <em>Server is restarting...</em>)</li>\n\t\t\t</ul>" , defaultValue: true } , _a); var SETTINGS_TABLE_ID = 'd2h-settings'; var SETTING_ID_PREFIX = 'dh2-setting-'; /** * settings */ function toName(key) { return typeof key === 'string' ? key : KEY[key]; } function getStoreKey(key) { return 'setting.' + toName(key); } var observedSettings = new Map(); function observe(key, fn) { var n = toName(key); if (!observedSettings.has(n)) { observedSettings.set(n, new Set()); } observedSettings.get(n).add(fn); } settings.observe = observe; function unobserve(key, fn) { var n = toName(key); if (!observedSettings.has(n)) { return false; } return observedSettings.get(n).delete(fn); } settings.unobserve = unobserve; var settingsProxies = new Map(); function get(key) { if (!CFG.hasOwnProperty(key)) { return false; } if (settingsProxies.has(key)) { var proxy = settingsProxies.get(key); return proxy.get(key); } var name = getStoreKey(key); return store.has(name) ? store.get(name) : CFG[key].defaultValue; } settings.get = get; function set(key, newValue) { if (!CFG.hasOwnProperty(key)) { return; } var oldValue = get(key); var n = toName(key); if (settingsProxies.has(key)) { var proxy = settingsProxies.get(key); proxy.set(key, oldValue, newValue); } else { store.set(getStoreKey(key), newValue); } if (oldValue !== newValue && observedSettings.has(n)) { observedSettings.get(n).forEach(function (fn) { return fn(key, oldValue, newValue); }); } } settings.set = set; function initSettingsStyle() { addStyle("\ntable.table-style1 tr:not([onclick])\n{\n\tcursor: initial;\n}\n#tab-container-profile h2.section-title\n{\n\tcolor: orange;\n\tline-height: 1.2rem;\n\tmargin-top: 2rem;\n}\n#tab-container-profile h2.section-title > span.note\n{\n\tfont-size: 0.9rem;\n}\n#" + SETTINGS_TABLE_ID + " tr.reload td:first-child::after\n{\n\tcontent: '*';\n\tfont-weight: bold;\n\tmargin-left: 3px;\n}\n\n.settings-container\n{\n\tlist-style: none;\n\tmargin: 5px 2.5%;\n\tpadding: 0;\n}\n.settings-container > li.setting\n{\n\tbackground-color: silver;\n\tborder: 1px solid black;\n\tborder-top-width: 0;\n}\n.settings-container > li.setting:first-child\n{\n\tborder-top-width: 1px;\n}\n.settings-container > li.setting,\n.settings-container > li.setting *\n{\n\tcursor: pointer;\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n.settings-container > li.setting:hover\n{\n\tbackground-color: gray;\n}\n.settings-container > li.setting > input[type=\"checkbox\"]\n{\n\tdisplay: none;\n}\n.settings-container > li.setting > label\n{\n\tdisplay: block;\n\tpadding: .25rem .5rem;\n}\n.settings-container > li.setting > input + label::before\n{\n\tbackground-image: url(images/icons/x.png);\n\tbackground-size: 20px;\n\tcontent: '';\n\tdisplay: inline-block;\n\theight: 20px;\n\tmargin: 0 .25rem;\n\twidth: 20px;\n\tvertical-align: middle;\n}\n.settings-container > li.setting > input:checked + label::before\n{\n\tbackground-image: url(images/icons/check.png);\n}\n\t\t"); } function initSettingTable() { function insertAfter(newChild, oldChild) { var parent = oldChild.parentElement; if (oldChild.nextElementSibling == null) { parent.appendChild(newChild); } else { parent.insertBefore(newChild, oldChild.nextElementSibling); } } function getCheckImageSrc(value) { return 'images/icons/' + (value ? 'check' : 'x') + '.png'; } var profileTable = document.getElementById('profile-toggleTable'); if (!profileTable) { return; } var settingsHeader = document.createElement('h2'); settingsHeader.className = 'section-title'; settingsHeader.innerHTML = "Userscript \"DH2 Fixed\"<br>\n\t\t\t<span class=\"note\" style=\"display: none;\">(* changes require reloading the tab)</span>"; var requiresReloadNote = settingsHeader.querySelector('.note'); insertAfter(settingsHeader, profileTable); var settingsTable = document.createElement('table'); settingsTable.id = SETTINGS_TABLE_ID; settingsTable.className = 'table-style1'; settingsTable.width = '40%'; settingsTable.innerHTML = "\n\t\t<tr style=\"background-color:grey;\">\n\t\t\t<th>Setting</th>\n\t\t\t<th>Enabled</th>\n\t\t</tr>\n\t\t"; function addRowClickListener(row, key, settingId) { row.addEventListener('click', function () { var newValue = !get(key); set(key, newValue); document.getElementById(settingId).src = getCheckImageSrc(newValue); }); } for (var k in CFG) { // convert it into a KEY var key = parseInt(k, 10); var setting = CFG[key]; if (setting == null) { console.error('missing setting entry:', key, toName(key)); continue; } if (setting.special) { continue; } var settingId = SETTING_ID_PREFIX + toName(key); var row = settingsTable.insertRow(-1); row.classList.add('setting'); if (setting.requiresReload) { row.classList.add('reload'); requiresReloadNote.style.display = ''; } row.setAttribute('onclick', ''); row.innerHTML = "\n\t\t\t<td>" + setting.name + "</td>\n\t\t\t<td><img src=\"" + getCheckImageSrc(get(key)) + "\" id=\"" + settingId + "\" class=\"image-icon-20\"></td>\n\t\t\t"; var tooltipEl = ensureTooltip(settingId, row); tooltipEl.innerHTML = setting.description; if (setting.requiresReload) { tooltipEl.innerHTML += "<span style=\"color: hsla(20, 100%, 50%, 1); font-size: .9rem; display: block; margin-top: 0.5rem;\">You have to reload the browser tab to apply changes to this setting.</span>"; } addRowClickListener(row, key, settingId); } insertAfter(settingsTable, settingsHeader); } function initProxies() { var row = document.querySelector('tr[data-tooltip-id="tooltip-profile-removeCraftingFilter"]'); if (row) { settingsProxies.set(KEY.hideCraftingRecipes , { get: function (key) { return getGameValue('profileRemoveCraftingFilter') != 1; } , set: function (key, oldValue, newValue) { if (oldValue != newValue) { row.click(); } } }); observer.add('profileRemoveCraftingFilter', function () { set(KEY.hideCraftingRecipes, getGameValue('profileRemoveCraftingFilter') != 1); }); } } function createSettingsContainer(settingList) { var settingsContainer = document.createElement('ul'); settingsContainer.className = 'settings-container'; for (var _i = 0, settingList_1 = settingList; _i < settingList_1.length; _i++) { var key = settingList_1[_i]; var settingId = 'setting-' + split2Words(KEY[key], '-'); var setting = CFG[key]; var listEl = document.createElement('li'); listEl.classList.add('setting'); if (setting.requiresReload) { listEl.classList.add('reload'); } var checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.id = settingId; checkbox.checked = get(key); var label = document.createElement('label'); label.htmlFor = settingId; label.textContent = setting.name; (function (key, checkbox) { checkbox.addEventListener('change', function () { set(key, checkbox.checked); }); })(key, checkbox); listEl.appendChild(checkbox); listEl.appendChild(label); settingsContainer.appendChild(listEl); var tooltipEl = ensureTooltip(settingId, listEl); tooltipEl.innerHTML = setting.description; if (setting.requiresReload) { tooltipEl.innerHTML += "<span style=\"color: hsla(20, 100%, 50%, 1); font-size: .9rem; display: block; margin-top: 0.5rem;\">You have to reload the browser tab to apply changes to this setting.</span>"; } } return settingsContainer; } function initCraftingSettings() { var craftingItems = document.getElementById('tab-sub-container-crafting'); if (!craftingItems) { return; } var br = craftingItems.nextElementSibling; var after = br.nextElementSibling; var parent = after.parentElement; var settingList = [KEY.hideCraftingRecipes, KEY.hideUselessItems]; var settingsContainer = createSettingsContainer(settingList); parent.insertBefore(settingsContainer, after); } function initChatSettings() { var controlDiv = document.querySelector('#div-chat > div:first-child'); if (!controlDiv) { return; } var btn = document.createElement('button'); btn.textContent = 'Chat Settings'; controlDiv.appendChild(btn); var dialog = document.createElement('div'); dialog.id = 'dialog-chat-settings'; dialog.style.display = 'none'; dialog.innerHTML = "<h2 style=\"margin-top: 0\">Chat Settings</h2>"; var settingList = [KEY.useNewChat, KEY.colorizeChat, KEY.intelligentScrolling, KEY.showTimestamps, KEY.showIcons, KEY.showTags]; var settingsContainer = createSettingsContainer(settingList); dialog.appendChild(settingsContainer); document.body.appendChild(dialog); btn.addEventListener('click', function () { window.$(dialog).dialog(); }); } function init() { initProxies(); initSettingsStyle(); initSettingTable(); initCraftingSettings(); initChatSettings(); } settings.init = init; var _a; })(settings || (settings = {})); /** * Code from https://github.com/davidmerfield/randomColor */ var colorGenerator; (function (colorGenerator) { // seed to get repeatable colors var seed = null; var COLOR_NOT_FOUND = { hueRange: [] , lowerBounds: [] , saturationRange: [] , brightnessRange: [] }; var COLOR_BOUNDS = { 'monochrome': { hueRange: [] , lowerBounds: [ [0, 0] , [100, 0] ] } , 'red': { hueRange: [-26, 18] , lowerBounds: [ [20, 100] , [30, 92] , [40, 89] , [50, 85] , [60, 78] , [70, 70] , [80, 60] , [90, 55] , [100, 50] ] } , 'orange': { hueRange: [19, 46] , lowerBounds: [ [20, 100] , [30, 93] , [40, 88] , [50, 86] , [60, 85] , [70, 70] , [100, 70] ] } , 'yellow': { hueRange: [47, 62] , lowerBounds: [ [25, 100] , [40, 94] , [50, 89] , [60, 86] , [70, 84] , [80, 82] , [90, 80] , [100, 75] ] } , 'green': { hueRange: [63, 178] , lowerBounds: [ [30, 100] , [40, 90] , [50, 85] , [60, 81] , [70, 74] , [80, 64] , [90, 50] , [100, 40] ] } , 'blue': { hueRange: [179, 257] , lowerBounds: [ [20, 100] , [30, 86] , [40, 80] , [50, 74] , [60, 60] , [70, 52] , [80, 44] , [90, 39] , [100, 35] ] } , 'purple': { hueRange: [258, 282] , lowerBounds: [ [20, 100] , [30, 87] , [40, 79] , [50, 70] , [60, 65] , [70, 59] , [80, 52] , [90, 45] , [100, 42] ] } , 'pink': { hueRange: [283, 334] , lowerBounds: [ [20, 100] , [30, 90] , [40, 86] , [60, 84] , [80, 80] , [90, 75] , [100, 73] ] } }; // shared color dictionary var colorDictionary = {}; function defineColor(name, hueRange, lowerBounds) { var _a = lowerBounds[0] , sMin = _a[0] , bMax = _a[1]; var _b = lowerBounds[lowerBounds.length - 1] , sMax = _b[0] , bMin = _b[1]; colorDictionary[name] = { hueRange: hueRange , lowerBounds: lowerBounds , saturationRange: [sMin, sMax] , brightnessRange: [bMin, bMax] }; } function loadColorBounds() { for (var name_1 in COLOR_BOUNDS) { defineColor(name_1, COLOR_BOUNDS[name_1].hueRange, COLOR_BOUNDS[name_1].lowerBounds); } } function randomWithin(min, max) { if (min === void 0) { min = 0; } if (max === void 0) { max = 0; } if (seed === null) { return Math.floor(min + Math.random() * (max + 1 - min)); } else { // seeded random algorithm from http://indiegamr.com/generate-repeatable-random-numbers-in-js/ seed = (seed * 9301 + 49297) % 233280; var rnd = seed / 233280.0; return Math.floor(min + rnd * (max - min)); } } function getColorInfo(hue) { // maps red colors to make picking hue easier if (hue >= 334 && hue <= 360) { hue -= 360; } for (var colorName in colorDictionary) { var color = colorDictionary[colorName]; if (color.hueRange.length > 0 && hue >= color.hueRange[0] && hue <= color.hueRange[1]) { return colorDictionary[colorName]; } } return COLOR_NOT_FOUND; } function getHueRange(colorInput) { var number = typeof colorInput === 'undefined' ? Number.NaN : colorInput; if (typeof number === 'string') { number = parseInt(number, 10); } if (colorInput && isNaN(number) && colorDictionary.hasOwnProperty(colorInput)) { var color = colorDictionary[colorInput]; if (color.hueRange.length > 0) { return color.hueRange; } } else if (!isNaN(number) && number < 360 && number > 0) { return [number, number]; } return [0, 360]; } function pickHue(options) { var hueRange = getHueRange(options.hue); var hue = randomWithin(hueRange[0], hueRange[1]); // instead of storing red as two seperate ranges, we group them, using negative numbers if (hue < 0) { return 360 + hue; } return hue; } function getSaturationRange(hue) { return getColorInfo(hue).saturationRange; } function pickSaturation(hue, options) { if (options.luminosity === 'random') { return randomWithin(0, 100); } if (options.hue === 'monochrome') { return 0; } var _a = getSaturationRange(hue) , sMin = _a[0] , sMax = _a[1]; switch (options.luminosity) { case 'bright': sMin = 55; break; case 'dark': sMin = sMax - 10; break; case 'light': sMax = 55; break; } return randomWithin(sMin, sMax); } function getMinimumBrightness(H, S) { var lowerBounds = getColorInfo(H).lowerBounds; for (var i = 0; i < lowerBounds.length - 1; i++) { var _a = lowerBounds[i] , s1 = _a[0] , v1 = _a[1]; var _b = lowerBounds[i + 1] , s2 = _b[0] , v2 = _b[1]; if (S >= s1 && S <= s2) { var m = (v2 - v1) / (s2 - s1); var b = v1 - m * s1; return m * S + b; } } return 0; } function pickBrightness(H, S, options) { var bMin = getMinimumBrightness(H, S); var bMax = 100; switch (options.luminosity) { case 'dark': bMax = bMin + 20; break; case 'light': bMin = (bMax + bMin) / 2; break; case 'random': bMin = 0; bMax = 100; break; } return randomWithin(bMin, bMax); } function HSVtoHSL(hsv) { var h = hsv[0]; var s = hsv[1] / 100; var v = hsv[2] / 100; var k = (2 - s) * v; return [ h , Math.round(s * v / (k < 1 ? k : 2 - k) * 10000) / 100 , k / 2 * 100 ]; } function HSVtoRGB(hsv) { // this doesn't work for the values of 0 and 360 here's the hacky fix var h = Math.min(Math.max(hsv[0], 1), 359); // Rebase the h,s,v values h = h / 360; var s = hsv[1] / 100; var v = hsv[2] / 100; var h_i = Math.floor(h * 6); var f = h * 6 - h_i; var p = v * (1 - s); var q = v * (1 - f * s); var t = v * (1 - (1 - f) * s); var r = 256; var g = 256; var b = 256; switch (h_i) { case 0: r = v; g = t; b = p; break; case 1: r = q; g = v; b = p; break; case 2: r = p; g = v; b = t; break; case 3: r = p; g = q; b = v; break; case 4: r = t; g = p; b = v; break; case 5: r = v; g = p; b = q; break; } return [Math.floor(r * 255), Math.floor(g * 255), Math.floor(b * 255)]; } function HSVtoHex(hsv) { function componentToHex(c) { var hex = c.toString(16); return hex.length == 1 ? '0' + hex : hex; } var rgb = HSVtoRGB(hsv); return '#' + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]); } function setFormat(hsv, options) { switch (options.format) { case 'hsvArray': return hsv; case 'hslArray': return HSVtoHSL(hsv); case 'hsl': var hsl = HSVtoHSL(hsv); return 'hsl(' + hsl[0] + ', ' + hsl[1] + '%, ' + hsl[2] + '%)'; case 'hsla': var hslColor = HSVtoHSL(hsv); var alpha = options.alpha || Math.random(); return 'hsla(' + hslColor[0] + ', ' + hslColor[1] + '%, ' + hslColor[2] + '%, ' + alpha + ')'; case 'rgbArray': return HSVtoRGB(hsv); case 'rgb': var rgb = HSVtoRGB(hsv); return 'rgb(' + rgb.join(', ') + ')'; case 'rgba': var rgbColor = HSVtoRGB(hsv); var alpha = options.alpha || Math.random(); return 'rgba(' + rgbColor.join(', ') + ', ' + alpha + ')'; case 'hex': default: return HSVtoHex(hsv); } } function generateColor(options) { // pick a hue (H) var H = pickHue(options); // use H to determine saturation (S) var S = pickSaturation(H, options); // use S and H to determine brightness (B) var B = pickBrightness(H, S, options); // return the HSB color in the desired format return setFormat([H, S, B], options); } function getRandom(options) { options = options || {}; seed = options.seed == null ? null : options.seed; // check if we need to generate multiple colors if (options.count !== null && options.count !== undefined) { var totalColors = options.count; var colors = []; options.count = null; while (totalColors > colors.length) { // Since we're generating multiple colors, the seed has to be incrememented. // Otherwise we'd just generate the same color each time... if (seed !== null) { seed += 1; } colors.push(generateColor(options)); } options.count = totalColors; return colors; } return generateColor(options); } colorGenerator.getRandom = getRandom; var ColorInterval = (function () { function ColorInterval(start, end) { this.start = start; this.end = end; this.left = null; this.right = null; this.value = null; } ColorInterval.prototype.getNextValue = function () { if (this.value == null) { this.value = (this.start + this.end) / 2; return this.value; } if (this.left == null) { this.left = new ColorInterval(this.start, this.value); return this.left.getNextValue(); } if (this.right == null) { this.right = new ColorInterval(this.value, this.end); return this.right.getNextValue(); } if (this.left.getHeight() <= this.right.getHeight()) { return this.left.getNextValue(); } else { return this.right.getNextValue(); } }; ColorInterval.prototype.getHeight = function () { return 1 + (this.left == null ? 0 : this.left.getHeight()) + (this.right == null ? 0 : this.right.getHeight()); }; return ColorInterval; }()); var rootInterval = new ColorInterval(0, 360); function getEquallyDistributed() { return 'hsl(' + rootInterval.getNextValue() + ', 100%, 80%)'; } colorGenerator.getEquallyDistributed = getEquallyDistributed; // populate the color dictionary loadColorBounds(); })(colorGenerator || (colorGenerator = {})); /** * notifications */ var notifications; (function (notifications) { notifications.name = 'notifications'; function event(title, options) { if ((!options || options.whenActive !== true) && !document.hidden && document.hasFocus()) { return; } if (!settings.get(settings.KEY.showNotifications)) { // notifications disabled: return stub notification return Promise.resolve( { close: function () {} }); } if (!("Notification" in window)) { return Promise.reject('Your browser does not support notifications.'); } return Notification.requestPermission() .then(function (permission) { if (permission === 'granted') { var n_1 = new Notification(title, options); n_1.onclick = function (event) { if (options && options.autoFocus !== false) { window.focus(); } if (options && options.autoClose !== false) { n_1.close(); } if (options && options.onclick) { options.onclick(n_1, event); } }; return Promise.resolve(n_1); } else { return Promise.reject('Notification permission denied'); } }); } notifications.event = event; function requestPermission() { if (settings.get(settings.KEY.showNotifications)) { Notification.requestPermission(); } } function init() { requestPermission(); settings.observe(settings.KEY.showNotifications, function () { return requestPermission(); }); } notifications.init = init; })(notifications || (notifications = {})); /** * game events */ var gameEvents; (function (gameEvents) { gameEvents.name = 'gameEvents'; // min time difference between two notifications with the same title (10 seconds) var MIN_TIME_DIFFERENCE = 10; gameEvents.enabled = { smelting: true , chopping: true , harvest: true , boat: true , battle: true , brewing: true , market: true }; var lastTimestamp = new Map(); function notifyTabClickable(title, body, icon, tabName) { var now = (new Date).getTime(); var timeDiff = now - (lastTimestamp.get(title) || 0); if (timeDiff < MIN_TIME_DIFFERENCE * 1e3) { return; } if (document.hidden || !document.hasFocus()) { lastTimestamp.set(title, now); notifications.event(title , { body: body , icon: 'images/' + icon , onclick: function () { window.openTab(tabName); } }); } } function observeTimer(k, fn) { observer.add(k, function (key, oldValue, newValue) { if (oldValue > 0 && newValue == 0) { fn(key, oldValue, newValue); } }); } function smelting() { observeTimer('smeltingPercD', function (key, oldValue, newValue) { if (!gameEvents.enabled.smelting) { return; } notifyTabClickable('Hot topic', 'Your smelting has finished.', getFurnaceLevelName() + 'Furnace.png', 'crafting'); }); } function chopping() { observer.add([ 'treeStage1' , 'treeStage2' , 'treeStage3' , 'treeStage4' , 'treeStage5' , 'treeStage6' ], function (key, oldValue, newValue) { if (!gameEvents.enabled.chopping) { return; } if (newValue == 4) { notifyTabClickable('Wood you be mine?', 'One or more of your trees are fully grown and can be chopped.', 'icons/woodcutting.png', 'woodcutting'); } }); } function harvest() { observer.add([ 'farmingPatchStage1' , 'farmingPatchStage2' , 'farmingPatchStage3' , 'farmingPatchStage4' , 'farmingPatchStage5' , 'farmingPatchStage6' ], function (key, oldValue, newValue) { if (!gameEvents.enabled.harvest) { return; } if (newValue == 4) { notifyTabClickable('Green thumb', 'One or more of your crops is ready for harvest.', 'icons/watering-can.png', 'farming'); } else if (newValue > 4) { notifyTabClickable('I didn\'t plant this', 'One or more of your crops died.', 'icons/watering-can.png', 'farming'); } }); } function boat() { observeTimer([ 'rowBoatTimer' , 'canoeTimer' ], function (k, oldValue, newValue) { if (!gameEvents.enabled.boat) { return; } var key = k.replace(/Timer$/, ''); notifyTabClickable('Fishy business', 'Your ' + split2Words(key).toLowerCase() + ' returned from its trip.', key + '.png', 'combat'); }); } function battle() { observeTimer('combatGlobalCooldown', function (key, oldValue, newValue) { if (!gameEvents.enabled.battle) { return; } notifyTabClickable('Ready to work', 'Your hero is eager to fight.', 'icons/combat.png', 'combat'); }); } function brewing() { observeTimer([ 'barPotionTimer' , 'seedPotionTimer' , 'stardustPotionTimer' , 'superStardustPotionTimer' ], function (key, oldValue, newValue) { if (!gameEvents.enabled.brewing) { return; } var potionKey = key.replace(/Timer$/, ''); if (getGameValue(potionKey) > 0) { notifyTabClickable('Cheers!', 'You can drink another ' + split2Words(potionKey) + '.', key.replace(/Timer$/, '') + '.png', 'brewing'); } }); } function market() { var _refreshMarketSlot = window.refreshMarketSlot; window.refreshMarketSlot = function (offerId, itemName, amount, price, collectText, slotId, timeLeft) { if (gameEvents.enabled.market && collectText > 0) { notifyTabClickable('Ka-ching', 'You\'ve sold ' + (amount > 0 ? 'some' : 'all') + ' ' + split2Words(itemName).toLowerCase() + ' to the market.', 'icons/shop.png', 'playermarket'); } _refreshMarketSlot(offerId, itemName, amount, price, collectText, slotId, timeLeft); }; } function gameValues() { observer.add('treasureMap', function (key, oldValue, newValue) { if (oldValue > newValue) { notifyTabClickable('Arrrr!', 'Your pirate found a treasure map.', 'treasureMap.png', 'items'); } }); } function init() { smelting(); chopping(); harvest(); boat(); battle(); brewing(); market(); gameValues(); } gameEvents.init = init; })(gameEvents || (gameEvents = {})); /** * hide crafting recipes of lower tiers or of maxed machines */ var hideCraftedRecipes; (function (hideCraftedRecipes) { hideCraftedRecipes.name = 'hideCraftedRecipes'; function setRecipeVisibility(key, visible) { var recipeRow = document.getElementById('crafting-' + key); if (recipeRow) { recipeRow.style.display = (!settings.get(settings.KEY.hideCraftingRecipes) || visible) ? '' : 'none'; } } function hideLeveledRecipes(max, getKey, init) { if (init === void 0) { init = false; } var keys2Observe = []; var maxLevel = 0; for (var i = max - 1; i >= 0; i--) { var level = i + 1; var key = getKey(i); var boundKey = getBoundKey(key); keys2Observe.push(key); keys2Observe.push(boundKey); if (getGameValue(key) > 0 || getGameValue(boundKey) > 0) { maxLevel = Math.max(maxLevel, level); } setRecipeVisibility(key, level > maxLevel); } if (init) { observer.add(keys2Observe, function () { return hideLeveledRecipes(max, getKey, false); }); } } function hideToolRecipe(key, init) { if (init === void 0) { init = false; } var emptyKey = getTierKey(key, 0); var keys2Observe = [emptyKey]; var hasTool = getGameValue(emptyKey) > 0; for (var i = 0; i < TIER_LEVELS.length; i++) { var boundKey = getBoundKey(getTierKey(key, i)); hasTool = hasTool || getGameValue(boundKey) > 0; keys2Observe.push(boundKey); } setRecipeVisibility(emptyKey, !hasTool); if (init) { observer.add(keys2Observe, function () { return hideToolRecipe(key, false); }); } } function hideRecipe(key, hideInfo, init) { if (init === void 0) { init = false; } var maxValue = typeof hideInfo.max === 'function' ? hideInfo.max() : hideInfo.max; var boundKey = getBoundKey(key); var unbound = getGameValue(key); var bound = getGameValue(boundKey); var extra = (hideInfo.extraKeys || []).map(function (k) { return getGameValue(k); }).reduce(function (p, c) { return p + c; }, 0); setRecipeVisibility(key, (bound + unbound + extra) < maxValue); if (init) { observer.add([key, boundKey], function () { return hideRecipe(key, hideInfo, false); }); } } function init() { function processRecipes(init) { if (init === void 0) { init = false; } // furnace hideLeveledRecipes(FURNACE_LEVELS.length, function (i) { return FURNACE_LEVELS[i] + 'Furnace'; }, init); // oil storage hideLeveledRecipes(OIL_STORAGE_SIZES.length, function (i) { return 'oilStorage' + (i + 1); }, init); // oven recipes hideLeveledRecipes(OVEN_LEVELS.length, function (i) { return OVEN_LEVELS[i] + 'Oven'; }, init); // tools for (var _i = 0, TIER_ITEMS_1 = TIER_ITEMS; _i < TIER_ITEMS_1.length; _i++) { var tool = TIER_ITEMS_1[_i]; hideToolRecipe(tool, init); } // other stuff for (var key in HIDE_RECIPES) { hideRecipe(key, HIDE_RECIPES[key], init); } if (init) { settings.observe(settings.KEY.hideCraftingRecipes, function () { return processRecipes(false); }); } } processRecipes(true); var _processCraftingTab = window.processCraftingTab; window.processCraftingTab = function () { var reinit = !!window.refreshLoadCraftingTable; _processCraftingTab(); if (reinit) { processRecipes(false); } }; } hideCraftedRecipes.init = init; })(hideCraftedRecipes || (hideCraftedRecipes = {})); /** * hide useless items */ var hideUselessItems; (function (hideUselessItems) { hideUselessItems.name = 'hideUselessItems'; function setItemVisibility(key, visible) { var itemBox = document.getElementById('item-box-' + key); if (itemBox) { itemBox.style.display = getGameValue(key) > 0 && (!settings.get(settings.KEY.hideUselessItems) || visible) ? '' : 'none'; } } function hideLeveledItems(max, getKey, init) { if (init === void 0) { init = false; } var keys2Observe = []; var maxLevel = 0; for (var i = max - 1; i >= 0; i--) { var level = i + 1; var key = getKey(i); var boundKey = getBoundKey(key); keys2Observe.push(key); keys2Observe.push(boundKey); if (getGameValue(boundKey) > 0) { maxLevel = Math.max(maxLevel, level); } setItemVisibility(key, level > maxLevel); } if (init) { observer.add(keys2Observe, function () { return hideLeveledItems(max, getKey, false); }); } } function hideItem(key, hideInfo, init) { if (init === void 0) { init = false; } var maxValue = typeof hideInfo.max === 'function' ? hideInfo.max() : hideInfo.max; var boundKey = getBoundKey(key); var bound = getGameValue(boundKey); var extra = (hideInfo.extraKeys || []).map(function (k) { return getGameValue(k); }).reduce(function (p, c) { return p + c; }, 0); setItemVisibility(key, (bound + extra) < maxValue); if (init) { observer.add([key, boundKey], function () { return hideItem(key, hideInfo, false); }); } } function init() { function processItems(init) { if (init === void 0) { init = false; } // furnace hideLeveledItems(FURNACE_LEVELS.length, function (i) { return FURNACE_LEVELS[i] + 'Furnace'; }, init); // oil storage hideLeveledItems(OIL_STORAGE_SIZES.length, function (i) { return 'oilStorage' + (i + 1); }, init); // oven recipes hideLeveledItems(OVEN_LEVELS.length, function (i) { return OVEN_LEVELS[i] + 'Oven'; }, init); // other stuff for (var key in HIDE_RECIPES) { hideItem(key, HIDE_RECIPES[key], init); } if (init) { settings.observe(settings.KEY.hideUselessItems, function () { return processItems(false); }); } } processItems(true); } hideUselessItems.init = init; })(hideUselessItems || (hideUselessItems = {})); /** * improve item boxes */ var improveItemBoxes; (function (improveItemBoxes) { improveItemBoxes.name = 'improveItemBoxes'; function hideNumberInItemBox(key, setVisibility) { if (setVisibility === void 0) { setVisibility = false; } var itemBox = document.getElementById('item-box-' + key); if (!itemBox) { return; } var numberElement = itemBox.lastElementChild; if (!numberElement) { return; } if (setVisibility) { numberElement.style.visibility = 'hidden'; } else { numberElement.style.display = 'none'; } } function addSpan2ItemBox(key) { hideNumberInItemBox(key); var itemBox = document.getElementById('item-box-' + key); if (!itemBox) { return; } var span = document.createElement('span'); itemBox.appendChild(span); return span; } function setOilPerSecond(span, oil) { span.innerHTML = "+ " + format.number(oil) + " L/s <img src=\"images/oil.png\" class=\"image-icon-20\" style=\"margin-top: -2px;\">"; } // show capacity of furnace function addFurnaceCaption() { for (var i = 0; i < FURNACE_LEVELS.length; i++) { var key = FURNACE_LEVELS[i] + 'Furnace'; var boundKey = getBoundKey(key); var capacitySpan = addSpan2ItemBox(boundKey); if (capacitySpan) { capacitySpan.className = 'capacity'; capacitySpan.textContent = 'Capacity: ' + format.number(window.getFurnaceCapacity(boundKey)); } } } // show oil cap of oil storage function addOilStorageCaption() { for (var i = 0; i < OIL_STORAGE_SIZES.length; i++) { var key = 'oilStorage' + (i + 1); var capSpan = addSpan2ItemBox(getBoundKey(key)); if (capSpan) { capSpan.className = 'oil-cap'; capSpan.textContent = 'Oil cap: ' + format.number(OIL_STORAGE_SIZES[i]); } } } // show oil per second function addOilCaption() { var handheldOilSpan = addSpan2ItemBox('handheldOilPump'); if (handheldOilSpan) { setOilPerSecond(handheldOilSpan, 1 * window.miner); observer.add('miner', function () { return setOilPerSecond(handheldOilSpan, 1 * window.miner); }); } var oilPipeSpan = addSpan2ItemBox('boundOilPipe'); if (oilPipeSpan) { setOilPerSecond(oilPipeSpan, 50); } // add number of workers as caption to oil factory var workerSpan = addSpan2ItemBox('boundOilFactory'); if (workerSpan) { var setCaption_1 = function () { return workerSpan.textContent = 'Workers: ' + window.oilFactoryWorkers; }; setCaption_1(); observer.add('oilFactoryWorkers', function () { return setCaption_1; }); } } function hideNumberCaption() { hideNumberInItemBox('emptyAnvil', true); hideNumberInItemBox('tap', true); hideNumberInItemBox('farmer', true); hideNumberInItemBox('planter', true); hideNumberInItemBox('cooksBook', true); hideNumberInItemBox('cooksPage', true); hideNumberInItemBox('combatDropTable', true); } // show current tier function addTierCaption() { for (var _i = 0, TIER_ITEMS_2 = TIER_ITEMS; _i < TIER_ITEMS_2.length; _i++) { var tierItem = TIER_ITEMS_2[_i]; for (var i = 0; i < TIER_LEVELS.length; i++) { var key = getTierKey(tierItem, i); var toolKey = tierItem == 'rake' ? key : getBoundKey(key); var tierSpan = addSpan2ItemBox(toolKey); if (tierSpan) { tierSpan.className = 'tier'; tierSpan.textContent = TIER_NAMES[i]; } } } } var boatKeys = ['rowBoat', 'canoe']; var boatTimerKeys = boatKeys.map(function (k) { return k + 'Timer'; }); function checkBoat(span, timerKey, init) { if (init === void 0) { init = false; } var isInTransit = getGameValue(timerKey) > 0; var otherInTransit = boatTimerKeys.some(function (k) { return k != timerKey && getGameValue(k) > 0; }); span.textContent = isInTransit ? 'In transit' : 'Ready'; span.style.visibility = otherInTransit ? 'hidden' : ''; if (init) { observer.add(boatTimerKeys, function () { return checkBoat(span, timerKey, false); }); } } // show boat progress function addBoatCaption() { for (var i = 0; i < boatKeys.length; i++) { var span = addSpan2ItemBox(getBoundKey(boatKeys[i])); if (span) { checkBoat(span, boatTimerKeys[i], true); } } } // show bonemeal function addBonemealCaption() { var noBonemealSpan = addSpan2ItemBox('boundBonemealBin'); if (!noBonemealSpan) { return; } noBonemealSpan.textContent = 'Bonemeal: 0'; var bonemealSpan = addSpan2ItemBox('boundFilledBonemealBin'); if (!bonemealSpan) { return; } bonemealSpan.dataset.itemDisplay = 'bonemeal'; bonemealSpan.textContent = format.number(window.bonemeal); var captionSpan = document.createElement('span'); captionSpan.textContent = 'Bonemeal: '; bonemealSpan.parentElement.insertBefore(captionSpan, bonemealSpan); } function warningBeforeSellingGems() { var _sellNPCItemDialogue = window.sellNPCItemDialogue; window.sellNPCItemDialogue = function (item, amount) { if (item == 'sapphire' || item == 'emerald' || item == 'ruby' || item == 'diamond' || item == 'bloodDiamond') { var itemName = key2Name(amount == 1 ? item : item.replace(/y$/, 'ie') + 's', true); if (amount == 0 || !window.confirm('Gems are precious and rare. Please consider carefully:\nDo you really want to sell ' + amount + ' ' + itemName + '?')) { return; } } else if (item == 'logs' || item == 'oakLogs' || item == 'willowLogs' || item == 'mapleLogs' || item == 'stardustLogs' || item == 'ancientLogs') { var itemName = key2Name(amount == 1 ? item.replace(/s$/, '') : item, true); if (amount == 0 || !window.confirm('Logs are time consuming to collect. Please consider carefully:\nDo you really want to sell ' + amount + ' ' + itemName + '?')) { return; } } _sellNPCItemDialogue(item, amount); }; } function init() { addFurnaceCaption(); addOilStorageCaption(); addOilCaption(); hideNumberCaption(); addTierCaption(); addBoatCaption(); addBonemealCaption(); warningBeforeSellingGems(); } improveItemBoxes.init = init; })(improveItemBoxes || (improveItemBoxes = {})); /** * add new chat */ var chat; (function (chat) { chat.name = 'chat'; var KEYWORD_LIST_KEY = 'keywordList'; var keywordList = store.get(KEYWORD_LIST_KEY) || []; var CHAT_HISTORY_KEY = 'chatHistory'; var MAX_CHAT_HISTORY_LENGTH = 100; var Type; (function (Type) { Type[Type["reload"] = -1] = "reload"; Type[Type["normal"] = 0] = "normal"; Type[Type["pmReceived"] = 1] = "pmReceived"; Type[Type["pmSent"] = 2] = "pmSent"; Type[Type["serverMsg"] = 3] = "serverMsg"; })(Type || (Type = {}));; var Tag; (function (Tag) { Tag[Tag["none"] = 0] = "none"; Tag[Tag["donor"] = 1] = "donor"; Tag[Tag["contributor"] = 2] = "contributor"; Tag[Tag["mod"] = 3] = "mod"; Tag[Tag["dev"] = 4] = "dev"; Tag[Tag["server"] = 5] = "server"; })(Tag || (Tag = {}));; /** * The chunk hiding starts with at least 10 chunks. * So there are at least * (chunkHidingMinChunks-1) * msgChunkSize + 1 = 9 * 100 + 1 = 901 * messages before the chunk hiding mechanism starts. */ var CHUNK_HIDING_MIN_CHUNKS = 10; var MSG_CHUNK_SIZE = 100; var RELOADED_CHAT_DATA = { timestamp: 0 , username: '' , userlevel: 0 , icon: 0 , tag: 0 , type: Type.reload , msg: '[...]' }; var CHAT_BOX_ID = 'div-chat'; var DEFAULT_CHAT_DIV_ID = 'div-chat-area'; var GENERAL_CHAT_DIV_ID = 'div-chat-general'; var PM_CHAT_TAB_PREFIX = 'tab-chat-pm-'; var PM_CHAT_DIV_PREFIX = 'div-chat-pm-'; var CHAT_TABS_ID = 'chat-tabs'; var CHAT_INPUT_ID = 'chat-input-text'; var CHAT_CLASS = 'div-chat-area'; var COLORIZE_CLASS = 'colorize'; var SpecialTab; (function (SpecialTab) { SpecialTab[SpecialTab["default"] = 0] = "default"; SpecialTab[SpecialTab["general"] = 1] = "general"; SpecialTab[SpecialTab["filler"] = 2] = "filler"; })(SpecialTab || (SpecialTab = {}));; var CHAT_SPECIAL_TAB_ID = (_a = {} , _a[SpecialTab.default] = 'tab-chat-default' , _a[SpecialTab.general] = 'tab-chat-general' , _a[SpecialTab.filler] = 'tab-chat-filler' , _a); var CONTEXTMENU_ID = 'player-contextmenu'; var CHAT_ICONS = [ null , { key: 'halloween2015' , title: 'Halloween 2015' } , { key: 'christmas2015' , title: 'Chirstmas 2015' } , { key: 'easter2016' , title: 'Holiday' } , { key: 'halloween2016' , title: 'Halloween 2016' } , { key: 'christmas2016' , title: 'Chirstmas 2016' } , { key: 'dh1Max' , title: 'Max Level in DH1' } , { key: 'hardcore' , title: 'Hardcore Account' } , { key: 'quest' , title: 'Questmaster' } ]; var CHAT_TAGS = [ null , { key: 'donor' , name: '' } , { key: 'contributor' , name: 'Contributor' } , { key: 'mod' , name: 'Moderator' } , { key: 'dev' , name: 'Dev' } , { key: 'yell' , name: 'Server Message' } ]; var LOCALE = 'en-US'; var LOCALE_OPTIONS = { hour12: false , year: 'numeric' , month: 'long' , day: 'numeric' , hour: '2-digit' , minute: '2-digit' , second: '2-digit' }; var TUTORIAL_CMD = 'tutorial'; var KEYWORD_ADD_CMD = 'keyword add'; var KEYWORD_REMOVE_CMD = 'keyword remove'; // load chat history var chatHistory = store.get(CHAT_HISTORY_KEY) || []; // find index of last message which is not a pm var isLastMsgNotReload = false; for (var i = chatHistory.length - 1; i >= 0; i--) { if (!isDataPM(chatHistory[i])) { isLastMsgNotReload = chatHistory[i].type != Type.reload; break; } } // insert a placeholder for a reloaded chat if (isLastMsgNotReload) { RELOADED_CHAT_DATA.timestamp = (new Date()).getTime(); chatHistory.push(RELOADED_CHAT_DATA); } // store chat colors for each user var user2Color = new Map(); var usedColors = new Set(); // reserve color for special messages (e.g. server messages): white usedColors.add('#ffffff'); function isMuted(user) { // ATTENTION: this will filter all people who are named similar to one of the muted people! return window.mutedPeople.some(function (name) { return user.indexOf(name) > -1; }); // return window.mutedPeople.indexOf(user) !== -1; } function isSpam(data) { // allow all messages from contributors, mods, devs and all server messages if (data.tag != Tag.none) { return false; } /** * get last message of current user */ var isThisPm = isDataPM(data); var msgUsername = data.type === Type.pmSent ? window.username : data.username; var historyIndex = chatHistory.indexOf(data); if (historyIndex == -1) { historyIndex = chatHistory.length; } var lastData = null; for (var i = historyIndex - 1; i >= 0 && (lastData === null); i--) { var dataBefore = chatHistory[i]; if (isThisPm === isDataPM(dataBefore)) { var beforeUsername = dataBefore.type == Type.pmSent ? window.username : dataBefore.username; if (beforeUsername === msgUsername) { lastData = dataBefore; } } } /** * compare message and don't allow the same message twice */ if (lastData && lastData.msg === data.msg && (data.timestamp - lastData.timestamp) < 10e3) { return true; } return false; } function handleScrolling(chatbox) { if (window.isAutoScrolling) { setTimeout(function () { return chatbox.scrollTop = chatbox.scrollHeight; }); } } // for chat messages which arrive before DOMContentLoaded and can not be displayed since the DOM isn't ready var chatInitialized = false; function processChatData(username, iconString, tagString, msg, isPM) { var tag = parseInt(tagString, 10); var userlevel = 0; var type = Type.normal; if (isPM == 1) { var match = msg.match(/^\s*\[(.+) ([A-Za-z0-9 ]+)\]: (.+?)\s*$/) || ['', '', username, msg]; type = match[1] == 'Sent to' ? Type.pmSent : Type.pmReceived; username = match[2]; msg = match[3]; } else if (tag == Tag.server) { type = Type.serverMsg; } else { var match = msg.match(/^\s*\((\d+)\): (.+?)\s*$/); if (match) { userlevel = parseInt(match[1], 10); msg = match[2]; } else { userlevel = window.getGlobalLevel(); } } // unlinkify when using DH2QoL to store the plain message if (window.addToChatBox.toString().includes('linkify(arguments[3])')) { msg = msg.replace(/<a href='([^']+)' target='_blank'>\1<\/a>/ig, '$1'); } if (type == Type.pmSent) { // turn some critical characters into HTML entities msg = msg.replace(/[<>]/g, function (char) { return '&#' + char.charCodeAt(0) + ';'; }); } return { timestamp: now() , username: username , userlevel: userlevel , icon: parseInt(iconString, 10) , tag: tag , type: type , msg: msg }; } function add2ChatHistory(data) { chatHistory.push(data); chatHistory = chatHistory.slice(-MAX_CHAT_HISTORY_LENGTH); store.set(CHAT_HISTORY_KEY, chatHistory); } function username2Id(username) { return username.replace(/[ \+]/g, '_'); } function getChatTab(username, specialTab) { var id = (specialTab != null) ? CHAT_SPECIAL_TAB_ID[specialTab] : PM_CHAT_TAB_PREFIX + username2Id(username); var tab = document.getElementById(id); if (!tab) { tab = document.createElement('div'); tab.className = 'chat-tab'; if (specialTab != null) { tab.classList.add(SpecialTab[specialTab]); } tab.id = id; tab.dataset.username = username; tab.dataset.new = '0'; if (username.length > 2) { tab.textContent = username; // thanks /u/Spino-Prime for pointing out this was missing var closeSpan = document.createElement('span'); closeSpan.className = 'close'; tab.appendChild(closeSpan); } var chatTabs = document.getElementById(CHAT_TABS_ID); var filler = chatTabs.querySelector('.filler'); if (filler) { chatTabs.insertBefore(tab, filler); } else { chatTabs.appendChild(tab); } } return tab; } function getChatDiv(username) { var id = username == '' ? GENERAL_CHAT_DIV_ID : PM_CHAT_DIV_PREFIX + username2Id(username); var div = document.getElementById(id); if (!div) { div = document.createElement('div'); div.setAttribute('disabled', 'disabled'); div.id = id; div.className = CHAT_CLASS; var defaultChat = document.getElementById(DEFAULT_CHAT_DIV_ID); var height = defaultChat.style.height; div.style.height = height; var chatDiv = defaultChat.parentElement; chatDiv.insertBefore(div, defaultChat); } return div; } function changeChatTab(oldTab, newTab) { if (oldTab) { oldTab.classList.remove('selected'); var oldChatDiv = void 0; if (oldTab.classList.contains('default')) { oldChatDiv = document.getElementById(DEFAULT_CHAT_DIV_ID); } else { oldChatDiv = getChatDiv(oldTab.dataset.username || ''); } oldChatDiv.classList.remove('selected'); } newTab.classList.add('selected'); newTab.dataset.new = '0'; var newChatDiv; if (newTab.classList.contains('default')) { newChatDiv = document.getElementById(DEFAULT_CHAT_DIV_ID); } else { newChatDiv = getChatDiv(newTab.dataset.username || ''); } newChatDiv.classList.add('selected'); var toUsername = newTab.dataset.username; var newTextPlaceholder = toUsername == '' ? window.username + ':' : 'PM to ' + toUsername + ':'; document.getElementById(CHAT_INPUT_ID).placeholder = newTextPlaceholder; if (window.isAutoScrolling) { setTimeout(function () { return newChatDiv.scrollTop = newChatDiv.scrollHeight; }); } } function closeChatTab(username) { // TODO: maybe delete pms stored for that user? var oldTab = document.querySelector('#' + CHAT_TABS_ID + ' .chat-tab.selected'); var tab2Close = getChatTab(username, null); if (oldTab.dataset.username == username) { var generalTab = getChatTab('', SpecialTab.general); changeChatTab(tab2Close, generalTab); } var tabContainer = tab2Close.parentElement; tabContainer.removeChild(tab2Close); } function isDataPM(data) { return data.type === Type.pmSent || data.type === Type.pmReceived; } var msgChunkMap = new Map(); var chatboxFragments = new Map(); function colorizeMsg(username) { if (username == '') { return null; } if (!user2Color.has(username)) { var color = void 0; do { // color = colorGenerator.getRandom({ luminosity: 'light' }); color = colorGenerator.getEquallyDistributed(); } while (usedColors.has(color)); user2Color.set(username, color); usedColors.add(color); addStyle("\n#" + CHAT_BOX_ID + "." + COLORIZE_CLASS + " .chat-msg[data-username=\"" + username + "\"]\n{\n\tbackground-color: " + color + ";\n}\n\t\t\t", 'name-color'); } return user2Color.get(username); } function createMessageSegment(data) { var isThisPm = isDataPM(data); var msgUsername = data.type === Type.pmSent ? window.username : data.username; var historyIndex = chatHistory.indexOf(data); var isSameUser = null; var isSameTime = null; for (var i = historyIndex - 1; i >= 0 && (isSameUser === null || isSameTime === null); i--) { var dataBefore = chatHistory[i]; if (isThisPm === isDataPM(dataBefore)) { if (isSameUser === null) { var beforeUsername = dataBefore.type == Type.pmSent ? window.username : dataBefore.username; isSameUser = beforeUsername === msgUsername; } if (dataBefore.type != Type.reload) { isSameTime = Math.floor(data.timestamp / 1000 / 60) - Math.floor(dataBefore.timestamp / 1000 / 60) === 0; } } } var d = new Date(data.timestamp); var hour = (d.getHours() < 10 ? '0' : '') + d.getHours(); var minute = (d.getMinutes() < 10 ? '0' : '') + d.getMinutes(); var icon = CHAT_ICONS[data.icon] || { key: '' , title: '' }; var tag = CHAT_TAGS[data.tag] || { key: '' , name: '' }; var formattedMsg = data.msg .replace(/<a href='(.+?)' target='_blank'>\1<\/a>/g, '$1') .replace(/(https?:\/\/[^\s"<>]+)/g, '<a target="_blank" href="$1">$1</a>'); colorizeMsg(msgUsername); var msgTitle = data.type == Type.reload ? 'Chat loaded on ' + d.toLocaleString(LOCALE, LOCALE_OPTIONS) : ''; var user = data.type === Type.serverMsg ? 'Server Message' : msgUsername; var levelAppendix = data.type == Type.normal ? ' (' + data.userlevel + ')' : ''; var userTitle = data.tag != Tag.server ? tag.name : ''; return "<span class=\"chat-msg\" data-type=\"" + data.type + "\" data-tag=\"" + tag.key + "\" data-username=\"" + msgUsername + "\">" + ("<span\n\t\t\t\tclass=\"timestamp\"\n\t\t\t\tdata-timestamp=\"" + data.timestamp + "\"\n\t\t\t\tdata-same-time=\"" + isSameTime + "\">" + hour + ":" + minute + "</span>") + ("<span class=\"user\" data-name=\"" + msgUsername + "\" data-same-user=\"" + isSameUser + "\">") + ("<span class=\"icon " + icon.key + "\" title=\"" + icon.title + "\"></span>") + ("<span class=\"name chat-tag-" + tag.key + "\" title=\"" + userTitle + "\">" + user + levelAppendix + ":</span>") + "</span>" + ("<span class=\"msg\" title=\"" + msgTitle + "\">" + formattedMsg + "</span>") + "</span>"; } function add2Chat(data) { if (!chatInitialized) { return; } var isThisPm = isDataPM(data); // don't mute pms (you can just ignore pm-tab if you like) if (!isThisPm && isMuted(data.username)) { return; } var userKey = isThisPm ? data.username : ''; var chatTab = getChatTab(userKey, isThisPm ? null : SpecialTab.general); if (!chatTab.classList.contains('selected')) { chatTab.dataset.new = (parseInt(chatTab.dataset.new || '0', 10) + 1).toString(); } if (isThisPm) { window.lastPMUser = data.username; } // username is 3-12 characters long var chatbox = getChatDiv(userKey); var msgChunk = msgChunkMap.get(userKey); if (!msgChunk || msgChunk.children.length >= MSG_CHUNK_SIZE) { msgChunk = document.createElement('div'); msgChunk.className = 'msg-chunk'; msgChunkMap.set(userKey, msgChunk); if (chatboxFragments != null) { if (!chatboxFragments.has(userKey)) { chatboxFragments.set(userKey, document.createDocumentFragment()); } chatboxFragments.get(userKey).appendChild(msgChunk); } else { chatbox.appendChild(msgChunk); } } var tmp = document.createElement('templateWrapper'); tmp.innerHTML = createMessageSegment(data); msgChunk.appendChild(tmp.children[0]); handleScrolling(chatbox); } function applyChatStyle() { addStyle("\nspan.chat-msg\n{\n\tdisplay: flex;\n\tpadding: 1px 0;\n}\n#" + CHAT_BOX_ID + ":not(." + COLORIZE_CLASS + ") span.chat-msg:nth-child(2n)\n{\n\tbackground-color: hsla(0, 0%, 90%, 1);\n}\n.chat-msg[data-type=\"" + Type.reload + "\"]\n{\n\tfont-size: 0.8rem;\n}\n.chat-msg .timestamp\n{\n\tdisplay: none;\n}\n#" + CHAT_BOX_ID + ".showTimestamps .chat-msg:not([data-type=\"" + Type.reload + "\"]) .timestamp\n{\n\tcolor: hsla(0, 0%, 50%, 1);\n\tdisplay: inline-block;\n\tfont-size: .9rem;\n\tmargin: 0;\n\tmargin-right: 5px;\n\tposition: relative;\n\twidth: 2.5rem;\n}\n.chat-msg .timestamp[data-same-time=\"true\"]\n{\n\tcolor: hsla(0, 0%, 50%, .1);\n}\n.chat-msg:not([data-type=\"" + Type.reload + "\"]) .timestamp:hover::after\n{\n\tbackground-color: hsla(0, 0%, 12%, 1);\n\tborder-radius: .2rem;\n\tcontent: attr(data-fulltime);\n\tcolor: hsla(0, 0%, 100%, 1);\n\tline-height: 1.35rem;\n\tpadding: .4rem .8rem;\n\tpointer-events: none;\n\tposition: absolute;\n\tleft: 2.5rem;\n\ttop: -0.4rem;\n\ttext-align: center;\n\twhite-space: nowrap;\n}\n\n#" + CHAT_BOX_ID + ".showTags .chat-msg[data-type=\"" + Type.pmReceived + "\"] { color: purple; }\n#" + CHAT_BOX_ID + ".showTags .chat-msg[data-type=\"" + Type.pmSent + "\"] { color: purple; }\n#" + CHAT_BOX_ID + ".showTags .chat-msg[data-type=\"" + Type.serverMsg + "\"] { color: blue; }\n#" + CHAT_BOX_ID + ".showTags .chat-msg[data-tag=\"contributor\"] { color: green; }\n#" + CHAT_BOX_ID + ".showTags .chat-msg[data-tag=\"mod\"] { color: #669999; }\n#" + CHAT_BOX_ID + ".showTags .chat-msg[data-tag=\"dev\"] { color: #666600; }\n.chat-msg:not([data-type=\"" + Type.reload + "\"]) .user\n{\n\tflex: 0 0 132px;\n\tmargin-right: 5px;\n\twhite-space: nowrap;\n}\n#" + GENERAL_CHAT_DIV_ID + " .chat-msg:not([data-type=\"" + Type.reload + "\"]) .user\n{\n\tflex-basis: 182px;\n}\n#" + CHAT_BOX_ID + ".showIcons #" + GENERAL_CHAT_DIV_ID + " .chat-msg:not([data-type=\"" + Type.reload + "\"]) .user\n{\n\tpadding-left: 22px;\n}\n.chat-msg .user[data-same-user=\"true\"]:not([data-name=\"\"])\n{\n\tcursor: default;\n\topacity: 0;\n}\n\n.chat-msg .user .icon\n{\n\tdisplay: none;\n}\n#" + CHAT_BOX_ID + ".showIcons .chat-msg .user .icon\n{\n\tdisplay: inline-block;\n\tmargin-left: -22px;\n}\n.chat-msg .user .icon::before\n{\n\tbackground-size: 20px 20px;\n\tcontent: '';\n\tdisplay: inline-block;\n\tmargin-right: 2px;\n\twidth: 20px;\n\theight: 20px;\n\tvertical-align: middle;\n}\n.chat-msg .user .icon.halloween2015::before\t{ background-image: url('images/chat-icons/1.png'); }\n.chat-msg .user .icon.christmas2015::before\t{ background-image: url('images/chat-icons/2.png'); }\n.chat-msg .user .icon.easter2016::before\t{ background-image: url('images/chat-icons/3.png'); }\n.chat-msg .user .icon.halloween2016::before\t{ background-image: url('images/chat-icons/4.png'); }\n.chat-msg .user .icon.christmas2016::before\t{ background-image: url('images/chat-icons/5.png'); }\n.chat-msg .user .icon.dh1Max::before\t\t{ background-image: url('images/chat-icons/6.png'); }\n.chat-msg .user .icon.hardcore::before\t\t{ background-image: url('images/chat-icons/7.png'); }\n.chat-msg .user .icon.quest::before\t\t\t{ background-image: url('images/chat-icons/8.png'); }\n\n.chat-msg .user:not([data-same-user=\"true\"]) .name\n{\n\tcolor: rgba(0, 0, 0, 0.7);\n\tcursor: pointer;\n}\n.chat-msg .user .name.chat-tag-donor::before\n{\n\tbackground-image: url('images/chat-icons/donor.png');\n\tbackground-size: 20px 20px;\n\tcontent: '';\n\tdisplay: inline-block;\n\theight: 20px;\n\twidth: 20px;\n\tvertical-align: middle;\n}\n.chat-msg .user .name.chat-tag-yell\n{\n\tcursor: default;\n}\n#" + CHAT_BOX_ID + ".showTags .chat-msg .user .name.chat-tag-contributor,\n#" + CHAT_BOX_ID + ".showTags .chat-msg .user .name.chat-tag-mod,\n#" + CHAT_BOX_ID + ".showTags .chat-msg .user .name.chat-tag-dev,\n#" + CHAT_BOX_ID + ".showTags .chat-msg .user .name.chat-tag-yell\n{\n\tcolor: white;\n\tdisplay: inline-block;\n\tfont-size: 10pt;\n\tmargin-top: -1px;\n\tpadding-bottom: 0;\n\ttext-align: center;\n\t/* 2px border, 10 padding */\n\twidth: calc(100% - 2*1px - 2*5px);\n}\n#" + CHAT_BOX_ID + ":not(.showTags) .chat-msg .user .name.chat-tag-contributor,\n#" + CHAT_BOX_ID + ":not(.showTags) .chat-msg .user .name.chat-tag-mod,\n#" + CHAT_BOX_ID + ":not(.showTags) .chat-msg .user .name.chat-tag-dev,\n#" + CHAT_BOX_ID + ":not(.showTags) .chat-msg .user .name.chat-tag-yell\n{\n\tbackground: initial;\n\tborder: inherit;\n\tfont-family: inherit;\n\tfont-size: inherit;\n\tpadding: initial;\n}\n\n.chat-msg[data-type=\"" + Type.reload + "\"] .user > *,\n.chat-msg[data-type=\"" + Type.pmReceived + "\"] .user > .icon,\n.chat-msg[data-type=\"" + Type.pmSent + "\"] .user > .icon\n{\n\tdisplay: none;\n}\n\n.chat-msg .msg\n{\n\tmin-width: 0;\n\toverflow: hidden;\n\tword-wrap: break-word;\n}\n\n#" + CHAT_BOX_ID + " ." + CHAT_CLASS + "\n{\n\twidth: 100%;\n\theight: 130px;\n\tdisplay: none;\n}\n#" + CHAT_BOX_ID + " ." + CHAT_CLASS + ".selected\n{\n\tdisplay: block;\n}\n#" + CHAT_TABS_ID + "\n{\n\tdisplay: flex;\n\tmargin: 10px -6px -6px;\n\tflex-wrap: wrap;\n}\n#" + CHAT_TABS_ID + " .chat-tab\n{\n\tbackground-color: gray;\n\tborder-top: 1px solid black;\n\tborder-right: 1px solid black;\n\tcursor: pointer;\n\tdisplay: inline-block;\n\tfont-weight: normal;\n\tpadding: 0.3rem .6rem;\n\tposition: relative;\n}\n#" + CHAT_TABS_ID + " .chat-tab.selected\n{\n\tbackground-color: transparent;\n\tborder-top-color: transparent;\n}\n#" + CHAT_TABS_ID + " .chat-tab.default\n{\n\tdisplay: none;\n}\n#" + CHAT_TABS_ID + " .chat-tab.filler\n{\n\tbackground-color: hsla(0, 0%, 90%, 1);\n\tborder-right: 0;\n\tbox-shadow: inset 5px 5px 5px -5px rgba(0, 0, 0, 0.5);\n\tcolor: transparent;\n\tcursor: default;\n\tflex-grow: 1;\n}\n#" + CHAT_TABS_ID + " .chat-tab::after\n{\n\tcolor: white;\n\tcontent: '(' attr(data-new) ')';\n\tfont-size: .9rem;\n\tfont-weight: bold;\n\tmargin-left: .4rem;\n}\n#" + CHAT_TABS_ID + " .chat-tab[data-new=\"0\"]::after\n{\n\tcolor: inherit;\n\tfont-weight: normal;\n}\n#" + CHAT_TABS_ID + " .chat-tab:not(.general).selected::after,\n#" + CHAT_TABS_ID + " .chat-tab:not(.general):hover::after\n{\n\tvisibility: hidden;\n}\n#" + CHAT_TABS_ID + " .chat-tab:not(.general).selected .close::after,\n#" + CHAT_TABS_ID + " .chat-tab:not(.general):hover .close::after\n{\n\tcontent: '\u00D7';\n\tfont-size: 1.5rem;\n\tposition: absolute;\n\ttop: 0;\n\tright: .6rem;\n\tbottom: 0;\n}\n\n#" + CONTEXTMENU_ID + "\n{\n\tbox-shadow: rgba(0, 0, 0, 0.8) 4px 4px 4px -2px;\n\tposition: fixed;\n}\n#" + CONTEXTMENU_ID + " .ui-widget-header\n{\n\tcursor: default;\n\tpadding: .25rem;\n}\n\t\t"); } function addIntelligentScrolling() { // add checkbox instead of button for toggling auto scrolling var btn = document.querySelector('input[value="Toggle Autoscroll"]'); var btnParent = btn.parentElement; var checkboxId = 'chat-toggle-autoscroll'; // create checkbox var toggleCheckbox = document.createElement('input'); toggleCheckbox.type = 'checkbox'; toggleCheckbox.id = checkboxId; toggleCheckbox.checked = true; // create label var toggleLabel = document.createElement('label'); toggleLabel.htmlFor = checkboxId; toggleLabel.textContent = 'Autoscroll'; btnParent.insertBefore(toggleCheckbox, btn); btnParent.insertBefore(toggleLabel, btn); btn.style.display = 'none'; var chatArea = document.getElementById(GENERAL_CHAT_DIV_ID); var showScrollTextTimeout = null; function setAutoScrolling(value, full) { if (full === void 0) { full = false; } if (window.isAutoScrolling != value) { toggleCheckbox.checked = value; window.isAutoScrolling = value; var icon_1 = 'none'; var color_1 = value ? 'lime' : 'red'; var text_1 = (value ? 'En' : 'Dis') + 'abled' + (full ? ' Autoscroll' : ''); if (full) { if (showScrollTextTimeout) { window.clearTimeout(showScrollTextTimeout); } showScrollTextTimeout = window.setTimeout(function () { return window.scrollText(icon_1, color_1, text_1); }, 300); } else { window.scrollText(icon_1, color_1, text_1); } return true; } return false; } toggleCheckbox.addEventListener('change', function () { setAutoScrolling(this.checked); if (this.checked && settings.get(settings.KEY.intelligentScrolling)) { chatArea.scrollTop = chatArea.scrollHeight - chatArea.clientHeight; } }); var placeholderTemplate = document.createElement('div'); placeholderTemplate.className = 'placeholder'; var childStore = new WeakMap(); function scrollHugeChat() { // # of children var chunkNum = chatArea.children.length; // start chunk hiding at a specific amount of chunks if (chunkNum < CHUNK_HIDING_MIN_CHUNKS) { return; } var visibleTop = chatArea.scrollTop; var visibleBottom = visibleTop + chatArea.clientHeight; var referenceTop = visibleTop - window.innerHeight; var referenceBottom = visibleBottom + window.innerHeight; var top = 0; // never hide the last element since its size may change at any time when a new message gets appended for (var i = 0; i < chunkNum - 1; i++) { var child = chatArea.children[i]; var height = child.clientHeight; var bottom = top + height; var isVisible = top >= referenceTop && top <= referenceBottom || bottom >= referenceTop && bottom <= referenceBottom || top < referenceTop && bottom > referenceBottom; var isPlaceholder = child.classList.contains('placeholder'); if (!isVisible && !isPlaceholder) { var newPlaceholder = placeholderTemplate.cloneNode(false); newPlaceholder.style.height = height + 'px'; chatArea.replaceChild(newPlaceholder, child); childStore.set(newPlaceholder, child); } else if (isVisible && isPlaceholder) { var oldChild = childStore.get(child); chatArea.replaceChild(oldChild, child); childStore.delete(child); } top = bottom; } } var delayedScrollStart = null; var delayedScrollTimeout = null; // does not consider pm tabs; may be changed in a future version? chatArea.addEventListener('scroll', function () { if (settings.get(settings.KEY.intelligentScrolling)) { var scrolled2Bottom = (chatArea.scrollTop + chatArea.clientHeight) >= chatArea.scrollHeight; setAutoScrolling(scrolled2Bottom, true); } var n = now(); if (delayedScrollStart == null) { delayedScrollStart = n; } if (delayedScrollStart + 300 > n) { if (delayedScrollTimeout) { window.clearTimeout(delayedScrollTimeout); } delayedScrollTimeout = window.setTimeout(function () { delayedScrollStart = null; delayedScrollTimeout = null; scrollHugeChat(); }, 50); } }); } function getSelectedTab() { return document.querySelector('#' + CHAT_TABS_ID + ' .chat-tab.selected'); } function clickChatTab(newTab) { var oldTab = getSelectedTab(); if (newTab == oldTab) { return; } changeChatTab(oldTab, newTab); } function clickCloseChatTab(tab) { var username = tab.dataset.username || ''; var chatDiv = getChatDiv(username); if (chatDiv.children.length === 0 || confirm("Do you want to close the pm tab of \"" + username + "\"?")) { closeChatTab(username); } } function checkSetting(init) { if (init === void 0) { init = false; } var enabled = settings.get(settings.KEY.useNewChat); // dis-/enable chat tabs var chatTabs = document.getElementById(CHAT_TABS_ID); chatTabs.style.display = enabled ? '' : 'none'; // dis-/enable checkbox for intelligent scrolling var intelScrollId = 'chat-toggle-intelligent-scroll'; var input = document.getElementById(intelScrollId); if (input) { input.style.display = enabled ? '' : 'none'; } var label = document.querySelector('label[for="' + intelScrollId + '"]'); if (label) { label.style.display = enabled ? '' : 'none'; } // virtually click on a tab var defaultTab = getChatTab('', SpecialTab.default); var generalTab = getChatTab('', SpecialTab.general); clickChatTab(enabled ? generalTab : defaultTab); if (init) { settings.observe(settings.KEY.useNewChat, function () { return checkSetting(false); }); } } function addChatTabs() { var chatBoxArea = document.getElementById(CHAT_BOX_ID); var chatTabs = document.createElement('div'); chatTabs.id = CHAT_TABS_ID; chatTabs.addEventListener('click', function (event) { var newTab = event.target; if (newTab.classList.contains('close')) { return clickCloseChatTab(newTab.parentElement); } if (!newTab.classList.contains('chat-tab') || newTab.classList.contains('filler')) { return; } clickChatTab(newTab); }); chatBoxArea.appendChild(chatTabs); // default tab (for disabled new chat) getChatTab('', SpecialTab.default); // general server chat var generalTab = getChatTab('', SpecialTab.general); generalTab.textContent = 'Server'; getChatDiv(''); getChatTab('', SpecialTab.filler); var _sendChat = window.sendChat; window.sendChat = function (inputEl) { var msg = inputEl.value; var selectedTab = document.querySelector('.chat-tab.selected'); if (selectedTab.dataset.username != '' && msg[0] != '/') { inputEl.value = '/pm ' + (selectedTab.dataset.username || '').replace(/ /g, '+') + ' ' + msg; } _sendChat(inputEl); }; } function switch2PmTab(username) { var newTab = getChatTab(username, null); clickChatTab(newTab); } function notifyPm(data) { notifications.event('Message from "' + data.username + '"' , { body: data.msg , onclick: function () { return switch2PmTab(data.username); } , whenActive: getSelectedTab().dataset.username != data.username }); } function checkMentionAndKeywords(data) { var lowerMsg = data.msg.toLowerCase(); if (lowerMsg.indexOf(window.username) > -1) { notifications.event('You\'ve been mentioned' , { body: data.msg }); } var match = []; for (var _i = 0, keywordList_1 = keywordList; _i < keywordList_1.length; _i++) { var keyword = keywordList_1[_i]; if (lowerMsg.indexOf(keyword) > -1) { match.push(keyword); } } if (match.length > 0) { notifications.event('Keyword: "' + match.join('", "') + '"' , { body: data.msg }); } } var addToChatBox_ = null; function newAddToChatBox(username, icon, tag, msg, isPM) { var data = processChatData(username, icon, tag, msg, isPM); if (isDataPM(data)) { if (data.type == Type.pmSent) { switch2PmTab(data.username); } notifyPm(data); } else if (isSpam(data)) { console.info('detected spam:', data); return; } else { // check mentioning and keywords only for non-pms checkMentionAndKeywords(data); } add2ChatHistory(data); add2Chat(data); var fn = addToChatBox_ == null ? window.addToChatBox : addToChatBox_; fn(username, icon, tag, msg, isPM); } chat.newAddToChatBox = newAddToChatBox; function openPmTab(username) { if (username == window.username || username == '') { return; } var userTab = getChatTab(username, null); clickChatTab(userTab); var input = document.getElementById(CHAT_INPUT_ID); input.focus(); } function newChat() { addChatTabs(); applyChatStyle(); addToChatBox_ = window.addToChatBox; window.addToChatBox = newAddToChatBox; chatInitialized = true; var chatbox = document.getElementById(CHAT_BOX_ID); chatbox.addEventListener('click', function (event) { var target = event.target; var userEl = target && target.parentElement; if (!target || !userEl || !target.classList.contains('name') || !userEl.classList.contains('user')) { return; } if (userEl.dataset.sameUser != 'true') { openPmTab(userEl.dataset.name || ''); } }); chatbox.addEventListener('mouseover', function (event) { var target = event.target; if (!target.classList.contains('timestamp') || !target.dataset.timestamp) { return; } var timestamp = parseInt(target.dataset.timestamp || '0', 10); target.dataset.fulltime = (new Date(timestamp)).toLocaleDateString(LOCALE, LOCALE_OPTIONS); target.dataset.timestamp = ''; }); // add context menu var contextmenu = document.createElement('ul'); contextmenu.id = CONTEXTMENU_ID; contextmenu.style.display = 'none'; contextmenu.innerHTML = "<li class=\"name ui-widget-header\"><div></div></li>\n\t\t<li class=\"open-pm\"><div>Open pm tab</div></li>\n\t\t<li class=\"mute\"><div>Mute</div></li>\n\t\t<li class=\"unmute\"><div>Unmute</div></li>"; document.body.appendChild(contextmenu); window.$(contextmenu).menu( { items: '> :not(.ui-widget-header)' }); var nameListEl = contextmenu.querySelector('.name'); var nameDivEl = nameListEl.firstElementChild; var muteEl = contextmenu.querySelector('.mute'); var unmuteEl = contextmenu.querySelector('.unmute'); chatbox.addEventListener('contextmenu', function (event) { var target = event.target; var userEl = target && target.parentElement; if (!userEl || !userEl.classList.contains('user')) { return; } var username = userEl.dataset.name; // ignore clicks on server messages or other special messages if (!username || userEl.dataset.sameUser == 'true') { return; } contextmenu.style.left = event.clientX + 'px'; contextmenu.style.top = event.clientY + 'px'; contextmenu.style.display = ''; contextmenu.dataset.username = username; nameDivEl.textContent = username; var isMuted = window.mutedPeople.indexOf(username) !== -1; muteEl.style.display = isMuted ? 'none' : ''; unmuteEl.style.display = isMuted ? '' : 'none'; event.preventDefault(); }); // add click listener for context menu and stop propagation contextmenu.addEventListener('click', function (event) { var target = event.target; event.stopPropagation(); while (target && target.id != CONTEXTMENU_ID && target.tagName != 'LI') { target = target.parentElement; } if (!target || target.id == CONTEXTMENU_ID) { return; } var username = contextmenu.dataset.username || ''; if (target.classList.contains('open-pm')) { openPmTab(username); } else if (target.classList.contains('mute')) { if (username == '') { return; } window.mutedPeople.push(username); window.scrollText('none', 'lime', '<em>' + username + '</em> muted'); } else if (target.classList.contains('unmute')) { if (username == '') { return; } var index = window.mutedPeople.indexOf(username); if (index !== -1) { window.mutedPeople.splice(index, 1); } window.scrollText('none', 'red', '<em>' + username + '</em> unmuted'); } else { return; } contextmenu.style.display = 'none'; }); // add click listener to hide context menu document.addEventListener('click', function (event) { if (contextmenu.style.display != 'none') { contextmenu.style.display = 'none'; } }); // handle settings var showSettings = [settings.KEY.showTimestamps, settings.KEY.showIcons, settings.KEY.showTags]; function setShowSetting(key) { var enabled = settings.get(key); chatbox.classList[enabled ? 'add' : 'remove'](settings.KEY[key]); } for (var _i = 0, showSettings_1 = showSettings; _i < showSettings_1.length; _i++) { var key = showSettings_1[_i]; setShowSetting(key); settings.observe(key, function (k) { return setShowSetting(k); }); } } var commands = ['pm', 'mute', 'ipmute']; function addCommandSuggester() { var input = document.getElementById(CHAT_INPUT_ID); input.addEventListener('keyup', function (event) { if (event.key == 'Backspace' || event.key == 'Delete' || event.key == 'Enter' || event.key == 'Tab' || input.selectionStart != input.selectionEnd || input.selectionStart != input.value.length || !input.value.startsWith('/')) { return; } var value = input.value.substr(1); for (var _i = 0, commands_1 = commands; _i < commands_1.length; _i++) { var cmd = commands_1[_i]; if (cmd.startsWith(value)) { input.value = '/' + cmd; input.selectionStart = 1 + value.length; input.selectionEnd = input.value.length; break; } } }); } function addOwnCommands() { commands.push(TUTORIAL_CMD); commands.push(KEYWORD_ADD_CMD); commands.push(KEYWORD_REMOVE_CMD); function processOwnCommands(value) { if (!value.startsWith('/')) { return value; } var msgPrefix = '/'; var msg = value.substr(1); if (msg.startsWith('pm')) { var split = msg.split(' '); msgPrefix = '/' + split.slice(0, 2).join(' ') + ' '; msg = split.slice(2).join(' '); } if (msg.startsWith(TUTORIAL_CMD)) { // thanks aguyd (https://greasyfork.org/forum/profile/aguyd) for the idea var name_2 = msg.substr(TUTORIAL_CMD.length).trim(); msgPrefix = ''; msg = 'https://www.reddit.com/r/DiamondHunt/comments/5vrufh/diamond_hunt_2_starter_faq/'; if (name_2.length != 0) { // maybe add '@' before the name? msg = name_2 + ', ' + msg; } } else if (msg.startsWith(KEYWORD_ADD_CMD)) { var keyword = msg.substr(KEYWORD_ADD_CMD.length).trim().toLowerCase(); if (keywordList.indexOf(keyword) == -1) { keywordList.push(keyword); store.set(KEYWORD_LIST_KEY, keywordList); } window.scrollText('none', 'lime', 'Keyword added: <em>' + keyword + '</em>'); } else if (msg.startsWith(KEYWORD_REMOVE_CMD)) { var keyword = msg.substr(KEYWORD_REMOVE_CMD.length).trim().toLowerCase(); var index = keywordList.indexOf(keyword); if (index != -1) { keywordList.splice(index, 1); store.set(KEYWORD_LIST_KEY, keywordList); } window.scrollText('none', 'lime', 'Keyword removed: <em>' + keyword + '</em>'); } return msgPrefix + msg; } var _sendChat = window.sendChat; window.sendChat = function (inputEl) { inputEl.value = processOwnCommands(inputEl.value); _sendChat(inputEl); }; } function checkColorize(init) { if (init === void 0) { init = false; } var chatDiv = document.getElementById(CHAT_BOX_ID); chatDiv.classList[settings.get(settings.KEY.colorizeChat) ? 'add' : 'remove'](COLORIZE_CLASS); if (init) { settings.observe(settings.KEY.colorizeChat, function () { return checkColorize(false); }); } } function init() { newChat(); addIntelligentScrolling(); addCommandSuggester(); addOwnCommands(); checkColorize(true); checkSetting(true); var _enlargeChat = window.enlargeChat; var chatBoxArea = document.getElementById(CHAT_BOX_ID); function setChatBoxHeight(height) { var defaultChat = document.getElementById(DEFAULT_CHAT_DIV_ID); defaultChat.style.height = height; var generalChat = document.getElementById(GENERAL_CHAT_DIV_ID); generalChat.style.height = height; var chatDivs = chatBoxArea.querySelectorAll('div[id^="' + PM_CHAT_DIV_PREFIX + '"]'); for (var i = 0; i < chatDivs.length; i++) { chatDivs[i].style.height = height; } } window.enlargeChat = function (enlargeB) { _enlargeChat(enlargeB); var defaultChatDiv = document.getElementById(DEFAULT_CHAT_DIV_ID); var height = defaultChatDiv.style.height; store.set('chat.height', height); setChatBoxHeight(height); handleScrolling(defaultChatDiv); }; setChatBoxHeight(store.get('chat.height')); // TEMP >>> (due to a naming issue, migrate the data) var oldChatHistoryKey = 'chatHistory2'; var oldChatHistory = store.get(oldChatHistoryKey); if (oldChatHistory != null) { store.set(CHAT_HISTORY_KEY, oldChatHistory); store.remove(oldChatHistoryKey); } // TEMP <<< // add history to chat chatHistory.forEach(function (d) { return add2Chat(d); }); if (chatboxFragments) { chatboxFragments.forEach(function (fragment, key) { var chatbox = getChatDiv(key); chatbox.appendChild(fragment); }); chatboxFragments = null; } // reset the new counter for all tabs var tabs = document.querySelectorAll('.chat-tab'); for (var i = 0; i < tabs.length; i++) { tabs[i].dataset.new = '0'; } } chat.init = init; var _a; })(chat || (chat = {})); /** * hopefully only temporary fixes */ var temporaryFixes; (function (temporaryFixes) { temporaryFixes.name = 'temporaryFixes'; // update spells being clickable in combat function setSpellsClickable() { var spellbox = document.getElementById('fight-spellboox'); if (spellbox) { spellbox.style.pointerEvents = window.isInCombat() ? '' : 'none'; } } // warn before unloading/reloading the tab if combat is in progress function combatWarnOnUnload() { if (!window.isInCombat()) { window.onbeforeunload = null; } else { if (window.onbeforeunload == null) { window.onbeforeunload = function () { return 'You are in a fight!'; }; } } } function fixCombatCountdown() { if (window.isInCombat() && window.combatCommenceTimer != 0) { document.getElementById('combat-countdown').style.display = ''; } } // fix exhaustion timer and updating brewing and cooking recipes function fixExhaustionTimer() { if (document.getElementById('tab-container-combat').style.display != 'none') { window.combatNotFightingTick(); } } function fixClientGameLoop() { var _clientGameLoop = window.clientGameLoop; window.clientGameLoop = function () { _clientGameLoop(); setSpellsClickable(); combatWarnOnUnload(); fixCombatCountdown(); fixExhaustionTimer(); }; } // fix elements of scrollText (e.g. when joining the game and receiving xp at that moment) function fixScroller() { var textEls = document.querySelectorAll('div.scroller'); for (var i = 0; i < textEls.length; i++) { var scroller = textEls[i]; if (scroller.style.position != 'absolute') { scroller.style.display = 'none'; } } } // fix style of tooltips function fixTooltipStyle() { addStyle("\nbody > div.tooltip > h2:first-child\n{\n\tmargin-top: 0;\n\tfont-size: 20pt;\n\tfont-weight: normal;\n}\n\t\t"); } // fix buiulding magic table dynamically function fixRefreshingMagicRecipes() { window.refreshLoadMagicTable = true; var _processMagicTab = window.processMagicTab; window.processMagicTab = function () { var _refreshLoadCraftingTable = window.refreshLoadCraftingTable; window.refreshLoadCraftingTable = window.refreshLoadMagicTable; _processMagicTab(); window.refreshLoadCraftingTable = _refreshLoadCraftingTable; }; } // move the strange leaf to brewing tab (thanks lasse_brus for this idea) function moveStrangeLeafs() { var strangeLeafBox = document.getElementById('item-box-strangeLeaf'); var brewingContainer = document.getElementById('tab-sub-container-brewing'); brewingContainer.appendChild(strangeLeafBox); // remove event listeners before binding the tooltip to it var $strangeLeafBox = window.$(strangeLeafBox); $strangeLeafBox.off('mouseover').off('mouseleave'); strangeLeafBox.title = ''; // bind tooltip to item box ensureTooltip('ingredient-secondary', strangeLeafBox); // change color var color1 = '#800080'; var color2 = '#990099'; strangeLeafBox.style.background = 'linear-gradient(' + color1 + ', ' + color2 + ')'; $strangeLeafBox .mouseover(function () { strangeLeafBox.style.background = 'none'; strangeLeafBox.style.backgroundColor = color2; }) .mouseleave(function () { strangeLeafBox.style.background = 'linear-gradient(' + color1 + ', ' + color2 + ')'; }); } // fix height of map item function fixTreasureMap() { var mapBox = document.getElementById('item-box-treasureMap'); var numSpan = mapBox.lastElementChild; numSpan.style.display = ''; numSpan.style.visibility = 'hidden'; } // fix wobbling tree places on hover (in wood cutting) function fixWoodcutting() { addStyle("\nimg.woodcutting-tree-img\n{\n\tborder: 1px solid transparent;\n}\n\t\t"); } // fix rake dialog function fixRakeDialog() { var _clicksRake = window.clicksRake; window.clicksRake = function () { _clicksRake(); var upgradeBtn = document.querySelector('#dialogue-id-upgrade-rake input[value="Upgrade"]'); if (upgradeBtn) { var hide = window.diamondRake == 1; upgradeBtn.style.display = hide ? 'none' : ''; } }; } // fix tooltip of promethium, whale and rainbowfish function fixTooltips() { var fishTooltipTemplate = document.querySelector('#tooltip-list > div[id^="tooltip-raw"]'); var oreTooltipTemplate = document.getElementById('tooltip-marble'); if (!fishTooltipTemplate || !oreTooltipTemplate) { return; } function ensureTooltip(item, tooltipTemplate, onCreate) { var tooltipId = 'tooltip-' + item; if (document.getElementById(tooltipId) != null) { return; } var newTooltip = tooltipTemplate.cloneNode(true); newTooltip.id = tooltipId; onCreate(newTooltip); tooltipTemplate.parentElement.appendChild(newTooltip); } function ensureRawFishTooltip(fish) { ensureTooltip('raw' + fish, fishTooltipTemplate, function (newTooltip) { var foodName = 'Raw' + split2Words(fish); newTooltip.firstChild.textContent = foodName; var foodKey = fish[0].toLowerCase() + fish.substr(1); var energy = window.getEnergyGained(foodKey); newTooltip.lastChild.firstChild.textContent = '+' + format.number(energy) + ' '; }); } var boxes = document.querySelectorAll('#tab-sub-container-combat-large-btns > span.item-box[id^="item-box-raw"]'); for (var i = 0; i < boxes.length; i++) { var food = boxes[i].id.replace('item-box-raw', ''); ensureRawFishTooltip(food); } // promethium ensureTooltip('promethium', oreTooltipTemplate, function (newTooltip) { var spans = newTooltip.getElementsByTagName('span'); var priceNode = newTooltip.lastChild; spans[0].textContent = 'Promethium'; spans[1].textContent = 'Can be used for... nothing at the moment.'; priceNode.textContent = ' ' + format.number(getPrice('promethium')); }); } // fix wobbling quest rows on hover (in quest book) function fixQuestBook() { addStyle("\n#table-quest-list tr\n{\n\tborder: 1px solid transparent;\n}\n\t\t"); } // this fix was realized first here: https://www.reddit.com/r/DiamondHunt/60z9h9/ function fixedLoadSkillTabs() { for (var _i = 0, SKILL_LIST_1 = SKILL_LIST; _i < SKILL_LIST_1.length; _i++) { var skil = SKILL_LIST_1[_i]; var unlocked = getGameValue(skil + 'Unlocked') == 1; if (!unlocked) { continue; } var xp = getGameValue(skil + 'Xp'); var currentLevelXp = window.getXpNeeded(window.getLevel(xp)); var nextLevelXp = window.getXpNeeded(window.getLevel(xp) + 1); var perc = (xp - currentLevelXp) / (nextLevelXp - currentLevelXp) * 100; var xpBarEl = document.getElementById('inner-skill-xp-bar-' + skil); xpBarEl.style.minWidth = xpBarEl.style.maxWidth = perc + '%'; } } function fixSkillBars() { var _loadSkillTabs = window.loadSkillTabs; window.loadSkillTabs = function () { _loadSkillTabs(); fixedLoadSkillTabs(); }; } function fixCraftingXpTooltip() { var el = document.getElementById('tooltip-skills-crafting-xp-left-value'); if (!el) { return; } var br = el.nextElementSibling; if (!br) { return; } var annoyingTick = br.nextSibling; if (!annoyingTick || annoyingTick.nodeType != Node.TEXT_NODE || !annoyingTick.textContent) { return; } annoyingTick.textContent = annoyingTick.textContent.replace('`', ''); } function fixScrollImages() { function fixIcon(icon) { return icon + (icon != 'none' && !/\..{3,4}$/.test(icon) ? '.png' : ''); } var _scrollTextHitSplat = window.scrollTextHitSplat; window.scrollTextHitSplat = function (icon, color, text, elId, cbType) { _scrollTextHitSplat(fixIcon(icon), color, text, elId, cbType); }; var _scrollText = window.scrollText; window.scrollText = function (icon, color, text) { _scrollText(fixIcon(icon), color, text); }; } function fixQuest8BraveryRecipe() { observer.add([ 'quest8' , 'braveryPotion' ], function () { var show = window.quest8 > 0 && window.braveryPotion == 0; var recipe = document.getElementById('brewing-braveryPotion'); if (recipe) { recipe.style.display = show ? '' : 'none'; } }); } // fix cooking dialog of uncookable fish (e.g. whale/rainbow fish) function fixCookingDialogForUncookableFish() { var _cookFoodDialogue = window.cookFoodDialogue; window.cookFoodDialogue = function (rawFood) { _cookFoodDialogue(rawFood); var dialog = document.getElementById('dialogue-id-cook-food'); if (!dialog) { return; } var isCookable = window.getHeatNeeded(rawFood) != 0; function hideWhenNotCookable(el, mustBeCookable) { el.style.display = isCookable == mustBeCookable ? '' : 'none'; } var boxes = dialog.getElementsByClassName('basic-smallbox'); var amountBox = boxes[1]; var notCookableBox = amountBox.nextElementSibling; if (notCookableBox.tagName != 'DIV') { var newEl = amountBox.cloneNode(false); newEl.innerHTML = "<b>Not cookable at the moment</b>"; notCookableBox.parentElement.insertBefore(newEl, notCookableBox); notCookableBox = newEl; } hideWhenNotCookable(amountBox, true); hideWhenNotCookable(notCookableBox, false); var heatNeededBox = document.getElementById('heat-needed-dyn'); if (heatNeededBox) { hideWhenNotCookable(heatNeededBox, true); hideWhenNotCookable(heatNeededBox.previousElementSibling, true); } var btn = dialog.querySelector('input[value="Cook"]'); if (btn) { btn.disabled = !isCookable; } // TODO: move to some other module like "requirementCheck" var levelReq = document.getElementById('dialogue-cook-levelReq'); var levelReqLabel = levelReq && levelReq.previousElementSibling; if (!levelReq || !levelReqLabel) { return; } var fulfilled = window.getCookingLevelReq(rawFood) > window.getLevel(window.cookingXp); levelReq.style.color = fulfilled ? 'rgb(204, 0, 0)' : ''; levelReq.style.fontWeight = fulfilled ? 'bold' : ''; levelReqLabel.style.color = fulfilled ? 'rgb(204, 0, 0)' : ''; }; } function fixHitText() { window.scrollTextHitSplat = function (icon, color, text, elId, cbType) { var imgTag = icon != 'none' ? "<img src=\"images/" + icon + "\" class=\"image-icon-50\" />" : ''; var elementChosen = document.getElementById(elId); if (!elementChosen) { return; } var rect = elementChosen.getBoundingClientRect(); var xCoord = (rect.left + rect.right) / 2; var yCoord = (rect.bottom + rect.top) / 2; var extraStyle = ''; if (cbType == 'melee') { extraStyle = 'border: 1px solid red; background-color: #4d0000;'; } else if (cbType == 'heal') { extraStyle = 'border: 1px solid green; background-color: lime;'; } var $elementToAppend = window.$("<div class=\"scroller\" style=\"" + extraStyle + " color: " + color + "; position: fixed;\">" + imgTag + text + "</div>").appendTo('body'); if (xCoord == 0 && yCoord == 0) { var tab = document.getElementById('tab-container-bar-combat'); var tabRect = tab.getBoundingClientRect(); var boxRect = $elementToAppend.get(0).getBoundingClientRect(); xCoord = elId == 'img-hero' ? (tabRect.left - boxRect.width) : tabRect.right; yCoord = tabRect.top; } $elementToAppend .css( { left: xCoord , top: yCoord }) .animate( { top: '-=50px' }, function () { return $elementToAppend.fadeOut(1000, function () { return $elementToAppend.remove(); }); }); }; } function fixBoatTooltips() { var boatBox = document.getElementById('item-box-boundRowBoat'); var boatTooltip = boatBox && document.getElementById(boatBox.dataset.tooltipId || ''); var canoeBox = document.getElementById('item-box-boundCanoe'); if (!boatBox || !canoeBox || !boatTooltip) { return; } var canoeTooltip = boatTooltip.cloneNode(true); canoeTooltip.id = 'tooltip-boundCanoe'; var header = canoeTooltip.firstElementChild; header.textContent = 'Canoe'; boatTooltip.parentElement.appendChild(canoeTooltip); canoeBox.dataset.tooltipId = 'tooltip-boundCanoe'; var boatDuration = document.createElement('div'); boatDuration.innerHTML = '<strong>Trip duration:</strong> 3 hours'; boatTooltip.appendChild(boatDuration); var canoeDuration = document.createElement('div'); canoeDuration.innerHTML = '<strong>Trip duration:</strong> 6 hours'; canoeTooltip.appendChild(canoeDuration); } function fixAlignments() { addStyle("\n#tab-container-crafting settings-container\n{\n\tmargin: 5px 30px;\n}\n#table-crafting-recipe,\n#table-brewing-recipe,\n#table-magic-recipe\n{\n\twidth: calc(100% - 2*20px - 2*10px);\n}\n#tab-sub-container-magic-items\n{\n\tmargin: 5px 0px;\n}\n#table-magic-recipe\n{\n\twidth: calc(100% - 2*10px);\n}\n\n#tab-container-farming\n{\n\tpadding: 0 20px;\n}\n#tab-sub-container-farming\n{\n\tmargin: 5px 0;\n\tmargin-bottom: -10px;\n}\ndiv.farming-patch,\ndiv.farming-patch-locked\n{\n\tmargin: 10px;\n}\n\n#combat-table-area\n{\n\tborder-spacing: 0;\n}\ndiv#hero-area.hero,\ndiv#monster-area.monster\n{\n\tmargin-left: 20px;\n\tmargin-right: 20px;\n\tmargin-top: 10px;\n}\ntable.table-hero-stats,\ndiv.hp-bar,\n#hero-area div.fight-spellbook\n{\n\tmargin-left: 0;\n}\ndiv.hp-bar\n{\n\tmin-width: calc(100% - 2px);\n}\n#hero-area span.fight-spell\n{\n\tmargin-bottom: 0;\n\tmargin-top: 0;\n}\n#hero-area span.fight-spell:first-child\n{\n\tmargin-left: 0;\n}\n#hero-area span.fight-spell:last-child\n{\n\tmargin-right: 0;\n}\n#hero-area > div:last-child,\n.imageMonster\n{\n\theight: 556px !important;\n\tmargin-top: -50px;\n}\n#monster-area div.hp-bar\n{\n\tmargin-top: 66px;\n\tmargin-bottom: 74px;\n}\n#monster-area > br:first-child,\n#monster-area table.table-hero-stats + br\n{\n\tdisplay: none;\n}\n.imageMonster\n{\n\talign-items: flex-end;\n\tdisplay: flex;\n\tposition: relative;\n}\n#combat-table-area[style$=\"auto;\"]\n{\n\tborder-color: transparent;\n}\n#img-monster\n{\n\tposition: absolute;\n}\n#img-monster[src$=\"/1.png\"]\n{\n\theight: 250px;\n}\n#img-monster[src$=\"/2.png\"]\n{\n\ttransform: translateY(30px);\n}\n#img-monster[src$=\"/3.png\"]\n{\n\theight: 180px;\n\ttransform: translateY(-350px);\n}\n#img-monster[src$=\"/4.png\"]\n{\n\theight: 180px;\n}\n#img-monster[src$=\"/5.png\"]\n{\n\theight: 700px;\n\ttransform: translateY(130px);\n}\n#img-monster[src$=\"/7.png\"]\n{\n\theight: 450px;\n\ttransform: translateY(30px);\n}\n#img-monster[src$=\"/8.png\"]\n{\n\theight: 280px;\n\ttransform: translateY(-260px);\n}\n#img-monster[src$=\"/9.png\"]\n{\n\theight: 450px;\n\ttransform: translateY(-10px);\n}\n#img-monster[src$=\"/11.png\"],\n#img-monster[src$=\"/15.png\"]\n{\n\ttransform: translateY(-180px);\n}\n#img-monster[src$=\"/14.png\"]\n{\n\theight: 500px;\n\tmargin-left: -50px;\n\tmargin-right: -50px;\n}\n#combat-table-area span.large-button,\n#combat-table-area span.medium-button\n{\n\tmargin: 10px;\n}\n#combat-table-area span.medium-button + br + br\n{\n\tdisplay: none;\n}\n\ndiv#market-slot-1.market-slot\n{\n\tfloat: initial;\n\tmargin-left: 10px !important;\n}\n\t\t"); } function addHeroStatTooltips() { var table = document.querySelector('#hero-area table.table-hero-stats'); if (!table) { return; } var statRow = table.rows.item(0); var attackCell = statRow.cells.item(0); attackCell.title = 'Attack Damage'; window.$(attackCell).tooltip(); var accuracyCell = statRow.cells.item(1); accuracyCell.title = 'Attack Accuracy'; window.$(accuracyCell).tooltip(); var speedCell = statRow.cells.item(2); speedCell.title = 'Attack Speed'; window.$(speedCell).tooltip(); var defenseCell = statRow.cells.item(3); defenseCell.title = 'Defense'; window.$(defenseCell).tooltip(); } function init() { fixClientGameLoop(); fixScroller(); fixTooltipStyle(); fixRefreshingMagicRecipes(); moveStrangeLeafs(); fixTreasureMap(); fixWoodcutting(); fixRakeDialog(); fixTooltips(); fixQuestBook(); fixSkillBars(); fixCraftingXpTooltip(); // apply fix for scroll images later to fix images in this code too fixHitText(); fixScrollImages(); fixQuest8BraveryRecipe(); fixCookingDialogForUncookableFish(); fixBoatTooltips(); fixAlignments(); addHeroStatTooltips(); } temporaryFixes.init = init; })(temporaryFixes || (temporaryFixes = {})); /** * improve timer */ var improveTimer; (function (improveTimer_1) { improveTimer_1.name = 'improveTimer'; function bindNewFormatter() { window.formatTime = function (seconds) { return format.timer(seconds); }; window.formatTimeShort2 = function (seconds) { return format.timer(seconds); }; } function improveSmeltingTimer() { addStyle("\n#notif-smelting > span:not(.timer)\n{\n\tdisplay: none;\n}\n\t\t"); var smeltingNotifBox = document.getElementById('notif-smelting'); var smeltingTimerEl = document.createElement('span'); smeltingTimerEl.className = 'timer'; smeltingNotifBox.appendChild(smeltingTimerEl); var smeltingInterval; function updatePercValues() { if (smeltingInterval) { window.clearInterval(smeltingInterval); } var delta = 0; smeltingInterval = window.setInterval(function () { return updateSmeltingTimer(++delta); }, 1000); updateSmeltingTimer(); } function updateSmeltingTimer(delta) { if (delta === void 0) { delta = 0; } var totalTime = window.smeltingPercD; // thanks at /u/marcus898 for your bug report var elapsedTime = Math.round(window.smeltingPerc * totalTime / 100) + delta; smeltingTimerEl.textContent = format.timer(Math.max(totalTime - elapsedTime, 0)); } observer.add('smeltingPercD', function () { return updatePercValues(); }); observer.add('smeltingPerc', function () { return updatePercValues(); }); updatePercValues(); } function improveTimer(cssRulePrefix, textColor, timerColor, infoIdPrefx, containerPrefix, updateFn) { addStyle("\n/* hide built in timer elements */\n" + cssRulePrefix + " > *:not(img):not(.info)\n{\n\tdisplay: none;\n}\n" + cssRulePrefix + " > div.info\n{\n\tcolor: " + textColor + ";\n\tmargin-top: 5px;\n\tpointer-events: none;\n\ttext-align: center;\n\tposition: absolute;\n\ttop: 0;\n\tleft: 0;\n\tright: 0;\n}\n" + cssRulePrefix + " > div.info > div.name\n{\n\tfont-size: 1.2rem;\n}\n" + cssRulePrefix + " > div.info > div.timer\n{\n\tcolor: " + timerColor + ";\n}\n\t\t"); for (var i = 0; i < 6; i++) { var num = i + 1; var infoId = infoIdPrefx + num; var container = document.getElementById(containerPrefix + num); container.style.position = 'relative'; var infoEl = document.createElement('div'); infoEl.className = 'info'; infoEl.id = infoId; infoEl.innerHTML = "<div class=\"name\"></div><div class=\"timer\"></div>"; container.appendChild(infoEl); updateFn(num, infoId, true); } } function updateTreeInfo(placeId, infoElId, init) { if (init === void 0) { init = false; } var infoEl = document.getElementById(infoElId); var nameEl = infoEl.firstElementChild; var timerEl = infoEl.lastElementChild; var idKey = 'treeId' + placeId; var growTimerKey = 'treeGrowTimer' + placeId; var lockedKey = 'treeUnlocked' + placeId; var treeId = getGameValue(idKey); if (treeId == 0) { var isLocked = placeId > 4 && getGameValue(lockedKey) == 0; nameEl.textContent = isLocked ? 'Locked' : 'Empty'; timerEl.textContent = ''; } else { nameEl.textContent = key2Name(window.getTreeName(treeId)) || 'Unknown Tree'; var remainingTime = window.TREE_GROW_TIME[treeId - 1] - getGameValue(growTimerKey); timerEl.textContent = remainingTime > 0 ? '(' + format.timer(remainingTime, true) + ')' : 'Fully grown'; } if (init) { observer.add([idKey, growTimerKey, lockedKey], function () { return updateTreeInfo(placeId, infoElId, false); }); } } // add tree grow timer function improveTreeGrowTimer() { improveTimer('.woodcutting-tree', 'white', 'yellow', 'wc-tree-info-', 'wc-div-tree-', updateTreeInfo); } function updatePatchInfo(patchId, infoElId, init) { if (init === void 0) { init = false; } var infoEl = document.getElementById(infoElId); var nameEl = infoEl.querySelector('.name'); var timerEl = infoEl.querySelector('.timer'); var idKey = 'farmingPatchSeed' + patchId; var growTimeKey = 'farmingPatchGrowTime' + patchId; var timerKey = 'farmingPatchTimer' + patchId; var stageKey = 'farmingPatchStage' + patchId; var stage = getGameValue(stageKey); var seedName = SEED_NAME[getGameValue(idKey)] || 'Unkown Plant'; if (stage == 0) { var isLocked = patchId > 4 && window.donorFarmingPatch == 0; nameEl.textContent = isLocked ? 'Locked' : 'Click to grow'; timerEl.textContent = ''; } else if (stage >= 4) { nameEl.textContent = stage > 4 ? 'Dead Plant' : seedName; timerEl.textContent = stage > 4 ? 'Click to remove' : 'Click to harvest'; } else { nameEl.textContent = seedName; var remainingTime = getGameValue(growTimeKey) - getGameValue(timerKey); timerEl.textContent = '(' + format.timer(remainingTime, true) + ')'; } if (init) { observer.add([idKey, timerKey, stageKey, 'donorFarmingPatch'], function () { return updatePatchInfo(patchId, infoElId, false); }); } } // add seed name and change color of timer function improveSeedGrowTimer() { improveTimer('div[id^="farming-patch-area-"]', 'black', 'blue', 'farming-patch-info-', 'farming-patch-area-', updatePatchInfo); } function init() { bindNewFormatter(); improveSmeltingTimer(); improveTreeGrowTimer(); improveSeedGrowTimer(); } improveTimer_1.init = init; })(improveTimer || (improveTimer = {})); /** * improve smelting dialog */ var improveSmelting; (function (improveSmelting) { improveSmelting.name = 'improveSmelting'; var TIME_NEEDED_ID = 'smelting-time-needed'; var LAST_SMELTING_AMOUNT_KEY = 'lastSmeltingAmount'; var LAST_SMELTING_BAR_KEY = 'lastSmeltingBar'; var smeltingValue = null; var amountInput; function prepareAmountInput() { amountInput = document.getElementById('input-smelt-bars-amount'); amountInput.type = 'number'; amountInput.min = '0'; amountInput.step = '5'; function onValueChange() { smeltingValue = null; window.selectBar('', null, amountInput, document.getElementById('smelting-furnace-capacity').value); } amountInput.addEventListener('mouseup', onValueChange); amountInput.addEventListener('keyup', onValueChange); amountInput.setAttribute('onkeyup', ''); } function setBarCap(bar, capacity) { if (bar == '') { bar = window.selectedBar; } var requirements = SMELTING_REQUIREMENTS[bar]; var maxAmount = parseInt(capacity, 10); for (var key in requirements) { var req = requirements[key]; maxAmount = Math.min(Math.floor(getGameValue(key) / req), maxAmount); } var value = parseInt(amountInput.value, 10); if (value > maxAmount) { smeltingValue = value; amountInput.value = maxAmount.toString(); } else if (smeltingValue != null) { amountInput.value = Math.min(smeltingValue, maxAmount).toString(); if (smeltingValue <= maxAmount) { smeltingValue = null; } } } function prepareTimeNeeded() { var neededMatsEl = document.getElementById('dialogue-furnace-mats-needed'); var parent = neededMatsEl && neededMatsEl.parentElement; if (!neededMatsEl || !parent) { return; } var br = document.createElement('br'); var timeBox = document.createElement('div'); timeBox.className = 'basic-smallbox'; timeBox.innerHTML = "<img src=\"images/icons/hourglass.png\" class=\"image-icon-30\">\n\t\tDuration: <span id=\"" + TIME_NEEDED_ID + "\"></span>"; var next = neededMatsEl.nextElementSibling; parent.insertBefore(br, next); parent.insertBefore(timeBox, next); } function updateTimeNeeded(value) { var timeEl = document.getElementById(TIME_NEEDED_ID); if (!timeEl) { return; } var num = parseInt(value, 10); var timePerBar = SMELTING_TIME[window.selectedBar]; timeEl.textContent = format.timer(timePerBar * num); } function init() { prepareAmountInput(); prepareTimeNeeded(); var _selectBar = window.selectBar; var updateSmeltingRequirements = function (bar, inputElement, inputBarsAmountEl, capacity) { _selectBar(bar, inputElement, inputBarsAmountEl, capacity); updateTimeNeeded(inputBarsAmountEl.value); }; window.selectBar = function (bar, inputElement, inputBarsAmountEl, capacity) { setBarCap(bar, capacity); // save selected bar if (bar != '') { store.set(LAST_SMELTING_BAR_KEY, bar); } // save amount store.set(LAST_SMELTING_AMOUNT_KEY, inputBarsAmountEl.value); updateSmeltingRequirements(bar, inputElement, inputBarsAmountEl, capacity); }; var lastBar = store.get(LAST_SMELTING_BAR_KEY); var lastAmount = store.get(LAST_SMELTING_AMOUNT_KEY); var _openFurnaceDialogue = window.openFurnaceDialogue; window.openFurnaceDialogue = function (furnace) { var capacity = window.getFurnaceCapacity(furnace); if (window.smeltingBarType == 0) { amountInput.max = capacity.toString(); } // restore amount var inputBarsAmountEl = document.getElementById('input-smelt-bars-amount'); if (inputBarsAmountEl && inputBarsAmountEl.value == '-1' && lastAmount != null) { inputBarsAmountEl.value = lastAmount; } _openFurnaceDialogue(furnace); // restore selected bar if ((!window.selectedBar || window.selectedBar == 'none') && lastBar != null) { window.selectedBar = lastBar; } // update whether requirements are fulfilled var barInputId = 'input-furnace-' + split2Words(window.selectedBar, '-').toLowerCase(); var inputElement = document.getElementById(barInputId); if (inputElement && inputBarsAmountEl) { updateSmeltingRequirements(window.selectedBar, inputElement, inputBarsAmountEl, capacity.toString()); } }; } improveSmelting.init = init; })(improveSmelting || (improveSmelting = {})); /** * add chance to time calculator */ var fishingInfo; (function (fishingInfo) { fishingInfo.name = 'fishingInfo'; /** * calculates the number of seconds until the event with the given chance happened at least once with the given * probability p (in percent) */ function calcSecondsTillP(chancePerSecond, p) { return Math.round(Math.log(1 - p / 100) / Math.log(1 - chancePerSecond)); } function addChanceTooltip(headline, chancePerSecond, elId, targetEl) { // ensure tooltip exists and is correctly binded var tooltipEl = ensureTooltip('chance-' + elId, targetEl); // set elements content var percValues = [1, 10, 20, 50, 80, 90, 99]; var percRows = ''; for (var _i = 0, percValues_1 = percValues; _i < percValues_1.length; _i++) { var p = percValues_1[_i]; percRows += "\n\t\t\t\t<tr>\n\t\t\t\t\t<td>" + p + "%</td>\n\t\t\t\t\t<td>" + format.time2NearestUnit(calcSecondsTillP(chancePerSecond, p), true) + "</td>\n\t\t\t\t</tr>"; } tooltipEl.innerHTML = "<h2>" + headline + "</h2>\n\t\t\t<table class=\"chance\">\n\t\t\t\t<tr>\n\t\t\t\t\t<th>Probability</th>\n\t\t\t\t\t<th>Time</th>\n\t\t\t\t</tr>\n\t\t\t\t" + percRows + "\n\t\t\t</table>\n\t\t"; } function addChanceStyle() { addStyle("\ntable.chance\n{\n\tborder-spacing: 0;\n}\ntable.chance th\n{\n\tborder-bottom: 1px solid gray;\n}\ntable.chance td:first-child\n{\n\tborder-right: 1px solid gray;\n\ttext-align: center;\n}\ntable.chance th,\ntable.chance td\n{\n\tpadding: 4px 8px;\n}\ntable.chance tr:nth-child(2n) td\n{\n\tbackground-color: white;\n}\n\t\t"); } function addXp() { var table = document.querySelector('#dialogue-id-fishingRod table'); if (!table) { return; } var rows = table.rows; for (var i = 0; i < rows.length; i++) { var row = rows.item(i); if (row.classList.contains('xp-added')) { continue; } if (i == 0) { var xpCell = document.createElement('th'); xpCell.textContent = 'XP'; row.appendChild(xpCell); } else { var cell = row.insertCell(-1); var rawFish = row.id.replace('dialogue-fishing-rod-tr-', ''); var xp = FISH_XP[rawFish]; cell.textContent = xp == null ? '?' : format.number(xp); } row.classList.add('xp-added'); } } function chance2TimeCalculator() { var fishList = ['shrimp', 'sardine', 'tuna', 'swordfish', 'shark']; for (var _i = 0, fishList_1 = fishList; _i < fishList_1.length; _i++) { var fish = fishList_1[_i]; var rawFish = 'raw' + capitalize(fish); var row = document.getElementById('dialogue-fishing-rod-tr-' + rawFish); if (!row) { continue; } var chanceCell = row.cells.item(4); var chance = (chanceCell.textContent || '') .replace(/[^\d\/]/g, '') .split('/') .reduce(function (p, c) { return p / parseInt(c, 10); }, 1); addChanceTooltip("One raw " + fish + " at least every:", chance, rawFish, row); } } function init() { addChanceStyle(); var _clicksShovel = window.clicksShovel; window.clicksShovel = function () { _clicksShovel(); var shovelChance = document.getElementById('dialogue-shovel-chance'); var titleEl = shovelChance.parentElement; var chance = 1 / window.getChanceOfDiggingSand(); addChanceTooltip('One sand at least every:', chance, 'shovel', titleEl); }; // depends on fishingXp var _clicksFishingRod = window.clicksFishingRod; window.clicksFishingRod = function () { _clicksFishingRod(); addXp(); chance2TimeCalculator(); }; } fishingInfo.init = init; })(fishingInfo || (fishingInfo = {})); /** * add tooltips for recipes */ var recipeTooltips; (function (recipeTooltips) { recipeTooltips.name = 'recipeTooltips'; function updateRecipeTooltips(recipeKey, recipes) { var table = document.getElementById('table-' + recipeKey + '-recipe'); var rows = table.rows; function recipe2Title(recipe) { return recipe.recipe .map(function (name, i) { return format.number(recipe.recipeCost[i]) + ' ' + split2Words(name).toLowerCase(); }) .join(' + '); }; for (var i = 1; i < rows.length; i++) { var row = rows.item(i); var key = row.id.replace(recipeKey + '-', ''); var recipe = recipes[key]; var requirementCell = row.cells.item(3); requirementCell.title = recipe2Title(recipe); window.$(requirementCell).tooltip(); } } function updateTooltipsOnReinitRecipes(key) { var capitalKey = capitalize(key); var processKey = 'process' + capitalKey + 'Tab'; var _processTab = window[processKey]; window[processKey] = function () { var reinit = !!getGameValue('refreshLoad' + capitalKey + 'Table'); _processTab(); if (reinit) { updateRecipeTooltips(key, getGameValue(key + 'Recipes')); } }; } function init() { updateTooltipsOnReinitRecipes('crafting'); updateTooltipsOnReinitRecipes('brewing'); updateTooltipsOnReinitRecipes('magic'); updateTooltipsOnReinitRecipes('cooksBook'); } recipeTooltips.init = init; })(recipeTooltips || (recipeTooltips = {})); /** * fix formatting of numbers */ var fixNumbers; (function (fixNumbers) { fixNumbers.name = 'fixNumbers'; function prepareRecipeForTable(recipe) { // create a copy of the recipe to prevent requirement check from failing var newRecipe = JSON.parse(JSON.stringify(recipe)); newRecipe.recipeCost = recipe.recipeCost.map(function (cost) { return format.number(cost); }); newRecipe.xp = format.number(recipe.xp); return newRecipe; } function fixNumberFormat() { var _addRecipeToBrewingTable = window.addRecipeToBrewingTable; window.addRecipeToBrewingTable = function (brewingRecipe) { _addRecipeToBrewingTable(prepareRecipeForTable(brewingRecipe)); }; var _addRecipeToMagicTable = window.addRecipeToMagicTable; window.addRecipeToMagicTable = function (magicRecipe) { _addRecipeToMagicTable(prepareRecipeForTable(magicRecipe)); }; var tooltipList = document.querySelectorAll('#tooltip-list div[id^="tooltip-"][id$="Seeds"]'); for (var i = 0; i < tooltipList.length; i++) { var tooltip = tooltipList[i]; tooltip.innerHTML = format.numbersInText(tooltip.innerHTML); } var fightEnergyCells = document.querySelectorAll('#dialogue-fight tr > td:nth-child(4)'); for (var i = 0; i < fightEnergyCells.length; i++) { var cell = fightEnergyCells[i]; cell.innerHTML = format.numbersInText(cell.innerHTML); } } function init() { fixNumberFormat(); } fixNumbers.init = init; })(fixNumbers || (fixNumbers = {})); /** * add slider for machines */ var betterMachines; (function (betterMachines) { betterMachines.name = 'betterMachines'; var $slider; function createSlider() { var br = document.querySelector('#dialogue-machinery-current-total ~ br'); var parent = br && br.parentElement; if (!br || !parent) { return; } var slider = document.createElement('div'); slider.style.margin = '10px 5px'; parent.insertBefore(slider, br); $slider = window.$(slider) .slider( { range: false , min: 0 , max: 10 , value: 0 , slide: function (event, ui) { return updateValue(ui.value); } }); // hide br and up/down arrows br.style.display = 'none'; var arrows = document.querySelectorAll('input[onclick^="turnOn("]'); for (var i = 0; i < arrows.length; i++) { arrows[i].style.display = 'none'; } var els = document.querySelectorAll('[onclick*="openMachineryDialogue("]'); var boundMachineKeyList = []; for (var i = 0; i < els.length; i++) { var match = els[i].id.match(/openMachineryDialogue\('(.+?)'\)/); if (match) { boundMachineKeyList.push(getBoundKey(match[1])); } } observer.add(boundMachineKeyList, function () { return updateMax(); }); } function updateMax() { var machineEl = document.getElementById('dialogue-machinery-chosen'); if (machineEl && machineEl.value != '') { var boundMachineKey = getBoundKey(machineEl.value); $slider.slider('option', 'max', getGameValue(boundMachineKey)); } } function updateValue(value) { var typeEl = document.getElementById('dialogue-machinery-chosen'); var numEl = document.getElementById('dialogue-machinery-current-on'); if (numEl && typeEl) { var valueBefore = parseInt(numEl.textContent || '0', 10); var machine = typeEl.value; var increment = valueBefore < value; var diff = Math.abs(valueBefore - value); for (var i = 0; i < diff; i++) { window.turnOn(machine, increment); } } } function init() { createSlider(); var _openMachineryDialogue = window.openMachineryDialogue; window.openMachineryDialogue = function (machineType) { _openMachineryDialogue(machineType); updateMax(); $slider.slider('value', getGameValue(machineType + 'On')); }; } betterMachines.init = init; })(betterMachines || (betterMachines = {})); /** * improve behaviour of amount inputs */ var amountInputs; (function (amountInputs) { amountInputs.name = 'amountInputs'; function getMax(recipe) { var max = Number.MAX_SAFE_INTEGER; for (var i = 0; i < recipe.recipe.length; i++) { max = Math.min(max, Math.floor(getGameValue(recipe.recipe[i]) / recipe.recipeCost[i])); } return max; } function setAmount(id, recipeCollection, key) { var numInput = document.getElementById(id); if (!numInput) { return; } var max = getMax(recipeCollection[key]); numInput.value = max.toString(); numInput.select(); } function init() { var _multiCraft = window.multiCraft; window.multiCraft = function (item) { _multiCraft(item); setAmount('dialogue-multicraft-input', window.craftingRecipes, item); }; var _brew = window.brew; window.brew = function (potion) { _brew(potion); setAmount('dialogue-brewing-input', window.brewingRecipes, potion); }; var _cooksBookInputDialogue = window.cooksBookInputDialogue; window.cooksBookInputDialogue = function (food) { _cooksBookInputDialogue(food); setAmount('dialogue-cooksBook-input', window.cooksBookRecipes, food); }; } amountInputs.init = init; })(amountInputs || (amountInputs = {})); /** * improves the top bar */ var newTopbar; (function (newTopbar) { newTopbar.name = 'newTopbar'; function init() { addStyle("\ntable.top-links,\ntable.top-links *\n{\n\tpadding: 0;\n}\ntable.top-links td > *\n{\n\tdisplay: inline-block;\n\tpadding: 2px 6px;\n}\n\t\t"); var table = document.querySelector('table.top-links'); if (!table) { return; } var row = table.rows.item(0); var cells = row.cells; var tabIdx = [2, 4]; var infoIdx = [5, 6]; var newRow = table.insertRow(-1); var linkCell = newRow.insertCell(-1); var tabCell = newRow.insertCell(-1); tabCell.style.textAlign = 'center'; var infoCell = newRow.insertCell(-1); infoCell.style.textAlign = 'right'; for (var i = 0; i < cells.length; i++) { var container = linkCell; if (tabIdx.indexOf(i) != -1) { container = tabCell; } else if (infoIdx.indexOf(i) != -1) { container = infoCell; } var cell = cells.item(i); var el = cell.firstElementChild; if (cell.childNodes.length > 1) { el = document.createElement('span'); el.style.color = 'yellow'; while (cell.childNodes.length > 0) { el.appendChild(cell.childNodes[0]); } } if (container.children.length > 0) { container.appendChild(document.createTextNode('|')); } if (el) { container.appendChild(el); } } var parent = row.parentElement; if (parent) { parent.removeChild(row); } var _openTab = window.openTab; window.openTab = function (newTab) { var oldTab = window.currentOpenTab; _openTab(newTab); var children = tabCell.children; for (var i = 0; i < children.length; i++) { var el = children[i]; var match = (el.getAttribute('onclick') || '').match(/openTab\('([^']+)'\)/); if (!match) { continue; } var tab = match[1]; if (oldTab == tab) { el.style.color = ''; } if (newTab == tab) { el.style.color = 'white'; } } }; } newTopbar.init = init; })(newTopbar || (newTopbar = {})); /** * style tweaks */ var styleTweaks; (function (styleTweaks) { styleTweaks.name = 'styleTweaks'; function addTweakStyle(setting, style) { if (setting != '') { var prefix = setting == '' ? '' : 'body.' + setting; style = style.replace(/(^\s*|,\s*|\}\s*)([^\{\},]+)(,|\s*\{)/g, '$1' + prefix + ' $2$3'); document.body.classList.add(setting); } addStyle(style, setting != '' ? setting : null); } // tweak oil production/consumption function tweakOil() { addTweakStyle('tweak-oil', "\nspan#oil-flow-values\n{\n\tmargin-left: .5em;\n\tpadding-left: 2rem;\n\tposition: relative;\n}\n#oil-flow-values > span:nth-child(-n+2)\n{\n\tfont-size: 0px;\n\tposition: absolute;\n\tleft: 0;\n\ttop: -0.75rem;\n\tvisibility: hidden;\n}\n#oil-flow-values > span:nth-child(-n+2) > span\n{\n\tfont-size: 1rem;\n\tvisibility: visible;\n}\n#oil-flow-values > span:nth-child(2)\n{\n\ttop: 0.75rem;\n}\n#oil-flow-values span[data-item-display=\"oilIn\"]::before\n{\n\tcontent: '+';\n}\n#oil-flow-values span[data-item-display=\"oilOut\"]::before\n{\n\tcontent: '-';\n}\n\t\t"); // make room for oil cell on small devices var oilFlowValues = document.getElementById('oil-flow-values'); var oilFlowCell = oilFlowValues.parentElement; oilFlowCell.style.width = '30%'; } function tweakSelection() { addTweakStyle('no-select', "\ntable.tab-bar,\nspan.item-box,\ndiv.farming-patch,\ndiv.farming-patch-locked,\ndiv#tab-sub-container-combat > span,\ntable.top-links a,\n#hero-area > div:last-child\n{\n\t-webkit-user-select: none;\n\t-moz-user-select: none;\n\t-ms-user-select: none;\n\tuser-select: none;\n}\n\t\t"); } // tweak stardust monitor of DH2QoL to keep it in place function tweakStardust() { addTweakStyle('dh2qol', "\n#dh2qol-stardustMonitor\n{\n\tdisplay: inline-block;\n\tmargin-left: .25rem;\n\ttext-align: left;\n\twidth: 2.5rem;\n}\n\t\t"); } function tweakSkillLevelText() { addTweakStyle('', "\ndiv.skill-xp-label\n{\n\ttext-shadow: white 0px 0px 0.5rem;\n}\n\t\t"); } function tweakFightDialog() { addTweakStyle('smaller-fight-dialog', "\n#dialogue-fight img[width=\"300px\"]\n{\n\twidth: 120px;\n\theight: 50px;\n}\n#dialogue-fight img[src=\"images/icons/combat.png\"] ~ br\n{\n\tdisplay: none;\n}\n\t\t"); } function init() { tweakOil(); tweakSelection(); tweakStardust(); tweakSkillLevelText(); tweakFightDialog(); } styleTweaks.init = init; })(styleTweaks || (styleTweaks = {})); /** * init */ var scriptInitialized = false; function init() { console.info('[%s] "DH2 Fixed %s" up and running.', (new Date).toLocaleTimeString(), version); scriptInitialized = true; var initModules = [ settings , notifications , gameEvents , temporaryFixes , hideCraftedRecipes , hideUselessItems , improveItemBoxes , chat , improveTimer , improveSmelting , fishingInfo , recipeTooltips , fixNumbers , betterMachines , amountInputs , newTopbar , styleTweaks ]; window.initModules = initModules; for (var _i = 0, initModules_1 = initModules; _i < initModules_1.length; _i++) { var module = initModules_1[_i]; try { module.init(); } catch (error) { console.error('Error during initialization in module "' + module.name + '":', error); } } } document.addEventListener('DOMContentLoaded', function () { var oldValues = new Map(); var _doCommand = window.doCommand; window.doCommand = function (data) { if (data.startsWith('REFRESH_ITEMS=')) { oldValues = new Map(); for (var _i = 0, _a = window.jsItemArray; _i < _a.length; _i++) { var key = _a[_i]; oldValues.set(key, getGameValue(key)); } _doCommand(data); if (!scriptInitialized) { init(); } return; } else if (!scriptInitialized) { if (data.startsWith('CHAT=')) { var parts = data.substr(5).split('~'); return chat.newAddToChatBox(parts[0], parts[1], parts[2], parts[3], 0); } else if (data.startsWith('PM=')) { return chat.newAddToChatBox(window.username, '0', '0', data.substr(3), 1); } } var formattedData = data; if (data.startsWith('STHS=') || data.startsWith('STE=') || data.startsWith('SM=') || data.startsWith('ST=')) { if (data.indexOf('Your account has been running for:') != -1) { data = data.replace(/Your account has been running for: (\d+) minutes./, function (wholeMatch, minutes) { return 'Your account has been running for ' + format.min2Str(minutes) + '.'; }); } formattedData = format.numbersInText(data); } var ret = _doCommand(formattedData); // notifications for this kind of message: "SM=An update has been scheduled for today." if (data.startsWith('SM=')) { if (settings.get(settings.KEY.showNotifications)) { var msg = data.substr(3) .replace(/<br\s*\/?>/g, '\n') .replace(/<img src='images\/(.+?)\.png'.+?\/?> (\d+)/g, function (wholeMatch, key, amount) { return format.number(amount) + ' ' + split2Words(key) + ', '; }) .replace(/(\s)\1+/g, '$1') .replace(/, $/, '') .replace(/<.+?>/g, ''); notifications.event('Message from server' , { body: msg }); } } return ret; }; var _refreshItemValues = window.refreshItemValues; window.refreshItemValues = function (itemKeyList, firstLoad) { _refreshItemValues(itemKeyList, firstLoad); for (var _i = 0, itemKeyList_1 = itemKeyList; _i < itemKeyList_1.length; _i++) { var key = itemKeyList_1[_i]; observer.notify(key, oldValues.get(key)); } }; }); /** * fix web socket errors */ var main; (function (main) { function webSocketLoaded(event) { var ws = window.webSocket; if (ws == null) { console.error('no webSocket instance found!'); return; } var messageQueue = []; var _onMessage = ws.onmessage; ws.onmessage = function (event) { return messageQueue.push(event); }; document.addEventListener('DOMContentLoaded', function () { messageQueue.forEach(function (event) { return window.onMessage(event); }); ws.onmessage = _onMessage; }); var commandQueue = []; var _cBytes = window.cBytes; window.cBytes = function (command) { return commandQueue.push(command); }; var _onOpen = ws.onopen; ws.onopen = function (event) { window.cBytes = _cBytes; commandQueue.forEach(function (command) { return window.cBytes(command); }); return _onOpen.call(ws, event); }; } function isScriptElement(el) { return el.nodeName === 'SCRIPT'; } function isWebSocketScript(script) { return script.src.includes('socket.js'); } var found = false; var scripts = document.head ? document.head.querySelectorAll('script') : []; for (var i = 0; i < scripts.length; i++) { if (isWebSocketScript(scripts[i])) { // does this work? scripts[i].onload = webSocketLoaded; found = true; } } if (!found) { // create an observer instance var mutationObserver_1 = new MutationObserver(function (mutationList) { mutationList.forEach(function (mutation) { if (mutation.addedNodes.length === 0) { return; } for (var i = 0; i < mutation.addedNodes.length; i++) { var node = mutation.addedNodes[i]; if (isScriptElement(node) && isWebSocketScript(node)) { mutationObserver_1.disconnect(); node.onload = webSocketLoaded; return; } } }); }); mutationObserver_1.observe(document.head , { childList: true }); } // fix scrollText (e.g. when joining the game and receiving xp at that moment) window.mouseX = window.innerWidth / 2; window.mouseY = window.innerHeight / 2; })(main || (main = {})); })();