Miracle Scripts

Let your cell spin, jump, shake, flip and wacky! Copy & paste custom emojis to the chatbox! Dance! Use Chat replacements!

As of 2019-10-16. See the latest version.

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Miracle Scripts
// @namespace    Miracle Scripts
// @version      1.0
// @description  Let your cell spin, jump, shake, flip and wacky! Copy & paste custom emojis to the chatbox! Dance! Use Chat replacements!
// @homepage     http://agarioforums.net/member.php?action=profile&uid=21263
// @author       You
// @license      MIT
// @icon         https://abload.de/img/mh3k8o.png
// @match        http://agma.io/
// @grant        none
// ==/UserScript==

// Source: http://stackoverflow.com/questions/1772179/get-character-value-from-keycode-in-javascript-then-trim#answer-23377822
window.keyboardMap = [
  "", // [0]
  "", // [1]
  "", // [2]
  "CANCEL", // [3]
  "", // [4]
  "", // [5]
  "HELP", // [6]
  "", // [7]
  "BACK_SPACE", // [8]
  "TAB", // [9]
  "", // [10]
  "", // [11]
  "CLEAR", // [12]
  "ENTER", // [13]
  "ENTER_SPECIAL", // [14]
  "", // [15]
  "SHIFT", // [16]
  "CONTROL", // [17]
  "ALT", // [18]
  "PAUSE", // [19]
  "CAPS_LOCK", // [20]
  "KANA", // [21]
  "EISU", // [22]
  "JUNJA", // [23]
  "FINAL", // [24]
  "HANJA", // [25]
  "", // [26]
  "ESCAPE", // [27]
  "CONVERT", // [28]
  "NONCONVERT", // [29]
  "ACCEPT", // [30]
  "MODECHANGE", // [31]
  "SPACE", // [32]
  "PAGE_UP", // [33]
  "PAGE_DOWN", // [34]
  "END", // [35]
  "HOME", // [36]
  "LEFT", // [37]
  "UP", // [38]
  "RIGHT", // [39]
  "DOWN", // [40]
  "SELECT", // [41]
  "PRINT", // [42]
  "EXECUTE", // [43]
  "PRINTSCREEN", // [44]
  "INSERT", // [45]
  "DELETE", // [46]
  "", // [47]
  "0", // [48]
  "1", // [49]
  "2", // [50]
  "3", // [51]
  "4", // [52]
  "5", // [53]
  "6", // [54]
  "7", // [55]
  "8", // [56]
  "9", // [57]
  "COLON", // [58]
  "SEMICOLON", // [59]
  "LESS_THAN", // [60]
  "EQUALS", // [61]
  "GREATER_THAN", // [62]
  "QUESTION_MARK", // [63]
  "AT", // [64]
  "A", // [65]
  "B", // [66]
  "C", // [67]
  "D", // [68]
  "E", // [69]
  "F", // [70]
  "G", // [71]
  "H", // [72]
  "I", // [73]
  "J", // [74]
  "K", // [75]
  "L", // [76]
  "M", // [77]
  "N", // [78]
  "O", // [79]
  "P", // [80]
  "Q", // [81]
  "R", // [82]
  "S", // [83]
  "T", // [84]
  "U", // [85]
  "V", // [86]
  "W", // [87]
  "X", // [88]
  "Y", // [89]
  "Z", // [90]
  "OS_KEY", // [91] Windows Key (Windows) or Command Key (Mac)
  "", // [92]
  "CONTEXT_MENU", // [93]
  "", // [94]
  "SLEEP", // [95]
  "NUMPAD0", // [96]
  "NUMPAD1", // [97]
  "NUMPAD2", // [98]
  "NUMPAD3", // [99]
  "NUMPAD4", // [100]
  "NUMPAD5", // [101]
  "NUMPAD6", // [102]
  "NUMPAD7", // [103]
  "NUMPAD8", // [104]
  "NUMPAD9", // [105]
  "MULTIPLY", // [106]
  "ADD", // [107]
  "SEPARATOR", // [108]
  "SUBTRACT", // [109]
  "DECIMAL", // [110]
  "DIVIDE", // [111]
  "F1", // [112]
  "F2", // [113]
  "F3", // [114]
  "F4", // [115]
  "F5", // [116]
  "F6", // [117]
  "F7", // [118]
  "F8", // [119]
  "F9", // [120]
  "F10", // [121]
  "F11", // [122]
  "F12", // [123]
  "F13", // [124]
  "F14", // [125]
  "F15", // [126]
  "F16", // [127]
  "F17", // [128]
  "F18", // [129]
  "F19", // [130]
  "F20", // [131]
  "F21", // [132]
  "F22", // [133]
  "F23", // [134]
  "F24", // [135]
  "", // [136]
  "", // [137]
  "", // [138]
  "", // [139]
  "", // [140]
  "", // [141]
  "", // [142]
  "", // [143]
  "NUM_LOCK", // [144]
  "SCROLL_LOCK", // [145]
  "WIN_OEM_FJ_JISHO", // [146]
  "WIN_OEM_FJ_MASSHOU", // [147]
  "WIN_OEM_FJ_TOUROKU", // [148]
  "WIN_OEM_FJ_LOYA", // [149]
  "WIN_OEM_FJ_ROYA", // [150]
  "", // [151]
  "", // [152]
  "", // [153]
  "", // [154]
  "", // [155]
  "", // [156]
  "", // [157]
  "", // [158]
  "", // [159]
  "CIRCUMFLEX", // [160]
  "EXCLAMATION", // [161]
  "DOUBLE_QUOTE", // [162]
  "HASH", // [163]
  "DOLLAR", // [164]
  "PERCENT", // [165]
  "AMPERSAND", // [166]
  "UNDERSCORE", // [167]
  "OPEN_PAREN", // [168]
  "CLOSE_PAREN", // [169]
  "ASTERISK", // [170]
  "PLUS", // [171]
  "PIPE", // [172]
  "HYPHEN_MINUS", // [173]
  "OPEN_CURLY_BRACKET", // [174]
  "CLOSE_CURLY_BRACKET", // [175]
  "TILDE", // [176]
  "", // [177]
  "", // [178]
  "", // [179]
  "", // [180]
  "VOLUME_MUTE", // [181]
  "VOLUME_DOWN", // [182]
  "VOLUME_UP", // [183]
  "", // [184]
  "", // [185]
  "SEMICOLON", // [186]
  "EQUALS", // [187]
  "COMMA", // [188]
  "MINUS", // [189]
  "PERIOD", // [190]
  "SLASH", // [191]
  "BACK_QUOTE", // [192]
  "", // [193]
  "", // [194]
  "", // [195]
  "", // [196]
  "", // [197]
  "", // [198]
  "", // [199]
  "", // [200]
  "", // [201]
  "", // [202]
  "", // [203]
  "", // [204]
  "", // [205]
  "", // [206]
  "", // [207]
  "", // [208]
  "", // [209]
  "", // [210]
  "", // [211]
  "", // [212]
  "", // [213]
  "", // [214]
  "", // [215]
  "", // [216]
  "", // [217]
  "", // [218]
  "OPEN_BRACKET", // [219]
  "BACK_SLASH", // [220]
  "CLOSE_BRACKET", // [221]
  "QUOTE", // [222]
  "", // [223]
  "META", // [224]
  "ALTGR", // [225]
  "", // [226]
  "WIN_ICO_HELP", // [227]
  "WIN_ICO_00", // [228]
  "", // [229]
  "WIN_ICO_CLEAR", // [230]
  "", // [231]
  "", // [232]
  "WIN_OEM_RESET", // [233]
  "WIN_OEM_JUMP", // [234]
  "WIN_OEM_PA1", // [235]
  "WIN_OEM_PA2", // [236]
  "WIN_OEM_PA3", // [237]
  "WIN_OEM_WSCTRL", // [238]
  "WIN_OEM_CUSEL", // [239]
  "WIN_OEM_ATTN", // [240]
  "WIN_OEM_FINISH", // [241]
  "WIN_OEM_COPY", // [242]
  "WIN_OEM_AUTO", // [243]
  "WIN_OEM_ENLW", // [244]
  "WIN_OEM_BACKTAB", // [245]
  "ATTN", // [246]
  "CRSEL", // [247]
  "EXSEL", // [248]
  "EREOF", // [249]
  "PLAY", // [250]
  "ZOOM", // [251]
  "", // [252]
  "PA1", // [253]
  "WIN_OEM_CLEAR", // [254]
  "" // [255]
];


(function() {
    'use strict';

    var settings = localStorage.getItem('miracleScripts');

    if (settings == null) {
        settings = {
            bindings: {
                animation: 17, // CRTL
                paste: 36, // POS1
                dance: 35 // END
            },
            replacements: ':D|:smile:\n:*(|:sob:'
        };
        localStorage.setItem('miracleScripts', JSON.stringify(settings));
    } else {
        settings = JSON.parse(settings);
    }

    // We need to have a delay, because the menu is not laoded right away
    setTimeout(function() {
        var $playButton = $('#playBtn');
        var $specateButton = $('#spectateBtn');

        $playButton.get(0).style.width = '40%';
        $specateButton.get(0).style.width = '40%';

        var $settingsButton = $('<button class="spec" style="width: 40px; margin-left: 7px; text-align: center; padding: 10px 0 20px 0" title="Miracle Scripts Settings">⚙️</button>');
        $settingsButton.insertAfter($playButton);

        var changeKey = function(event) {
            var name = this.name.substr(4);
            $(this).val(window.keyboardMap[event.keyCode]);
            settings.bindings[name] = event.keyCode;
            localStorage.setItem('miracleScripts', JSON.stringify(settings));
        };

        // Weird Agma scripting... press enter in the replacements textarea and the chatbox gets focused!
        // Therefore catch the keydown event (that happens earlier) and insert the linebreak manually,
        // focus again (delayed) and go to the end of the text where the linebreak is.
        // We can improve this later on...
        var addReturn = function(event) {
            if (event.keyCode == 13) {
                var textarea = this;
                $(textarea).text($(this).text() + '\n').focus();
                setTimeout(function(){
                    $(textarea).focus();
                    textarea.setSelectionRange(textarea.value.length, textarea.value.length);
                }, 1);
            }
        };
        var changeReplacements = function(event) {
            settings.replacements = $(this).val();
            localStorage.setItem('miracleScripts', JSON.stringify(settings));
        };

        var $modal = $('<div id="miracle-settings" style="position: fixed; width: 100%; height: 100%; padding: 50px; color: #FF69B4; background-color: rgba(0,0,0,0.95); z-index: 999; display: none"></div>');
        $modal.append('<h1>Miracle Scripts Settings</h1>');
        $modal.append('<small style="color: #717171">This script does not work on mobile devices! Support: <a href="http://agarioforums.net/showthread.php?tid=61388" target="_blank" style="color: #717171">agarioforums.net</small>');
        var $element = $('<input name="key_animation" value="' + window.keyboardMap[settings.bindings.animation] + '"/>').keyup(changeKey);
        $modal.append('<br><br>Animation-Key:<br>', $element);
        $element = $('<input name="key_paste" value="' + window.keyboardMap[settings.bindings.paste] + '"/>').keyup(changeKey);
        $modal.append('<br>Paste-Key:<br>', $element);
        $element = $('<input name="key_dance" value="' + window.keyboardMap[settings.bindings.dance] + '"/>').keyup(changeKey);
        $modal.append('<br>Dance-Key:<br>', $element);
        $element = $('<textarea rows="6" style="width: 100%; max-width: 500px">').text(settings.replacements).keydown(addReturn).keyup(changeReplacements);
        $modal.append('<br><br>Chat-Replacements (1 per line):<br>', $element, '<br>🧐 <span style="color: #717171">Avoid using the search text in the replacement!</span>');
        $modal.append($('<br><a href="#" style="display: inline-block; margin-top: 20px; padding: 10px; color: white; background-color: #FF69B4">Close</a>').click(function() { $modal.hide() }));

        $('body').append($modal);

        $settingsButton.click(function(event)
        {
            $modal.show();

            event.preventDefault();
        });
    }, 500);
})();


(function() {
    'use strict';

    /**
     * Returns a random number between min (inclusive) and max (exclusive)
     * Source: MDN
     */
    var getRandomArbitrary = function(min, max) {
        return Math.random() * (max - min) + min;
    }

    var chatAnimate = function()
    {
        // The available commands
        var items = ['spin', 'flip', 'shake', 'jump'];

        // Choose randomly an item of the items array
        // Source: https://stackoverflow.com/questions/5915096/get-random-item-from-javascript-array
        var item = items[Math.floor(Math.random()*items.length)];

        // Combine with wacky
        item = 'wacky' + item;

        // Add text into the chatbox and focus it (Note: acutally "/" is no longer necessary)
        $('#chtbox').val('/' + item).focus();

        // Stop the event so that the pressed key won't be written into the chatbox!
        event.preventDefault();
    }

    window.addEventListener('keydown', function(event)
    {
        // Do nothing if menu is open
        if (document.getElementById('overlays').style.display != 'none' || document.getElementById('advert').style.display != 'none') {
            return;
        }

        var settings = JSON.parse(localStorage.getItem('miracleScripts'));

        if (event.keyCode == settings.bindings.animation) {
            chatAnimate();
        }
    });
})();


(function() {
    'use strict';

    window.addEventListener('keydown', function(event)
    {
        // Do nothing if menu is open
        if (document.getElementById('overlays').style.display != 'none' || document.getElementById('advert').style.display != 'none') {
            return;
        }

        var settings = JSON.parse(localStorage.getItem('miracleScripts'));

        if (event.keyCode == settings.bindings.paste) {
            var text = prompt('Please paste your text or emjoi here');

            // focus() only works when there is a delay after the prompt has been closed
            setTimeout(function(){
                // Add text into the chatbox and focus it
                $('#chtbox').val($('#chtbox').val() + text).focus();
            }, 200);
        }
    });
})();


(function() {
    'use strict';

    var angle = 0;
    var angleSpeed = 20;
    var distance = 50;
    var dancing = false;

    var dance = function()
    {
        angle += angleSpeed;
        if (angle > 360) {
            angle = 0;
        }

        var x = window.innerWidth/2 + Math.sin(angle * Math.PI / 180) * distance;
        var y = window.innerHeight/2 + Math.cos(angle * Math.PI / 180) * distance;
        $('canvas').trigger($.Event('mousemove', {clientX: x, clientY: y}));

        if (dancing) {
            window.requestAnimationFrame(dance);
        }
    }

    window.addEventListener('keyup', function()
    {
        // Do nothing if menu is open
        if (document.getElementById('overlays').style.display != 'none' || document.getElementById('advert').style.display != 'none') {
            return;
        }

        var settings = JSON.parse(localStorage.getItem('miracleScripts'));

        if (event.keyCode == settings.bindings.dance) {
            dancing = ! dancing;

            if (dancing) {
                window.requestAnimationFrame(dance);
            }
        }
    });
})();


(function() {
    'use strict';

    $('#chtbox').keyup(function(event)
    {
        var settings = JSON.parse(localStorage.getItem('miracleScripts'));

        var lines = settings.replacements.split('\n');

        var text = $('#chtbox').val();

        lines.forEach(function(line) {
            var replacement = line.split('|');
            if (replacement.length == 2) {
                text = text.replace(replacement[0], replacement[1]);
                $('#chtbox').val(text).focus();
            }
        });
    });
})();


console.log('🌸 Miracle Scripts successfully loaded!');