Greasy Fork

Greasy Fork is available in English.

StarRepublik Tools

Various enhancements and tools for StarRepublik

当前为 2016-07-19 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name            StarRepublik Tools
// @name:bg         StarRepublik Инструменти
// @name:ro         Unelte StarRepublik
// @description     Various enhancements and tools for StarRepublik
// @description:bg  Различни подобрения и инструменти за StarRepublik
// @description:ro  Diverse îmbunătățiri și unelte pentru StarRepublik
// @namespace       http://www.linuxmint.ro/
// @version         1.4.3
// @license         CC BY 4.0
// @author          Nicolae Crefelean
// @include         https://www.starrepublik.com/*
// @grant           none
// ==/UserScript==

$(function() {

    // add custom styles
    $('head').append('<style></style>');
    $('style')
        .append('#srtools { font-size: 13px; padding: 5px; background-color: #121925; border-radius: 2px; margin-top: 5px; margin-bottom: 10px }')
        .append('.srtselect { width: 200px; height: 30px; background-color: #121925; color: #cecece; border: 1px solid #595959; border-radius: 2px; padding: 2px }');

    var srtversion = '1.4.3',
        letters = ['α', 'β', 'γ', 'Δ', 'Ω'],
        effectDelay = 150,
        locale = {
            bg: {
                name: 'Български',
                medalsStr: 'Медали',
                starshipPartsPointsStr: 'Изисквани Седмични турнирни точки',
                baseDamage: 'Bаза щети',
                battles: 'Битките',
                move: 'Ход',
                building: 'Cграда',
                myLocation: 'Моето място',
                encloseInFrame: 'Приложете в рамка'
            },
            en: {
                name: 'English',
                medalStr: 'Medals',
                starshipPartsPointsStr: 'Weekly tournament points required',
                baseDamage: 'Base damage',
                battles: 'Battles',
                move: 'Move',
                building: 'Building',
                myLocation: 'My location',
                encloseInFrame: 'Enclose in frame'
            },
            es: {
                name: 'Español',
                medalStr: 'Medallas',
                starshipPartsPointsStr: 'Puntos de torneo semanal necesaria',
                baseDamage: 'Daño base',
                battles: 'Batallas',
                move: 'Moverse',
                building: 'Edificio',
                myLocation: 'Mi ubicación',
                encloseInFrame: 'Encerrar en un marco'
            },
            it: {
                name: 'Italiano',
                medalStr: 'Medaglie',
                starshipPartsPointsStr: 'Punti Torneo Settimanale richiesti',
                baseDamage: 'Danno base',
                battles: 'Battaglie',
                move: 'Spostati',
                building: 'Costruzione',
                myLocation: 'La mia posizione',
                encloseInFrame: 'Incornicia'
            },
            ro: {
                name: 'Română',
                medalStr: 'Medalii',
                starshipPartsPointsStr: 'Puncte necesare în turneul săptămânal',
                baseDamage: 'Daune de bază',
                battles: 'Bătălii',
                move: 'Mutare',
                building: 'Clădire',
                myLocation: 'Locația mea',
                encloseInFrame: 'Încadrează în ramă'
            },
            sr: {
                name: 'Srpski',
                medalStr: 'Medalje',
                starshipPartsPointsStr: 'Delovi zvezdane krstarice',
                baseDamage: 'Bazna steta',
                battles: 'Bitke',
                move: 'Predji na',
                building: 'Zgrada',
                myLocation: 'Moja lokacija',
                encloseInFrame: 'Priložiti u okviru'
            }
        },
        defaultLang = getLocale();

    // adds the StarRepublik Tools settings box on the sidebar
    if ($('.stardate').length > 0) {
        $('.stardate').after('<div class="row-fluid" id="srtools"></div>');
        $('#srtools')
            .html('<div class="text-center">StarRepublik Tools v' + srtversion + '</div>')
            .append('<select class="center-block srtselect"></select>');
        $.each(locale, function(i, v) {
            $('.srtselect').append('<option value="' + i + '"' + (i === defaultLang ? ' selected' : '') + '>' + v.name + '</option>');
        });
    }

    // Adds links to the Battles and the Change location pages.
    $('.dropdown:eq(0) > .dropdown-menu')
        .append('<li><a href="/battles/">' + getString('battles') + '</a></li>')
        .append('<li><a href="/change-location/">' + getString('move') + '</a></li>');

    // Set the default language as English, or if the browser requests
    // a language available in the script, it will choose it automatically.
    // The language can also be changed by the user. Refresh required.
    function setLocale(lang) {
        if (localStorage.locale === undefined) {
            var langList = navigator.languages,
                language = 'en',
                found = false;
            for (i=0; !found; i++) {
                if (locale[langList[i]] !== undefined) {
                    language = langList[i];
                    found = true;
                }
            }
            localStorage.locale = language;
            return;
        }
        if (lang !== undefined && lang in locale) {
            localStorage.locale = lang;
        }
    }

    // Returns the default locale and sets one if not available.
    function getLocale() {
        if (localStorage.locale === undefined) {
            setLocale();
        }
        return localStorage.locale;
    }

    // Returns a string based on its identifier. Defaults to English if missing.
    function getString(id) {
        lang = getLocale();
        var str = locale[lang][id] === undefined ? (locale.en[id] === undefined ? id : locale.en[id]) : locale[lang][id];
        return str;
    }

    // Event handler for the language switcher.
    $('.srtselect').change(function() {
        setLocale(this.value);
    });

    // Returns the user ID.
    function getUserId() {
        return $("#main-menu a:eq(1)").attr('href').split('/')[2];
    }

    // Returns the user profile link.
    function getUserProfileLink() {
        return $("#main-menu a:eq(1)").attr('href');
    }

    // Return the base damage.
    function getBaseDamage(skill, rank) {
        return Math.round(Math.pow(10 * skill * (1 + rank / 20), 0.8));
    }

    // Add the base damage data to the military wings on the user profile page.
    function getBaseDamageStats() {
        $.get('/api/profile/' + getUserId() + '/', function(data) {
            var d = data.user.military,
                baseDamage = {
                    interceptor: 0,
                    bomber: 0,
                    fighter: 0
                };
            baseDamage.interceptor = getBaseDamage(d.skills.interceptor, d.rank),
            baseDamage.bomber = getBaseDamage(d.skills.bomber, d.rank),
            baseDamage.fighter = getBaseDamage(d.skills.fighter, d.rank);
            $('#baseI').html(getString('baseDamage') + ': ' + baseDamage.interceptor + '<br>+20% = ' + Math.round(baseDamage.interceptor * 1.2));
            $('#baseB').html(getString('baseDamage') + ': ' + baseDamage.bomber + '<br>+20% = ' + Math.round(baseDamage.bomber * 1.2));
            $('#baseF').html(getString('baseDamage') + ': ' + baseDamage.fighter + '<br>+20% = ' + Math.round(baseDamage.fighter * 1.2));
        });
    }

    // Creates the HTML/CSS/JS foundation for the base damage tooltips in the user profile.
    function addBaseDamageTooltips() {
        $('style')
            .append('.skill-desc > .description { position: absolute; z-index: 10; margin-top: -132px; margin-left: -15px; width: 100%; background-color: #070d15; border: 1px solid #101924; padding: 10px; border-radius: 3px }');
        $('.skills:eq(1) .skill:eq(2)').addClass('description-container skill-desc')
            .append('<div style="display: none;" class="description"><div class="row-fluid" id="baseI"></div></div>');
        $('.skills:eq(1) .skill:eq(3)').addClass('description-container skill-desc')
            .append('<div style="display: none;" class="description"><div class="row-fluid" id="baseB"></div></div>');
        $('.skills:eq(1) .skill:eq(4)').addClass('description-container skill-desc')
            .append('<div style="display: none;" class="description"><div class="row-fluid" id="baseF"></div></div>');
        $('.skills:eq(1) .skill').slice(2, 5).hover(function() {
            $(this).find(".description").toggle();
        });
    }

    // Displays the number of medals and total Credits earned (in the user profile).
    function calcCredits() {
        var rewards = {
            hard_worker: 5,
            expert: 5,
            political_activist: 5,
            congress_member: 10,
            country_leader: 20,
            prosperous_journalist: 3,
            media_mogul: 5,
            society_builder: 50,
            weekly_runner: 100,
            hunter: 3,
            wing_commander: 2,
            battle_hero: 5,
            deft_shooter: 3,
            ace: 10,
            rebellion_hero: 10,
            juggernaut: 20,
            patriot: 5,
            faithfull_ally: 5,
            super_soldier: 5
        },
            medal_count = 0,
            earned_credits = 0,
            medal_name,
            medal_counter;
        $('.medals-list li').each(function() {
            medal_name = $(this).find('img').attr('src').split('/').pop().split('.')[0];
            medal_counter = Number($(this).find('.medal-quantity').text().trim());
            if (medal_name in rewards) {
                earned_credits += rewards[medal_name] * medal_counter;
                medal_count += medal_counter;
            }
        });
        $('.achievements').last().append(' (' + medal_count + ': ' + earned_credits + ' Cr)');
    }

    // Code executed while viewing a user profile.
    if (/^\/profile\/[0-9]+\/$/.test(document.location.pathname)) {
        addBaseDamageTooltips();
        getBaseDamageStats();
        calcCredits();
    }

    // Reset the medals data (on the battlefield).
    function clearTopMedals() {
        var medals = ['.defender-ds', '.attacker-ds', '.defender-bh', '.attacker-bh', '.defender-ace', '.attacker-ace'],
            medal;
        for (i = 0; i < 7; i++) {
            medal = medals[i];
            $(medal + ' a').removeAttr('href');
            $(medal + ' a img').removeAttr('src');
            $(medal + ' div.username').text('');
            $(medal + ' span.damage').text('');
            $(medal + ' span.shoots').text('');
        }
    }

    // Build and place the squadron switcher next to the stats Close button (on the battlefield).
    function addSquadronSwitcher() {
        var squads = [],
            sclass;
        $('.close-statistics:eq(1)').attr('class',$('.close-statistics:eq(1)').attr('class').replace(/4/g, '1'));
        for (i = 1; i < 6; i++) {
            sclass = 'squadSwitch' + ($('.statistics:eq(1)').data('squadron') == i ? ' btn-primary' : '');
            squads.push("<a role='button' class='btn " + sclass + "'>" + letters[i - 1] + "</a>");
        }
        $('.close-statistics:eq(1)').before("<div class='col-lg-3 col-md-3 col-sm-3 col-xs-3'>" + squads.join('') + "</div>");
    }

    // Set the width of the statistics overlay to the same width as the battlefield.
    if (/^\/military\/battle\//.test(document.location.pathname)) {
        $('.battle-statistics').css('width', '100%');
        addSquadronSwitcher();
    }

    // Event handler for clicking the squadron switcher buttons (on the battlefield).
    $('.squadSwitch').on("click", function() {
        var squad = letters.indexOf($(this).text());
        clearTopMedals();
        $('.squadSwitch').removeClass('btn-primary');
        $('.squadSwitch:eq(' + squad + ')').addClass('btn-primary');
        $('.statistics:eq(1)').data('squadron', squad + 1).click();
    });

    // Counts the number of sectors owned by a country and adds it to the section header.
    function getCountryDetails() {
        var sectors = $('.country-content .society-list:eq(1) li').length;
        $('.country-content .society-list:eq(1) > div').append(' (' + sectors + ')');
    }

    // Code executed while viewing the Society page of a country.
    if (/^\/country\/society\//.test(document.location.pathname)) {
        getCountryDetails();
    }

    // Code executed while viewing the Congress candidature proposal page.
    if (/^\/politics\/congress-proposal\/$/.test(document.location.pathname)) {
        $('#id_sector').addClass('srtselect');
        getCandidatesBySector();
    }

    // Returns the country ID of the displayed country on the Congress candidature proposal page.
    function getCountryFromCongressProposal() {
        return $(".inline-country-flag").parent().attr("href").split('/')[3];
    }

    // Calculates the number of candidates per sector and adds them in the sector selector.
    function getCandidatesBySector() {
        $.get('https://www.starrepublik.com/politics/congress-candidates/' + getCountryFromCongressProposal() + '/', function(data) {
            if ($(data).find('.citizens-list li').length > 0) {
                var sectors = {},
                    sector;
                $(data).find('.citizens-list li').each(function() {
                    sector = $(this).find('.sector').text().trim();
                    if (sector in sectors) {
                        sectors[sector] += 1;
                    } else {
                        sectors[sector] = 1;
                    }
                });
                $('#id_sector option').each(function() {
                    if (this.value !== '') {
                        current = this.innerHTML;
                        this.innerHTML += " (" + (sectors[current] > 4 ? '!!! ' : '') + (current in sectors ? sectors[current] : 0) + "/5)";
                    }
                });
            }
        });
    }

    // Code executed while viewing the storage.
    if (/^\/storage\/$/.test(document.location.pathname)) {
        var minParts = Math.min(
                itemsCount('ion_ammo'),
                itemsCount('ion_stock'),
                itemsCount('ion_chip')
            );
        setCannonPartBalance(minParts);
        setWeaponBalance(minParts);
        addStarshipPartsRequirements();
    }

    // Returns the number of items by image name (in the storage).
    function itemsCount(img) {
        return Number($('.storage-list:eq(0) li img[src="/media/images/products/' + img + '.jpg"]').parent().next().text().trim()) || 0;
    }

    // Add the positive/negative sign to non-zero balances (for storage items).
    function setBalance(num) {
        return (num === 0 ? '' : (num > 0 ? '-' : '+')) + Math.abs(num).toString();
    }

    // Add the balance to each weapon type (in the storage).
    function setWeaponBalance(cannons) {
        var weaponMultiplier = {'q1': 10, 'q2': 8, 'q3': 6, 'q4': 4, 'q5': 2},
            quality,
            balance;
        for (i = 1; i < 6; i++) {
            quality = 'q' + i.toString();
            balance = setBalance(cannons * weaponMultiplier[quality] - itemsCount('weapon_' + quality));
            $('.item-creation-list li img[src="/media/images/products/weapon_' + quality + '.jpg"]').attr('alt', quality).parent().next().text(balance);
        }
    }

    // Add the balance to each cannon part (in the storage).
    function setCannonPartBalance(count) {
        var cannonParts = {1: 'ammo', 2: 'stock', 3: 'chip'},
            balance;
        $('.item-creation-list:eq(1) .item-to-create .quantity').text(count).prev().find('img').attr('alt', 'cannons');
        for (i = 1; i < 4; i++) {
            balance = setBalance(count - itemsCount('ion_' + cannonParts[i]));
            $('.item-creation-list:eq(1) img[src="/media/images/products/ion_' + cannonParts[i] + '.jpg"]').attr('alt', cannonParts[i]).parent().next().text(balance);
        }
    }

    // Adds the Starship parts requirements in the user storage.
    function addStarshipPartsRequirements() {
        var req = [1500, 2000, 2500, 2750, 5000],
            reqText = getString('starshipPartsPointsStr');
        $('.item-details').css('z-index', '1');
        $('.storage-list:eq(1) li').each(function(i, v) {
            item = $(v).find('.item-name').append('<div class="details">' + reqText + ': ' + req[i] + '</div>');
        });
    }

    // Code executed while viewing the congress candidates page.
    if (/^\/politics\/congress-candidates\//.test(document.location.pathname)) {
        buildCongressCandidatesArticle();
    }

    // Build the congress candidates list in BB-code format.
    function getCongressCandidatesList() {
        if ($('.citizens-list li').length > 0) {
            var congressCandidatesList = {},
                cit;
            $('.citizens-list li').each(function() {
                cit = {};
                cit.cname = $(this).find('.name').text().trim();
                cit.curl = $(this).find('.name a').attr('href').trim();
                cit.sector = '[b]' + $(this).find('.sector').text().trim() + '[/b]';
                cit.pname = $(this).find('.party').text().trim();
                cit.purl = $(this).find('.party a').attr('href').trim();

                if (!(cit.sector in congressCandidatesList)) {
                    congressCandidatesList[cit.sector] = {};
                }

                cit.bbcit = '[url=https://www.starrepublik.com' + cit.curl + ']' + cit.cname + '[/url]';
                cit.bbprt = '[url=https://www.starrepublik.com' + cit.purl + ']' + cit.pname + '[/url]';
                congressCandidatesList[cit.sector][cit.bbcit] = cit.bbprt;
            });
            return congressCandidatesList;
        }
    }

    // Build the congress candidates text area and populate it with data.
    function buildCongressCandidatesArticle() {
        var congressCandidatesArticle = '',
            list = getCongressCandidatesList();
        if (list) {
            $.each(list, function(index, value) {
                congressCandidatesArticle += "\n" + index + "\n";
                $.each(value, function(idx, val) {
                    congressCandidatesArticle += idx + ' - ' + val + "\n";
                });
            });
            congressCandidatesArticle = "[center]" + congressCandidatesArticle.trim() + "[/center]";
            $('.party-content > .section-header.politics').append(' [<span id="toggleArticle" style="cursor: pointer">+</span>]');
            $('.citizens-list').before("<div id='congressCandidatesArticle' class='col-md-12' style='display: none'><p><textarea class='form-control' style='resize: vertical'>" + congressCandidatesArticle + "</textarea></p></div>");
        }
    }

    // Event handler for clicking the congress candidates list button.
    $('#toggleArticle').click(function () {
        if ($('#congressCandidatesArticle').css('display') === 'none') {
            $('#congressCandidatesArticle').show(effectDelay);
            $('#toggleArticle').html('&mdash;');
        } else {
            $('#congressCandidatesArticle').hide(effectDelay);
            $('#toggleArticle').html('+');
        }
    });

    // Remove the existing building information from the sector information panel.
    function removeBuildings() {
        $('.sector-info .buildings').remove();
    }

    // Get the list of buildings for a given sector id.
    function getRegionBuildings(id) {
        removeBuildings();
        $.get('/country/sector/' + id + '/', function(data) {
            var btype,
                bquality,
                owner = $(data).find('.country-header div:eq(1) a').attr('href');
            $('.sector-info .owner div:eq(1)').wrapInner('<a href="' + owner + '"></a>');
            if ($(data).find('.building').length) {
                removeBuildings();
                $('.sector-info').append('<div class="row buildings"></div>');
                $(data).find('.building').each(function() {
                    btype = $(this).find('.header').text().trim();
                    bquality = $(this).find('.quality').text().trim();
                    $('.sector-info .buildings').append('<div class="col-lg-6 col-md-6 col-sm-6 col-xs-6">' + getString('building') + '</div><div class="col-lg-6 col-md-6 col-sm-6 col-xs-6 value">' + btype + " " + bquality + '</div>');
                });
            } else {
                removeBuildings();
            }
        });
    }

    // Add the user's location panel in the side panel.
    function addMyLocationToMap(location) {
        $('style').append('.location-info { margin-top: 10px; padding: 0; border: 1px solid #101924; background-color: #02060b; border-radius: 5px; line-height: 25px }');
        $('style').append('.location-info .row { padding-bottom: 7px }');
        $('.sidebar div.row:eq(0)').after('<div class="location-info" id="srtlocinfo"></div>');
        $('#srtlocinfo').append('<div class="section-header social">' + getString('myLocation') + '</div>');
        $('#srtlocinfo').append('<div class="row"><div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 text-center">' + location + '</div></div>');
    }

    // Event handlers for sector mouse-over and clicking.
    function addMapEventHandlers() {
        $('image').on('click', function() {
            getRegionBuildings($(this).data('sector'));
        });
        $('.svg-map image').mouseenter(function() {
            var sector = '#' + $(this).data('sector');
            $('#srtcurrsector').html(' [' + $(sector).data('x') + ':' + $(sector).data('y') + ']');
        });
        $('g path, .svg-map image').mouseleave(function() {
            $('#srtcurrsector').html('');
        });
        $('g path').mouseenter(function() {
            $('#srtcurrsector').html(' [' + $(this).data('x') + ':' + $(this).data('y') + ']');
        });
    }

    // Code executed on the Galaxy map page.
    if (/^\/galaxy-map\/$/.test(document.location.pathname)) {
        var countries = {},
            t,
            region,
            bulidings;
        $('style').append('.srtmapdef { border: 1px solid #1e81b1 !important; box-shadow: 0 0 5px #1e81b1 }');
        $('#owners').addClass('srtmapdef');
        $('.section-header:eq(1)').append('<span id="srtcurrsector"></span>');
        $.get('/api' + getUserProfileLink(), function(data) {
            addMyLocationToMap(data.user.location.label);
        });
        addMapEventHandlers();
        $('#original, #owners, #resources, #battles').click(function() {
            $('#original, #owners, #resources, #battles').removeClass('srtmapdef');
            $(this).addClass('srtmapdef');
            setTimeout(addMapEventHandlers, 1000);
        });
    }

    // Get the comment count for a given article id.
    function getComments() {
        $('.articles-list li').each(function() {
            var link = $(this).find('.title a').attr('href'),
                commimg = '<img src="/media/images/main/comments.png">',
                comments;
            $.get(link, function(data) {
                comments = '&bull; ' + commimg + '  ' + $(data).find('.commentator').length;
                $(this).find('.publication-date').append('<span class="artcomments">' + comments + '</span>');
            });
        });
    }

    // Add the comment count for the articles on the main page and the newspaper page.
    if ($('.newspaper-content').length) {
        $('style')
            .append('.artcomments { margin-left: 5px }')
            .append('.artcomments img { height: 10px; margin-top: -2px }');
        getComments();
    }

    // Code executed while viewing an article - adds endorsement count and Credits amount, plus comment count.
    if (/\/newspaper\/article\/[0-9]+/.test(document.location.pathname)) {
        $('style').append('.thumbnail { background-color: #20314f; display: table; border: 0 }');
        $('.article .text').html($('.article .text').html().replace(/\[e\](.*?)\[\/e]/gi, '<div class="thumbnail text-center">$1</div>'));
        if ($('.endorsers').length) {
            var blue = $('.endorsers .blue').length,
                green = $('.endorsers .green').length,
                red = $('.endorsers .red').length,
                total = blue + green + red,
                credits = blue * 1 + green * 0.5 + red * 0.25;
            $('.endorsers').prev().append(' (' + total + ': ' + credits + ' Cr)');
        }
        if ($('.commentator').length) {
            $('.comments-list div.social').append(' (' + $('.commentator').length + ')');
        }
    }

    // Code executed while creating or editing an article.
    if (/^\/newspaper\/(write|edit)-article\//.test(document.location.pathname)) {
        myBbcodeSettings.markupSet.push({ closeWith:'[/e]', key: 'E', name:getString('encloseInFrame'), openWith:'[e]'});
        $('#id_text').markItUpRemove();
        $('#id_text').markItUp(myBbcodeSettings);
        var srtbbselect = $('.markItUpHeader ul li').last().attr('class').split(/\s/)[1];
        $('style').append('.bbcode .' + srtbbselect + ' a { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAMAAACelLz8AAAAElBMVEUAAAAAAAAAAAAAAAAAAAAAAADgKxmiAAAABXRSTlMAEKCm3Dwyid4AAAAlSURBVHgBY2DFCWggxcyIFTADpZgYsAKmESI1KsXChBWw4EtRANDOA/lDmlQ4AAAAAElFTkSuQmCC); background-size: cover }');
    }
});