您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Combine dropped crystals after hunting
// ==UserScript== // @name Crystal Check // @match http://*.legacy-game.net/hunting3.php // @match http://*.legacy-game.net/inventory.php* // @version 1.11 // @namespace https://greasyfork.org/users/4585 // @description Combine dropped crystals after hunting // @grant none /*global $ */ // ==/UserScript== /***************************************************** General Methods /****************************************************/ //Method to create elements on the fly without injecting html function create(type, attr, text, parent) { var ele = document.createElement(type); for (var x in attr) { if (x.hasOwnProperty) { ele.setAttribute(x, attr[x]); } } if (text) { ele.innerHTML = text; } if (parent) { parent.appendChild(ele); } return ele; } //Return user cookies as object function getCookies() { return document.cookie .split(/[;\s]+/g) .reduce(function(a, b) { a[b.split('=')[0]] = b.split('=')[1]; return a; }, {}); } /***************************************************** Inventory /****************************************************/ //Inventory API to manipulate inventory items function Inventory(html) { this.items = getItems(); this.key = $(html).find('form').attr('action').match(/[a-zA-Z]+$/g).pop(); var key = this.key; //Inventory items encapsulated to organise data function Item(name, slot, trades, id) { this.name = name; this.slot = slot; this.trades = trades; this.id = id; //Crystal merging method this.merge = function(that, callback) { var slot1 = this.slot; var slot2 = that.slot; $.ajax({ type: "POST", url: "inventory10.php?i=" + slot1 + "&key=" + key, async: false, data: { item: slot2 }, success: function(data) { //If method available, use on response data to check for further crystal merging //Response from merging should be the redirected inventory page, which can be used to //refresh inventory data if (callback) callback.call(this, data); } }); }; } //captures all item data for the inventory & encapsulates as an object function getItems() { //Match javascript lines on inventory.php for item id & trades //Each resulting index corresponds to the slot in inventory var itemPreviews = html.match(/(itemPreviews\[)((.|\n)*?)(Default|table>');/g); var tempItems = []; $(html).find('img.item').each(function() { var slot = parseInt($(this).attr('name')); var dat = itemPreviews[slot].replace("Un-tradable", "0 Trade").match(/(\d+)(?=(&c=|\sTrade))/g); tempItems.push(new Item($(this).attr('title'), slot, dat[0], dat[1])); }); return tempItems; } //Returns all crystals in the inventory, sorted by item id (newest first) this.getCrystals = function() { return this.items //check if item is a crystal (must be have some word before crystal Crystal to avoid Crstal Rings) .filter(function(a) { return a.name.match(/.+Crystal/) !== null; }) //order from newest to oldest (item id descending) .sort(function(a, b) { return b.id - a.id; }); }; //Returns an array of matching size/colour crystals //Ordered by trades on given crystal ascending, then everything else descending this.matchCrystal = function(crystal) { return this.getCrystals().filter(function(a) { return a.id !== crystal.id && a.name == crystal.name && crystal.name.search('Perfect')==-1; }).sort(function(a, b) { return (a.trades >= crystal.trades && b.trades >= crystal.trades) ? a.trades - b.trades : b.trades - a.trades; }); }; } /***************************************************** Hunting Page Methods /****************************************************/ function huntMerge() { //Once a crystal drop has been detected function checkDrop() { //Display 'found match' message on single line row function singleRow(crystal) { var r = create('tr', {}, false, $('tbody:contains("Item Found")')[0]); create('td', { width: "100%", class: "standardrow", align: "center", colspan: "2" }, 'You have a matching ' + crystal.name + ' (' + crystal.trades + 't) in your inventory. <span class="merge" style="cursor:pointer;">[Merge]</span>', r); } //create 'item drop' row displaying merged crystal image + result message function doubleRow(crystal) { var r = create('tr', {}, false, $('tbody:contains("Item Found")')[0]); create('td', { width: "10%", class: "standardrow", align: "center" }, "<img src='img-bin/items/" + crystal.name.toLowerCase() + ".png'/>", r); create('td', { width: "90%", class: "standardrow", align: "center" }, crystal.name + " added to inventory.", r); } $.ajax({ url: 'inventory.php', async: true, success: function(data) { var inv = new Inventory(data); var drop = inv.getCrystals()[0]; option(drop, inv.matchCrystal(drop)); //recursive method - if crystal match, display option to merge - if merged, display result //if crystal match with previous result, offer to match again, etc function option(crystal, matches) { if (matches.length > 0) { singleRow(matches[0]); $('span.merge').click(function() { $(this).remove(); //merge newest crystal [0] with best matching crystal [1] crystal.merge(matches[0], //anonymous function as input for merge callback to display merge option on previously merged crystal function(data) { var nextInv = new Inventory(data); var newCrystal = nextInv.getCrystals()[0]; doubleRow(newCrystal); option(newCrystal, nextInv.matchCrystal(newCrystal)); } ); }); } } } }); } //Build a clickable button which allows the user to attack //the same hunt group again without visiting the hunt page again //If there are buttons present, the fight is ongoing //If there is a page title, user is on error or multiattack screen if (!($('.button').length || $('.pagetitle').length)) { //Create Start Another Hunt button & position next to Back to Hunting page url, change row to fit //Button defaulted to disabled while waiting for attack string var td = $('td:has("#back-to-hunting")'); td.prop("width", "50%"); var newCell = create("td", { class: "standardrow", width: "50%", align: "center" }, false, td.parent()[0]), newButt = create("input", { type: "button", class: "button", value: "Start Another Hunt", disabled: "disabled" }, false, newCell); td.before(newCell); //Gather attack string from hunting.php && cookie info for next hunt form var form = create("form", { action: "hunting3.php", method: 'post', style: "display:none;" }, false, document.body), attackString, cookies = getCookies(); create("input", { type: "hidden", name: "group", value: cookies.hunting_group }, false, form); create("input", { type: "hidden", name: "level", value: cookies.hunting_level }, false, form); create("input", { type: "submit", value: "Attack Target", class: "button", id: "hunt-" + cookies.hunting_group + "-" + cookies.hunting_level }, false, form); $.ajax({ url: 'hunting.php', async: true, success: function(data) { attackString = data.match(/([a-zA-Z]{20})(?=">')/g).pop(); create("input", { type: "hidden", name: "attackstring", value: attackString }, false, form); newButt.disabled = false; } }); //Button method - disable to prevent multi-attack & submit to proceed $(newButt).click(function() { $(this).prop("disabled", true); form.submit(); }); //Hunt Group 18 - Crystal Entities and crystal drop if (cookies.hunting_group == "18" && $('tbody:contains("Item Found")').length) { checkDrop(); } } } /***************************************************** Inventory Page Methods /****************************************************/ function invMerge() { //Call current inventory as instance of inventory object defined above for managing crystals var inv = new Inventory(document.body.innerHTML); $('img[title*=" Crystal"]').each(function() { //Build selectbox containing matching crystal options & merge button var slot = $(this).attr('name'); var row = create('tr', {}, false, false); var col1 = create('td', { colspan: '2' }, false, row); var select = create('select', { name: 'item', id: 'crystalSelect', class: 'selectbox', style: 'width:100%;' }, false, col1); var col2 = create('td', {}, false, row); var merge = create('input', { id: 'merge', type: 'button', class: 'button', style: 'width:100%', value: 'Merge' }, false, col2); var crystal = inv.getCrystals().reduce(function(a, b) { return b.slot == slot ? b : a; }, null); var matches = inv.matchCrystal(crystal); if (matches.length > 0) { matches.forEach(function(a) { create('option', { value: a.slot }, a.trades + ' Trades | ID:' + a.id, select); }); } else { create('option', {}, 'No Matching Crystals', select); select.disabled = true; merge.disabled = true; } select.selectedIndex = 0; //Add selectbox & button after crystal is selected in inventory $(this).click(function() { $('#ItemPreview tbody tbody:contains("Use")').append(row); }); //Merging! $(merge).click(function() { //Re-create 'crystal to be merged' input as child of form create("input", { type: "hidden", name: "item", value: select.selectedOptions[0].value }, false, document.getElementsByTagName('form')[0]); //remove unneeded Save Changes input $('[name=itemarray]').remove(); //Override Save Changes form for with merging url $('form').attr('action', 'inventory10.php?i=' + crystal.slot + '&key=' + inv.key).submit(); }); }); } /***************************************************** Misc /****************************************************/ //call methods where relevant switch (location.pathname) { case '/inventory.php': invMerge(); break; case '/hunting3.php': huntMerge(); break; }