Crystal Check

Combine dropped crystals after hunting

目前為 2014-08-19 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name            Crystal Check
// @match           http://dev.legacy-game.net/hunting3.php
// @version         1.0
// @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();
    var key = $(html).find('form').attr('action').match(/[a-zA-Z]+$/g).pop();
    //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(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 Trades").match(/(\d+)(?=(&c=|\sTrades))/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;});
    };
    //Searches for best match of given crystal within the inventory
    this.matchCrystal = function(crystal){
        var matches = this.getCrystals().filter(function(a){return a.id !== crystal.id && a.name == crystal.name;});
        return matches.length > 0 ? 
            [crystal,matches.reduce(function(a,b){return a.trades === crystal.trades?a:a.trades>b.trades?a:b;})]:
            null;
    };
}

/*****************************************************
                    Hunting Setup                    
/****************************************************/

//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:false,
        success:function(data){
            var inv = new Inventory(data);
            var drop = inv.getCrystals()[0];
            console.log(inv.matchCrystal(drop));
            option(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(match){
                if(match){
                    singleRow(match[1]);
                    $('span.merge').click(function(){
                        $(this).remove();
                        //merge newest crystal [0] with best matching crystal [1]
                        match[0].merge(match[1],
                            //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(nextInv.matchCrystal(newCrystal));
                            }
                        );
                    });
                }
            }
        }
    });
}


/*****************************************************
                    Hunt Again Button                    
/****************************************************/

//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 Hunt Again button & position next to Back to Hunting page url, change row to fit
    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:"Hunt Again"},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:false,
        success:function(data){
            attackString = data.match(/([a-zA-Z]{20})(?=">')/g).pop();
            create("input",{type:"hidden",name:"attackstring",value:attackString},false,form);
        }
    });
    //Button method - disable to prevent multi-attack & submit to proceed
    $(newButt).click(function(){
        $(this).attr("disabled", true);
        form.submit();
    });
    //Hunt Group 18 - Crystal Entities and crystal drop
    if(cookies.hunting_group == "18" && $('tbody:contains("Item Found")').length){
        checkDrop();
    }
}