The West Perseus Toolkit

Useful tools for The West.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name        The West Perseus Toolkit
// @author      Mr. Perseus
// @namespace   tw-perseus
// @description Useful tools for The West.
// @include     https://*.the-west.*/game.php*
// @include     http://*.the-west.*/game.php*
// @include     https://*.tw.innogames.*/game.php*
// @include     http://*.tw.innogames.*/game.php*
// @version     1.3.0
// @grant       none
// ==/UserScript==

(function(fn) {
    const script = document.createElement('script');
    script.setAttribute('type', 'application/javascript');
    script.textContent = `(${fn})();`;
    document.body.appendChild(script);
    document.body.removeChild(script);
})(() => {
    $(document).ready(() => {
        const TWPT = {
            base64: {
                menuImage:
                    "url('data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAASABIAAD/4QCMRXhpZgAATU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAABmgAwAEAAAAAQAAABkAAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/AABEIABkAGQMBIgACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAUDBAQEAwUEBAQFBQUGBwwIBwcHBw8LCwkMEQ8SEhEPERETFhwXExQaFRERGCEYGh0dHx8fExciJCIeJBweHx7/2wBDAQUFBQcGBw4ICA4eFBEUHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh4eHh7/3QAEAAL/2gAMAwEAAhEDEQA/APHLTT9Z1bU7101HUApunA2t8qgHp0rqbXwHq0ttuOo6kGI67zXpX7PEA1bw5rGmGCF3S6llRmAGMOSQTjjI5r0iNLRtEvpBEgCNEA2QNoO7+eBXwmPzDFqs4wdld213sfQUIUlH3o3/AOCfJHjfw54i8PKsrajqSLhHG9iMgkeorpvt93/z9Tf9917h+0FdaMPAWvQ3yJNeyWkK2I8v5rVgvLFv4geDtFeBbx6frXuZZiJ1qT53do4qyXNeKsf/0PP/AIdePv8AhHW1TTGvmtop7lvMHK5AbPb612yfEjRfIZBfwFWxkZPOOmRXmV1/rR9Kb2r5fE5LSxE/aOTR7VLHSpR5eVMu/E74gx6zaPZ28jTGQqhbDEkZ6fhUGW/55tUEf+tH1FSV3YXDQwkOSBz1q0q0rs//2Q==')",
            },
            version: '1.3.0',
            settingsKey: 'TWPT_preferences',
            defaultPreferences: {
                CinemaSkipButton: true,
                ZoomMap: true,
                DisablePremiumNotifications: true,
                NineTimesFifteenButton: true,
                HideDrawingMap: true,
                ChatImprovements: true,
                AlwaysShowFortBattleRecruitment: true,
            },
            preferences: {},
            currentZoom: 1,
        };

        TWPT.Updater = {
            init() {
                setTimeout(TWPT.Updater.load, 5000);
            },

            load() {
                $.getScript(
                    'https://rawcdn.githack.com/mr-perseus/tw-js-library/master/script-updater.js',
                    () => {
                        if (scriptUpdater.TWPT > TWPT.version) {
                            const updateMessage = new west.gui.Dialog(
                                'Update: The West Perseus Toolkit',
                                `<span>Update Available<br><br><b>v${scriptUpdater.TWPT}:</b><br>${scriptUpdater.TWPTNew}</span>`,
                                west.gui.Dialog.SYS_WARNING,
                            )
                                .addButton('Update', () => {
                                    updateMessage.hide();
                                    window.location.href =
                                        'https://greasyfork.org/scripts/370137-the-west-perseus-toolkit/code/The%20West%20Perseus%20Toolkit.user.js';
                                })
                                .addButton('cancel')
                                .show();
                        }
                    },
                );
            },
        };

        TWPT.Settings = {
            init() {
                const storage = JSON.parse(
                    localStorage.getItem(TWPT.settingsKey),
                );
                TWPT.preferences = storage || TWPT.defaultPreferences;

                const div = $('<div class="ui_menucontainer" />');
                const link = $(
                    '<div id="TWPT_Menu" class="menulink" title="The West Perseus Toolkit" />',
                )
                    .css('background-image', TWPT.base64.menuImage)
                    .css('background-position', '0px 0px')
                    .mouseenter(function() {
                        $(this).css('background-position', '-2px 0px');
                    })
                    .mouseleave(function() {
                        $(this).css('background-position', '0px 0px');
                    });

                $(link).on('click', () => {
                    TWPT.Settings.refreshMenu();
                });

                $('#ui_menubar').append(
                    div
                        .append(link)
                        .append('<div class="menucontainer_bottom" />'),
                );
            },

            refreshMenu() {
                const win = wman
                    .open('TWPTSettings', 'TWPT Settings', 'noreload')
                    .setMaxSize(1268, 838)
                    .setMiniTitle('TWPT Settings');
                const scrollPane = new west.gui.Scrollpane();

                const setTitle = function(name) {
                    scrollPane.appendContent(
                        `<p><span style="font-size: 130%; font-weight: bold; font-style: italic; display: inline-block; margin-top: 20px;">${name}</span></p>`,
                    );
                };

                const setCheckBox = function(prefName, text) {
                    const checkbox = new west.gui.Checkbox(text);
                    checkbox.setId(`TWPT_${prefName}`);
                    if (TWPT.preferences[prefName]) {
                        checkbox.toggle();
                    }
                    checkbox.setCallback(() => {
                        TWPT.preferences[prefName] = checkbox.isSelected();
                        localStorage.setItem(
                            TWPT.settingsKey,
                            JSON.stringify(TWPT.preferences),
                        );
                        TWPT.Settings.refreshMenu();
                        new UserMessage(
                            'Okay. Please refresh your page.',
                            'success',
                        ).show();
                    });
                    scrollPane.appendContent(checkbox.getMainDiv());
                    scrollPane.appendContent('<br/>');
                };

                setTitle('Enabled Features');
                setCheckBox(
                    'CinemaSkipButton',
                    'Enable the Cinema Skip button (allows to skip cinema videos after 5 seconds).',
                );
                setCheckBox(
                    'ZoomMap',
                    'Enable the Zoom feature (hover the minimap icon on the top right and scroll up / down to zoom out / in).',
                );
                setCheckBox(
                    'DisablePremiumNotifications',
                    'Suppress energy refill and automation premium notifications.',
                );
                setCheckBox(
                    'NineTimesFifteenButton',
                    'Add a button to job windows which allows you to start 9x 15 second jobs at once.',
                );
                setCheckBox(
                    'HideDrawingMap',
                    'Hides "Drawing Map" flag which is buggy sometimes.',
                );
                setCheckBox(
                    'ChatImprovements',
                    'Enable Chat improvements: show online / idle status in Saloon chat.',
                );
                setCheckBox(
                    'AlwaysShowFortBattleRecruitment',
                    'Always show the recruitment button in fort battle windows. (even if you have no permissions)',
                );
                setTitle('Feedback');
                scrollPane.appendContent(
                    '<ul style="margin-left:15px;line-height:18px;">' +
                        '<li>Send a message to <a target="_blank" href="https://www.the-west.de/?ref=west_invite_linkrl&player_id=83071&world_id=1&hash=0dc5">Mr. Perseus on world DE1</a></li>' +
                        '<li>Contact me on <a target="_blank" href="https://greasyfork.org/forum/messages/add/Mr. Perseus">Greasy Fork</a></li>' +
                        '<li>Send me a message on the <a target="_blank" href="https://forum.beta.the-west.net/index.php?conversations/add&to=Mr.%20Perseus">The West Beta Forum</a> or the <a target="_blank" href="https://forum.the-west.de/index.php?conversations/add&to=Mr.%20Perseus">German The West Forum</a></li>' +
                        '</ul><br />Check out other scripts on <a target="_blank" href="https://greasyfork.org/de/users/179973-mr-perseus">Greasyfork</a>.',
                );

                setTitle(
                    'Import / Export settings from various userscripts (to clipboard)',
                );

                const exportButton = new west.gui.Button(
                    'Export settings',
                    () => {
                        const settings = {};

                        const settingsKeysToStore = [
                            'TWDW_preferences',
                            'TWPT_preferences',
                            'TWToolkit_preferences',
                            'TWCalc_Wardrobe',
                            'TWCalc_Settings',
                            'TWDS_h_',
                            'TWDS_settings',
                            'twir_features',
                        ];

                        Object.entries(localStorage).forEach(([key, value]) => {
                            if (
                                settingsKeysToStore.some((settingToStore) =>
                                    key.startsWith(settingToStore),
                                )
                            ) {
                                settings[key] = value;
                            }
                        });

                        console.log('exporting settings', settings);

                        navigator.clipboard
                            .writeText(JSON.stringify(settings))
                            .then(
                                () => {
                                    new UserMessage(
                                        'Successfully copied settings to clipboard. Please save it somewhere.',
                                        'success',
                                    ).show();
                                },
                                (error) => {
                                    console.error('TWPT error', error);
                                    new UserMessage(
                                        'Failed saving to clipboard. (see console for further details)',
                                        'error',
                                    ).show();
                                },
                            );
                    },
                );
                scrollPane.appendContent(exportButton.getMainDiv());

                scrollPane.appendContent(
                    '<div style="margin-left: 20px;display:inline-block">Enter here: <input id="TWPT_import"/></div>',
                );
                const importButton = new west.gui.Button(
                    'Import settings',
                    () => {
                        try {
                            const stringImport = $('#TWPT_import').val();

                            const settings = JSON.parse(stringImport);

                            Object.entries(settings).forEach(([key, value]) => {
                                console.log(`Importing ${key} = ${value}`);
                                localStorage[key] = value;
                            });

                            new UserMessage(
                                'Successfully imported settings.',
                                'success',
                            ).show();
                        } catch (error) {
                            console.error('TWPT error', error);
                            new UserMessage(
                                'Failed saving to clipboard. (see console for further details)',
                                'error',
                            ).show();
                        }
                    },
                );
                scrollPane.appendContent(importButton.getMainDiv());

                win.appendToContentPane(scrollPane.getMainDiv());
            },
        };

        TWPT.CinemaSkipButton = {
            init() {
                const button = new west.gui.Button('Skip ad', () => {
                    CinemaWindow.controller('rewards');
                });

                CinemaWindow.backup_twpt_cotroller = CinemaWindow.controller;
                CinemaWindow.controller = function(key) {
                    button.setVisible(false);
                    button.disable();

                    // Uncomment the following line if you want to access rewards directly.
                    // if (key === "video") return CinemaWindow.backup_twpt_cotroller("rewards");

                    if (key === 'video') {
                        let count = 15;
                        const countDown = () => {
                            if (count > 0) {
                                button.setCaption(`Skip ad (${count})`);
                                setTimeout(countDown, 1000);
                                count -= 1;
                            } else {
                                button.setCaption('Skip ad');
                                button.enable();
                            }
                        };
                        button.setVisible(true);
                        countDown();
                    }

                    // If there is no ad available you should be able to get the rewards.
                    if (key === 'noVideo') {
                        return CinemaWindow.backup_twpt_cotroller('rewards');
                    }

                    return CinemaWindow.backup_twpt_cotroller(key);
                };

                CinemaWindow.backup_twpt_open = CinemaWindow.open;
                CinemaWindow.open = function(townId) {
                    CinemaWindow.backup_twpt_open(townId);
                    const header = $(this.window.divMain).find(
                        '.tw2gui_inner_window_title',
                    );
                    button.divMain.setAttribute(
                        'style',
                        'margin-left: 20px; margin-top: -20px; position: absolute',
                    );
                    button.divMain.lastChild.setAttribute(
                        'style',
                        'line-height: normal; padding-top: 10px;',
                    );
                    button.setVisible(false);
                    header.append(button.getMainDiv());
                };
            },
        };

        TWPT.ZoomMap = {
            init() {
                $(window).bind('mousewheel', (event) => {
                    if ($('#ui_minimap').is(':hover')) {
                        if (event.originalEvent.wheelDelta >= 0) {
                            if (TWPT.currentZoom < 1.95)
                                TWPT.currentZoom += 0.1;
                        } else if (TWPT.currentZoom > 0.75)
                            TWPT.currentZoom -= 0.1;

                        document.getElementById('map').style.zoom =
                            TWPT.currentZoom;
                    }
                });
            },
        };

        TWPT.DisablePremiumNotifications = {
            init() {
                Premium.checkForEnergyPremium = function(
                    callback,
                    failCallback,
                ) {
                    if (typeof failCallback !== 'undefined')
                        return failCallback();

                    return () => {};
                };
                Premium.checkForAutomationPremium = function(
                    callback,
                    failCallback,
                ) {
                    if (typeof failCallback !== 'undefined')
                        return failCallback();

                    return () => {};
                };
            },
        };

        TWPT.NineTimesFifteenButton = {
            init() {
                JobWindow.backup_twpt_initView = JobWindow.initView;
                JobWindow.initView = function() {
                    JobWindow.backup_twpt_initView.apply(this, arguments);
                    const button = new west.gui.Button('9x 15s', () => {
                        button.disable();
                        const jobAmountNum = this.window.divMain.getElementsByClassName(
                            'job-amount-num',
                        )[0];
                        const numberBefore = jobAmountNum.innerHTML;
                        jobAmountNum.innerHTML = '9';
                        $(this.window.divMain)
                            .find('.job_durationbar.job_durationbar_short')
                            .click();
                        setTimeout(() => {
                            button.enable();
                            jobAmountNum.innerHTML = numberBefore;
                        }, 5000);
                    });

                    const buttonDiv = button.getMainDiv();
                    buttonDiv.style['z-index'] = '5';
                    buttonDiv.style.bottom = '25px';
                    buttonDiv.style.left = '300px';
                    this.window.divMain
                        .querySelector('div.tw2gui_window_content_pane')
                        .appendChild(button.getMainDiv());
                };
            },
        };

        TWPT.HideDrawingMap = {
            init() {
                GameLoader.backup_twpt_async = GameLoader.async;
                GameLoader.async = function(message, signal, callback, max) {
                    GameLoader.backup_twpt_async(
                        message,
                        signal,
                        callback,
                        max,
                        true,
                        true,
                    );
                };
            },
        };

        TWPT.ChatImprovements = {
            init() {
                Chat.Resource.Client.prototype.isStranger = function() {
                    return false;
                };
            },
        };

        TWPT.AlwaysShowFortBattleRecruitment = {
            init() {
                FortBattleWindow.backup_twpt_getInfoArea =
                    FortBattleWindow.backup_twpt_getInfoArea ||
                    FortBattleWindow.getInfoArea;
                FortBattleWindow.getInfoArea = function() {
                    this.preBattle.battleData.canSetPrivilege = true;
                    return FortBattleWindow.backup_twpt_getInfoArea.apply(
                        this,
                        arguments,
                    );
                };
            },
        };

        try {
            TWPT.Updater.init();
            TWPT.Settings.init();
            Object.keys(TWPT.preferences).forEach((property) => {
                if (TWPT.preferences[property]) {
                    try {
                        TWPT[property].init();
                    } catch (err) {
                        console.error(
                            `TWPT Error with feature "${property}".`,
                            err,
                        );
                    }
                }
            });
        } catch (err) {
            console.error('TWPT ERROR', err);
        }
    });
});