Crystal Check

Combine dropped crystals after hunting

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

// ==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();
    }
}