vnx5

Zursor master main script

May 20th, 2019 (edited)
11,071
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. "use strict"
  2.  
  3. // Beta client for the Zursor Master project
  4. // Please do not paste this script itself into tampermonkey or cursors.io, instead please use the tampermonkey extension that I have provided here: https://pastebin.com/krbGjJ9v
  5. // Especially since this script is still in development, the tampermonkey extension provided is automatically updated
  6. // update as of oct. 13, 2020: Script has been updated to avoid any CORB/CORS errors. Change the __ip variable to the new server ip when it updates. Get the server ip by going to the 'Network' tab in inspect element, go to the 'WS' tab, and refresh the page. DM me on discord at 8y8x#5342 if the script should be updated
  7. window.zM = {};
  8. window.zMDK = {};
  9. async function wait(ms = 1000) {
  10.     setTimeout(()=>{return new Promise(async resolve => resolve());},ms);
  11. }
  12. window.D = document;
  13. let __ip = '128.199.12.58';
  14. (async function(styles, init, cfg, dependencies, elements) {
  15.     zM.dependenciesLoaded = 0b000000;
  16.     zM.version = '0.2';
  17.  
  18.     zM.cfg = cfg.raw;
  19.     zM.createConfig = cfg.createConfig;
  20.     zM.saveConfig = cfg.saveConfig;
  21.     zM.getConfig = cfg.getConfig;
  22.  
  23.     zM.returnAfterUndeployed = false;
  24.     zM.antiIdle = true;
  25.  
  26.     // load developer kit for plugins
  27.     // it isn't exactly done yet, I plan to only do it once I'm mostly done the whole script- and it's stable and everything
  28.     /**
  29.      * Tools for modifying the localStorage configuration
  30.      *
  31.      * .generate() - creates a default config, returns the result. Optionally, you can put the object pointer as a parameter.
  32.      * .save() - saves the parameter provided. Returns true/false dependant if errors occur.
  33.      * .get() - returns the saved config. Optionally, you can put the object pointer as a  parameter.
  34.      */
  35.     zMDK.config = {
  36.         generate: cfg.createConfig,
  37.         save: cfg.saveConfig,
  38.         get: cfg.getConfig
  39.     }
  40.  
  41.     // some useful shortcuts
  42.     window.head = D.head,
  43.     window.body = D.body;
  44.  
  45.     // disable all elements on page
  46.     var temp = [];
  47.     temp = body.getElementsByTagName('*');
  48.     for (var i = 0; i < temp.length; ++i) temp[i].style.display = 'none';
  49.  
  50.     // delete all header elements
  51.     head.innerHTML = '<title>Loading...</title>';
  52.  
  53.     // add a container
  54.     temp = D.createElement('div');
  55.     temp.style.cssText = 'background:linear-gradient(45deg, rgba(33,33,33,1) 0%, rgba(66,66,66,1) 100%);position:fixed;top:0px;left:0px;width:100vw;height:100vh;';
  56.     temp.id = 'zM-container'
  57.     body.appendChild(temp);
  58.  
  59.     zM.el = zMDK.elements = {};
  60.     zM.el.container = temp;
  61.  
  62.     zM.fleet = [];
  63.     zM.fSel = NaN; // NaN for news
  64.  
  65.     temp = styles();
  66.  
  67.     zM.el.style = {
  68.         fleetTopbarContainer: temp[0]
  69.     }
  70.  
  71.     zM.pos = {
  72.         mouseX: 400,
  73.         mouseY: 300,
  74.         lastMouseX: 400,
  75.         lastMouseY: 300
  76.     }
  77.  
  78.     zM.useWallhack = true;
  79.  
  80.     zM.ease = function(n, o, upd) {
  81.         var dist = n - o,
  82.             prog = (Date.now() - upd) / 100,
  83.             maxMin = Math.min(Math.max(0, prog), 1);
  84.  
  85.         return o + (maxMin ** 2 * (3 - 2 * maxMin)) * dist;
  86.     }
  87.  
  88.     zM.isLoading = false;
  89.  
  90.     zM.game = {
  91.         m28nCursorsIP: `${__ip}:2828`
  92.     }
  93.  
  94.     zM.asyncWaitUntil = async function(toEval) {
  95.         return new Promise(resolve => {
  96.             var temp = setInterval(()=>{if (eval(toEval)) resolve(), clearInterval(temp);},1);
  97.         });
  98.     }
  99.  
  100.     zM.origin = (location.hostname === 'cursors.io' || location.href.startsWith('file:///')) ? 'cursors' : location.hostname === 'kursors.io' ? 'kursors' : 'localhost';
  101.  
  102.     zM.movement = 1;
  103.  
  104.     // I decided to load the loading bars before the loading API therefore it works for when the script is starting first
  105.     var temp = [D.createElement('div'), D.createElement('div'), D.createElement('div'), D.createElement('div')];
  106.  
  107.     temp[0].className = 'zM-loading-outer';
  108.     zM.el.container.appendChild(temp[0]);
  109.  
  110.     temp[1].className = 'zM-loading-title';
  111.     temp[0].appendChild(temp[1]);
  112.     temp[1].textContent = 'Loading...'
  113.  
  114.     temp[2].className = 'zM-loading-bar-outer';
  115.     temp[0].appendChild(temp[2]);
  116.        
  117.     temp[3].className = 'zM-loading-bar-fill';
  118.     temp[2].appendChild(temp[3]);
  119.  
  120.     zM.el.loadingOuter = temp.shift();
  121.     zM.el.loadingTitle = temp.shift();
  122.     zM.el.loadingBarFill = temp.pop();
  123.  
  124.     // loading bar API
  125.     zM.setLoadingWidth = function(width = 50) {
  126.         zM.el.loadingBarFill.style.width = 'calc(' + width + '%' + ' - 10px)';
  127.     }
  128.  
  129.     zM.showLoading = function() {
  130.         zM.el.loadingOuter.style.display = 'block';
  131.         D.getElementsByTagName('title')[0].textContent = 'Loading...';
  132.     }
  133.  
  134.     zM.hideLoading = function() {
  135.         zM.el.loadingOuter.style.display = 'none';
  136.         D.getElementsByTagName('title')[0].textContent = 'zM / No fleets yet';
  137.     }
  138.  
  139.     zM.setLoadingTitle = function(title) {
  140.         zM.el.loadingTitle.textContent = title;
  141.     }
  142.  
  143.     zM.clickQueue = 0;
  144.  
  145.     zM.updateTabs = function() { // updates fleet tabs
  146.         zM.el.fleetTopbarOuter.innerHTML = '';
  147.         zM.el.fleetTopbarContainer.innerHTML = '';
  148.         zM.el.fleetTopbarOuter.appendChild(zM.el.fleetTopbarContainer);
  149.         zM.el.fleetTopbarOuter.appendChild(zM.el.fleetTopbarAdd);
  150.         zM.el.fleetTopbarAdd.appendChild(zM.el.fleetTopbarAddImg);
  151.         zM.el.fleetTopbarOuter.appendChild(zM.el.fleetTopbarHint);
  152.  
  153.         for (var i = 0; i < zM.fleet.length; ++i) {
  154.             var f = zM.fleet[i];
  155.             zM.fleet[i].el.container.style.display = 'none';
  156.             zM.el.fleetTopbarContainer.innerHTML += `<div style="position: absolute;    top: 0px;    left: ${100/zM.fleet.length*i}%;    width: ${100/zM.fleet.length}%;    height: 35px;    border-right: 1px solid #fffc;    background-color: ${i === zM.fSel ? '#fff3' : '#fff0'};transition: 0.3s;"><div style="position: absolute;    top: 0px;    left: 0px;    width: 100%;    height: 35px;    background-color: #0000;    transition: 0.3s;" onmouseenter="this.style.backgroundColor = '#0003';" onmouseout="this.style.backgroundColor = '#0000'" onclick="zM.fSel = ${i}; zM.updateTabs()"><div style="color:#fffc;font-family:\'Nova Flat\',Montserrat,sans-serif;font-weight:300;padding:8px;pointer-events:none;white-space:nowrap;overflow-x:hidden;user-select:none;">${zM.fSel === i ? '(Selected)' : ''} #${i} / (${f.botsOpened}/${f.maxBots}) / ${f.name}</div></div></div>`;
  157.         }
  158.  
  159.         zM.fleet[zM.fSel].updateTabs();
  160.     }
  161.  
  162.     zM.createFleet = function(ip, port, ipv6, startbots, maxbots, name) {
  163.         var nF;
  164.         var temp2 = function() {
  165.             clearInterval(temp[2]);
  166.             clearInterval(temp[3]);
  167.             clearInterval(temp[4]);
  168.             zM.setLoadingWidth(0);
  169.             zM.setLoadingTitle('Server isn\'t a valid cursors.io server.');
  170.             nF.bots.forEach(X => X.socket.close());
  171.             setTimeout(zM.hideLoading, 2000);
  172.         };
  173.         var temp = [
  174.             setInterval(() => {
  175.                 if (!zM.isLoading) clearInterval(temp[0]), zM.isLoading = true, temp[1]();
  176.             }, 50),
  177.  
  178.             function() {
  179.                 zM.el.fleetTopbarHint.style.display = 'none';
  180.                 zM.el.fleetPromptOuter.style.display = 'none';
  181.                 zM.setLoadingWidth(0);
  182.                 zM.setLoadingTitle('Creating fleet object...');
  183.                 zM.showLoading();
  184.  
  185.                
  186.  
  187.                 nF = new zM.Fleet(ip, port, ipv6, startbots, maxbots, name);
  188.  
  189.                 zM.fSel = zM.fleet.push(nF) - 1;
  190.                
  191.                 nF.createGUI(zM.el.container)
  192.                 temp[2] = setInterval(() => {
  193.                     zM.setLoadingTitle('Connecting bots ('+nF.botsOpened+'/'+startbots+')');
  194.                     zM.setLoadingWidth(100/startbots*nF.botsPinged);
  195.                     if (nF.verified === false) temp2();
  196.                     else if (startbots <= nF.botsPinged) {
  197.                         clearInterval(temp[2]);
  198.                         setTimeout(async ()=>{
  199.                             zM.isLoading = false;
  200.                             zM.hideLoading(),
  201.                             zM.updateTabs(),
  202.                             zM.el.game.style.display = 'block';
  203.                             await zM.asyncWaitUntil('!(Date.now() % 50)');
  204.                             nF.startTickLoop();
  205.                         }, 800);
  206.                     }
  207.                 }, 50);
  208.             }
  209.         ]
  210.     }
  211.  
  212.     // get IP
  213.     if (window.m28n) {
  214.         m28n.findServerPreference('cursors', (err, end  ) => {
  215.             if (err) {
  216.                 console.error(err);
  217.             } else {
  218.                 zM.game.m28nCursorsIP = (end.ipv4 || ('[' + end.ipv6 + ']')) + ':2828';
  219.             }
  220.         });
  221.     }
  222.  
  223.  
  224.  
  225.  
  226.  
  227.  
  228.  
  229.     zM.clog = [
  230.  
  231.         //
  232.         //
  233.         // Beta v0.2
  234.         //
  235.         // VVVVVVVVV
  236.  
  237.         {
  238.             type: 'title',
  239.             msg: 'Beta v0.2'
  240.         },
  241.         {
  242.             type: 'desc',
  243.             msg: 'I added several new improvements, mostly to the GUI, a full list is below:<br><br>'
  244.         },
  245.         {
  246.             type: 'desc',
  247.             msg: '• Added a changelog and a little information thingy at the bottom right. I plan to make it contain more information soon'
  248.         },
  249.         {
  250.             type: 'desc',
  251.             msg: '• Cursor movements are now synchronized, they should no longer split up'
  252.         },
  253.         {
  254.             type: 'desc',
  255.             msg: '• Script now loads the Nova Flat font used'
  256.         },
  257.     ];
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.     //dependencies.forEach(i => zM.el.container.appendChild(temp = D.createElement('script'), temp.src = 'http://pastebin.com/raw/'+i, temp));
  265.     dependencies.forEach(eval);
  266.  
  267.     zM.setLoadingWidth(0);
  268.     zM.showLoading();
  269.     zM.setLoadingTitle('Loading dependencies...');
  270.     temp = setInterval(() => {
  271.         if (zM.dependenciesLoaded == 0b111111) {
  272.             zM.setLoadingWidth(100);
  273.             clearInterval(temp);
  274.             elements.forEach(i => i(zM.el.container));
  275.             head.getElementsByTagName('title')[0].textContent = 'zM / No fleets yet' // run all element functions
  276.             setTimeout(zM.hideLoading,800);
  277.         } else {
  278.             var done = 0;
  279.             for (var i = 0; i < temp.length; ++i) {
  280.                 done += (zM.dependenciesLoaded & 2**i) ? 1 : 0;
  281.             }
  282.             zM.setLoadingWidth((100 / 16 * done) | 0);
  283.         }
  284.     }, 50);
  285.  
  286.     init();
  287. })(
  288.     function() { // add <style>
  289.         var out = [];
  290.         var temp = [ // fleet topbar
  291.             '.zM-' + 'fleet-topbar-outer {',
  292.             '   position: fixed;    top: 0px;    left: 0px;',
  293.             '   width: 100vw;    height: 35px;',
  294.             '   background-color: rgba(0,0,0,.2);',
  295.             '}',
  296.             '',
  297.             '.zM-' + 'fleet-topbar-container {',
  298.             '   position: fixed;    top: 0px;    left: 0px;',
  299.             '   width: calc(100vw - 45px);    height: 35px;',
  300.             '}',
  301.             '',
  302.             '.zM-' + 'fleet-topbar-tab {',
  303.             '   display: inline-block;',
  304.             '}',
  305.             '',
  306.             '.zM-' + 'fleet-topbar-add {',
  307.             '   position: fixed;    top: 0px;    right: 0px;',
  308.             '   width: 45px;    height: 35px;',
  309.             '   background-color: rgba(0,0,0,.0);',
  310.             '   transition: 0.3s;',
  311.             '   cursor: pointer;    user-select: none;',
  312.             '}',
  313.             '',
  314.             '.zM-' + 'fleet-topbar-add:hover {',
  315.             '   background-color: rgba(0,0,0,.2)',
  316.             '}',
  317.             '',
  318.             '.zM-' + 'fleet-topbar-hint {',
  319.             '   color: rgba(255, 255, 255, .3);',
  320.             '   text-align: right;    font-family: Montserrat, sans-serif;',
  321.             '   font-weight: 200;    font-size: 14px;',
  322.             '   padding-right: 55px;',
  323.             '   padding-top: 8px;    user-select: none;',
  324.             D.createElement('style')
  325.         ];
  326.         // adds style element to "out"
  327.         out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
  328.  
  329.         // --------------------------------------------------------
  330.  
  331.         var temp = [ // fleet prompt
  332.             '.zM-' + 'fleet-prompt-outer {',
  333.             '   position: fixed;    top: 85px;    left: 50px;',
  334.             '   width: calc( 100vw - 100px );    height: calc( 100vh - 135px );',
  335.             '   background-color: #0003;   display: none;    border-radius: 20px;    z-index: 5000;',
  336.             '}',
  337.             '',
  338.             '.zM-' + 'fleet-prompt-container {',
  339.             '   position: fixed;    top: 85px;    left: calc( 50vw - 300px );',
  340.             '   width: 600px; height: calc( 100vh - 135px );',
  341.             '}',
  342.             '',
  343.             '.zM-' + 'fleet-prompt-title {',
  344.             '   text-align: center;    font-family: \'Nova Flat\', Montserrat, sans-serif;    font-weight: 300;',
  345.             '   color: rgba(255, 255, 255, .8);    font-size: 24px;    padding-top: 10px;    user-select: none;',
  346.             '}',
  347.             '',
  348.             '.zM-' + 'fleet-prompt-entry {',
  349.             '   width: 580px;    height: 50px;    ',
  350.             '   background-color: rgba(0, 0, 0, .1);',
  351.             '   border-radius: 10px;',
  352.             '   margin-left: 10px;    margin-top: 10px;',
  353.             '}',
  354.             '',
  355.             '.zM-' + 'fleet-prompt-opt {',
  356.             '   text-align: right;    color: rgba(255, 255, 255, .5);    font-family: \'Nova Flat\', Montserrat, sans-serif;',
  357.             '   font-weight: 300;    font-size: 14px;',
  358.             '   padding-right: 20px;    padding-top: 16px;    width: 280px;    display: inline-block;    user-select: none;',
  359.             '}',
  360.             '',
  361.             '.zM-' + 'fleet-prompt-create {',
  362.                 'position: absolute;    bottom: 10px;    left: 95px;',
  363.                 'width: 200px;    height: 20px;',
  364.                 'background-color: #0c6;    font-family: \'Nova Flat\', Montserrat, sans-serif;',
  365.                 'font-size: 16px;    font-weight: 300;    color: #0008;    text-align: center;',
  366.                 'border-top-left-radius: 10px;    border-bottom-left-radius: 10px;    user-select: none;    cursor: pointer;',
  367.             '}',
  368.             '',
  369.             '.zM-' + 'fleet-prompt-cancel {',
  370.                 'position: absolute;    bottom: 10px;    left: 305px;',
  371.                 'width: 200px;    height: 20px;',
  372.                 'background-color: #666;    font-family: \'Nova Flat\', Montserrat, sans-serif;',
  373.                 'font-size: 16px;    font-weight: 300;    color: #0008;    text-align: center;',
  374.                 'border-top-right-radius: 10px;    border-bottom-right-radius: 10px;    user-select: none;    cursor: pointer;',
  375.             '}',
  376.             D.createElement('style')
  377.         ];
  378.         // adds style element to "out"
  379.         out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
  380.  
  381.         // --------------------------------------------------------
  382.  
  383.         var temp = [ // loading bar stuff
  384.             '.zM-' + 'loading-outer {',
  385.                 'position: fixed;    top: 0px;    left: 0px;',
  386.                 'width: 100vw;    height: 100vh;    background: linear-gradient(45deg, rgba(33,33,33,1) 0%, rgba(66,66,66,1) 100%);',
  387.                 'z-index: 50000;    display: none;',
  388.             '}',
  389.             '',
  390.             '.zM-' + 'loading-title {',
  391.                 'position: fixed;    top: calc(50vh - 32px);    left: 50vw;',
  392.                 'color: #fffb;    font-family: Montserrat, sans-serif;    font-weight: 300;    font-size: 24px;',
  393.                 'transform: translateX(-50%);    z-index: 50001;    user-select: none;',
  394.             '}',
  395.             '',
  396.             '.zM-' + 'loading-bar-outer {',
  397.                 'position: fixed;    top: 50vh;    left: calc(50vw - 200px);',
  398.                 'width: 400px;    height: 30px;    background-color: #0003;    border-radius: 15px;',
  399.             '}',
  400.             '',
  401.             '.zM-' + 'loading-bar-fill {',
  402.                 'width: 0%;    height: 20px;    background-color: #3c5;    border-radius: 10px;    margin: 5px;    transition: 0.5s;',
  403.             '}',
  404.             D.createElement('style')
  405.         ];
  406.         // adds style element to "out"
  407.         out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
  408.  
  409.         // --------------------------------------------------------
  410.  
  411.         var temp = [ // fleet page
  412.             '.zM-' + 'fleet-gui-container {',
  413.                 'position: fixed;    top: 35px;    left: 0px;    width: 100vw;    height: calc(100vh - 35px);    z-index:1000;',
  414.             '}',
  415.             '',
  416.             '.zM-' + 'fleet-gui-topbarOuter {',
  417.                 'position: fixed;    top: 35px;    left: 0px;    width: 100vw;    height: 35px;    background-color: #0002;    z-index:1001;',
  418.             '}',
  419.             '',
  420.             '.zM-' + 'fleet-gui-topbar {',
  421.                 'position: fixed;    top: 35px;    left: 0px;    width: calc(100vw - 45px);    height: 35px;    z-index:1002;',
  422.             '}',
  423.             '',
  424.             '.zM-' + 'fleet-gui-tabNew {',
  425.                 'position: fixed;    top: 35px;    right: 0px;    width: 45px;    height: 35px;    background-color: #0000;    transition: 0.3s;    z-index:1003;    cursor: pointer;',
  426.             '}',
  427.             '',
  428.             '.zM-' + 'fleet-gui-tabNew:hover {',
  429.             '   background-color: rgba(0,0,0,.2)',
  430.             '}',
  431.             '',
  432.             '.zM-' + 'fleet-gui-tabNewImg {',
  433.                 'position: fixed;    top: 35px;    right: 0px;    width: 45px;    height: 35px;    pointer-events: none;    z-index:1004;    user-select:none;',
  434.             '}',
  435.             D.createElement('style')
  436.         ];
  437.         // adds style element to "out"
  438.         out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
  439.  
  440.         // --------------------------------------------------------
  441.  
  442.         var temp = [ // news page
  443.             '.zM-' + 'news-outer {',
  444.                 'position: fixed;    top: 35px;    left: 0px;    width: 100vw;    height: calc(100vh - 35px);    z-index: 9000;',
  445.             '}',
  446.             '',
  447.             '.zM-' + 'news-container {',
  448.                 'position: absolute;    top: calc(50vh - 190px);    left: calc(50vw - 500px);    width: 1000px;    height: 380px;    z-index 9001;',
  449.             '}',
  450.             '',
  451.             '.zM-' + 'news-page-top {',
  452.                 'z-index: 9002;',
  453.                 'width: 1000px; margin-left: 0px; margin-bottom: 10px;    height: 120px;    background-color: #0003;    border-top-left-radius: 75px;    border-top-right-radius: 75px;',
  454.             '}',
  455.             '',
  456.             '.zM-' + 'news-page-mid {',
  457.                 'z-index: 9002;',
  458.                 'width: 1000px; margin-left: 0px; margin-bottom: 10px;    height: 120px;    background-color: #0003',
  459.             '}',
  460.             '',
  461.             '.zM-' + 'news-page-bottom {',
  462.                 'z-index: 9002;',
  463.                 'width: 1000px; margin-left: 0px; margin-bottom: 10px;    height: 120px;    background-color: #0003;    border-bottom-left-radius: 75px;    border-bottom-right-radius: 75px;',
  464.             '}',
  465.             '',
  466.             D.createElement('style')
  467.         ];
  468.         // adds style element to "out"
  469.         out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
  470.  
  471.         // --------------------------------------------------------
  472.  
  473.         var temp = [ // game
  474.             '.zM-' + 'game {',
  475.                 'position: fixed;    top: 80px;    left: 10px;    width: 800px;    height: 600px;    background-color: #fff;    z-index: 9000;    display: none;    cursor: none;',
  476.             '}',
  477.             D.createElement('style')
  478.         ];
  479.         // adds style element to "out"
  480.         out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
  481.  
  482.         // --------------------------------------------------------
  483.  
  484.         var temp = [ // bottom-right info area
  485.             '.zM-' + 'info-outer {',
  486.                 'position: fixed; bottom: 10px; right: 10px; width: 200px; height: 40px; background-color: #0003; border-radius: 20px; z-index: 20000;',
  487.             '}',
  488.             '',
  489.             '.zM-' + 'info-ver {',
  490.                 'position: absolute; top: 10px; left: 10px; font-family: Montserrat, sans-serif; color: #fff8; user-select: none; z-index: 20001;',
  491.             '}',
  492.             '',
  493.             '.zM-' + 'info-clog-button-outer {',
  494.                 'position: absolute; top: 5px; right: 5px; width: 120px; height: 30px; background-color: #0003; user-select: none; z-index: 20002; border-radius: 15px; cursor: pointer;',
  495.             '}',
  496.             '',
  497.             '.zM-' + 'info-clog-button {',
  498.                 'position: absolute; top: 8px; left: 12px; font-size: 12px; color: #fff8; user-select: none; z-index: 20003; pointer-events: none; font-family: Montserrat;',
  499.             '}',
  500.             D.createElement('style')
  501.         ];
  502.         // adds style element to "out"
  503.         out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
  504.  
  505.         // --------------------------------------------------------
  506.  
  507.         var temp = [ // changelog area
  508.             '.zM-' + 'clog-outer {',
  509.                 'position: fixed; top: 0px; left: 0px; width: 100vw; height: 100vh; background:linear-gradient(45deg, rgba(33,33,33,1) 0%, rgba(66,66,66,1) 100%); z-index: 15000; display: none;',
  510.             '}',
  511.             '',
  512.             '.zM-' + 'clog-container {',
  513.                 'position: fixed; top: 50px; left: calc(50vw - 400px); width: 800px; height: calc(100vh - 100px); background-color: #0003; border-radius: 50px; z-index: 15001;',
  514.             '}',
  515.             '',
  516.             '.zM-' + 'clog-title {',
  517.                 'color: #fffc; font-family: Montserrat; font-weight: 300; font-size: 36px; z-index: 15002; margin-bottom: 20px; margin-left: 30px; margin-top: 30px; user-select: none;',
  518.             '}',
  519.             '',
  520.             '.zM-' + 'clog-desc {',
  521.                 'color: #fff8; font-family: Montserrat; font-weight: 400; font-size: 14px; z-index: 15002; margin-bottom: 10px; margin-left: 30px; user-select: none;',
  522.             '}',
  523.             '',
  524.             '.zM-' + 'clog-close {',
  525.                 'position: fixed; top: 0px; right: 0px; width: 45px; height: 35px; cursor: pointer; user-select: none;',
  526.             '}',
  527.             '',
  528.             D.createElement('style')
  529.         ];
  530.         // adds style element to "out"
  531.         out[out.push(temp.pop()) - 1].innerHTML = temp.join('\n');
  532.  
  533.         for (var i = 0; i < out.length; ++i) head.appendChild(out[i]);
  534.         return out;
  535.     },
  536.     function() { // initialize, start different tasks
  537.         zM.promptFleet = function() {
  538.             if (isNaN(zM.fSel)) {
  539.                 zM.el.newsOuter.style.display = 'none';
  540.             } else {
  541.                 var temp = parseInt(zM.fSel);
  542.                 var f = zM.fleet[temp];
  543.                 if (f) {
  544.                     f.el.container.style.display = 'none';
  545.                 }
  546.             }
  547.             zM.el.game.style.display = 'none';
  548.             zM.el.fleetPromptOuter.style.display = 'block';
  549.         }
  550.  
  551.         zM.zWs = new WebSocket('ws://localhost:2882');
  552.        
  553.     },
  554.     (function(cfg) { // loads configuration
  555.         function createConfig(x) { // "x" is a pointer to the variable to change
  556.  
  557.             if (!x.keybinds) {
  558.                 x.keybinds = []
  559.             }
  560.  
  561.             return x;
  562.         }
  563.         function saveConfig(x) {
  564.             try {
  565.                 var out = JSON.stringify(x);
  566.                 localStorage.setItem('zM', btoa(out));
  567.  
  568.                 return true;
  569.             } catch(err) {
  570.                 switch (true) {
  571.                     case err instanceof TypeError: {
  572.                         console.error('[CFG Loader] Error with saving the configuration');
  573.                     }
  574.  
  575.  
  576.                     default: { // other unhandled errors
  577.                         console.error('[CFG Loader] Error with loading the configuration: Unhandled error occured');
  578.                     }
  579.                 }
  580.  
  581.                 console.debug(err);
  582.  
  583.                 return false;
  584.             }
  585.         }
  586.         function getConfig(x) {
  587.             try {
  588.                 var out = localStorage.getItem('zM'); // null
  589.                 if (!out) throw 'Undefined storage';
  590.                 out = atob(out); // DOMException errors
  591.                 out = JSON.parse(out); // SyntaxErrors
  592.                 if (x) x = out;
  593.                 return out;
  594.             } catch(err) {
  595.                 switch (true) {
  596.                     case err instanceof DOMException: { // atob error, invalid configuration
  597.                         console.error('[CFG Loader] Error with loading the configuration: Configuration was incorrectly saved');
  598.                     } break;
  599.  
  600.  
  601.                     case err instanceof SyntaxError: { // JSON errors return syntax errors for some reason
  602.                         console.error('[CFG Loader] Error with loading the configuration: Configuration is not an object');
  603.                     } break;
  604.                     default: { // other unhandled errors
  605.                         console.error('[CFG Loader] Error with loading the configuration: Unhandled error occured');
  606.                     }
  607.                 }
  608.  
  609.                 console.debug(err);
  610.  
  611.                 if (x) x = {};
  612.                 return null;
  613.             }
  614.         }
  615.         if (cfg === null) { // if the localstorage has been erased or script has never been used before
  616.             cfg = {};
  617.             createConfig(cfg);
  618.         } else {
  619.             try {
  620.                 cfg = getConfig(cfg);
  621.                 if (!cfg) saveConfig((createConfig(cfg), cfg));
  622.             } catch(err) {
  623.                 switch (true) {
  624.                     case err instanceof DOMException: { // atob error, invalid configuration
  625.                         console.error('[CFG Loader] Error with loading the configuration: Configuration was incorrectly saved');
  626.                     } break;
  627.  
  628.  
  629.                     case err instanceof SyntaxError: { // JSON errors return syntax errors for some reason
  630.                         console.error('[CFG Loader] Error with loading the configuration: Configuration is not an object');
  631.                     } break;
  632.                     default: { // other unhandled errors
  633.                         console.error('[CFG Loader] Error with loading the configuration: Unhandled error occured');
  634.                     }
  635.                 }
  636.  
  637.                 console.debug(err);
  638.  
  639.                 // technically these functions don't need to be placed in each other, they use pointers anyway
  640.                 cfg = {};
  641.                 saveConfig(createConfig(cfg));
  642.             }
  643.         }
  644.  
  645.         return {
  646.             raw: cfg,
  647.             getConfig: getConfig,
  648.             saveConfig: saveConfig,
  649.             createConfig: createConfig
  650.         }
  651.     })(localStorage.getItem('zM')),
  652.  
  653.     // ---
  654.     // list of dependencies (pastebin) below
  655.     // edit as of oct. 13, 2020: pastebin now uses CORS and doesn't allow requests, so the scripts are now embedded here instead
  656.     // ---
  657.     [
  658.         /* zM external images */
  659.         `zM.dependenciesLoaded |= 0b000001;
  660.  
  661.         window.zMIMG = {
  662.             add: {img:null,uri:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAjCAYAAAAAEIPqAAAAc0lEQVRYR+2VSQoAIAwDzf8fXRE8FqF1ozCetYQxSdUKHhXU3BD96tcgDekFAeyBPX7aw8xM0lEbHh3mwUH0pAJp7EF7OARGQ2QXS6YOCSJBJIjBxLHGWeNBy+xev97TuwK994i+QRXSr6hCGtJBAiUrrwPx1zwkY3UoxAAAAABJRU5ErkJggg=="},
  663.             close: {img:null,uri:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAC0AAAAjCAYAAAAAEIPqAAAAu0lEQVRYR+2VUQrAIAxD7f0P7fBDGLLZtKSCkP0a18czbtYufOxC5iboU6cm0zK9MaB6qB6qx6kOVJvuvXczgy91NL/yw4M8wSgImtvNo0GPIR6Qt+6JmetU6B04C3jMoEN/gTOBy6Df4GzgUmik42iHy74e64un4WtMr6BscPpF/ANkglOhPTBvHe04DRoFQnPlf8QoSDR/7OuBHnUmR6tHZnh2j6Cz5qL7ZDpqLJuX6ay56D6ZjhrL5h8i/mQkg2UCqwAAAABJRU5ErkJggg=="},
  664.             cursor: {img:null,uri:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAAACXBIWXMAAAsTAAALEwEAmpwYAAAKT2lDQ1BQaG90b3Nob3AgSUNDIHByb2ZpbGUAAHjanVNnVFPpFj333vRCS4iAlEtvUhUIIFJCi4AUkSYqIQkQSoghodkVUcERRUUEG8igiAOOjoCMFVEsDIoK2AfkIaKOg6OIisr74Xuja9a89+bN/rXXPues852zzwfACAyWSDNRNYAMqUIeEeCDx8TG4eQuQIEKJHAAEAizZCFz/SMBAPh+PDwrIsAHvgABeNMLCADATZvAMByH/w/qQplcAYCEAcB0kThLCIAUAEB6jkKmAEBGAYCdmCZTAKAEAGDLY2LjAFAtAGAnf+bTAICd+Jl7AQBblCEVAaCRACATZYhEAGg7AKzPVopFAFgwABRmS8Q5ANgtADBJV2ZIALC3AMDOEAuyAAgMADBRiIUpAAR7AGDIIyN4AISZABRG8lc88SuuEOcqAAB4mbI8uSQ5RYFbCC1xB1dXLh4ozkkXKxQ2YQJhmkAuwnmZGTKBNA/g88wAAKCRFRHgg/P9eM4Ors7ONo62Dl8t6r8G/yJiYuP+5c+rcEAAAOF0ftH+LC+zGoA7BoBt/qIl7gRoXgugdfeLZrIPQLUAoOnaV/Nw+H48PEWhkLnZ2eXk5NhKxEJbYcpXff5nwl/AV/1s+X48/Pf14L7iJIEyXYFHBPjgwsz0TKUcz5IJhGLc5o9H/LcL//wd0yLESWK5WCoU41EScY5EmozzMqUiiUKSKcUl0v9k4t8s+wM+3zUAsGo+AXuRLahdYwP2SycQWHTA4vcAAPK7b8HUKAgDgGiD4c93/+8//UegJQCAZkmScQAAXkQkLlTKsz/HCAAARKCBKrBBG/TBGCzABhzBBdzBC/xgNoRCJMTCQhBCCmSAHHJgKayCQiiGzbAdKmAv1EAdNMBRaIaTcA4uwlW4Dj1wD/phCJ7BKLyBCQRByAgTYSHaiAFiilgjjggXmYX4IcFIBBKLJCDJiBRRIkuRNUgxUopUIFVIHfI9cgI5h1xGupE7yAAygvyGvEcxlIGyUT3UDLVDuag3GoRGogvQZHQxmo8WoJvQcrQaPYw2oefQq2gP2o8+Q8cwwOgYBzPEbDAuxsNCsTgsCZNjy7EirAyrxhqwVqwDu4n1Y8+xdwQSgUXACTYEd0IgYR5BSFhMWE7YSKggHCQ0EdoJNwkDhFHCJyKTqEu0JroR+cQYYjIxh1hILCPWEo8TLxB7iEPENyQSiUMyJ7mQAkmxpFTSEtJG0m5SI+ksqZs0SBojk8naZGuyBzmULCAryIXkneTD5DPkG+Qh8lsKnWJAcaT4U+IoUspqShnlEOU05QZlmDJBVaOaUt2ooVQRNY9aQq2htlKvUYeoEzR1mjnNgxZJS6WtopXTGmgXaPdpr+h0uhHdlR5Ol9BX0svpR+iX6AP0dwwNhhWDx4hnKBmbGAcYZxl3GK+YTKYZ04sZx1QwNzHrmOeZD5lvVVgqtip8FZHKCpVKlSaVGyovVKmqpqreqgtV81XLVI+pXlN9rkZVM1PjqQnUlqtVqp1Q61MbU2epO6iHqmeob1Q/pH5Z/YkGWcNMw09DpFGgsV/jvMYgC2MZs3gsIWsNq4Z1gTXEJrHN2Xx2KruY/R27iz2qqaE5QzNKM1ezUvOUZj8H45hx+Jx0TgnnKKeX836K3hTvKeIpG6Y0TLkxZVxrqpaXllirSKtRq0frvTau7aedpr1Fu1n7gQ5Bx0onXCdHZ4/OBZ3nU9lT3acKpxZNPTr1ri6qa6UbobtEd79up+6Ynr5egJ5Mb6feeb3n+hx9L/1U/W36p/VHDFgGswwkBtsMzhg8xTVxbzwdL8fb8VFDXcNAQ6VhlWGX4YSRudE8o9VGjUYPjGnGXOMk423GbcajJgYmISZLTepN7ppSTbmmKaY7TDtMx83MzaLN1pk1mz0x1zLnm+eb15vft2BaeFostqi2uGVJsuRaplnutrxuhVo5WaVYVVpds0atna0l1rutu6cRp7lOk06rntZnw7Dxtsm2qbcZsOXYBtuutm22fWFnYhdnt8Wuw+6TvZN9un2N/T0HDYfZDqsdWh1+c7RyFDpWOt6azpzuP33F9JbpL2dYzxDP2DPjthPLKcRpnVOb00dnF2e5c4PziIuJS4LLLpc+Lpsbxt3IveRKdPVxXeF60vWdm7Obwu2o26/uNu5p7ofcn8w0nymeWTNz0MPIQ+BR5dE/C5+VMGvfrH5PQ0+BZ7XnIy9jL5FXrdewt6V3qvdh7xc+9j5yn+M+4zw33jLeWV/MN8C3yLfLT8Nvnl+F30N/I/9k/3r/0QCngCUBZwOJgUGBWwL7+Hp8Ib+OPzrbZfay2e1BjKC5QRVBj4KtguXBrSFoyOyQrSH355jOkc5pDoVQfujW0Adh5mGLw34MJ4WHhVeGP45wiFga0TGXNXfR3ENz30T6RJZE3ptnMU85ry1KNSo+qi5qPNo3ujS6P8YuZlnM1VidWElsSxw5LiquNm5svt/87fOH4p3iC+N7F5gvyF1weaHOwvSFpxapLhIsOpZATIhOOJTwQRAqqBaMJfITdyWOCnnCHcJnIi/RNtGI2ENcKh5O8kgqTXqS7JG8NXkkxTOlLOW5hCepkLxMDUzdmzqeFpp2IG0yPTq9MYOSkZBxQqohTZO2Z+pn5mZ2y6xlhbL+xW6Lty8elQfJa7OQrAVZLQq2QqboVFoo1yoHsmdlV2a/zYnKOZarnivN7cyzytuQN5zvn//tEsIS4ZK2pYZLVy0dWOa9rGo5sjxxedsK4xUFK4ZWBqw8uIq2Km3VT6vtV5eufr0mek1rgV7ByoLBtQFr6wtVCuWFfevc1+1dT1gvWd+1YfqGnRs+FYmKrhTbF5cVf9go3HjlG4dvyr+Z3JS0qavEuWTPZtJm6ebeLZ5bDpaql+aXDm4N2dq0Dd9WtO319kXbL5fNKNu7g7ZDuaO/PLi8ZafJzs07P1SkVPRU+lQ27tLdtWHX+G7R7ht7vPY07NXbW7z3/T7JvttVAVVN1WbVZftJ+7P3P66Jqun4lvttXa1ObXHtxwPSA/0HIw6217nU1R3SPVRSj9Yr60cOxx++/p3vdy0NNg1VjZzG4iNwRHnk6fcJ3/ceDTradox7rOEH0x92HWcdL2pCmvKaRptTmvtbYlu6T8w+0dbq3nr8R9sfD5w0PFl5SvNUyWna6YLTk2fyz4ydlZ19fi753GDborZ752PO32oPb++6EHTh0kX/i+c7vDvOXPK4dPKy2+UTV7hXmq86X23qdOo8/pPTT8e7nLuarrlca7nuer21e2b36RueN87d9L158Rb/1tWeOT3dvfN6b/fF9/XfFt1+cif9zsu72Xcn7q28T7xf9EDtQdlD3YfVP1v+3Njv3H9qwHeg89HcR/cGhYPP/pH1jw9DBY+Zj8uGDYbrnjg+OTniP3L96fynQ89kzyaeF/6i/suuFxYvfvjV69fO0ZjRoZfyl5O/bXyl/erA6xmv28bCxh6+yXgzMV70VvvtwXfcdx3vo98PT+R8IH8o/2j5sfVT0Kf7kxmTk/8EA5jz/GMzLdsAAAAgY0hSTQAAeiUAAICDAAD5/wAAgOkAAHUwAADqYAAAOpgAABdvkl/FRgAAAYZJREFUeNq0ls1OxDAMhMdOdhcegztnjpx4/9dYiQsXJLRLa3PAXrlWWpqgjRSljdT5JpO/kqriXoVxx1IBgIhiX3zRf4snUUp9OgqqQcTrBOAYBHUUwMmlv18NcDADHODd4i5ciQi2gj4BnAKkG8Dpudxm8hfwAeBhFMAp8xLXvT2/A3gcATQzbwDOI4C8iSiue1W91RHA6g5VVRDRAtQLWBVPolBViEgX4M+zxSE+ih7AZix5ch2yNyLe4zhM6q3dM4JdR26cWIelERztmCibzpm5GUWspZTFu220kp3XLC4iC3f28RuA2auqzgC+AVxU9QLgy4Q5Ht21FYELMzMAvAIQE5sMINZ6n7SO47q2eSyeF/toAnAxMRf3OiWwrolrWCnPNszZzvcs7peIxMjiBVOTsNjzk4HdtYtPSQAJsoiHLAa2dXqwZXUy13HY1418tdVG53GS1Gbd+xwgyfWuC1qDyxiPBECXcHauQWBu3P5dwtk5QhxbeWLUOVaEhwrd80f0ZwDurOt8AKnDvAAAAABJRU5ErkJggg=="},
  665.             public: {img:null,uri:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAABrElEQVRIS7WWvU7DQBCEZw3hR6KhAImSnpqSiseghzcCet4OBSEh8R8bjb3jrM4kurOTk1Z27OSb3XN21oYtLtsiG//B47VmingE6TwVlECxUATynPELYM8zJjCN7GIivALA+PZfHwGoPRZ+lFCWgOCE7gDYNbP35qEGbttbxwAIZjU/pQIRPgMwM7O3Fs7VCZx6NayoSEBwZk34PoBXPDZ4vgFOnnqBMwAfLpItEOF8iAcAXgRn2lMEUvghgHmETxHIgo8VyIaPESiClwoUw0sERsFzBbLg7d9x1Vo22qf3AbuZXdgM4FVVzev7RdtESYY93szQNJ1JhnNaxVfo4npt5qGBrt1j6DMKdiphDHYvg+e0CX5nmLmZzeUtdlcxwysvkzCWLIfkkdckom1ZDVeHOvjS/ZxQlSy47FiOKaGVe955S7cu3N8JYzYpXN5OEW2VwIMHunRF4JzeHrIWXNsSh0YUaaGKgZ/7iKP1coDwyyqbAn3JyT8znbPt58Ek8oyZNe+p5EmTiCDNUA4OBtdGZqgmfzwSvpHpH7do4+8t8fls5Y1rjTuNu/UHX28RMaWkZ08AAAAASUVORK5CYII='},
  666.             movement: {img:null,uri:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAABr0lEQVRIS7WWzU7CUBCFz1TxJ3HjxsSle9cuXfkowL5Pwh6eEWNiIv5BzYE5dWjF3NuWJpNeSvnOzC1zpoYjHnZENv6Cx2tVH/EI0ropKIFsoQjkmvEN4MwzJrAZycVEeAGA8em/vgKw8Vj7WUJJAoITegLg1MzeNpMJbD4n4BoAwazmK1cgwkcARmb2SjgPF7jxalhRloDgzJrwcwAv1XQKzGZAWUrgFsDKRZIFIpwP8QLAcw1n+j0EmvBLAMs9eA+BNHhHgXR4B4E8eKZAPjxDoBs8USANXpYH2z002rv3AbuZtlG14EVRLNfj8a6J9jOsBcwMVbUzybCmVXyELt78n/lvAz25x9BnFOxUwhjsXgbXtAne087czJbylmKxYIaPXiZhLFkOyTOvSUTbchiuDnXwg/s5oSpZcNmxHFNCB/d86y2+uffu74QxmyZc3k4RbZXArQdauyKAO3p7yFpwbUscGlFkC1W0/NxHHK2XA4Q3q2wK1CU3/pvNObv93JpEnjGz5ncqudckIkgzlIODwWOQGarJH8+EDzL94xYN/t4Sn89R3riS3kVybvoBL+YcMQOUqAIAAAAASUVORK5CYII='},
  667.             local: {img:null,uri:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAABrklEQVRIS7WWvU7DQBCEZw3hR6KhCBIlPTUlFY9BD28E9Hk7ZISExH9sNGbH2dgY3dmJpZUvif3N7jk7a8MWD9siG3/B43f1FPEI0rorKIFsoQjkmvENYM8zJrAbycVEeAGA8el3HwGoPJZ+llCSgOCE7gDYNbPX6r6G3TT3HwMgmNV85QpE+AzAzMxeCOfhAideDSvKEhCcWRO+D+C5fgBw/Qgs5hI4BfDmIskCEc6HeADgqYUz/QkCXfghgHINPkEgDT5SIB0+QiAPnimQD88QGAdPFEiDL+aD7R4a7d37gN1M26h78KIoyuVd9dtE6xm2AmaGuvYuXq1pFR+hi6v/M1810JV7DH1GwU4ljMHuZXBNm+A1/czNrJS3FLdNhpdeJmEsWQ7JM7+TiLZlGK4OdfCF+zmhKllw2bEcU0KDe954i2/uufs7YcymC5e3U0RbJXDvgbauCOCM3h6yFlzbEodGFGmgip6f+4ij9XKA8GKVTYG25M5/sztnm8+9SeQZM2v+ppInTSKCNEM5OBg8NjJDNfnjmfCNTP+4RRt/b4nPZytvXEnvIjkX/QBfbxExMnV8VAAAAABJRU5ErkJggg=='},
  668.             follow: {img:null,uri:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAABwklEQVRIS7WWS07DQBBEawzhE7FBgkgs2bMBJJasWHAQYM9JWAcukkvAPfgEISGFf4zK6YpaY4xm4sRSy5PEedU9dlc7YIFHWCAbf8H9d2UbcQ/SOhaUQLaQB3LN+AawYhkTGEdyMR5eAGB82r83AIwtfuwsoSQBwQldArAcQhidPxzgevuWgE0ABLOar1wBD+8A6IQQXgnnYQI9q4YVZQkIzqwJXwXwcvF4iKutAS6fTiWwA+DNRJIFPJw3cQ3As+DMvo1ADF8HMPTwNgJJ8FkFkuGzCGTBcwWy4TkCM8FTBRrh/e4Ao+6ky/k4Nh2u0d6tD9jNtI2yBi+KYnh2v181UZThlB9CQFlOTNKtaRUfrovH/26La6AT8xj6jIKdShiD3cvgmjbBa+qZhxCG8pab3h0zPLYyCWPJckie+Z1EtC3NcHWogY/MzwlVyYLLjuWYEmrc88pbbHP3zN8JYzYxXN5OEW2VwLUbOnVFALv0dpe14NoWPzS8SAVV1PzcRhytlwOEF6tsCkxLjh7NeM5Wn2uTyDJm1vxNJbeaRARphnJwMHjMZYZq8vsz4XOZ/n6L5v7e4u/PQt64kt5Fci76BTTHKDGf8J1/AAAAAElFTkSuQmCC'},
  669.             admin: {img:null,uri:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAeCAYAAADHJYVoAAAB80lEQVRIS7WWuW7CUBBF7zghi5QmBZFSUlpKaaVMlc+ghvwDNXXKADWf494fgYgiRSIrftF1ZuDhBdkslkbez515z++OBUfc5IhslMH9a24fcR9kx3lBE2gs5AN5zPgFcKYZE5iP2sX48AAA41vfvgKQaix1b0K1BAxO6AmAUxFZpCMH6WfvXwMgmNX8NBXw4S0ALRF5J5ybCtxoNayokYDBmTXh5wDe3BhAdwZM2yZwC+BDRWoL+HBO4gWA1xWc6e8hkIdfApi7uAeEw/WkJQNINOF5owrqwYndQWAL/BnAYvOTayhQCo/jGGEYln7LSZIgiqJaQ1QK78UOw3J2JjhIgEmUvbp1DnaC1xWoBWemVZtWwIX2qeuAq5m24QrwIAjm6csSs+4/rj0F0N80ShGBc7qK18e0ii9vFaelmWPsMrgHflSPoc9YcKUSxuDqZfCYNsFnipmLyNyNWBUgTwEzfNAyCWPJ5pDc85qJ2LBUw7lCmbmC79XPCbWSDW52bI5pQpVjnnmLTt6d+jthzCYPN2+niA2VgQsTunJFAB16u5e1wW1Y/Kbhi2RQi4Kfa4uj9bKB8GErmwKrknOfZr7PZueFTqQZM2ves5L36kQEWQ9l42BwO0gPtc7v7wk/SPf3h+jg/y3+/Bzlj6vanXa88we7KRoxQlE4ggAAAABJRU5ErkJggg=='}
  670.         }
  671.        
  672.         for (var i in zMIMG) {
  673.             if (zMIMG.hasOwnProperty(i)) {
  674.                 zMIMG[i].img = new Image();
  675.                 zMIMG[i].img.src = zMIMG[i].uri;
  676.             }
  677.         }`,
  678.         /* zM fleet class */
  679.         `zM.dependenciesLoaded |= 0b000010;
  680.  
  681.         zM.Fleet = class {
  682.             constructor (ip, port, ipv6, maxbots, startbots, name) {
  683.                 console.log(startbots);
  684.                 this.ip = ip;
  685.                 this.port = port;
  686.                 this.maxBots = maxbots;
  687.                 this.startBots = startbots;
  688.                 this.name = name;
  689.                 this.ipv6 = ipv6;
  690.                 this.cSel = 0;
  691.        
  692.                 this.wsIp = 'ws://' + (this.ipv6?'['+this.ip+']':this.ip) + ':' + this.port;
  693.        
  694.                 this.bots = [];
  695.        
  696.                 this.ids = [];
  697.        
  698.                 this.botsPinged = 0;
  699.                 this.botsOpened = 0;
  700.                 this.botsIds = 0;
  701.                 this.botsLevels = 0;
  702.                 this.botsBusy = 0;
  703.                 this.botsDeployed = 0;
  704.                 this.botsUpdated = 0;
  705.                 this.verified = true;
  706.        
  707.                 this.isHelping = false;
  708.        
  709.                 this.el = {};
  710.        
  711.                 this.helpers = [];
  712.        
  713.                 var extF = this;
  714.        
  715.                 this.helpIndex = 0;
  716.        
  717.                 this.helpLoop = setInterval(()=>{
  718.                     ++this.helpIndex;
  719.                     if (this.isHelping && this.helpers.length > 0) {
  720.                         for (var i = 0; i < this.helpers.length; ++i) {
  721.                             this.helpers[i].toHelp = [];
  722.                             this.helpers[i].helping = true;
  723.                             if (this.helpers[i].socket.readyState != 1) this.helpers.splice(i--, 1);
  724.                         }
  725.                         var todo = [];
  726.                         var obj = this.bots[this.cSel].obj;
  727.                         for (var i = 0; i < obj.length; ++i) {
  728.                             if (obj[i].type === 4) todo.push(obj[i]);
  729.                         }
  730.                         var amount = todo.length / this.helpers.length;
  731.                         var j = 0;
  732.                         var count = amount;
  733.                         for (var i = 0; i < this.helpers.length; ++i) {
  734.                             for (; j < count | 0; ++j) {
  735.                                 var obj = todo[j];
  736.                                 var moves = zM.path(this.helpers[i].realX, this.helpers[i].realY, obj.x + (obj.w>>1), obj.y + (obj.h>>1), this.helpers[i].obj, this.helpers[i].grid);
  737.                                 if ((this.helpers[i].realX === obj.x + (obj.w>>1) && this.helpers[i].realY === obj.y + (obj.h>>1)) ? true : moves.length > 1) this.helpers[i].toHelp.push(todo[j]);
  738.                             }
  739.                             count += amount;
  740.                         }
  741.                         var f = this;
  742.                         if (this.isHelping) for (var j = 0; j < this.helpers.length; ++j) {
  743.                             var index = this.helpIndex % this.helpers[j].toHelp.length;
  744.                             if (isNaN(index)) index = this.helpIndex % this.helpers[0].toHelp.length; // has nothing to do, copy off other bots
  745.                             if (isNaN(index)) index = 0; // still undefined, no buttons at all
  746.                             console.log(j, this.helpers[j]);
  747.                             console.log(index, this.helpers[j].toHelp[index]);
  748.                             if (this.helpers[j].toHelp.length <= index) continue;
  749.                             var moves = zM.path(this.helpers[j].realX, this.helpers[j].realY, this.helpers[j].toHelp[index].x + (this.helpers[j].toHelp[index].w>>1), this.helpers[j].toHelp[index].y + (this.helpers[j].toHelp[index].h>>1), this.helpers[j].obj, this.helpers[j].grid);
  750.                             moves.forEach(Y => {
  751.                                 zM.packet.moveSocket([this.helpers[j].socket], Y[0], Y[1], [this.helpers[j]]);
  752.                             });
  753.                             for (var k = 0; k < 10; ++k) zM.packet.clickSocket([this.helpers[j].socket], this.helpers[j].toHelp[index].x + (this.helpers[j].toHelp[index].w>>1), this.helpers[j].toHelp[index].y + (this.helpers[j].toHelp[index].h>>1), [this.helpers[j]])
  754.                         }
  755.                     }
  756.                 },300);
  757.        
  758.                 this.elTemplate = {
  759.                     tab: '<div style="width: '
  760.                 }
  761.        
  762.                 setTimeout(()=>{for (var i = 0; i < startbots; ++i) this.bots.push(new zM.Bot(this));},300);
  763.             }
  764.        
  765.             createGUI(c) {
  766.                 var temp = this.el = {
  767.                     container: D.createElement('div'),
  768.                     topbarOuter: D.createElement('div'),
  769.                     topbar: D.createElement('div'),
  770.                     tabNew: D.createElement('div'),
  771.                     tabNewImg: D.createElement('img')
  772.                 }
  773.        
  774.                 temp.container.className = 'zM-fleet-gui-container';
  775.                 c.appendChild(temp.container);
  776.        
  777.                 temp.topbarOuter.className = 'zM-fleet-gui-topbarOuter';
  778.                 temp.container.appendChild(temp.topbarOuter);
  779.        
  780.                 temp.topbar.className = 'zM-fleet-gui-topbar';
  781.                 temp.topbarOuter.appendChild(temp.topbar);
  782.        
  783.                 temp.tabNew.className = 'zM-fleet-gui-tabNew';
  784.                 temp.topbarOuter.appendChild(temp.tabNew);
  785.        
  786.                 temp.tabNewImg.className = 'zM-fleet-gui-tabNewImg';
  787.                 temp.tabNewImg.src = zMIMG.add.uri;
  788.                 temp.tabNew.appendChild(temp.tabNewImg);
  789.        
  790.                 temp.tabNew.addEventListener('click', ev => {
  791.                     this.bots.push(new zM.Bot(this));
  792.                 });
  793.        
  794.                 this.updateTabs();
  795.             }
  796.        
  797.             updateTabs() {
  798.                 this.el.container.style.display = 'block';
  799.                 this.el.topbar.innerHTML = '';
  800.                 this.el.topbarOuter.appendChild(this.el.tabNew);
  801.                 this.el.tabNew.appendChild(this.el.tabNewImg);
  802.                 var nb = [];
  803.                 for (var i = 0; i < this.bots.length; ++i) {
  804.                     if (this.bots[i].socket.readyState == 1) nb.push(this.bots[i]);
  805.                 }
  806.                 for (var i = 0; i < nb.length; ++i) {
  807.                     var b = nb[i];
  808.                     this.el.topbar.innerHTML += \`<div style="position: absolute;    top: 0px;    left: \${100/nb.length*i}%;    width: \${100/nb.length}%;    height: 35px;    border-right: 1px solid #fffc;    background-color: \${i === this.cSel ? '#fff3' : '#fff0'};transition: 0.3s;"><div style="position: absolute;    top: 0px;    left: 0px;    width: 100%;    height: 35px;    background-color: #0000;    transition: 0.3s;" onmouseenter="this.style.backgroundColor = '#0003';" onmouseout="this.style.backgroundColor = '#0000'" onclick="zM.fleet[zM.fSel].cSel = \${i}; zM.fleet[zM.fSel].updateTabs()"><div style="color:#fffc;font-family:\'Nova Flat\',Montserrat,sans-serif;font-weight:300;padding:8px;pointer-events:none;white-space:nowrap;overflow-x:hidden;user-select:none;">\${eval(\`zM.fleet[zM.fSel].cSel === \${i} ? '(Selected)' : ''\`)} #\${i} / ID \${b.id} / LVL \${b.level}</div></div></div>\`;
  809.                 }
  810.             }
  811.        
  812.             /* depreciated, only solves for selected bot
  813.             startTickLoop() {
  814.                 this.tickLoop = setInterval(()=>{
  815.                     var b = this.bots[this.cSel];
  816.        
  817.                     var toMove = [];
  818.                     for (var i = 0; i < this.bots.length; ++i) {
  819.                         if (this.bots[i].level === b.level) if (zM.useWallhack) toMove.push(this.bots[i].socket);
  820.                     }
  821.        
  822.                     if (zM.useWallhack) {
  823.                         var moves = zM.path(b.realX, b.realY, zM.pos.mouseX>>1, zM.pos.mouseY>>1, b.obj);
  824.                         moves.forEach(Y => {
  825.                             zM.packet.moveSocket(toMove, Y[0], Y[1]);
  826.                         });
  827.                     } else {
  828.                         zM.packet.moveSocket(toMove, zM.pos.mouseX>>1, zM.pos.mouseY>>1);
  829.                     }
  830.        
  831.                     for (;-1<zM.clickQueue;--zM.clickQueue) zM.packet.clickSocket(toMove, zM.pos.mouseX>>1, zM.pos.mouseY>>1);
  832.        
  833.                     if (zM.drawing) zM.packet.drawSocket(toMove, zM.pos.lastMouseX>>1, zM.pos.lastMouseY>>1, zM.pos.mouseX>>1, zM.pos.mouseY>>1);
  834.        
  835.                     zM.pos.lastMouseX = zM.pos.mouseX;
  836.                     zM.pos.lastMouseY = zM.pos.mouseY;
  837.                 }, 50);
  838.             }*/
  839.        
  840.             // alternative, solves for each bot- causes lots of lag without grid
  841.             startTickLoop() {
  842.                 this.tickLoop = setInterval(()=>{
  843.                     for (var i = 0; i < zM.fleet.length; ++i) {
  844.                         if (zM.fleet[i] === this) break;
  845.                     }
  846.                    
  847.                     if (i !== zM.fSel) return;
  848.                     var b = this.bots[this.cSel];
  849.        
  850.                     var toMoveSocket = [];
  851.                     var toMove = [];
  852.                     for (var i = 0; i < this.bots.length; ++i) {
  853.                         // disconnect after 90 min of AFK, should bypass any bans from AFKing
  854.                         if (Date.now() - this.bots[i].packets.lastSent > 5400000) this.bots[i].socket.close();
  855.                         if (
  856.                             this.bots[i].level === b.level &&
  857.                             !this.bots[i].helping && !this.bots[i].deployed
  858.                         ) toMove.push(this.bots[i]), toMoveSocket.push(this.bots[i].socket);
  859.                     }
  860.        
  861.                     if (zM.movement) {
  862.                         if (zM.useWallhack) {
  863.                             // solve first
  864.                             toMove.forEach(X => {
  865.                                 // random here is anti-idle disconnect
  866.                                 if (!(X.realX === zM.pos.mouseX>>1 && X.realY === zM.pos.mouseY>>1) || (Math.random() >= 0.99 && zM.antiIdle)) {
  867.                                     var moves = zM.path(X.realX, X.realY, zM.pos.mouseX>>1, zM.pos.mouseY>>1, b.obj, b.grid);
  868.                                     X.toDo = moves;
  869.                                     X.realX = zM.pos.mouseX>>1;
  870.                                     X.realY = zM.pos.mouseY>>1;
  871.                                 }
  872.                             });
  873.        
  874.                             // then send packets synchronized, all together
  875.                             var count = 0;
  876.                             for (var i = 0; i < toMove.length; ++i) count = Math.max(count, toMove[i].toDo.length);
  877.                             for (var i = 0; i < count; ++i) {
  878.                                 toMove.forEach(X => {
  879.                                     if (i >= X.toDo.length) return;
  880.                                     zM.packet.moveSocket([X.socket], X.toDo[i][0], X.toDo[i][1], [X]);
  881.                                 });
  882.                             }
  883.                         } else {
  884.                             zM.packet.moveSocket(toMoveSocket, zM.pos.mouseX>>1, zM.pos.mouseY>>1, toMove);
  885.                         }
  886.                     } else {
  887.                         if (zM.clickQueue >= 1) {
  888.                             toMove.forEach(X => {
  889.                                 var moves = zM.path(X.realX, X.realY, zM.pos.mouseX>>1, zM.pos.mouseY>>1, b.obj, b.grid);
  890.                                 moves.forEach(Y => {
  891.                                     zM.packet.moveSocket([X.socket], Y[0], Y[1], [X]);
  892.                                 });
  893.                             });
  894.                         }
  895.                         if (zM.antiIdle) {
  896.                             toMove.forEach(X => {
  897.                                 // random here is anti-idle disconnect, if movement is disabled.
  898.                                 if (Date.now() - X.packets.lastSent > 10000) zM.packet.moveSocket([X.socket], X.realX, X.realY, [X]);
  899.                             });
  900.                         }
  901.                     }
  902.        
  903.                     for (;0<zM.clickQueue;--zM.clickQueue) zM.packet.clickSocket(toMoveSocket, zM.pos.mouseX>>1, zM.pos.mouseY>>1, toMove);
  904.                    
  905.                     if (zM.drawing && zM.movement) zM.packet.drawSocket(toMoveSocket, zM.pos.lastMouseX>>1, zM.pos.lastMouseY>>1, zM.pos.mouseX>>1, zM.pos.mouseY>>1, toMove);
  906.        
  907.                     zM.pos.lastMouseX = zM.pos.mouseX;
  908.                     zM.pos.lastMouseY = zM.pos.mouseY;
  909.                 }, 50);
  910.             }
  911.         }`,
  912.         /* zM bot class */
  913.         `zM.dependenciesLoaded |= 0b000100
  914.  
  915.         zM.Bot = class {
  916.             constructor (fleet) {
  917.                 this.fleet = fleet;
  918.        
  919.                 this.socket = new WebSocket(this.fleet.wsIp);
  920.                 this.socket.binaryType = 'arraybuffer';
  921.        
  922.                 this.opened = false;
  923.                 this.isOpen = false;
  924.        
  925.                 this.level = -1;
  926.                 this.id = -1;
  927.        
  928.                 this.obj = [];
  929.                 this.players = [];
  930.                 this.clicks = [];
  931.                 this.drawings = [];
  932.        
  933.                 this.realX = 400;
  934.                 this.realY = 300;
  935.        
  936.                 this.local = 0;
  937.        
  938.                 this.packets = {
  939.                     receivedTotal: 0,
  940.                     sentTotal: 0,
  941.                     receivedPS: 0,
  942.                     sentPS: 0
  943.                 }
  944.        
  945.                 this.toHelp = [];
  946.                 this.toDo = [];
  947.        
  948.                 this.timestampStart = 0;
  949.        
  950.                 this.helping = false;
  951.                 this.deployed = false;
  952.        
  953.                 this.prevLevels = [];
  954.        
  955.                 this.socket.addEventListener('open', () => {
  956.                     ++this.fleet.botsOpened;
  957.                     this.opened = true;
  958.                     this.isOpen = true;
  959.                     ++this.fleet.botsPinged;
  960.                     zM.updateTabs();
  961.                 });
  962.        
  963.                 this.socket.addEventListener('close', () => {
  964.                     if (this.opened) {
  965.                         --this.fleet.botsOpened;
  966.                         var i = this.fleet.ids.indexOf(this.id);
  967.                         if (i != -1) this.fleet.ids.splice(i, 1);
  968.                     }
  969.                     else ++this.fleet.botsPinged;
  970.                     this.isOpen = false;
  971.        
  972.                     for (var i = 0; i < this.fleet.bots.length; ++i) if (this.fleet.bots[i] == this) { console.log('y'); this.fleet.bots.splice(i,1); break; }
  973.        
  974.                     zM.updateTabs();
  975.                 });
  976.        
  977.                 this.socket.addEventListener('message', ev => {
  978.                     var buf = ev.data,
  979.                         dat = new DataView(buf);
  980.        
  981.                     ++this.packets.receivedTotal;
  982.                     ++this.packets.receivedPS;
  983.                     setTimeout(()=>{--this.packets.receivedPS},1000);
  984.        
  985.                     var type = dat.getUint8(0);
  986.                     if (type === 0) this.id = dat.getUint32(1, 1), ++this.fleet.botsIds, this.fleet.ids.push(this.id);
  987.                     else if (type === 1) {
  988.                         var out = zM.parse.cursors(buf, 1);
  989.                         this.local = out.shift();
  990.                         var players = out.shift();
  991.                         var idsHere = [];
  992.                         // create players for all new ids
  993.                         for (var i = 0; i < players.length; ++i) {
  994.                             if (players[i].id === this.id) this.realX = players[i].x, this.realY = players[i].y;
  995.                             var index = -1;
  996.                             for (var j = 0; j < this.players.length; ++j) {
  997.                                 if (this.players[j].id === players[i].id) {index = j; break;}
  998.                             }
  999.                             if (index === -1) this.players.push({
  1000.                                 x: players[i].x,
  1001.                                 y: players[i].y,
  1002.                                 lastUpdate: Date.now(),
  1003.                                 ox: players[i].x,
  1004.                                 oy: players[i].y,
  1005.                                 id: players[i].id
  1006.                             });
  1007.                         }
  1008.                         for (var i = 0; i < players.length; ++i) {
  1009.                             for (var j = 0; j < this.players.length; ++j) {
  1010.                                 if (this.players[j].id === players[i].id) {
  1011.                                     this.players[j].ox = zM.ease(this.players[j].x, this.players[j].ox, this.players[j].lastUpdate);
  1012.                                     this.players[j].oy = zM.ease(this.players[j].y, this.players[j].oy, this.players[j].lastUpdate);
  1013.                                     this.players[j].x = players[i].x;
  1014.                                     this.players[j].y = players[i].y;
  1015.                                     this.players[j].lastUpdate = Date.now();
  1016.                                     idsHere.push(players[i].id);
  1017.                                 }
  1018.                             }
  1019.                         }
  1020.                         var nPl = [];
  1021.                         for (var i = 0; i < idsHere.length; ++i) {
  1022.                             for (var j = 0; j < this.players.length; ++j) {
  1023.                                 if (idsHere[i] === this.players[j].id) nPl.push(this.players[j]);
  1024.                             }
  1025.                         }
  1026.        
  1027.                         this.players = nPl;
  1028.                         var off = out.shift();
  1029.        
  1030.                         out = zM.parse.clicks(buf, off);
  1031.                         for (;0 < out[0].length;) {
  1032.                             this.clicks.push(out[0].shift());
  1033.                         }
  1034.        
  1035.                         off = out.pop();
  1036.        
  1037.                         out = zM.parse.remove(buf, off);
  1038.                         for (var i = 0; i < out[0].length; ++i) {
  1039.                             for (var j = 0; j < this.obj.length; ++j) {
  1040.                                 if (this.obj[j].id === out[0][i]) {this.obj.splice(j, 1); break;}
  1041.                             }
  1042.                         }
  1043.        
  1044.                         off = out.pop();
  1045.        
  1046.                         out = zM.parse.objects(buf, off);
  1047.                         var obj = zM.parse.objData(out.shift());
  1048.        
  1049.                         for (var i = 0; i < obj.length; ++i) {
  1050.                             var index = -1;
  1051.                             for (var j = 0; j < this.obj.length; ++j) {
  1052.                                 if (this.obj[j].id === obj[i].id) {index = j; break;};
  1053.                             }
  1054.                             if (index === -1) this.obj.push(obj[i]);
  1055.                             else this.obj[j] = obj[i];
  1056.                         }
  1057.        
  1058.                         off = out.pop();
  1059.        
  1060.                         out = zM.parse.drawing(buf, off);
  1061.        
  1062.                         for (var i = 0; i < out[0].length; ++i) {
  1063.                             var todo = out[0][i];
  1064.                             this.drawings.push(todo);
  1065.                         }
  1066.        
  1067.                         this.online = dat.getUint32(dat.byteLength-4, true);
  1068.        
  1069.                     } else if (type === 4) {
  1070.                         if (this.level === -1) ++this.fleet.botsLevels;
  1071.        
  1072.                         this.drawings = [];
  1073.        
  1074.                         this.realX = dat.getUint16(1, true);
  1075.                         this.realY = dat.getUint16(3, true);
  1076.        
  1077.                         var objdata = zM.parse.objects(buf, 5);
  1078.                         this.obj = zM.parse.objData(objdata[0]);
  1079.        
  1080.                         var grid = 100;
  1081.                         for (var i = 0; i < this.obj.length; ++i) {
  1082.                             if (grid <= 1) {grid = 1; break;}
  1083.                             if (this.obj[i].type === 1) if (
  1084.                                 (this.obj[i].x/grid|0) != (this.obj[i].x/grid) ||
  1085.                                 (this.obj[i].y/grid|0) != (this.obj[i].y/grid) ||
  1086.                                 (this.obj[i].w/grid|0) != (this.obj[i].w/grid) ||
  1087.                                 (this.obj[i].h/grid|0) != (this.obj[i].h/grid)
  1088.                             ) --grid, i = -1;
  1089.                         }
  1090.        
  1091.                         this.grid = grid;
  1092.        
  1093.                         var compare = [];
  1094.                         for (var i = 0; i < this.obj.length; ++i) {
  1095.                             var o = this.obj[i];
  1096.                             if (o.type === 0) {
  1097.                                 compare.push({
  1098.                                     x: o.x,
  1099.                                     y: o.y,
  1100.                                     size: o.size,
  1101.                                     content: o.content
  1102.                                 });
  1103.                             } else if (o.type === 1) {
  1104.                                 if (o.color === '#000000') compare.push({
  1105.                                     x: o.x,
  1106.                                     y: o.y,
  1107.                                     w: o.w,
  1108.                                     h: o.h
  1109.                                 });
  1110.                             } else if (o.type === 2) {
  1111.                                 compare.push({
  1112.                                     x: o.x,
  1113.                                     y: o.y,
  1114.                                     w: o.w,
  1115.                                     h: o.h,
  1116.                                     isBad: o.isBad
  1117.                                 });
  1118.                             } else {
  1119.                                 compare.push({
  1120.                                     x: o.x,
  1121.                                     y: o.y,
  1122.                                     w: o.w,
  1123.                                     h: o.h,
  1124.                                     color: o.color
  1125.                                 });
  1126.                             }
  1127.                         }
  1128.                         compare = JSON.stringify(compare);
  1129.                         var i = this.prevLevels.indexOf(compare);
  1130.                         if (i != -1) this.level = i;
  1131.                         else ++this.level, this.prevLevels.push(compare);
  1132.        
  1133.                         this.fleet.updateTabs();
  1134.                     } else if (type === 5) {
  1135.                         this.realX = dat.getUint16(1, true);
  1136.                         this.realY = dat.getUint16(3, true);
  1137.                     }
  1138.                 });
  1139.             }
  1140.         }`,
  1141.        
  1142.         `zM.dependenciesLoaded |= 0b001000;
  1143.         let ctx;
  1144.        
  1145.         zM.reqLoad = function() {
  1146.             zM.r = {
  1147.                 fps: 0,
  1148.                 hudText: function(text, x, y, subLength = 0, color = '#fff') {
  1149.                     ctx.font = '12px "Nova Flat"';
  1150.                     ctx.globalAlpha = .5;
  1151.                     ctx.lineWidth = 3;
  1152.                     ctx.strokeStyle = '#000';
  1153.                     ctx.strokeText(text, x-ctx.measureText(text).width*subLength, y);
  1154.        
  1155.                     ctx.globalAlpha = 1;
  1156.                     ctx.fillStyle = color;
  1157.                     ctx.fillText(text, x-ctx.measureText(text).width*subLength, y);
  1158.                 },
  1159.                 infLvl: 5
  1160.             }
  1161.             ctx = zM.el.game.getContext('2d');
  1162.         }
  1163.        
  1164.         zM.reqDo = function() {
  1165.             ctx.clearRect(0, 0, 800, 600);
  1166.        
  1167.             if (isNaN(zM.fSel)) {
  1168.                 ctx.font = '60px "Nova Flat"';
  1169.                 ctx.fillStyle = '#000';
  1170.                 var t = 'No fleet selected';
  1171.                 ctx.fillText(t, 400 - ctx.measureText(t).width/2, 330);
  1172.             } else if (!zM.fleet[zM.fSel]) {
  1173.                 ctx.font = '60px "Nova Flat"';
  1174.                 ctx.fillStyle = '#000';
  1175.                 var t = 'Undefined fleet selected';
  1176.                 ctx.fillText(t, 400 - ctx.measureText(t).width/2, 330);
  1177.             } else if (!zM.fleet[zM.fSel].bots[zM.fleet[zM.fSel].cSel]) { // you can get this if the bot no longer exists (or an invalid bot selected state)
  1178.                 ctx.font = '60px "Nova Flat"';
  1179.                 ctx.fillStyle = '#000';
  1180.                 var t = 'Lost connection to server';
  1181.                 ctx.fillText(t, 400 - ctx.measureText(t).width/2, 330);
  1182.             } else {
  1183.                 var b = zM.fleet[zM.fSel].bots[zM.fleet[zM.fSel].cSel];
  1184.        
  1185.                 if (b.socket.readyState == WebSocket.CONNECTING) {
  1186.                     ctx.font = '60px "Nova Flat"';
  1187.                     ctx.fillStyle = '#000';
  1188.                     var t = 'Connecting';
  1189.                     ctx.fillText(t, 400 - ctx.measureText(t).width/2, 330);
  1190.                 } else { // we don't need to handle closed states, the bot will be gone
  1191.                     for (var i = 0; i < b.obj.length; ++i) {
  1192.                         var o = b.obj[i];
  1193.                         switch (o.type) {
  1194.                             case 0:
  1195.                                 ctx.globalAlpha = 1;
  1196.                                 ctx.font = o.size + 'px "Nova Flat"';
  1197.                                 ctx.fillStyle = '#000';
  1198.                                 var x = o.x*2;
  1199.                                 if (o.isCentered) x -= ctx.measureText(o.content).width/2;
  1200.                                 ctx.fillText(o.content, x, o.y*2);
  1201.                                 break;
  1202.                             case 1:
  1203.                                 ctx.globalAlpha = 1;
  1204.                                 ctx.fillStyle = o.color;
  1205.                                 ctx.fillRect(o.x*2, o.y*2, o.w*2, o.h*2);
  1206.                                 ctx.globalAlpha = .2;
  1207.                                 ctx.strokeStyle = '#000';
  1208.                                 ctx.lineWidth = 1;
  1209.                                 ctx.strokeRect(o.x*2+1, o.y*2+1, o.w*2-2, o.h*2-2);
  1210.                                 break;
  1211.                             case 2:
  1212.                                 ctx.globalAlpha = .2;
  1213.                                 ctx.fillStyle = o.isBad?'#f00':'#0f0';
  1214.                                 ctx.fillRect(o.x*2, o.y*2, o.w*2, o.h*2);
  1215.                                 break;
  1216.                             case 3:
  1217.                                 ctx.globalAlpha = .2;
  1218.                                 ctx.fillStyle = o.color;
  1219.                                 ctx.fillRect(o.x*2, o.y*2, o.w*2, o.h*2);
  1220.                                 ctx.font = '24px "Nova Flat"';
  1221.                                 ctx.fillStyle = '#000';
  1222.                                 ctx.globalAlpha = .5;
  1223.                                 ctx.fillText(o.count, o.x*2 + o.w - ctx.measureText(o.count).width/2, o.y*2+o.h+9);
  1224.                                 break;
  1225.                             case 4:
  1226.                                 ctx.globalAlpha = 1;
  1227.                                 ctx.fillStyle = o.color;
  1228.                                 ctx.fillRect(o.x*2, o.y*2, o.w*2, o.h*2);
  1229.        
  1230.                                 ctx.globalAlpha = .2;
  1231.                                 ctx.fillStyle = '#000';
  1232.                                 ctx.fillRect(o.x*2, o.y*2, o.w*2, o.h*2);
  1233.        
  1234.                                 ctx.globalAlpha = 1;
  1235.                                 ctx.fillStyle = o.color;
  1236.                                 ctx.fillRect(o.x*2+8, o.y*2+8, o.w*2-16, o.h*2-16);
  1237.        
  1238.                                 var l = Date.now() - o.lastClickAt > 150 ? 8 : 16;
  1239.        
  1240.                                 ctx.globalAlpha = .2;
  1241.                                 ctx.lineWidth = 1;
  1242.                                 ctx.strokeStyle = '#000';
  1243.                                 ctx.beginPath(),
  1244.        
  1245.                                 ctx.moveTo(o.x*2+1, o.y*2+1),
  1246.                                 ctx.lineTo(o.x*2+o.w*2-2, o.y*2+1),
  1247.                                 ctx.lineTo(o.x*2+o.w*2-2, o.y*2+o.h*2-2),
  1248.                                 ctx.lineTo(o.x*2+1, o.y*2+o.h*2-2),
  1249.                                 ctx.lineTo(o.x*2+1, o.y*2+1);
  1250.        
  1251.                                 ctx.lineTo(o.x*2+1+l, o.y*2+1+l);
  1252.        
  1253.                                 ctx.moveTo(o.x*2+o.w*2-2, o.y*2+1),
  1254.                                 ctx.lineTo(o.x*2+o.w*2-2-l, o.y*2+1+l);
  1255.        
  1256.                                 ctx.moveTo(o.x*2+o.w*2-2, o.y*2+o.h*2-2);
  1257.                                 ctx.lineTo(o.x*2+o.w*2-2-l, o.y*2+o.h*2-2-l);
  1258.        
  1259.                                 ctx.moveTo(o.x*2+1, o.y*2+o.h*2-2),
  1260.                                 ctx.lineTo(o.x*2+1+l, o.y*2+o.h*2-2-l);
  1261.        
  1262.                                 ctx.moveTo(o.x*2+l, o.y*2+l),
  1263.                                 ctx.lineTo(o.x*2+o.w*2-l, o.y*2+l),
  1264.                                 ctx.lineTo(o.x*2+o.w*2-l, o.y*2+o.h*2-l),
  1265.                                 ctx.lineTo(o.x*2+l, o.y*2+o.h*2-l),
  1266.                                 ctx.lineTo(o.x*2+l, o.y*2+l);
  1267.        
  1268.                                 ctx.stroke();
  1269.        
  1270.                                 ctx.fillStyle = '#000';
  1271.                                 ctx.globalAlpha = .5;
  1272.                                 ctx.font = '24px "Nova Flat"';
  1273.                                 ctx.fillText(o.count, o.x*2 + o.w - ctx.measureText(o.count).width/2, o.y*2+o.h+9);
  1274.                         }
  1275.                     }
  1276.        
  1277.                     ctx.strokeStyle = '#000';
  1278.                     ctx.lineWidth = 1.5;
  1279.                     for (var i = 0; i < b.clicks.length; ++i) {
  1280.                         if (typeof b.clicks[i] === 'object') {
  1281.                             if (Date.now() - b.clicks[i].time > 500) b.clicks.splice(i--, 1);
  1282.                             else {
  1283.                                 ctx.beginPath(),
  1284.                                 ctx.globalAlpha = .5 - (Date.now() - b.clicks[i].time)/1000;
  1285.                                 var radius = (Date.now() - b.clicks[i].time)/20;
  1286.                                 if (radius < 0.1) radius = 0.1 // Anti-crash failsafe
  1287.                                 ctx.arc(b.clicks[i].x*2, b.clicks[i].y*2, radius, 0, 2*Math.PI);
  1288.                                 ctx.stroke();
  1289.                             }
  1290.                         }
  1291.                     }
  1292.        
  1293.                     ctx.strokeStyle = '#000';
  1294.                     ctx.lineWidth = 1;
  1295.                     ctx.globalAlpha = .3;
  1296.                     for (var i = 0; i < b.drawings.length; ++i) {
  1297.                         if (typeof b.drawings[i] === 'object') {
  1298.                             if (Date.now() - b.drawings[i].time > 10000) b.drawings.splice(i--, 1);
  1299.                             else {
  1300.                                 ctx.beginPath(),
  1301.                                 ctx.moveTo(b.drawings[i].x*2, b.drawings[i].y*2);
  1302.                                 ctx.lineTo(b.drawings[i].x2*2, b.drawings[i].y2*2);
  1303.                                 ctx.stroke();
  1304.                             }
  1305.                         }
  1306.                     }
  1307.        
  1308.                     ctx.globalAlpha = 1;
  1309.                     ctx.font = '12px "Nova Flat"';
  1310.                     for (var i = 0; i < b.players.length; ++i) {
  1311.                         var img;
  1312.                         if (zM.fleet[zM.fSel].ids.indexOf(b.players[i].id) != -1) {
  1313.                             for (var j = 0; i < zM.fleet[zM.fSel].bots.length; ++j) {
  1314.                                 if (zM.fleet[zM.fSel].bots[j]) if (zM.fleet[zM.fSel].bots[j].id == b.players[i].id) break;
  1315.                             }
  1316.                             if (j < zM.fleet[zM.fSel].bots.length) {
  1317.                                 if (zM.fleet[zM.fSel].bots[j].helping || zM.fleet[zM.fSel].bots[j].deployed) img = zMIMG.movement.img;
  1318.                                 else img = zMIMG.local.img;
  1319.                             } else img = zMIMG.local.img;
  1320.                         } else img = zMIMG.cursor.img;
  1321.                         var x = zM.ease(b.players[i].x, b.players[i].ox, b.players[i].lastUpdate)*2;
  1322.                         var y = zM.ease(b.players[i].y, b.players[i].oy, b.players[i].lastUpdate)*2;
  1323.                         ctx.drawImage(img, x-4, y-5);
  1324.                         x += 5;
  1325.                         y-= 2;
  1326.                         if (x + ctx.measureText(\`\${b.players[i].id}\`).width > 790) x = 790 - ctx.measureText(\`\${b.players[i].id}\`).width;
  1327.                         if (y - 12 < 10) y = 22;
  1328.                         zM.r.hudText(\`\${b.players[i].id}\`, x, y);
  1329.                     }
  1330.        
  1331.                     switch (zM.r.infLvl) {
  1332.                         case 5:
  1333.                             zM.r.hudText(\`Received (tp/ps) \${b.packets.receivedTotal} / \${b.packets.receivedPS}\`, 790, 22, 1);
  1334.                             zM.r.hudText(\`Sent (tp/ps) \${b.packets.sentTotal} / \${b.packets.sentPS}\`, 790, 36, 1);
  1335.                         case 4:
  1336.                         case 3:
  1337.                         case 2:
  1338.                             zM.r.hudText(\`Level \${b.level}\`, 10, 36);
  1339.                         case 1:
  1340.                             zM.r.hudText(
  1341.                                 b.local < 30 ? 'Use shift+click to draw ('+b.local+' > 0)' :
  1342.                                 b.local < 100 ? 'Too many cursors, drawing is disabled ('+b.local+' > 30)' :
  1343.                                 b.local < 1010 ? 'Too many cursors, not all cursors are shown ('+b.local+' > 100)' :
  1344.                                 'Use shift+click to draw ('+b.local+' > 1010)'
  1345.                             , 10, 590);
  1346.        
  1347.                             zM.r.hudText(\`\${b.online} players online\`, 790, 590, 1);
  1348.                         case 0:
  1349.                     }
  1350.                 }
  1351.             }
  1352.        
  1353.             if (zM.r.infLvl >= 2) zM.r.hudText('FPS ' + zM.r.fps,10,22);
  1354.        
  1355.             ctx.fillStyle = zM.movement?'#ff0':'#f00';
  1356.             ctx.globalAlpha = 0.3;
  1357.             ctx.beginPath();
  1358.             ctx.moveTo(zM.pos.mouseX+3, zM.pos.mouseY+6);
  1359.             ctx.arc(zM.pos.mouseX+3, zM.pos.mouseY+6, 20, 0, 2*Math.PI);
  1360.             ctx.fill();
  1361.        
  1362.             ctx.globalAlpha = 1;
  1363.             ctx.drawImage(zMIMG.cursor.img, zM.pos.mouseX-4, zM.pos.mouseY-5);
  1364.        
  1365.        
  1366.             zM.reqAfter();
  1367.         }
  1368.        
  1369.         zM.reqAfter = function() {
  1370.             ++zM.r.fps;
  1371.             requestAnimationFrame(zM.reqDo);
  1372.             setTimeout(()=>{--zM.r.fps},1000);
  1373.         }`,
  1374.  
  1375.         /* zM packet parsing */
  1376.         `zM.dependenciesLoaded |= 0b010000;
  1377.  
  1378.         zM.parse = {
  1379.             /**
  1380.              * Returns an array as [local, players, offset]
  1381.              */
  1382.             cursors: function(buffer, offset) {
  1383.                 var dat = new DataView(buffer);
  1384.                 var local = dat.getUint16(offset, true);
  1385.        
  1386.                 offset += 2;
  1387.        
  1388.                 var players = [];
  1389.                 for (var i = 0; i < local; ++i) {
  1390.                     players.push({
  1391.                         id: dat.getUint32(offset, true),
  1392.                         x: dat.getUint16(offset + 4, true),
  1393.                         y: dat.getUint16(offset + 6, true),
  1394.                     });
  1395.                     offset += 8;
  1396.                 }
  1397.        
  1398.                 return [local, players, offset];
  1399.             },
  1400.        
  1401.             /**
  1402.              * Returns an array as [clicks, offset]
  1403.              */
  1404.             clicks: function(buffer, offset) {
  1405.                 var dat = new DataView(buffer);
  1406.                
  1407.                 var count = dat.getUint16(offset, true);
  1408.                 var clicks = [];
  1409.        
  1410.                 offset += 2;
  1411.                 for (var i = 0; i < count; ++i) {
  1412.                     clicks.push({
  1413.                         x: dat.getUint16(offset, true),
  1414.                         y: dat.getUint16(offset + 2, true),
  1415.                         time: Date.now()
  1416.                     });
  1417.                     offset += 4;
  1418.                 }
  1419.        
  1420.                 return [clicks, offset];
  1421.             },
  1422.        
  1423.             /**
  1424.              * Returns an array as [clicks, offset]
  1425.              */
  1426.             drawing: function(buffer, offset) {
  1427.                 var dat = new DataView(buffer);
  1428.                
  1429.                 var count = dat.getUint16(offset, true);
  1430.                 var drawings = [];
  1431.        
  1432.                 offset += 2;
  1433.                 for (var i = 0; i < count; ++i) {
  1434.                     drawings.push({
  1435.                         x: dat.getUint16(offset, true),
  1436.                         y: dat.getUint16(offset + 2, true),
  1437.                         x2: dat.getUint16(offset + 4, true),
  1438.                         y2: dat.getUint16(offset + 6, true),
  1439.                         time: Date.now()
  1440.                     });
  1441.                     offset += 8;
  1442.                 }
  1443.        
  1444.                 return [drawings, offset];
  1445.             },
  1446.        
  1447.             /**
  1448.              * Returns an array as [ids, offset]
  1449.              */
  1450.             remove: function(buffer, offset) {
  1451.                 var dat = new DataView(buffer);
  1452.        
  1453.                 var count = dat.getUint16(offset, true);
  1454.                 var ids = [];
  1455.        
  1456.                 offset += 2;
  1457.                 for (var i = 0; i < count; ++i) {
  1458.                     ids.push(dat.getUint32(offset, true));
  1459.                     offset += 4;
  1460.                 }
  1461.        
  1462.                 return [ids, offset];
  1463.             },
  1464.        
  1465.             /**
  1466.              * Parses objdata (string) and outputs as objects.
  1467.              */
  1468.             objData: function(objdata) {
  1469.                 var obj = objdata;
  1470.                 var nObj = [];
  1471.        
  1472.                 for (var i = 0; i < obj.length; ++i) {
  1473.                     var nO = {};
  1474.                     obj[i] = obj[i].split(/\\.+/g);
  1475.                     nO.id = parseInt(obj[i].shift());
  1476.                     var type = obj[i].shift();
  1477.                     switch (type) {
  1478.                         case '0':
  1479.                             nO.type = 0;
  1480.                             nO.x = parseInt(obj[i].shift());
  1481.                             nO.y = parseInt(obj[i].shift());
  1482.                             nO.size = parseInt(obj[i].shift());
  1483.                             nO.isCentered = obj[i].shift() === 'false'?false:true;
  1484.        
  1485.                             nO.content = obj[i].join('');
  1486.                             break;
  1487.                         case '1':
  1488.                             nO.type = 1;
  1489.                             nO.x = parseInt(obj[i].shift());
  1490.                             nO.y = parseInt(obj[i].shift());
  1491.                             nO.w = parseInt(obj[i].shift());
  1492.                             nO.h = parseInt(obj[i].shift());
  1493.                             nO.color = obj[i].shift();
  1494.                             break;
  1495.                         case '2':
  1496.                             nO.type = 2;
  1497.                             nO.x = parseInt(obj[i].shift());
  1498.                             nO.y = parseInt(obj[i].shift());
  1499.                             nO.w = parseInt(obj[i].shift());
  1500.                             nO.h = parseInt(obj[i].shift());
  1501.                             nO.isBad = obj[i].shift()==='false'?false:true;
  1502.                             break;
  1503.                         case '3':
  1504.                             nO.type = 3;
  1505.                             nO.x = parseInt(obj[i].shift());
  1506.                             nO.y = parseInt(obj[i].shift());
  1507.                             nO.w = parseInt(obj[i].shift());
  1508.                             nO.h = parseInt(obj[i].shift());
  1509.                             nO.count = parseInt(obj[i].shift());
  1510.                             nO.color = obj[i].shift();
  1511.                             break;
  1512.                         case '4':
  1513.                             nO.type = 4;
  1514.                             nO.x = parseInt(obj[i].shift());
  1515.                             nO.y = parseInt(obj[i].shift());
  1516.                             nO.w = parseInt(obj[i].shift());
  1517.                             nO.h = parseInt(obj[i].shift());
  1518.                             nO.count = parseInt(obj[i].shift());
  1519.                             nO.color = obj[i].shift();
  1520.                             nO.lastClickAt = 0;
  1521.                             break;
  1522.                     }
  1523.        
  1524.                     nObj.push(nO);
  1525.                 }
  1526.        
  1527.                 return nObj;
  1528.             },
  1529.        
  1530.             /**
  1531.              * Returns an array as [objdata, offset]
  1532.              * objdata is required to be further parsed with zM.parse.objData()
  1533.              */
  1534.             objects: function(buffer, offset) {
  1535.                 var dat = new DataView(buffer);
  1536.        
  1537.                 var count = dat.getUint16(offset, true);
  1538.                 var objdata = [];
  1539.        
  1540.                 offset += 2;
  1541.                 for (var i = 0; i < count; ++i) {
  1542.                     var id = dat.getUint32(offset, true);
  1543.                     offset += 4;
  1544.                     var type = dat.getUint8(offset);
  1545.                     var objdat = id+'.';
  1546.                     ++offset;
  1547.                     switch (type) {
  1548.                         case 0:
  1549.                             objdat += '0.';
  1550.                             objdat += \`\${dat.getUint16(offset, true)}.\`;
  1551.                             objdat += \`\${dat.getUint16(offset+2, true)}.\`;
  1552.                             objdat += \`\${dat.getUint8(offset+4)}.\`;
  1553.                             objdat += \`\${!!dat.getUint8(offset+5)}.\`;
  1554.                             offset += 5;
  1555.                             for (;1;) if (dat.getUint8(++offset) != 0) objdat += String.fromCharCode(dat.getUint8(offset));
  1556.                                       else break;
  1557.                            
  1558.                             ++offset;
  1559.                             break;
  1560.                         case 1:
  1561.                             objdat += '1.';
  1562.                             objdat += \`\${dat.getUint16(offset, true)}.\`;
  1563.                             objdat += \`\${dat.getUint16(offset+2, true)}.\`;
  1564.                             objdat += \`\${dat.getUint16(offset+4, true)}.\`;
  1565.                             objdat += \`\${dat.getUint16(offset+6, true)}.\`;
  1566.                             var color = dat.getUint32(offset+8, true).toString(16);
  1567.                             for (; color.length < 6;) color = '0' + color;
  1568.                             objdat += '#' + color + '.';
  1569.        
  1570.                             offset += 12;
  1571.        
  1572.                             break;
  1573.        
  1574.                         case 2:
  1575.                             objdat += '2.';
  1576.                             objdat += \`\${dat.getUint16(offset, true)}.\`;
  1577.                             objdat += \`\${dat.getUint16(offset+2, true)}.\`;
  1578.                             objdat += \`\${dat.getUint16(offset+4, true)}.\`;
  1579.                             objdat += \`\${dat.getUint16(offset+6, true)}.\`;
  1580.                             objdat += \`\${!!dat.getUint8(offset+8)}.\`;
  1581.                             offset += 9;
  1582.                             break;
  1583.        
  1584.                         case 3:
  1585.                             objdat += '3.';
  1586.                             objdat += \`\${dat.getUint16(offset, true)}.\`;
  1587.                             objdat += \`\${dat.getUint16(offset+2, true)}.\`;
  1588.                             objdat += \`\${dat.getUint16(offset+4, true)}.\`;
  1589.                             objdat += \`\${dat.getUint16(offset+6, true)}.\`;
  1590.                             objdat += \`\${dat.getUint16(offset+8, true)}.\`;
  1591.                             var color = dat.getUint32(offset+10, true).toString(16);
  1592.                             for (; color.length < 6;) color = '0' + color;
  1593.                             objdat += '#' + color + '.';
  1594.            
  1595.                             offset += 14;
  1596.                             break;
  1597.        
  1598.                         case 4:
  1599.                             objdat += '4.';
  1600.                             objdat += \`\${dat.getUint16(offset, true)}.\`;
  1601.                             objdat += \`\${dat.getUint16(offset+2, true)}.\`;
  1602.                             objdat += \`\${dat.getUint16(offset+4, true)}.\`;
  1603.                             objdat += \`\${dat.getUint16(offset+6, true)}.\`;
  1604.                             objdat += \`\${dat.getUint16(offset+8, true)}.\`;
  1605.                             var color = dat.getUint32(offset+10, true).toString(16);
  1606.                             for (; color.length < 6;) color = '0' + color;
  1607.                             objdat += '#' + color + '.';
  1608.                             offset += 14;
  1609.                             break;
  1610.                     }
  1611.                     objdata.push(objdat);
  1612.                 }
  1613.        
  1614.                 return [objdata, offset];
  1615.             }
  1616.         }
  1617.        
  1618.         zM.packet = {
  1619.             /**
  1620.              *
  1621.              * @param {array} sockets Array of sockets to move
  1622.              */
  1623.             moveSocket(sockets, x, y, bots) {
  1624.                 var buf = new ArrayBuffer(9),
  1625.                     dat = new DataView(buf);
  1626.        
  1627.                 dat.setUint8(0, 1);
  1628.                 dat.setUint16(1, x, true);
  1629.                 dat.setUint16(3, y, true);
  1630.                 dat.setUint32(5, -1, true);
  1631.                 sockets.forEach(X => typeof X.send === 'function' && X.send(buf));
  1632.                 bots.forEach(X => {
  1633.                     ++X.packets.sentTotal;
  1634.                     ++X.packets.sentPS;
  1635.                     setTimeout(()=>{--X.packets.sentPS},1000);
  1636.                     X.packets.lastSent = Date.now();
  1637.                 });
  1638.             },
  1639.        
  1640.             /**
  1641.              *
  1642.              * @param {array} sockets Array of sockets to click with
  1643.              */
  1644.             clickSocket(sockets, x, y, bots) {
  1645.                 var buf = new ArrayBuffer(9),
  1646.                     dat = new DataView(buf);
  1647.        
  1648.                 dat.setUint8(0, 2);
  1649.                 dat.setUint16(1, x, true);
  1650.                 dat.setUint16(3, y, true);
  1651.                 dat.setUint32(5, -1, true);
  1652.                 sockets.forEach(X => typeof X.send === 'function' && X.send(buf));
  1653.                 bots.forEach(X => {
  1654.                     ++X.packets.sentTotal;
  1655.                     ++X.packets.sentPS;
  1656.                     setTimeout(()=>{--X.packets.sentPS},1000);
  1657.                     X.packets.lastSent = Date.now();
  1658.                 });
  1659.             },
  1660.        
  1661.             /**
  1662.              *
  1663.              * @param {array} sockets Array of sockets to draw with
  1664.              */
  1665.             drawSocket(sockets, x, y, x2, y2, bots) {
  1666.                 var buf = new ArrayBuffer(9),
  1667.                     dat = new DataView(buf);
  1668.        
  1669.                 dat.setUint8(0, 3);
  1670.                 dat.setUint16(1, x, true);
  1671.                 dat.setUint16(3, y, true);
  1672.                 dat.setUint16(5, x2, true);
  1673.                 dat.setUint16(7, y2, true);
  1674.                 sockets.forEach(X => typeof X.send === 'function' && (X.send(buf)));
  1675.                 bots.forEach(X => {
  1676.                     ++X.packets.sentTotal;
  1677.                     ++X.packets.sentPS;
  1678.                     setTimeout(()=>{--X.packets.sentPS},1000);
  1679.                     X.packets.lastSent = Date.now();
  1680.                 });
  1681.             }
  1682.         }`,
  1683.         /* zM Pathfinder */
  1684.         `zM.dependenciesLoaded |= 0b100000;
  1685.  
  1686.         var visit = [];
  1687.        
  1688.         zM.dos = function(dx, dy, items, gridSpace) {
  1689.             var gridX = 400/gridSpace,
  1690.                 gridY = 300/gridSpace;
  1691.             var grid = [];
  1692.             visit = [];
  1693.             for (var i = 0; i < gridY; i++) {
  1694.                 grid[i] = [];
  1695.                 visit[i] = [];
  1696.                 for (var j = 0; j < gridX; j++) grid[i][j] = 0, visit[i][j] = 0;
  1697.             }
  1698.             items.forEach(function(d) {
  1699.                 if (d.type === 1) {
  1700.                     for (var i = 0; i < d.h; i+=gridSpace) {
  1701.                         for (var j = 0; j < d.w; j+=gridSpace) {
  1702.                             grid[(d.y+i)/gridSpace][(d.x+j)/gridSpace] = 3;
  1703.                         }
  1704.                     }
  1705.                 }
  1706.             });
  1707.             var bfs = [[dx,dy]],
  1708.                 bfs2 = [];
  1709.             while (bfs.length) {
  1710.                 bfs.forEach(function(dat) {
  1711.                     var x = dat[0],
  1712.                         y = dat[1];
  1713.                     if (grid[y][x] == 3) return;
  1714.                     grid[y][x] = 3;
  1715.                     for (var X = x + 1; X < gridX && !(grid[y][X] & 1); X++) {
  1716.                         grid[y][X] |= 1;
  1717.                         if (!visit[y][X]) {
  1718.                             visit[y][X] = [x, y], bfs2.push([X, y]);
  1719.                         }
  1720.                     }
  1721.                     for (var X = x - 1; X >= 0 && !(grid[y][X] & 1); X--) {
  1722.                         grid[y][X] |= 1;
  1723.                         if (!visit[y][X]) {
  1724.                             visit[y][X] = [x, y], bfs2.push([X, y]);
  1725.                         }
  1726.                     }
  1727.                     for (var Y = y + 1; Y < gridY && !(grid[Y][x] & 2); Y++) {
  1728.                         grid[Y][x] |= 2;
  1729.                         if (!visit[Y][x]) {
  1730.                             visit[Y][x] = [x, y], bfs2.push([x, Y]);
  1731.                         }
  1732.                     }
  1733.                     for (var Y = y - 1; Y >= 0 && !(grid[Y][x] & 2); Y--) {
  1734.                         grid[Y][x] |= 2;
  1735.                         if (!visit[Y][x]) {
  1736.                             visit[Y][x] = [x, y], bfs2.push([x, Y]);
  1737.                         }
  1738.                     }
  1739.                 });
  1740.                 bfs = bfs2;
  1741.                 bfs2 = [];
  1742.             }
  1743.         }
  1744.        
  1745.         zM.path = function(ox, oy, dx, dy, items, grid) {
  1746.        
  1747.             var rdx = dx, rdy = dy;
  1748.             ox /= grid;
  1749.             oy /= grid;
  1750.             dx /= grid;
  1751.             dy /= grid;
  1752.        
  1753.             ox |= 0;
  1754.             oy |= 0;
  1755.             dx |= 0;
  1756.             dy |= 0;
  1757.            
  1758.             var mov = [];
  1759.             if (!(ox == dx && oy == dy)) {
  1760.                 zM.dos(ox,oy,items,grid);
  1761.                 var xy2 = [dx,dy];
  1762.                 while (visit[xy2[1]][xy2[0]]) {
  1763.                     mov.push(xy2);
  1764.                     xy2 = visit[xy2[1]][xy2[0]];
  1765.                 }
  1766.        
  1767.                 mov.reverse();
  1768.             }
  1769.        
  1770.             for (var i = 0; i < mov.length; ++i) {
  1771.                 mov[i][0] *= grid;
  1772.                 mov[i][0] += grid/2;
  1773.                 mov[i][1] *= grid;
  1774.                 mov[i][1] += grid/2;
  1775.             }
  1776.             mov.push([rdx, rdy]);
  1777.             return mov;
  1778.         }`
  1779.     ],
  1780.    
  1781.     // ---
  1782.     // add elements from functions below:
  1783.     // ---
  1784.  
  1785. [
  1786.     function(c) {
  1787.         var temp = [D.createElement('link')];
  1788.         temp[0].href = 'https://fonts.googleapis.com/css?family=Montserrat:100,200,300,400';
  1789.         temp[0].rel = 'stylesheet';
  1790.         head.appendChild(temp[0]);
  1791.  
  1792.         temp[1] = D.createElement('link');
  1793.         temp[1].href = 'https://fonts.googleapis.com/css?family=Nova+Flat&display=swap';
  1794.         temp[1].rel = 'stylesheet';
  1795.         head.appendChild(temp[1]);
  1796.     },
  1797.     function(c) { // news area (null fleet selected)
  1798.         var temp = [D.createElement('div')];
  1799.         temp[0].className = 'zM-news-outer';
  1800.  
  1801.         temp[1] = D.createElement('div');
  1802.         temp[1].className = 'zM-news-container';
  1803.         temp[0].appendChild(temp[1]);
  1804.  
  1805.         temp[2] = D.createElement('div');
  1806.         temp[2].className = 'zM-news-page-top';
  1807.         temp[1].appendChild(temp[2]);
  1808.  
  1809.         temp[3] = D.createElement('div');
  1810.         temp[3].className = 'zM-news-page-mid';
  1811.         temp[1].appendChild(temp[3]);
  1812.  
  1813.         temp[4] = D.createElement('div');
  1814.         temp[4].className = 'zM-news-page-bottom';
  1815.         temp[1].appendChild(temp[4]);
  1816.  
  1817.         zM.el.newsOuter = temp[0];
  1818.         zM.el.newsPageTop = temp[2];
  1819.         zM.el.newsPageMid = temp[3];
  1820.         zM.el.newsPageBottom = temp[4];
  1821.         c.appendChild(temp[0]);
  1822.     },
  1823.     function(c) { // fleet prompt
  1824.         var temp = [D.createElement('div')];
  1825.         temp[0].className = 'zM-fleet-prompt-outer';
  1826.  
  1827.         temp[1] = D.createElement('div');
  1828.         temp[1].className = 'zM-fleet-prompt-container';
  1829.         temp[0].appendChild(temp[1]);
  1830.  
  1831.         temp[2] = D.createElement('div');
  1832.         temp[2].className = 'zM-fleet-prompt-title';
  1833.         temp[2].textContent = 'Create new fleet';
  1834.         temp[1].appendChild(temp[2]);
  1835.  
  1836.  
  1837.         temp[3] = D.createElement('div');
  1838.         temp[3].className = 'zM-fleet-prompt-entry';
  1839.         temp[1].appendChild(temp[3]);
  1840.  
  1841.         temp[4] = D.createElement('div');
  1842.         temp[4].className = 'zM-fleet-prompt-opt';
  1843.         temp[4].textContent = 'Use premade IPs'
  1844.         temp[3].appendChild(temp[4]);
  1845.  
  1846.         temp[5] = D.createElement('input');
  1847.         temp[5].type = 'checkbox';
  1848.         temp[5].checked = true;
  1849.         temp[5].addEventListener('change', () => {
  1850.             if (temp[5].checked) {
  1851.                 temp[6].style.display = 'block';
  1852.                 temp[10].style.display = 'none';
  1853.                 temp[13].style.display = 'none';
  1854.                 temp[16].style.display = 'none';
  1855.                 if (temp[12].value + ':' + temp[15].value === `${ip}:2828`) temp[8].value = "0";
  1856.                 else if (temp[12].value + ':' + temp[15].value === 'kursors.io/ws:8080') temp[8].value = "1";
  1857.                 else if (temp[12].value + ':' + temp[15].value === 'localhost:9004') temp[8].value = "2";
  1858.             } else {
  1859.                 temp[6].style.display = 'none';
  1860.                 temp[10].style.display = 'block';
  1861.                 temp[13].style.display = 'block';
  1862.                 temp[16].style.display = 'block';
  1863.  
  1864.                 // set input values
  1865.                 switch (temp[8].value) {
  1866.                     case "0": {
  1867.                         temp[12].value = __ip;
  1868.                         temp[15].value = '2828';
  1869.                         break;
  1870.                     }
  1871.                     case "1": {
  1872.                         temp[12].value = 'kursors.io/ws';
  1873.                         temp[15].value = '8080';
  1874.                         break;
  1875.                     }
  1876.                     case "2": {
  1877.                         temp[12].value = 'localhost';
  1878.                         temp[15].value = '9004';
  1879.                         break;
  1880.                     }
  1881.                 }
  1882.  
  1883.                 temp[18].checked = false;
  1884.             }
  1885.         })
  1886.         temp[3].appendChild(temp[5]);
  1887.  
  1888.  
  1889.         temp[6] = D.createElement('div');
  1890.         temp[6].className = 'zM-fleet-prompt-entry';
  1891.         temp[1].appendChild(temp[6]);
  1892.  
  1893.         temp[7] = D.createElement('div');
  1894.         temp[7].className = 'zM-fleet-prompt-opt';
  1895.         temp[7].textContent = 'Select an IP to connect to:'
  1896.         temp[6].appendChild(temp[7]);
  1897.  
  1898.         // dropdown
  1899.         temp[8] = D.createElement('select');
  1900.         temp[8].style.outline = 'none';
  1901.         temp[6].appendChild(temp[8]);
  1902.  
  1903.         temp[9] = [D.createElement('option'), D.createElement('option'), D.createElement('option')];
  1904.         temp[9][0].value = "0";
  1905.         temp[9][0].textContent = `cursors.io ${__ip}:2828)`;
  1906.         temp[9][1].value = "1";
  1907.         temp[9][1].textContent = 'kursors.io (kursors.io/ws:8080)';
  1908.         temp[9][2].value = "2";
  1909.         temp[9][2].textContent = 'local server (localhost:9004)';
  1910.  
  1911.         temp[9].forEach(X => temp[8].appendChild(X));
  1912.  
  1913.         temp[10] = D.createElement('div');
  1914.         temp[10].className = 'zM-fleet-prompt-entry';
  1915.         temp[10].style.display = 'none';
  1916.         temp[1].appendChild(temp[10]);
  1917.  
  1918.         temp[11] = D.createElement('div');
  1919.         temp[11].className = 'zM-fleet-prompt-opt';
  1920.         temp[11].textContent = 'IP address:'
  1921.         temp[10].appendChild(temp[11]);
  1922.         temp[12] = D.createElement('input');
  1923.         temp[12].type = 'text';
  1924.         temp[12].style.outline = 'none';
  1925.         temp[12].width = 200;
  1926.         temp[10].appendChild(temp[12]);
  1927.  
  1928.         temp[13] = D.createElement('div');
  1929.         temp[13].className = 'zM-fleet-prompt-entry';
  1930.         temp[13].style.display = 'none';
  1931.         temp[1].appendChild(temp[13]);
  1932.  
  1933.         temp[14] = D.createElement('div');
  1934.         temp[14].className = 'zM-fleet-prompt-opt';
  1935.         temp[14].textContent = 'Port:'
  1936.         temp[13].appendChild(temp[14]);
  1937.         temp[15] = D.createElement('input');
  1938.         temp[15].type = 'text';
  1939.         temp[15].style.outline = 'none';
  1940.         temp[15].width = 200;
  1941.         temp[13].appendChild(temp[15]);
  1942.  
  1943.         temp[16] = D.createElement('div');
  1944.         temp[16].className = 'zM-fleet-prompt-entry';
  1945.         temp[16].style.display = 'none';
  1946.         temp[1].appendChild(temp[16]);
  1947.  
  1948.         temp[17] = D.createElement('div');
  1949.         temp[17].className = 'zM-fleet-prompt-opt';
  1950.         temp[17].textContent = 'Using IPv6:'
  1951.         temp[16].appendChild(temp[17]);
  1952.         temp[18] = D.createElement('input');
  1953.         temp[18].type = 'checkbox';
  1954.         temp[18].style.outline = 'none';
  1955.         temp[16].appendChild(temp[18]);
  1956.  
  1957.         // max bots
  1958.         temp[19] = D.createElement('div');
  1959.         temp[19].className = 'zM-fleet-prompt-entry';
  1960.         temp[1].appendChild(temp[19]);
  1961.  
  1962.         temp[20] = D.createElement('div');
  1963.         temp[20].className = 'zM-fleet-prompt-opt';
  1964.         temp[20].textContent = 'Maximum bots to this fleet:';
  1965.         temp[19].appendChild(temp[20]);
  1966.  
  1967.         temp[21] = D.createElement('input');
  1968.         temp[21].type = 'number';
  1969.         temp[19].appendChild(temp[21]);
  1970.         temp[21].addEventListener('change', ev => {
  1971.             var num = Math.min(100, Math.max(parseInt(temp[21].value), 0));
  1972.             if (isNaN(num)) num = 3;
  1973.             temp[21].value = num;
  1974.         });
  1975.  
  1976.        
  1977.  
  1978.         if (zM.origin === 'cursors') temp[21].value = 3;
  1979.         else temp[21].value = 20;
  1980.  
  1981.  
  1982.         // start bots
  1983.         temp[22] = D.createElement('div');
  1984.         temp[22].className = 'zM-fleet-prompt-entry';
  1985.         temp[1].appendChild(temp[22]);
  1986.  
  1987.         temp[23] = D.createElement('div');
  1988.         temp[23].className = 'zM-fleet-prompt-opt';
  1989.         temp[23].textContent = 'Start with # bots:';
  1990.         temp[22].appendChild(temp[23]);
  1991.  
  1992.         temp[24] = D.createElement('input');
  1993.         temp[24].type = 'number';
  1994.         temp[22].appendChild(temp[24]);
  1995.         temp[24].addEventListener('change', ev => {
  1996.             var num = Math.min(100, Math.max(parseInt(temp[24].value), 0));
  1997.             if (isNaN(num)) num = 3;
  1998.             temp[24].value = num;
  1999.         });
  2000.  
  2001.         if (zM.origin === 'cursors') temp[24].value = 3;
  2002.         else temp[24].value = 20;
  2003.  
  2004.  
  2005.         // zursor username
  2006.         temp[25] = D.createElement('div');
  2007.         temp[25].className = 'zM-fleet-prompt-entry';
  2008.         temp[1].appendChild(temp[25]);
  2009.  
  2010.         temp[26] = D.createElement('div');
  2011.         temp[26].className = 'zM-fleet-prompt-opt';
  2012.         temp[26].textContent = 'Fleet name (public):';
  2013.         temp[25].appendChild(temp[26]);
  2014.  
  2015.         temp[27] = D.createElement('input');
  2016.         temp[27].type = 'text';
  2017.         temp[25].appendChild(temp[27]);
  2018.  
  2019.  
  2020.         // confirmation buttons
  2021.         temp[28] = D.createElement('div');
  2022.         temp[28].className = 'zM-fleet-prompt-create';
  2023.         temp[28].textContent = 'Create fleet';
  2024.         temp[1].appendChild(temp[28]);
  2025.  
  2026.         temp[29] = D.createElement('div');
  2027.         temp[29].className = 'zM-fleet-prompt-cancel';
  2028.         temp[29].textContent = 'Cancel';
  2029.         temp[1].appendChild(temp[29]);
  2030.  
  2031.         temp[29].addEventListener('click', ev => {
  2032.             temp[0].style.display = 'none';
  2033.             if (isNaN(zM.fSel)) zM.el.newsOuter.style.display = 'block';
  2034.             else zM.updateTabs();
  2035.         });
  2036.  
  2037.         temp[28].addEventListener('click', () => {
  2038.             var ip, port, ipv6 = false;
  2039.  
  2040.             if (!temp[5].checked) ip = temp[12].value, port = temp[15].value, ipv6 = temp[18].checked;
  2041.             else {
  2042.                 switch (temp[8].value) {
  2043.                     case "0": ip = __ip; port = '2828'; break;
  2044.                     case "1": ip = 'kursors.io/ws'; port = '8080'; break;
  2045.                     default: ip = 'localhost'; port = '9004'; break;
  2046.                 }
  2047.             }
  2048.  
  2049.             var maxBots = parseInt(temp[21].value),
  2050.                 startBots = parseInt(temp[24].value);
  2051.  
  2052.             var name = temp[27].value;
  2053.             if (name.length === 0) name = 'Unnamed fleet';
  2054.             zM.createFleet(ip, port, ipv6, maxBots, startBots, name);
  2055.         });
  2056.  
  2057.  
  2058.  
  2059.         // give temp to zM.el
  2060.         zM.el.fleetPromptOuter = temp[0];
  2061.         zM.el.fleetPromptContainer = temp[1];
  2062.         c.appendChild(temp[0]);
  2063.     },
  2064.     function(c) { // fleet topbar
  2065.         var temp = [D.createElement('div')];
  2066.         temp[0].className = 'zM-fleet-topbar-outer';
  2067.         c.appendChild(temp[0]);
  2068.         temp[4] = D.createElement('div');
  2069.         temp[4].className = 'zM-fleet-topbar-container';
  2070.         temp[0].appendChild(temp[4]);
  2071.  
  2072.  
  2073.         temp[1] = D.createElement('div');
  2074.         temp[1].className = 'zM-fleet-topbar-add';
  2075.         temp[4].appendChild(temp[1]);
  2076.         temp[1].addEventListener('click', ev => {
  2077.             zM.promptFleet();
  2078.         });
  2079.  
  2080.  
  2081.         temp[2] = D.createElement('img');
  2082.         temp[2].src = zMIMG.add.uri;
  2083.         temp[2].width = 45, temp[2].height = 35, temp[2].style.cssText = 'position:absolute;top:0px;left:0px;opacity:0.8;'
  2084.         temp[1].appendChild(temp[2]);
  2085.  
  2086.  
  2087.         temp[3] = D.createElement('div');
  2088.         temp[3].className = 'zM-fleet-topbar-hint';
  2089.         temp[3].textContent = 'Add fleet here to start playing';
  2090.         temp[0].appendChild(temp[3]);
  2091.  
  2092.  
  2093.         // give temp to zM.el
  2094.         zM.el.fleetTopbarOuter = temp.shift();
  2095.         zM.el.fleetTopbarContainer = temp.pop();
  2096.         zM.el.fleetTopbarAdd = temp.shift();
  2097.         zM.el.fleetTopbarAddImg = temp.shift();
  2098.         zM.el.fleetTopbarHint = temp.shift();
  2099.     },
  2100.     function(c) {
  2101.         var temp = document.createElement('canvas');
  2102.  
  2103.         temp.className = 'zM-game';
  2104.         temp.width = 800;
  2105.         temp.height = 600;
  2106.         c.appendChild(temp);
  2107.  
  2108.         temp.addEventListener('mousemove', ev => {
  2109.             zM.pos.mouseX = ev.offsetX;
  2110.             zM.pos.mouseY = ev.offsetY;
  2111.         });
  2112.  
  2113.         temp.addEventListener('mousedown', ev => {
  2114.             if (ev.shiftKey || ev.ctrlKey) zM.drawing = true;
  2115.             else {
  2116.                 ++zM.clickQueue;
  2117.             }
  2118.         });
  2119.  
  2120.         temp.addEventListener('mouseup', ev => {
  2121.             zM.drawing = false;
  2122.         });
  2123.  
  2124.         addEventListener('keydown', ev => {
  2125.             if (isNaN(zM.fSel)) return;
  2126.             console.log(ev.key);
  2127.             switch (ev.key) {
  2128.                 // all possible keys that can be drawn
  2129.                 case 'A':
  2130.                 case 'a':case 'B':case 'b':case 'C':case 'c':
  2131.                 case 'D':case 'd':case 'E':case 'e':case 'F':
  2132.                 case 'f':case 'G':case 'g':case 'H':case 'h':
  2133.                 case 'I':case 'i':case 'J':case 'j':case 'K':
  2134.                 case 'k':case 'L':case 'l':case 'M':case 'm':
  2135.                 case 'N':case 'n':case 'O':case 'o':case 'P':
  2136.                 case 'p':case 'Q':case 'q':case 'R':case 'r':
  2137.                 case 'S':case 's':case 'T':case 't':case 'U':
  2138.                 case 'u':case 'V':case 'v':case 'W':case 'w':
  2139.                 case 'X':case 'x':case 'Y':case 'y':case 'Z':
  2140.                 case 'z':case '1':case '2':case '3':case '4':
  2141.                 case '5':case '6':case '7':case '8':case '9':
  2142.                 case '0':case '!':case '@':case '#':case '$':
  2143.                 case '%':case '^':case '&':case '*':case '(':
  2144.                 case ')':case '`':case '~':case '-':case '_':
  2145.                 case '=':case '+':case '[':case ']':case '{':
  2146.                 case '}':case '\\':case '|':case ';':case ':':
  2147.                 case '\'':case '"':case '.':case ',':case '<':
  2148.                 case '>':case '/':case '?':
  2149.  
  2150.                 case '¡':
  2151.                 case '¢':case '£':case '¤':case '¥':case '¦':
  2152.                 case '§':case '¨':case '©':case 'ª':case '«':
  2153.                 case '¬':case '®':case '¯':case '°':case '±':
  2154.                 case '²':case '³':case '´':case 'µ':case '¶':
  2155.                 case '·':case '¸':case '¹':case 'º':case '»':
  2156.                 case '¼':case '½':case '¾':case '¿':
  2157.  
  2158.                 case 'À':
  2159.                 case 'Á':case 'Â':case 'Ã':case 'Ä':case 'Å':
  2160.                 case 'Æ':case 'Ç':case 'È':case 'É':case 'Ê':
  2161.                 case 'Ë':case 'Ì':case 'Í':case 'Î':case 'Ï':
  2162.                 case 'Ð':case 'Ñ':case 'Ò':case 'Ó':case 'Ô':
  2163.                 case 'Õ':case 'Ö':case 'Ø':case 'Ù':case 'Ú':
  2164.                 case 'Û':case 'Ü':case 'Ý':case 'Þ':case 'ß':
  2165.                 case 'à':case 'á':case 'â':case 'ã':case 'ä':
  2166.                 case 'å':case 'æ':case 'ç':case 'è':case 'é':
  2167.                 case 'ê':case 'ë':case 'ì':case 'í':case 'î':
  2168.                 case 'ï':case 'ð':case 'ñ':case 'ò':case 'ó':
  2169.                 case 'ô':case 'õ':case 'ö':case 'ø':case 'ù':
  2170.                 case 'ú':case 'û':case 'ü':case 'ý':case 'þ':
  2171.                 case 'ÿ':
  2172.                     //zM.fleet[zM.fSel].
  2173.                     break;
  2174.  
  2175.                 case 'F1':
  2176.                     ev.preventDefault();
  2177.                     zM.movement ^= 1;
  2178.                     break;
  2179.  
  2180.                 case 'F2':
  2181.                     var f = zM.fleet[zM.fSel];
  2182.                     ev.preventDefault();
  2183.                     var i = 0;
  2184.                     for (; i < f.bots.length; ++i) {
  2185.                         if (f.bots[i]) if (!f.bots[i].deployed && !f.bots[i].helping && i !== f.cSel && f.bots[i].level === f.bots[f.cSel].level) break;
  2186.                     }
  2187.                     if (f.bots[i]) {
  2188.                         var b = f.bots[i];
  2189.                         b.deployed = true;
  2190.                     }
  2191.                     break;
  2192.  
  2193.                 case 'F3':
  2194.                     var f = zM.fleet[zM.fSel];
  2195.                     ev.preventDefault();
  2196.                     var i = 0;
  2197.                     for (; i < f.bots.length; ++i) {
  2198.                         if (f.bots[i]) if (f.bots[i].deployed && f.bots[i].level === f.bots[f.cSel].level) break;
  2199.                     }
  2200.                     if (i < f.bots.length) {
  2201.                         var b = f.bots[i];
  2202.                         var s = f.bots[f.cSel];
  2203.                         b.deployed = false;
  2204.                        
  2205.                         if (zM.returnAfterUndeployed) {
  2206.                             var moves = zM.path(b.realX, b.realY, s.realX, s.realY, b.obj, b.grid);
  2207.                             moves.forEach(Y => {
  2208.                                 zM.packet.moveSocket([b.socket], Y[0], Y[1], [b]);
  2209.                             });
  2210.                         }
  2211.                     }
  2212.                     break;
  2213.  
  2214.                 case 'F4':
  2215.                     ev.preventDefault();
  2216.                     var f = zM.fleet[zM.fSel];
  2217.                     if (f.isHelping) break;
  2218.                     f.isHelping = true;
  2219.                     var helpers = [];
  2220.                     for (var i = 0; i < f.bots.length; ++i) {
  2221.                         console.log(!f.bots[i].helping && !f.bots[i].deployed && i !== f.cSel && f.bots[i].level === f.bots[f.cSel].level);
  2222.                         console.log('1 ' + !f.bots[i].helping);
  2223.                         console.log('2 ' + !f.bots[i].deployed);
  2224.                         console.log('3 ' + (i !== f.cSel));
  2225.                         console.log('4 ' + (f.bots[i].level === f.bots[f.cSel].level));
  2226.                         if (f.bots[i]) if (!f.bots[i].helping && !f.bots[i].deployed && i !== f.cSel && f.bots[i].level === f.bots[f.cSel].level) helpers.push(f.bots[i]);
  2227.                     }
  2228.                     f.helpers = helpers;
  2229.                     break;
  2230.  
  2231.                 case 'F5':
  2232.                     ev.preventDefault();
  2233.                     for (var i = 0; i < zM.fleet[zM.fSel].helpers.length; ++i) {
  2234.                         zM.fleet[zM.fSel].helpers[i].helping = false;
  2235.                     }
  2236.                     zM.fleet[zM.fSel].helpers = [];
  2237.                     zM.fleet[zM.fSel].isHelping = false;
  2238.                     break;
  2239.             }
  2240.         });
  2241.  
  2242.         zM.el.game = temp;
  2243.  
  2244.         zM.reqLoad();
  2245.  
  2246.         zM.reqDo();
  2247.     },
  2248.  
  2249.     function(c) {
  2250.         var temp = [D.createElement('div')];
  2251.  
  2252.         temp[0].className = 'zM-info-outer';
  2253.         c.appendChild(temp[0]);
  2254.  
  2255.         temp[1] = D.createElement('div');
  2256.         temp[1].className = 'zM-info-ver';
  2257.         temp[1].textContent = 'v' + zM.version;
  2258.         temp[0].appendChild(temp[1]);
  2259.  
  2260.         temp[2] = D.createElement('div');
  2261.         temp[2].className = 'zM-info-clog-button-outer';
  2262.         temp[0].appendChild(temp[2]);
  2263.  
  2264.         temp[3] = D.createElement('div');
  2265.         temp[3].className = 'zM-info-clog-button';
  2266.         temp[3].textContent = 'view changelog';
  2267.         temp[2].appendChild(temp[3]);
  2268.  
  2269.  
  2270.  
  2271.  
  2272.         temp[4] = D.createElement('div');
  2273.         temp[4].className = 'zM-clog-outer';
  2274.         c.appendChild(temp[4]);
  2275.  
  2276.         temp[5] = D.createElement('div');
  2277.         temp[5].className = 'zM-clog-container';
  2278.         temp[4].appendChild(temp[5]);
  2279.  
  2280.  
  2281.         temp[6] = D.createElement('div');
  2282.         temp[6].className = 'zM-clog-close';
  2283.         temp[4].appendChild(temp[6]);
  2284.  
  2285.         temp[7] = D.createElement('img');
  2286.         temp[7].src = zMIMG.close.uri;
  2287.         temp[6].appendChild(temp[7]);
  2288.  
  2289.  
  2290.         zM.el.clogOuter = temp[4];
  2291.         zM.el.clogContainer = temp[5];
  2292.  
  2293.         temp[2].addEventListener('click', ev => {
  2294.             zM.el.clogOuter.style.display = 'block';
  2295.         });
  2296.         temp[6].addEventListener('click', ev => {
  2297.             zM.el.clogOuter.style.display = 'none';
  2298.         });
  2299.  
  2300.  
  2301.         var out = [];
  2302.         for (var i = 0; i < zM.clog.length; ++i) {
  2303.             var temp = D.createElement('div');
  2304.             if (zM.clog[i].type === 'title') {
  2305.                 temp.className = 'zM-clog-title';
  2306.                 temp.innerHTML = zM.clog[i].msg;
  2307.                 out.push(temp);
  2308.             } else {
  2309.                 temp.className = 'zM-clog-desc';
  2310.                 temp.innerHTML = zM.clog[i].msg;
  2311.                 out.push(temp);
  2312.             }
  2313.         }
  2314.  
  2315.         out.forEach(X => zM.el.clogContainer.appendChild(X));
  2316.     }
  2317. ]
  2318. );
Add Comment
Please, Sign In to add comment