IdleScape - Lootify

Addons for the IdleScape Fighting System

当前为 2021-01-23 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         IdleScape - Lootify
// @namespace    D4IS
// @version      1.0.1
// @description  Addons for the IdleScape Fighting System
// @author       D4M4G3X
// @match        http*://*idlescape.com/game
// @grant        none
// @require http://code.jquery.com/jquery-3.4.1.min.js
// ==/UserScript==

(function() {
    'use strict';
    let runs = [{}];
    let total = {};
    let totalLoot = {};
    let isSetup = false;
    let time = 0;
    let prices = getMarketPrices();
    /* ############## CSS STYLES ############## */
    let styles = {};
    styles.boxshadow = {
        'webkit-box-shadow': '0 1px 3px rgba(0,0,0,.3),inset 0 1px 1px rgba(255,255,255,.2)',
        '-moz-box-shadow': '0 1px 3px rgba(0,0,0,.3),inset 0 1px 1px rgba(255,255,255,.2)',
        'box-shadow': '0 1px 3px rgba(0,0,0,.3),inset 0 1px 1px rgba(255,255,255,.2)',
    };
    styles.header = {
        'display': 'flex',
        'justify-content': 'space-between',
        'align-items': 'center',
        'border-radius': '8px',
        'padding': '4px 0 4px 10px',
        'background-color': '#2d2d2d',
    };
    styles.mobheader = Object.assign({}, styles.boxshadow, styles.header, {
        'margin': '4px auto',
    });
    styles.lootheader = Object.assign({}, styles.boxshadow, styles.header, {
        'margin': '0 auto',
    });
    styles.headerImage = Object.assign({}, styles.boxshadow, {
        'background-color': '#313b46',
        'border-radius': '100%',
        'padding': '4px',
        'height': '35px',
        'width': '35px',
    });
    styles.entry = {
        'border-radius': 'none',
        'padding': '4px 8px',
        'border-bottom': '1px dotted #2d2d2d',
    };
    styles.submenu = {
        'width': '80%',
        'margin': '0 auto',
        'padding': '5px 0',
    };
    styles.lootwrap = {
        'border-radius': '8px',
        'background-color': '#3c3c3c',
    };
    styles.setting = Object.assign({}, styles.boxshadow, {
        'width':'80%',
        'display':'flex',
        'margin':'4px auto',
        'padding': '4px 8px',
        'justify-content': 'space-between',
        'align-items': 'center',
        'background-color': '#3c3c3c',
        'border-radius': '8px',
    });
    styles.input = {
        'background-color': '#FFF',
        'margin': '0',
        'font-size': '14px',
    };
    styles.inputCheck = Object.assign({}, styles.input, {
        'margin': '0 25px',
        'opacity': '1',
        'position': 'relative',
        'pointer-events': 'auto',
        'transform': 'scale(1.5)',
    });
    styles.inputNumber = Object.assign({}, styles.input, {
        'height': '20px',
        'width': '50px',
        'border-radius': '10px',
        'padding': '0px 4px 0 10px',
    });
    /* ############## INTERVALS ############## */
    let mainInterval = setInterval(()=> {
        if ($('.status-bar').length) {
            if(!isSetup) {
                isSetup = true;
                setupSettings();
                setupLogs();
                setupTime();
                setupKPH();
                !isIron() ? setupGPH() : 1;
            }
        }
        if (isStatus('Fighting')) {
            time++;
            saveLogs();
            mergeLogs();
            renderLogs();
            renderTime();
            renderKPH();
            !isIron() ? renderGPH() : 1;
        }
        cleanChat();
        if ($('.combat-zone').length) {
            $('.combat-zone').unbind().click(function() {
                let $zone = $(this);
                $.each(getLogMobs(), function(key, mob) {
                    if (!getZoneMobs($zone.text()).includes(mob)) {
                        submitStats(getLogs(), getTH());
                        clearLogs();
                    }
                });
            });
        }
    }, 1000);
    let pasteInterval = setInterval(()=> {
        if (isStatus('Fighting')) {
            if(window.localStorage.getItem(getUsername() + '-AutoPaster') == 'true') {
                submitStats(getLogs(), getTH());
                clearLogs('single');
            }
        }
    }, getPasteInterval() * 60 * 1000);
    let adInterval = setInterval(()=> {
        chat({
            'msg': 'Lootify - Please report bugs to D4M4G3X#6263 on Discord!',
            'color': '#00a0fd',
            'glow': '#00a0fd',
        });
    }, 15 * 60 * 1000);
    let updateInterval = setInterval(()=> {
        prices = getMarketPrices();
    }, 5 * 60 * 1000);
    /* ############## SETUP AND RENDER ############## */
    function setupSettings() {
        let $lootBtn;
        if ($('.btn-loot-log').length) {
            $('.btn-loot-log').remove();
        }
        if (getMenuItem('Loot Log')) {
            editMenuItem('Loot Log');
        }
        if(!getMenuItem('Lootify', 'category')) {
            setMenuItem({
                'text': 'Lootify',
                'clone': 'Gathering',
                'before': getMenuItem('Gathering', 'category'),
            }, 'category');
        }
        if(!getMenuItem('Lootify')) {
            $lootBtn = setMenuItem({
                'icon': '/images/money_icon.png',
                'text': 'Lootify Settings',
                'class': 'btn-lootify',
                'after': getMenuItem('Lootify', 'category'),
                'click': function() {
                    $('.log-paster-settings').toggle();
                },
            });
        } else {
            $lootBtn = $('.btn-lootify');
        }
        if (!$('.log-paster-settings').length) {
            let $wrap = $('<div/>', {
                'class': 'log-paster-settings'
            }).hide();
            $lootBtn.after($wrap);
            addSetting({
                'text': 'Enable Auto Paster',
                'name': 'AutoPaster',
                'type': 'checkbox',
                'default': 'false',
                'change': function() {
                    window.localStorage.setItem(getUsername() + '-AutoPaster', $(this).prop('checked'));
                }
            }).appendTo($wrap);
            addSetting({
                'text': 'Paste Interval (minutes)',
                'name': 'AutoPasterInterval',
                'type': 'number',
                'min': 15,
                'max': 60,
                'default': 30,
                'change': function() {
                    if($(this).val() >= $(this).attr('min') && $(this).val() <= $(this).attr('max')) {
                        window.localStorage.setItem(getUsername() + '-AutoPasterInterval', $(this).val());
                    }
                }
            }).appendTo($wrap);
            addSetting({
                'text': 'Item TH Level',
                'name': 'itemTH',
                'type': 'number',
                'min': 0,
                'max': 6,
                'change': function() {
                    if($(this).val() >= $(this).attr('min') && $(this).val() <= $(this).attr('max')) {
                        window.localStorage.setItem(getUsername() + '-itemTH', $(this).val());
                    }
                }
            }).appendTo($wrap);
        }
    }
    function setupLogs() {
        if(!getMenuItem('Loot Log')) {
            setMenuItem({
                'icon': '/images/ui/inventory_icon.png',
                'text': 'Loot Log',
                'class': 'btn-loot-log',
                'before': getMenuItem('Gathering', 'category'),
                'click': function() {
                    $('.item-log-clone').toggle();
                },
            });
        }
        let $logwrap = $('.item-log-window');
        $logwrap.hide();
        let $clone = $logwrap.clone();
        $clone.addClass('item-log-clone').removeClass('hidden');
        $clone.css(styles.submenu);
        $clone.find('.item-log-timer').remove();
        $clone.find('.item-log-info').remove();
        $clone.find('.drawer-setting-large').addClass('clone').unbind().click(function() {
            submitStats(getLogs(), getTH());
            clearLogs();
        }).text('Paste and Reset Log');
        getMenuItem('Loot Log').after($clone);
    }
    function setupTime() {
        if (!getMenuItem('Elapsed:')) {
            let $timeStats = setMenuItem({
                'class': 'time-stats',
                'text': 'Elapsed: 0S',
                'icon': '/images/clock.png',
                'after': $('.log-paster-settings'),
                'css': {
                    'font-size': '14px',
                }
            });
        }
    }
    function renderTime() {
        $('.time-stats').find('span').text('Elapsed: ' + getTime(time));
    }
    function setupKPH() {
        if (!getMenuItem('Kills:')) {
            let $kphStats = setMenuItem({
                'class': 'kph-stats',
                'text': 'Kills: 0 p/h',
                'icon': '/images/combat/combat_level.png',
                'after': $('.time-stats'),
                'click': function() {
                    $('.kph-wrap').toggle();
                },
                'css': {
                    'font-size': '14px',
                },
            });
            $kphStats.after($('<div/>', {
                'class': 'kph-wrap'
            }).css(styles.submenu).hide());
        }
    }
    function renderKPH() {
        let mobkills = {};
        $.each(total, function(mob, mobinfo) {
            mobkills[mob] = mobinfo.count;
        });
        let totalkills = function() {
            let c = 0;
            $.each(mobkills, function(mob, kills) {
                c += kills;
            });
            return c;
        };
        $('.kph-stats').find('span').text('Kills: ' + addCommas(Math.floor((totalkills()/time)*3600)) + ' p/h');
        $('.kph-wrap').empty();
        $.each(mobkills, function(mob, count) {
            let $mobwrap = $('<div/>').css(styles.mobheader).appendTo($('.kph-wrap'));
            $mobwrap.append($('<span/>').css('display','block').text(mob + ': ' + Math.floor((count/time)*3600) + ' p/h'));
        });
    }
    function setupGPH() {
        if (!getMenuItem('Gold:')) {
            let $gphStats = setMenuItem({
                'class': 'gph-stats',
                'text': 'Loot value: 0 p/h',
                'icon': '/images/ui/shop_icon.png',
                'after': $('.kph-wrap'),
                'click': function() {
                    $('.gph-wrap').toggle();
                },
                'css': {
                    'font-size': '14px',
                }
            });
            $gphStats.after($('<div/>', {
                'class': 'gph-wrap'
            }).css(styles.submenu).hide());
        }
    }
    function renderGPH() {
        let totalGold = 0;
        $.each(totalLoot, function(item, count) {
            if (item === 'Gold') {
                totalGold += count;
            } else {
                totalGold += prices[item] * count;
            }
        });
        $('.gph-stats').find('span').text('Gold: ' + addCommas(Math.floor((totalGold/time)*3600)) + ' p/h');
        $('.gph-wrap').empty();
        let $lootwrap = $('<div/>').css(styles.mobheader).appendTo($('.gph-wrap'));
        $lootwrap.append($('<span/>').css('display','block').text('Loot value: ' + addCommas(Math.floor(totalGold))));
    }
    function saveLogs() {
        let $logcats = $('.item-log-window:not(.item-log-clone)').find('.item-log-cateogry');
        if ($logcats.length) {
            $logcats.each(function() {
                if( $(this).find('.item-log-category-closed').length ) {
                    $(this).find('.item-log-category-closed').click();
                }
                let mobs = $(this).find('.item-log-category-open').text().split(" x ");
                !runs[0][mobs[0]] ? runs[0][mobs[0]] = {} : 1;
                runs[0][mobs[0]].count = parseInt(mobs[1]);
                $(this).find('.item-log-item').each(function() {
                    if( $(this).text() !== "None" ) {
                        let loot = $(this).text().split(" x ");
                        !runs[0][mobs[0]].loot ? runs[0][mobs[0]].loot = {} : 1;
                        !runs[0][mobs[0]].loot[loot[0]] ? runs[0][mobs[0]].loot[loot[0]] = {} : 1;
                        runs[0][mobs[0]].loot[loot[0]].count = parseInt(loot[1]);
                    }
                });
            });
        }
    }
    function mergeLogs() {
        if(runs) {
            total = {};
            totalLoot = {};
            $.each(runs, function(num, run) {
                $.each(run, function(mobname, mobinfo) {
                    !total[mobname] ? total[mobname] = {} : 1;
                    !total[mobname].count ? total[mobname].count = 0 : 1;
                    total[mobname].count += mobinfo.count;
                    $.each(mobinfo.loot, function(lootname, lootinfo) {
                        /* SET TOTAL LOOT PER MOB */
                        !total[mobname].loot ? total[mobname].loot = {} : 1;
                        !total[mobname].loot[lootname] ? total[mobname].loot[lootname] = {} : 1;
                        !total[mobname].loot[lootname].count ? total[mobname].loot[lootname].count = 0 : 1;
                        total[mobname].loot[lootname].count += lootinfo.count;
                        /* SET TOTAL LOOT OVERALL */
                        !totalLoot[lootname] ? totalLoot[lootname] = 0 : 1;
                        totalLoot[lootname] += lootinfo.count;
                    });
                });
            });
            delete total[''];
        }
    }
    function renderLogs() {
        if(!runs) { return; }
        let $cat, $mobwrap;
        $('.item-log-clone').find('.item-log-cateogry').remove();
        $.each(total, function(mob, mobinfo) {
            $cat = $('<div/>', {
                'class':'item-log-cateogry noselect'
            }).css(styles.lootwrap);
            $mobwrap = $('<div/>').css(styles.lootheader).appendTo($cat);
            $mobwrap.append($('<div/>').text(mob + ' x ' + mobinfo.count));
            $mobwrap.append($('<img/>').css(styles.headerImage).addClass('drawer-item-icon').attr('src', getMobIcon(mob)));
            $.each(mobinfo.loot, function(loot, lootinfo) {
                $cat.append($('<div/>').css(styles.entry).text(loot + ' x ' + lootinfo.count));
            });
            $('.item-log-clone').prepend($cat);
        });
    }
    /* ############## ACTIONS ############## */
    function getLogs() {
        let logs = [];
        let $logcats = $('.item-log-window:not(.item-log-clone)').find('.item-log-cateogry');
        if ($logcats.length) {
            $logcats.each(function(k,v) {
                if( $(this).find('.item-log-category-closed').length ) {
                    $(this).find('.item-log-category-closed').click();
                }
                if( $(this).find('.item-log-category-open').length ) {
                    logs.push($(this).find('.item-log-category-open').text());
                    $(this).find('.item-log-item').each(function() {
                        if( $(this).text() !== "None" ) {
                            logs.push($(this).text());
                        }
                    });
                }
            });
        }
        return logs;
    }
    function clearLogs(m = 'all') {
        if (m == 'single') {
            runs.unshift({});
        } else if (m == 'all') {
            time = 0;
            runs = [{}];
            total = {};
            isSetup = false;
            $('.item-log-clone').remove();
        }
        $('.item-log-window').find('.drawer-setting-large.active:not(.clone)').click();
    }
    function submitStats(logs, th) {
        if (logs.length < 1) {
            return false;
        }
        let targetUrl = "https://docs.google.com/forms/u/0/d/e/1FAIpQLSch3eG9Tqts0tIvnkk-C5JZeTwfbkWXhxkIpFnxyyaNO26h4Q/formResponse";
        let logEntryId = "entry.558332813";
        let thEntryId = "entry.22586929";
        let finalTH = (parseInt(th) > 0) ? "TH "+th : "None";
        let fullUrl = targetUrl + "?" + thEntryId + '=' + encodeURIComponent(finalTH) + "&" + logEntryId + "=" + encodeURIComponent(logs.join("\n"));
        $.ajax({
            url: fullUrl,
        });
        chat({
            'msg': 'Lootify - Loot log pasted!',
            'color': '#00a0fd',
            'glow': '#00a0fd',
        });
    }
    /* ############## GAME LIBRARY ############## */
    /* === FILTERS === */
    function isIron() {
        return $('.header-league-icon').attr('src') === '/images/leagues/ironman_league_icon_v5.png';
    }
    function isStatus(txt) {
        return $('.status-bar').length && ~$('.status-bar').text().indexOf(txt);
    }
    /* === GET DATA === */
    function getUsername() {
        return $('.navbar1-box').text().split(' ')[1];
    }
    function getTH() {
        return parseInt($('.itemTH').val());
    }
    function getLogMobs() {
        let mobs = [];
        $.each(total, function(mob, info) {
            mobs.push(mob);
        });
        return mobs;
    }
    function getZoneMobs(zone) {
        let mobs = [];
        switch (zone) {
            case 'Farm':
                mobs = ['Cow', 'Chicken', 'Small Rat'];
                break;
            case 'Caves':
                mobs = ['Imp', 'Greater Imp'];
                break;
            case 'City':
                mobs = ['Guard', 'Black Knight'];
                break;
            case 'Lava Maze':
                mobs = ['Deadly Red Spider', 'Lesser Demon'];
                break;
            case 'Valley of Giants':
                mobs = ['Fire Giant', 'Moss Giant', 'Ice Giant'];
                break;
        }
        return mobs;
    }
    function getPasteInterval() {
        let interval = parseInt($('.AutoPasterInterval').val());
        interval = interval ? interval : 30;
        interval = interval < 15 ? 15 : interval;
        interval = interval > 60 ? 60 : interval;
        return interval;
    }
    function getMarketPrices() {
        let p = {};
        $.getJSON( "https://api.idlescape.xyz/prices", function( data ) {
            if(data) {
                $.each(data.items, function(k, v) {
                    p[v.name] = v.price;
                });
            } else {
                p = false;
            }
        });
        return p;
    }
    function getMobIcon(name) {
        let link = 'https://idlescape.com/images/combat/monsters/';
        switch (name) {
            case 'Giant Rat':
                link += 'rat.png';
                break;
            case 'Chicken':
                link += 'chicken.png';
                break;
            case 'Cow':
                link += 'cow.png';
                break;
            case 'Goblin':
                link += 'goblin.png';
                break;
            case 'Imp':
            case 'Greater Imp':
                link += 'imp.png';
                break;
            case 'Guard':
                link += 'guard.svg';
                break;
            case 'Black Knight':
                link += 'black_knight.png';
                break;
            case 'Deadly Red Spider':
                link += 'deadly_red_spider.png';
                break;
            case 'Lesser Demon':
                link += 'lesser_demon_no_highlight.png';
                break;
            case 'Spriggan':
                link += 'spriggan.png';
                break;
            case 'Greater Demon':
                link += 'greater-demon.png';
                break;
            case 'Fire Giant':
                link += 'fire_giant.png';
                break;
            case 'Moss Giant':
                link += 'moss_giant.png';
                break;
            case 'Ice Giant':
                link += 'ice_giant.png';
                break;
            case 'Abberant Shrimp':
                link += 'shrimp_abberation.png';
                break;
        }
        return link;
    }
    /* === ACTIONS === */
    function chat(args) {
        let e = setInterval(()=> {
            let $chat = $('.chat-message-list > div')
            if( $chat.length ) {
                clearInterval(e);
                let $msg = $('<div/>', {
                    'class': 'chat-message msg-lootify'
                }).appendTo($chat);
                if (args['date'] !== false) {
                    let $date = $('<span/>', {
                        'class': 'message-time-stamp',
                    }).text('['+getDate(new Date)+']').appendTo($msg);
                }
                args['color'] = args['color'] ? args['color'] : '#00A0FD';
                args['glow'] = args['glow'] ? '0 0 3px '+args['glow'] : 'none';
                let $txt = $('<span/>', {
                    'class':'chat-message-system'
                }).css({
                    'font-size': '14px',
                    'color': args['color'],
                    'text-shadow': args['glow'],
                }).text(args['msg']).appendTo($msg);
            }
        }, 1000);
    }
    function cleanChat() {
        $('.chat-message-list > div').find('.msg-lootify:first-child').remove();
    }
    function setMenuItem(args, type = 'item') {
        let $item, $img, e;
        args['text'] = args['text'] ? args['text'] : 'Menu item';
        args['clone'] = args['clone'] ? args['clone'] : 'Shops';
        $item = getMenuItem(args['clone'], type).clone();
        if(args['class']) {
            $item.addClass(args['class']);
        }
        if(args['css']) {
            $item.css(args['css']);
        }
        $img = $item.find('img').clone();
        $item.unbind().empty();
        if(type === 'item') {
            $item.append($('<span/>').text(args['text']));
        } else if (type === 'category') {
            $item.append($('<b/>').text(args['text']));
        }
        if (args['icon']) {
            $img.attr('src', args['icon']).prependTo($item);
        }
        args['before'] ? args['before'].before($item) : 1;
        args['after'] ? args['after'].after($item) : 1;
        if (typeof args['click'] === 'function') {
            $item.click(args['click']);
        }
        return $item;
    }
    function getMenuItem(txt, type='item') {
        let $item;
        $.each($('.drawer-' + type), function() {
            if (~$(this).text().indexOf(txt)) {
                $item = $(this);
            }
        });
        return $item;
    }
    function editMenuItem(txt) {
        getMenuItem(txt).text('Hidden').hide();
    }
    function removeMenuItem(txt) {
        getMenuItem(txt).remove();
    }
    function addSetting(args) {
        args['text'] = args['text'] ? args['text'] : 'New setting';
        args['name'] = args['name'] ? args['name'] : args['text'].replace(' ', '-').toLowerCase();
        args['type'] = args['type'] ? args['type'] : 'text';
        args['default'] = args['default'] ? args['default'] : 0;
        let $setting = $('<div/>').css(styles.setting).append($('<span/>')).append($('<input/>'));;
        $setting.find('span').text(args['text']);
        $setting.find('input').addClass(args['name']).attr('type', args['type']);
        switch(args['type']) {
            case 'checkbox':
                $setting.find('input').css(styles.inputCheck);
                break;
            case 'number':
                $setting.find('input').css(styles.inputNumber);
                break;
        }
        if (args['min']) {
            $setting.find('input').attr('min', args['min']);
        }
        if (args['max']) {
            $setting.find('input').attr('max', args['max']);
        }
        let val = window.localStorage.getItem(getUsername() + '-' + args['name']);
        if (args['type'] === 'checkbox') {
            val = val ? val : args['default'];
            val = val == 'true' ? true : false;
            $setting.find('input').prop('checked', val);
        }
        if (val) {
            $setting.find('input').val(val)
        } else {
            $setting.find('input').val(args['default']);
        }
        if (args['change']) {
            $setting.find('input').change(args['change']);
        }
        return $setting;
    }
    /* ############## GENERAL LIBRARY ############## */
    function addCommas(nStr) {
        nStr += '';
        let x = nStr.split('.');
        let x1 = x[0];
        let x2 = x.length > 1 ? '.' + x[1] : '';
        let rgx = /(\d+)(\d{3})/;
        while (rgx.test(x1)) {
            x1 = x1.replace(rgx, '$1' + ',' + '$2');
        }
        return x1 + x2;
    }
    function getDate(date) {
        let h = date.getHours();
        let m = date.getMinutes();
        let s = date.getSeconds()
        m = m < 10 ? '0'+m : m;
        s = s < 10 ? '0'+s : s;
        let strTime = h + ':' + m + ':' + s;
        if(~$('.chat-message .message-time-stamp').text().indexOf(' AM]') || ~$('.chat-message .message-time-stamp').text().indexOf(' PM]')) {
            let ampm = h >= 12 ? 'PM' : 'AM';
            h = h % 12;
            h = h ? h : 12;
            strTime = h + ':' + m + ':' + s + ' '  + ampm
        }
        return strTime;
    }
    function getTime(t) {
        let snum = parseInt(t, 10);
        let h = Math.floor(snum / 3600);
        let m = Math.floor((snum - (h * 3600)) / 60);
        let s = snum - (h * 3600) - (m * 60);
        let tStr = parseInt(h) > 0 ? h+'H ' : '';
        tStr += parseInt(m) > 0 ? m+'M ' : '';
        tStr += parseInt(s) > 0 ? s+'S ' : '';
        return tStr;
    }
})();